Upload a Java WebApp to Google App Engine

October 9th, 2009 by Henri Bezemer

The Google App Engine supports the Sun Java Servlet Specification, together with a bunch of other standard and Google specific Java API’s (not including EJB). Google lets you run your Java webapp for free but with limited CPU time, bandwidth and number of requests per day. If one of these resources has been consumed your app will lock up for the rest of the day and respond only with HTTP code 403 ‘Forbidden’. If you need more you can pay for additional resources. The resource quota for a free account are more than adequate for a proof of concept.

In this post I’ll show you how to build a very simple Java Servlet that can be uploaded to and run on Google App Engine. I’ll assume that you will be using a free App Engine account.

The first thing to do is to create an application on App Engine. This will be a container for you webapp. You can create a maximum of ten applications. If you name your application something like foobar, then your webapp can be found at http://foobar.appspot.com once you’ve deployed it. To create an application go to https://appengine.google.com/. Use or create a Google account to log in. If you’re an iGoogle, Gmail or Calendar user then you have a Google account. Note that to start using the App Engine service you’ll have to provide your mobile phone number to let Google send you a SMS. This SMS (for which you may or may not have to pay depending on your country and provider) contains an activation number. Once your account is activated, you can create the application, provided you come up with an unique name.

For this proof of concept I’m using the following development setup:

  • Windows XP
  • Sun JDK 1.5.0 (21)
  • Eclipse Galileo (not really needed in this simple case, even Notepad would do).
  • Maven 2.2.1
  • m2eclipse Eclipse Plugin (if you use Eclipse).

My project structure (which was created using maven’s archeType 18) looks like this:

pom.xml
src/
      main/
            java/
                  com/
                        zienit/
                              simpleweb/
                                    SimpleServlet.java
            webapp/
                  WEB-INF/
                        web.xml
                        appengine-web.xml

There are 4 important files in the project:

  • pom.xml: Maven’s Project Object Model which drives the build process.
  • SimpleServlet.java: the only Java source file.
  • web.xml: the standard webapp deployment descriptor.
  • appengine-web.xml: the App Engine specific deployment descriptor.

I’ll give you each of these file:

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.zienit</groupId>
	<artifactId>simpleweb</artifactId>
	<packaging>war</packaging>
	<version>1.0-SNAPSHOT</version>
	<name>simpleweb</name>
	<url>http://www.zienit.nl</url>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.4</version>
			<scope>provided</scope>
		</dependency>
	</dependencies>
	<build>
		<finalName>simpleweb</finalName>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.5</source>
					<target>1.5</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

Note that Maven will be instructed to compile the Java sourcecode for JDK 1.5 and to have the javax.servlet API on the classpath during compilation. The next file to look at is SimpleServlet.java.

package com.zienit.simpleweb;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class SimpleServlet extends HttpServlet {

	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {

		resp.setContentType("text/html");
		PrintWriter out = resp.getWriter();
		out.write("<html>\n<head>\n<title>Simple Servlet</title>\n</head>\n<body>");
		out.write("<p>" + getServletConfig().getServletName() + " says ");
		out.write(getServletConfig().getInitParameter("message") + "</p>");
		out.close();
	}
}

This is the simplest of simple Servlets: It only prints a message. The message itself is a parameter in web.xml which I show next:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
		version="2.4">
	<display-name>Simple Web Application</display-name>
	<servlet>
		<servlet-name>simple</servlet-name>
		<servlet-class>com.zienit.simpleweb.SimpleServlet</servlet-class>
		<init-param>
			<param-name>message</param-name>
			<param-value>Hello App Engine!</param-value>
		</init-param>
	</servlet>
	<servlet-mapping>
		<servlet-name>simple</servlet-name>
		<url-pattern>/simple</url-pattern>
	</servlet-mapping>
</web-app>

And finally appengine-web.xml

<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
	<application>foobar</application>
	<version>1</version>
</appengine-web-app>

There doesn’t seem to be a documented schemaLocation for this namespace, so Eclipse will complain that it can’t validate this XML. To bad. Note that you have to tailor this file: the name of the application that you’ve created in the first step must be typed between <application> and </application>.

Now ask Maven to do its magic. I’m assuming you’re using the command line. Go to the directory that contains pom.xml and type:

mvn package

We now have a few extra directories in the project. You might think that \target\simpleweb.war is the file of interest. It is not. The App Engine deployment tool needs an exploded webapp. We’re in luck because Maven created this in the \target\simpleweb directory. Talking about the App Engine deployment tool: where is it? You may have noticed that up till this point you didn’t see anything App Engine specific besides the deployment descriptor appengine-web.xml. Unfortunately, to perform the last step – deployment – we need to download the App Engine SDK to get the deployment tool. Besides the tool you’ll also get a local App Engine to test your stuff before you deploy. Download the SDK at http://code.google.com/appengine/downloads.html and unzip it to an appropriate directory. The deployment tool ends up in the bin subdirectory and is called appcfg. At the command line, go to that directory and type:

appcfg update <path-to-your-project>\target\simpleweb

When I ran it the first time, the tool failed because it could not locate javac on my system (the Java compiler that you get with the Sun JDK). It turned out that I have a java.exe in c:\windows\system32 that thinks that it belongs to a JRE and not a JDK. I renamed that file to something harmless and thus made sure that java.exe from the installed JDK was executed. Then it ran fine.

After deployment you can see the fruits of your labor at http://<name-of-your-application>.appspot.com/simple. Go to https://appengine.google.com/ and check out the cool App Engine dashboard.

No Comments

Comments are closed.