Tuesday, October 13, 2009

Determining runtime environment on Google App Engine



Google recommends to determine the runtime environment of a Google App Engine application using ServletContext.getServerInfo(). In development this will be "Google App Engine Development/x.x.x" and in production it will be "Google App Engine/x.x.x".

But in some places, like Service classes, you might not have a access to the ServletContext object. Easiest way to work around this is to create a ServletContextListener which determines the environment and then stores it in a System property. The System property can be accesses from any place. You can of course also write a (static) Environment.get() utility class which return the System property.

Below you can find an example implementation of such a ServletContextListener to determine the runtime environment. As you can read the javadocs you can also use other environments then development and production. To start the application in test mode, just add a VM argument when you start your application using "-Druntime.environment=test".


import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

/**
* Simple listener to set the App Engine runtime environment via a system property.
*
* Example web.xnl definition:
*
* <listener>
* <listener-class>com.footdex.web.listener.RuntimeEnvironmentConfigurerListener</listener-class>
* </listener>
*
* The runtime environment can then be accessed from any place (without reference to
* ServletContext) via System.getProperty(RuntimeEnvironmentConfigurerListener.KEY).
*
* In case a system property is already set for the RuntimeEnvironmentConfigurerListener.KEY,
* the system property will not be overridden. This allows to startup the application
* in a custom environment other than development or production. This can be done typically
* using a VM argument like "-Druntime.environment=test".
*
* @author Marcel Overdijk
*/
public class RuntimeEnvironmentConfigurerListener implements ServletContextListener {

public static final String KEY = "runtime.environment";
public static final String DEVELOPMENT = "development";
public static final String PRODUCTION = "production";

@Override
public void contextInitialized(ServletContextEvent event) {
if (System.getProperty(KEY) == null) {
String serverInfo = event.getServletContext().getServerInfo();
// ServletContext.getServerInfo() will return "Google App Engine Development/x.x.x"
// when run locally, and "Google App Engine/x.x.x" otherwise.
if (serverInfo.contains("Development")) {
System.setProperty(KEY, DEVELOPMENT);
}
else {
System.setProperty(KEY, PRODUCTION);
}
}
}

@Override
public void contextDestroyed(ServletContextEvent event) {
}
}

1 comment:

Marcel Overdijk said...

Note that from SDK 1.3.0 you can also use the GAE native com.google.appengine.api.utils.SystemProperty to determine the runtime environment (see http://code.google.com/intl/nl/appengine/docs/java/javadoc/)