Maven project for Google Appengine Java SDK

Google Appengine ships with an Eclipse plugin which appears to assume a particular project structure. Since some of us don’t use Eclipse, and all of us use maven, we prefer to use the standard maven structure for the project, which works equally well standalone, and with all major IDEs.

Because the jars distributed Google App Engine appear to different from the same version jars available in the maven repositories, this procedure will require you to add pretty much all Google distributed jars to your local repository which is obviously far from ideal.

Download the SDK

Start by downloading the Google Appengine SDK for Java here: http://code.google.com/appengine/downloads.html, and unzip the distribution package, in our case appengine-java-sdk-1.2.0.zip

Publish the library jars to Maven repository

Next publish the appengine libraries to your maven repository so that we can list them as dependencies in your pom.xml file.

mvn install:install-file -Dfile=lib/appengine-tools-api.jar -DgroupId=com.google -DartifactId=appengine-tools -Dversion=1.2.0 -DgeneratePom=true -Dpackaging=jar
 
mvn install:install-file -Dfile=lib/user/appengine-api-1.0-sdk-1.2.0.jar -DgroupId=com.google -DartifactId=appengine-sdk-1.2.0-api -Dversion=1.2.0 -DgeneratePom=true -Dpackaging=jar
 
mvn install:install-file -Dfile=lib/shared/appengine-local-runtime-shared.jar -DgroupId=com.google -DartifactId=appengine-local-runtime-shared -Dversion=1.2.0 -DgeneratePom=true -Dpackaging=jar
 
mvn install:install-file -Dfile=lib/user/orm/datanucleus-appengine-1.0.0.final.jar -DgroupId=org.datanucleus -DartifactId=datanucleus-appengine -Dversion=1.0.0.final -DgeneratePom=true -Dpackaging=jar
 
mvn install:install-file -Dfile=lib/user/orm/datanucleus-appengine-1.0.0.final.jar -DgroupId=org.datanucleus -DartifactId=datanucleus-appengine -Dversion=1.0.0.final -DgeneratePom=true -Dpackaging=jar
 
mvn install:install-file -Dfile=lib/user/orm/datanucleus-core-1.1.0.jar -DgroupId=org.datanucleus -DartifactId=datanucleus-core -Dversion=1.1.0 -DgeneratePom=true -Dpackaging=jar
 
mvn install:install-file -Dfile=lib/user/orm/datanucleus-jpa-1.1.0.jar -DgroupId=org.datanucleus -DartifactId=datanucleus-jpa -Dversion=1.1.0 -DgeneratePom=true -Dpackaging=jar

