Showing posts with label Google App Engine. Show all posts
Showing posts with label Google App Engine. Show all posts

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) {
}
}

Wednesday, October 7, 2009

ConfigSlurperPlaceholderConfigurer for Spring



Lately I'm working on Spring 3.0 hobby project in my spare time. Frequent readers of my blog or followers me on Twitter might think: Why plain Spring and not just Grails? So let me explain that first:


  1. I love Grails (and Groovy), and if I could make the decision I would use it on every project! But...

  2. I want to host my hobby project cheap, and even Amazon EC2/AWS is to expensive currently. So I decided to host my application on Google App Engine. And to be honest, Grails support for GAE is just alpha/beta state in my opinion (I hope it will change one day). So Grails was not an option.

  3. I've been coding Groovy and Grails for a while now and also doing commercial projects. But I have the feeling my basic Java and Spring knowledge might become a little bit rusty. And to face the facts, there is a change that one of my next clients will not use Groovy/Grails, but just Java and one of the 1,000,000 Java frameworks outhere. So with my hobby project I will be up to date with the latest Java and Spring 3.0 expertise!



But let's get back to the title of this post: ConfigSlurperPlaceholderConfigurer for Spring. In my hobby project I needed the concept of per environment configuration. Yes, in Grails you have it out-of-the-box but in Spring not.

I searched the web and found some interesting thoughts:


What I like about Grails' concept of per environment configuration is that you can define global config properties and just override them in a specific environment if needed. So if 90% of my properties are the same for each environment I don't need to specify them for all environment but just once.

This concept was not supported by the RuntimeEnvironmentPropertiesConfigurer, and also not by the GroovyPlaceholderConfigurer. I know the GroovyPlaceholderConfigurer uses a Groovy ConfigSlurper and this does support per environment configuration (Grails uses it!). So I decided to create a proper ConfigSlurperPlaceholderConfigurer which also supports different environments using a system property. At the end this is how my Spring config now looks:

Example XML context definition:

<bean class="org.springframework.beans.factory.config.ConfigSlurperPlaceholderConfigurer">
<property name="environment" value="#{systemProperties['runtime.environment']}" />
<property name="defaultEnvironment" value="production" />
<property name="location" value="/WEB-INF/config.groovy" />
</bean>

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"><value>${dataSource.driverClassName}</value></property>
<property name="url"><value>${dataSource.url}</value></property>
<property name="username"><value>${dataSource.username}</value></property>
<property name="password"><value>${dataSource.password}</value></property>
</bean>


Example config.groovy:

dataSource {
driverClassName = "org.hsqldb.jdbcDriver"
username = "sa"
password = ""
}
environments {
development {
dataSource {
url = "jdbc:hsqldb:mem:devDB"
}
}
test {
dataSource {
url = "jdbc:hsqldb:mem:testDb"
}
}
production {
dataSource {
url = "jdbc:hsqldb:file:prodDb;shutdown=true"
password = "secret"
}
}
}


I created a new issue in Spring JIRA to add this to core. If you are interested you can vote for the issue. It also contains the source code if you want to use it in your own project.

Sunday, June 14, 2009

Google App Engine Datastore doubts



I have been looking into Google App Engine since the beginning. I played a little bit with it using Python and Django but never did some serious work. As GAE/J was released back in April I decided to have a serious look by building a real application.

I mean the GAE promise is everything I need: easy to build, easy to maintain, easy to scale and I can run it on Google's infrastructure. And when my application won't be the next Twitter, most likely it will cost me nothing to host it as Google offers enough free quotas for medium and small application. I should also mention that now Grails also runs on GAE (using the App Engine plugin) my life couldn't get easier, but...

The only thing GAE does not offer is a relational datastore. GAE's Datastore, based on BigTable, is a hierarchical, schema-less, non-relational datastore.

One of the nice things relational databases support are the aggregate functions like count, sum, avg etc. If you are using GAE you must "Shift processing from reads to writes" as mentioned in The Softer Side Of Schemas - Mapping Java Persistence Standards To the Google App Engine Datastore presented at Google I/O. In practice this means that when inserting or updating a record you must calculate and store the count, sum, avg, etc. values of the whole table. But what if you have many conditional groupings? Let's take an example:


@Entity
class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
String id;

String name;
//Date birthdate;
Integer age;
String address;
String city;
String postalCode;
}


Now imagine I want to be able to (1) get the total number of persons and (2) the average age. Everytime I would create, update or delete a person I should calculate both and store them. Not a big deal, but in my opinion already to much hassle.

But then I also want these values per city... So for each city I should store these values. Next I want them also per postalCode or a specific range of the postalCode. You see where I'm going to? Every create, update or delete of a person would result in a lot of caluculation and storing values.

And then worse, my agile product owner comes in and want to add a boolean indicating a person is a male or not. And guess what, number of persons and average age should additionally be calculated also for this male/female indicator, and to make it worse also in combination with city and postalCode...

I truly believe GAE's Datastore is suitable for many applications don't needing features part of most relational databases. But if you need aggregate queries or common SQL functions (both most likely needed when you are trying to get some analytical data) you should really think twice.

I hope one day GAE's current Datastore will support aggregate functions or additionally a relational datastore will be provided. Then I think GAE would be my preferred Cloud platform.



Wednesday, April 8, 2009

Java support on Google App Engine



Just read the first blog posts (Google App Engine Blog, GR8 Conference, The Aquarium) about the announcement that Java is the next programming language supported on Google App Engine.

This is so funny, as I think just before Google released the announcement I put a question on the Google App Engine discussion group about when we can expect the new language and which language it would be. So my qusetion is answered now.

Since Google App Engine was announced I've always followed it with interest. I'm really excited/interested in the Cloud computing model so I don't have to maintain a deployment server/server park myself. Also the fact that I will just use more resources on the cloud infrastructure when my application needs is just great. I don't have create a cluster or whatever myself.

The reason I put the question on the forum yesterday was that I'm working on a small personal application I like to host on the internet somewhere in the future. Important thing is that the hosting has to be cheap when starting up. I've looked into Mor.ph but it would still cost me $31 a month to host my Java application. This does not sound expensive, buy hey I'm not a business!

In the past I hosted a couple of PHP websites using Drupal and I must say good PHP hosting is cheap and works very good. So I was already thinking of alternative scenario to develop my application in PHP, and not in Grails ;-(
I had already downloaded CakePHP and was experimenting a bit with it. I must say CakePHP is really easy to learn for Grails developers as it uses a lot of the same concepts as Grails and also RoR.

But with the annoucement of Google that Java will be supported I will be putting my PHP alternative in the fridge again. Also a very big plus that SpringSource's Groovy team has worked together with Google to make sure Groovy works well on Google App Engine. Let't hope the same thing counts for Grails one day.