Current Status

Actively playing with all possible backend services

22 August, 2018

Deploying Spring Boot application to Google Cloud App Engine

If you have worked with AWS and GCP, you should have understood that AWS' Elastic Beanstalk and Google's App Engine(GAE) enable deploying our applications without the need to understand how to build or scale the underlying infrastructure.

Their promise is great, and for most use cases as there are no servers to maintain. We simply upload our applications and they are ready to go.
If everything works as promised Beanstalk or the Google App engine will take care of scaling, load balancing, traffic splitting, logging, versioning, roll out and roll backs, and security scanning etc. Pretty simple , ah?

Today I am going to share simple steps to deploy your first Spring boot (with Java and Maven)  application to  Google Cloud App Engine.

So let's create s simple create a Spring Boot Java API on Google App Engine.

I asume you have set up Google Cloud SDK in your local. (https://cloud.google.com/sdk/gcloud). Alternatively you can use Cloud Shell.

$ gcloud auth list
$ gcloud config list

Bootstrap your application using SPRING INITIALIZR:
https://start.spring.io/


Unzip the file and open with your IDE:


Add the "Cloud SDK-based" maven plugin to the POM file:

<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>1.3.2</version>
</plugin>




Make sure to remove spring-boot-starter-tomcat dependency if it is there in the POM.
Spring Boot also includes a JUL to SLF4J bridge might interferes with App Engine's log handler. To make sure we get proper log entries, let us exclude the jul-to-slf4j artifact by marking it's scope as "provided".

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jul-to-slf4j</artifactId>
    <scope>provided</scope>
</dependency>


Also add javax.servlet-api dependency as provided

<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>


Then adding App Engine Descriptor is the most important task of this:
App Engine Java applications use Descriptor file (another configuration file), named appengine-web.xml, to specify the app's registered application ID(unused for Cloud SDK based tooling) and the version identifier of the latest code:

we must add create a new src/main/webapp/WEB-INF/appengine-web.xml descriptor file:

$ mkdir -p src/main/webapp/WEB-INF/
$ touch src/main/webapp/WEB-INF/appengine-web.xml

<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
  <application>_our_app_id_</application><!-- unused for Cloud SDK based tooling -->
  <version>1</version><!-- unused for Cloud SDK based tooling -->
  <threadsafe>true</threadsafe>
</appengine-web-app>




get the "OUR_PROJECT_ID" from the command line:

$ gcloud config list --format 'value(core.project)'

Ok, let's get to your Spring project and write a simple API:




you can find sample code here : https://github.com/belpamulle/springboot-appengine

Let us run the app in local:
mvn package
mvn appengine:run

if you get this error:

Failed to execute goal com.google.cloud.tools:appengine-maven-plugin:1.3.2:run (default-cli) on project bankapi: Dev App Server does not support App Engine Flexible Environment applications. -> [Help 1]

make sure project's Packaging = war



Deploying the Application into App Engine:

1) Initialize the project to run in the your desired region:
$ gcloud app create --region australia-southeast1

2)Then, deploy your application into App Engine environment, run :
$ mvn appengine:deploy

Now we can visit the API at http://{OUR_PROJECT_ID}.appspot.com in your web browser.



Success ! :)

Clean up:
You can Disable your application/Delete your project



***
Note that behind the scene App engine uses Jetty web server underneath and runs on Google Kubernetes Engine, so you should check Google Kubernetes Engine pricing if you are going to leave your app running after testing or make sure to clean up your work. The environment should be scale down to 0 instances when no one is using it, and automatically scale up when traffic is coming.

2 comments:

Paddy's Day 2005, Dublin said...

Posting In case anyone else hits the same issues as me.

I hit errors like "[INFO] GCLOUD: Caused by: java.io.FileNotFoundException: /path/app-0.0.1-SNAPSHOT/WEB-INF/web.xml (No such file or directory)" when running locally, and "Unable to stage app: Class file is Java 8 but max supported is Java 7: /path/app-api-0.0.1-SNAPSHOT/WEB-INF/classes/com/app.class" when attempting to deploy.

I found that I had to add the following to appengine-web.xml:

< runtime >java8< /runtime >

Ref: https://cloud.google.com/appengine/docs/standard/java/runtime

Priya said...
This comment has been removed by the author.

Some Popular Posts