We are also going to need the jdo-api-2.3-SNAPSHOT artifacts and the transactiona-api-1.1.jar (which can be downloaded from http://download.java.net/maven/1/javax.transaction/jars/ ) as they do not appear to be available in the central maven repository.

mvn install:install-file -Dfile=lib/user/orm/jdo2-api-2.3-SNAPSHOT.jar -DgroupId=javax.jdo -DartifactId=jdo2-api -Dversion=2.3-SNAPSHOT -DgeneratePom=true -Dpackaging=jar
 
mvn install:install-file -DgroupId=javax.transaction -DartifactId=transaction-api           -Dversion=1.1 -Dpackaging=jar -Dfile=/Users/torstenek/Desktop/transaction-api-1.1.jar

The enhancer tools from central has a dependency to a different version of datanucleus-core, so we need to create a local artifact for this one as well.

mvn install:install-file -Dfile=lib/tools/orm/datanucleus-enhancer-1.1.0.jar -DgroupId=org.datanucleus -DartifactId=datanucleus-enhancer -Dversion=1.1.0 -DgeneratePom=true -Dpackaging=jar

This project also uses the maven-datanucleus-plugin (see the POM). We had to hack the pom file to ensure that the datanucleus dependencies match point to the versions we just added manually to the repository.

repository/org/datanucleus/maven-datanucleus-plugin/1.1.0/

Create the Maven project structure and pom.xml

The simplest way to create a maven webapp project is to use the maven archetype plugin. Let’s create a maven version of the guestbook demo included in the SDK.

mvn archetype:create -DgroupId=com.google -DartifactId=guestbook -DarchetypeArtifactId=maven-archetype-webapp

Configure your POM

The finished POM for the guestbook project should look something like this

<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.google</groupId>
    <artifactId>guestbook</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>guestbook Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.google</groupId>
            <artifactId>appengine-tools</artifactId>
            <version>1.2.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.google</groupId>
            <artifactId>appengine-local-runtime-shared</artifactId>
            <version>1.2.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.google</groupId>
            <artifactId>appengine-sdk-1.2.0-api</artifactId>
            <version>1.2.0</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <artifactId>standard</artifactId>
            <groupId>taglibs</groupId>
            <version>1.1.2</version>
            <type>jar</type>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <artifactId>jstl</artifactId>
            <groupId>javax.servlet</groupId>
            <version>1.1.2</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.geronimo.specs</groupId>
            <artifactId>geronimo-el_1.0_spec</artifactId>
            <version>1.0.1</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.geronimo.specs</groupId>
            <artifactId>geronimo-jsp_2.1_spec</artifactId>
            <version>1.0.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.geronimo.specs</groupId>
            <artifactId>geronimo-servlet_2.5_spec</artifactId>
            <version>1.2</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.geronimo.specs</groupId>
            <artifactId>geronimo-jpa_3.0_spec</artifactId>
            <version>1.1.1</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.geronimo.specs</groupId>
            <artifactId>geronimo-jta_1.1_spec</artifactId>
            <version>1.1.1</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.datanucleus</groupId>
            <artifactId>datanucleus-appengine</artifactId>
            <version>1.0.0.final</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>javax.jdo</groupId>
            <artifactId>jdo2-api</artifactId>
            <version>2.3-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.datanucleus</groupId>
            <artifactId>datanucleus-core</artifactId>
            <version>1.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.datanucleus</groupId>
            <artifactId>datanucleus-jpa</artifactId>
            <version>1.1.0</version>
        </dependency>
    </dependencies>
    <repositories>
        <repository>
            <id>DataNucleus_Repos2</id>
            <name>DataNucleus Repository</name>
            <url>http://www.datanucleus.org/downloads/maven2</url>
        </repository>
    </repositories>
    <build>
        <finalName>guestbook</finalName>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.5</source>
                    <target>1.5</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.datanucleus</groupId>
                <artifactId>maven-datanucleus-plugin</artifactId>
                <version>1.1.0</version>
                <configuration>
                    <mappingIncludes>**/*.class</mappingIncludes>
                    <verbose>true</verbose>
                    <enhancerName>ASM</enhancerName>
                    <api>JPA</api>
                </configuration>
                <executions>
                    <execution>
                        <phase>compile</phase>
                        <goals>
                            <goal>enhance</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

After you execute %mvn package your deployable app will be in the folder target/guestbook. You should be able to deploy it and run it using the standard instructions for the Appengine Java SDK. I’m moving on to make sure I can run it in Intellij Idea. More on that later.

I’m still waiting for my Java account to activate at Google so I haven’t tried uploading the app yet.

Share and Enjoy:
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks

7 Comments

  1. Thai Ha Says:

    Hi all,
    I have just created a simple HelloWorld application using maven 2 which can be deployed to Google App Engine with simple command “mvn install”
    Anyone who is interested can download it from

    http://winkjava.110mb.com/gaehelloworld/helloworld.zip

  2. Running Google Appengine Java apps in Intellij Idea | SalientPoint Says:

    [...] having created a standard maven project for the guestbook app as described in this previous post, running the application in Intellij Idea is pretty straight [...]

  3. admin Says:

    Posted a note on how to get the project running in Intellij Idea here: http://www.salientpoint.com/blog/?p=516

  4. Brian Fox Says:

    Jason is working with Google to Mavenize the sdk and create a plugin for gae:

    http://www.sonatype.com/people/2009/04/my-google-app-engine-maven-plugin-wishlist/
    http://www.sonatype.com/people/2009/04/mavenizing-the-appengine-sdk/

  5. Renan Huanca » Hola Mundo con Google App Engine y Maven Says:

    [...] Maven project for Google Appengine Java SDK [...]

  6. Our JSR 286 Portal now runs on Google App Engine | SalientPoint Says:

    [...] som tinkering around with the build process and with our development environment our (very close to) JSR 286 compliant Java portal happily runs [...]

  7. JSR 286 Portal on Google App Engine | SalientPoint Says:

    [...] som tinkering around with the build process and with our development environment our (very close to) JSR 286 compliant Java portal happily runs [...]

Leave a comment