Foojay Today

How to Deploy a Vaadin Application to Google Cloud App Engine

July 26, 2022

I tried to deploy a Vaadin application to Google Cloud App Engine.

It was not as straightforward as expected, so I want to share my findings.

The example project is available on GitHub: https://github.com/simasch/vaadin-appengine-demo

The Vaadin Application

First, I’ve created a new Vaadin application: https://start.vaadin.com

Then I did a production build:

mvn package -Pproduction

That will generate an executable JAR file in the target directory.

First Deployment

This JAR file I’ve deployed to App Engine using the CLI:

gcloud app deploy

This seemed to work, but when I tried to access the app I got an error in the logs:

java.lang.UnsupportedClassVersionError: io/seventytwo/demo/gae/Application 
has been compiled by a more recent version of the Java Runtime (class file version 61.0), 
this version of the Java Runtime only recognizes class file versions up to 55.0

Google App Engine is using Java 11 by default, but I want to use Java 17.

Using Java 17

But how can I configure another Java version? After reading the documentation, I found out that I can add an app.yaml in the src/appengine folder with this content:

runtime: java17

Maven Plugin

I also noticed that I could use a Maven plugin to deploy the application:

<plugin>
    <groupId>com.google.cloud.tools</groupId>
    <artifactId>appengine-maven-plugin</artifactId>
    <version>2.4.2</version>
    <configuration>
        <projectId>GCLOUD_CONFIG</projectId>
        <version>GCLOUD_CONFIG</version>
    </configuration>
</plugin>

So I simply can execute:

mvn package appengine:deploy -Pproduction

After the deployment was finished, I tried to reaccess the application. This time it failed with this message:

java.lang.NullPointerException: Cannot invoke "java.io.RandomAccessFile.length()" because "this.cache" is null
at javax.imageio.stream.FileCacheImageOutputStream.close ( javax/imageio.stream/FileCacheImageOutputStream.java:229 )
at javax.imageio.ImageIO.write ( javax/imageio/ImageIO.java:1598 )
at com.vaadin.flow.server.PwaIcon.setImage ( com/vaadin.flow.server/PwaIcon.java:220 )

Memory Limit

The exception comes from the PWA support of Vaadin, so I removed the @PWA annotation and the application run.

But looking at the logs, I’ve found issues with memory limits:

Exceeded soft memory limit of 256 MB with 262 MB after servicing 1 requests total. 
Consider setting a larger instance class in app.yaml.

By default, an instance of type F1 is allocated, which was not enough to start the Vaadin application.

So finally, I configured an F2 instance in the app.yaml

runtime: java17
instance_class: F2

Session State

As you may know, Vaadin applications have server state and may also have push enabled that will use WebSockets.

We must enable session affinity to ensure that our application runs correctly in multiple instances.

This can be done in the app.yaml as well

network:
    session_affinity: true

But what does session affinity mean? Let’s check the documentation:

session_affinity

Optional. Set to true to configure App Engine to route multiple sequential requests for a given user to the same App Engine instance such as when storing user data locally during a session.

Session affinity enables inspecting the value of a cookie to identify multiple requests by the same user and then directs all such requests to the same instance. If the instance is rebooted, unhealthy, overloaded or becomes unavailable when the number of instances has been scaled down, session affinity will be broken and further requests are then routed to a different instance.

Note that enabling session affinity can affect your load balancing setup. This parameter is disabled by default.

Conclusion

Deploying to Google App Engine is straight-forwarded using the Maven plugin, but you must analyze the log files and probably configure the Java version, the instance size, and session affinity.

Related Articles

View All

Author(s)

  • Simon Martinelli

    Programming Software Architect at 72 Services LLC, Vaadin Community Award Winner

Comments (2)

Your email address will not be published.

Highlight your code snippets using [code lang="language name"] shortcode. Just insert your code between opening and closing tag: [code lang="java"] code [/code]. Or specify another language.

Save my name, email, and website in this browser for the next time I comment.

Ludo

Hi, Thanks for the post.
We will change the Cloud SDK CLI to use the java17 by default, now that it is GA.
For memory usage on F1 instance class, we are investigating some options…
Thanks for the nice blog!

Simon Martinelli

Thank you for the information. I’m happy you liked it.

Subscribe to foojay updates:

https://foojay.io/feed/
Copied to the clipboard