The Java 8 runtime

In 2009, Java became the second language to run on App Engine, and it is also supported by the majority of Google Cloud products and services. In September 2017, Java 8 support became generally available. App Engine services written in Java take the form of one or more servlets that conform to the Java Servlet 3.1 and 2.5 specifications. At runtime, App Engine provides these servlets through a managed Jetty 9 server. Similar to Python, requests are mapped to servlets through handlers defined in the application's configuration file.

While currently supported, the Java 7 runtime for App Engine is deprecated and will be officially shut down on January 16, 2019. The Java 7 runtime has quite a few limitations compared to Java 8. It is strongly advised to use the Java 8 runtime if possible.

In order to develop App Engine services in Java, development machines must have the following components installed locally:

  • Java Development Kit (JDK) 8
  • Apache Maven 3.5+ or Gradle 3.4.1+
  • Google Cloud App Engine Java Extensions

The App Engine Java extensions can be installed through gcloud by running gcloud components install app-engine-java. This component provides tools needed to build and run Java services locally using the development server, and to deploy services to App Engine. Google provides plugins for both Maven and Gradle, as well as plugins for popular IDEs.

An easy way to get started developing Java services for App Engine is to generate them using the Maven archetypes provided by Google. This can be done with the following command:

mvn archetype:generate \
-DarchetypeGroupId=com.google.appengine.archetypes \
-DarchetypeArtifactId=appengine-skeleton-archetype \
-Dappengine-version=1.9.59

Follow the prompts to provide a GroupId, Artifact Id, version, and package. Maven will then generate a basic Java 8 project that can be deployed to the App Engine standard environment.

The resulting project structure has a few important pieces:

  • pom.xml: The Maven Project Object Model (POM), configured with Google App Engine libraries.
  • src/main/webapp/WEB-INF/web.xml: The application configuration file. This is functionally similar to the app.yaml file used in other languages.
  • src/main/java/.../HelloAppEngine.java: A basic Java web servlet.

Additionally, the default Maven configuration includes a few App Engine-specific Maven goals, including mvn appengine:run and mvn appengine:deploy.

As with Python, popular frameworks such as Spring can be used when building App Engine services in Java. When considering using such a framework, keep in mind that services running in the App Engine standard environment should be relatively lightweight and have a low startup time. This is paramount for maintaining scalability and low running costs.

It is also important to keep in mind that the Java runtime works by managing user-defined servlets. This means that frameworks with embedded servers and frameworks that do not comply with the Java Servlet specification might not be a good fit. Developers looking to build services using these frameworks may find the flexible environment to be a better fit.

As with our Go example, a simple Java implementation of the colors service is available in the book's source code in chapter_04/example_03. This service was initialized using the Google-provided Maven artifact discussed previously.

While services written in other languages can be run locally using dev_appserver.py, the App Engine plugins for Maven and Gradle include Java-specific methods for using the App Engine development server. We can run the colors service using the App Engine development server by executing mvn appengine:run from within the example_03 directory. This will cause Maven to run any unit tests, build the service, and serve it on http://localhost:8080. To see what a colors response looks like, visit: http://localhost:8080/colors. For Java services, the App Engine development server admin console is available at /_ah/admin.

Note that when running multiple services on the App Engine development server, Java services running through Maven and Gradle plugins are separated from those running through dev_appserver.py. This is due to a new development server instance being created. Due to this, simulated services such as Memcache and Datastore are not shared between these services. This also means that in order to run Java services in tandem with other services, a unique port must be specified in the App Engine plugin configuration. For Maven, the service's port can be configured as follows:

The pom.xml is as follows:

<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>1.3.1</version>
<configuration>
<enableJarClasses>false</enableJarClasses>
<port>8081</port>
<address>0.0.0.0</address>
</configuration>
</plugin>