Multi Module Projects with Google AppEngine and IntelliJ

Ramesh Lingappan
5 min readAug 21, 2017

In my previous post AppEngine with IntelliJ and Gradle, i have shared how to setup AppEngine project structure using IntelliJ and Gradle, the pros of it.

One of the things i have mentioned in it is Multi Module, Google AppEngine has support for deploying multiple microservices (called “services” in appengine, previously called “modules”), check here https://cloud.google.com/appengine/docs/standard/java/an-overview-of-app-engine

For example,
- a webapp for dashboard
- a API app for hosting Apis
- a Backend app running reports

Each of the above apps can be deployed as independent services under same project in Google Appengine, thus all sharing same Memcache, Datastore and other services but running in different server instance.

Sounds great, isn’t it ? :), yes but, each microservices is independent project, so how we can share common services like, Dao’s, Models, Business logic, Utils etc among all microservices?

Their Comes the Rescue “IntelliJ Modules” IntelliJ has good support for modules which makes it the perfect IDE for developing shared code base. Lets see how we can build multi module project.

The Sample project which we are going to discuss is available in Github, https://github.com/ramesh-dev/gae-multi-module-intellij-gradle,

Lets Begin…

Start by creating a new IntelliJ Gradle Project , check out the post (AppEngine with IntelliJ and Gradle) for detailed explanation.
Once done project structure should looks like below,

Project Structure

Go ahead and delete the src folder , since we wont be needing it.

Next up we are going to include our dependencies such as servlet and appengine libraries and we are going to do it in a better way, so create a new file called “dependencies.gradle” under gradle folder and include the following content in it,

dependencies.gradle

This is a nice way to specify all of application dependencies & configuration in one place. The project structure should now look like below,

Project structure with Dependencies.gradle

Lets go over few dependencies as those are new compared to my previous post, Since AppEngine Standard now supports Java 8, we are going to use Servlet 3.1

servletApi: "javax.servlet:javax.servlet-api:$libVersions.servletApi",

here, $libVersions.servletApi will be replaced with the value 3.1.0.

Next up, we are going to use the new Gradle Plugin for appengine (App Gradle Plugin) instead of the old one Appengine Gradle Plugin (which is now deprecated), we will see how to use this plugin shortly. Everything else is a regular gradle stuff.

googleGradlePlugin : "com.google.cloud.tools:appengine-gradle-plugin:${libVersions.googleGradlePlugin}"

finally, replace your root build.gradle file with following content,

root build.gradle

Creating Common Module (java)

We are going to write all of application common code in one java project called “commons”, which will be added as dependency to other modules.
Create a new Module by right clicking root project then > New -> Module , choose gradle from let menu and name it “Commons”

and in the Commons/build.gradle file,

here we specify a dependencies which are required by this java project, for now its only servlet and appengine libraries,

Thats it, lets write some code, in Commons Module , under src/main/java folder, create new java class called “GreetingService.java” which will be used in other modules,

package com.rameshl.demos.service;

/**
* MultiModules
* Created by Ramesh on 8/21/17.
*/
public class GreetingService {

public String getGreetings(String name) {
return "Hello " + name;
}
}

Creating Web Module (webapp)

Lets create a appengine webapp module, create new module called “WebApp” just like how we created the Commons module, the major change is in build.gradle file, so replace WebApp/build.gradle file content with following,

here we are adding the war plugins and the new appengine task plugin

apply plugin: 'war'
apply plugin: 'com.google.cloud.tools.appengine'

and we are adding our Commons Module as a dependency by specifying,

// Commons module
compile project(":Commons")

and their comes the new way to define configuration for running or deploying appengine application,

// App Engine tasks configuration
appengine {
run {
port = config.gae.port.default
jvmFlags = config.gae.defaultJvmFlags
}

deploy { // deploy configuration
project = 'project-id'
version = 1
stopPreviousVersion = false // default - stop the current version
promote = false
}
}

In the new plugin, the devserver configuration now goes into run{} block, their we can specify port, jvmFlags, storagePath etc

and in order to deploy to appengine, the deployment configuration now goes into deploy{} block unlike the old manner of specifying it in appengine-web.xml, read App Gradle Plugin Goals for more options

Lets try to use all, create a new java class “GreetingServlet.java” in WebApp module under package com.rameshl.demo.servlets,

The code is self explanatory, its an servlet class, upon get request, it use GreetingService from Commons module to compute greeting message and write it as response.

In order to run the project, open terminal window and cd to WebApp folder and type ‘gradle appengineRun’ (you can also create run configuration)

Ramesh$ cd WebApp/
Ramesh$ gradle appengineRun

the appengine dev server should start now,

Starting a Gradle Daemon (subsequent builds will be faster)
:Commons:compileJava
:Commons:processResources UP-TO-DATE
:Commons:classes
:Commons:jar
:WebApp:compileJava
:WebApp:processResources UP-TO-DATE
:WebApp:classes
:WebApp:war
:WebApp:explodeWar
:WebApp:assemble
:WebApp:appengineRun
2017-08-21 15:55:55.221:INFO::main: Logging initialized @783ms
Aug 21, 2017 10:25:55 AM com.google.appengine.tools.development.IsolatedAppClassLoader checkWorkingDirectory
2017-08-21 15:55:55.708:INFO:oejs.Server:main: jetty-9.3.18.v20170406
2017-08-21 15:55:57.226:INFO:oeja.AnnotationConfiguration:main: Scanning elapsed time=1380ms
2017-08-21 15:55:57.524:INFO:oejsh.ContextHandler:main: Started
2017-08-21 15:55:57.534:INFO:oejs.AbstractConnector:main: Started NetworkTrafficSelectChannelConnector@479cbee5{HTTP/1.1,[http/1.1]}{localhost:8880}
2017-08-21 15:55:57.581:INFO:oejs.Server:main: Started @3143ms
Aug 21, 2017 10:25:57 AM com.google.appengine.tools.development.jetty9.JettyContainerService startHotDeployScanner
INFO: Full scan of the web app in place every 3s.
Aug 21, 2017 10:25:57 AM com.google.appengine.tools.development.AbstractModule startup
INFO: Module instance default is running at http://localhost:8880/
Aug 21, 2017 10:25:57 AM com.google.appengine.tools.development.AbstractModule startup
INFO: The admin console is running at http://localhost:8880/_ah/admin
Aug 21, 2017 3:55:57 PM com.google.appengine.tools.development.DevAppServerImpl doStart
INFO: Dev App Server is now running
> Building 90% > :WebApp:appengineRun

head over to browser and type http://localhost:8880/greet,

localhost /greet

Congrats!! You multi module project is ready for use.

Like WebApp module, you can create N number of other microservices like API, Reporting, Workers and deploy to appengine, all of which using common shared code.

Here is a project structure with two web modules, and one shared common java module,

I have put together all of which we have gone through and also created one more Module called API, in a Github Repo
https://github.com/ramesh-dev/gae-multi-module-intellij-gradle

Hope this is helps!!! Thanks for reading

--

--