Create a single executable jar (fat jar or uber jar) and deploy to Google app engine

pravanjan palai
3 min readNov 5, 2019
AppEngine 2nd generation with java 11

Google App Engine now supports Java 11 runtime, Now we can deploy single execute JAR files. Google has released a sample application using Maven. I have not found a clear article using Gradle so I decided to write one.

In this article, we would create a single executable jar using Servlet web framework with Gradle build management tool. We deploy the jar file and deploy it to the Google app engine.

prerequisite

  1. Java 11 ( i am using Adobe open Jdk 11)
  2. Gradle 4.4 and above.

We have the complete example in Github. You can run the below command on the terminal.

git clone git@github.com:pravanjan/fatjar-gradle-appengine-java11-servlet.gitcd fatjar-gradle-appengine-java11-servletgradle clean buildgradle run

Then Open your browser with http://localhost:8080/hello

If you have a problem with running the above example please write in the comments below.

Let’s start with build.gradle file and check the plugin and dependencies.

buildscript {      // Configuration for building
repositories {
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.+'
classpath "com.github.jengelman.gradle.plugins:shadow:4.0.4"

}
}

repositories { // repositories for JARs you access in your code
maven {
url 'https://maven-central.storage.googleapis.com' // Google's mirror of Maven Central
}
jcenter()
mavenCentral()
}

apply plugin: 'application'
apply plugin: 'com.google.cloud.tools.appengine'
apply plugin: "com.github.johnrengelman.shadow"

mainClassName = 'com.pravanjan.main.App'
ext {
jettyVersion = '9.4.6.v20170531'
}

dependencies {
compile 'javax.servlet:javax.servlet-api:3.0.1'
compile "org.eclipse.jetty:jetty-server:${jettyVersion}"
compile "org.eclipse.jetty:jetty-servlet:${jettyVersion}"
compile "org.eclipse.jetty:jetty-webapp:${jettyVersion}"
compile group: 'commons-codec', name: 'commons-codec', version: '+'
compile group: 'com.google.guava', name: 'guava', version: '+'
}


// [START model]
appengine {

deploy {
projectId = ""
version = "10"
stopPreviousVersion = false // default - stop the current version
promote = false // default - & make this the current version
}
stage {
artifact = "${buildDir}/libs/${project.name}.jar"
}
}
// [END gradle]

shadow plugin is the Gradle version of the maven shade plugin. This would help relocate the packages for applications and libraries.

We are using AppEngine plugin version 2 which would support jar deployment.

Using Jetty in embedded mode with Servlet. As we see shadow plugin would expect us to declare the main class in build.gradle file. Now, let's look into the main class which starts the server and initializes all servlet to Servlet context.

We have two methods in the main method

public static void main(String args[])throws Exception{

Server server = new Server(8080);
HandlerList handlers = new HandlerList();
ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/");

registerServlets(context);

handlers.addHandler(context);
server.setHandler(handlers);
server.start();
server.join();
}

As we can see its calling registerServlets to add all the servlet to context. This method use reflection to read the file inside the package and instantiate them and add them to the Servlet context.

registerServlet complete code.

I have written this method for the sample app, I would not recommend using it in production.

To deploy this app to Appengine standard add app.yaml file to sr.main/appengine/

Add this below content to your app.yaml file

# [START runtime]
runtime: java11
entrypoint: java -Xmx64m -jar fatjar-gradle-appengine-java11-servlet.jar

When we run Gradle appengineDeploy it would create folder staged-app which would hold your jar file and app.yaml file and then upload to google cloud.

Thanks for reading. The next article we would look into how to configure the RestEasy framework and deploy the jar file to AppEngine standard.

--

--