A.Mahdy AbdelAziz

How to make a Vaadin app installable in mobile and desktop

Should you distribute your application as a standalone executable file, or as a web application? What about mobile devices, should you enhance the mobile experience of your web app, or create a native mobile app instead? And what about other smart devices?

Delivering a web application solves many problems, such as unifying the experience across devices, and guaranteeing that your users are running the latest version without prompts to upgrade. However, native apps have an advantage that you can have them installed as part of the operating system apps, access device hardware, and send notifications.

Progressive Web App (PWA) is the new standard that helps you modernize your web app and make it installable, access hardware, and give a native app experience. There are plenty of articles and tutorials about how PWA works and how to implement those features in your web app. This tutorial covers a subset of those specific to Vaadin apps:

  1. How to get PWA features in your Vaadin app, with Java only

  2. How to override the default settings and customize the service worker

Before we start, two key concepts of PWA need to be explained: Manifest file, and ServiceWorker. The manifest file is a JSON-formatted file that describes the app, such as name, entry point, theme color, and more. The ServiceWorker is a Javascript file that is responsible for delivering advanced functionalities to your app: manage push notifications, load an offline version of the app when there is no network connection, and similar features.

The good news is that modern browsers help you with your PWA experience. You request access to device orientation with a few lines of code, and the browser does the low-level device APIs for you, regardless of the operating system or platform. The bad news though is, for Java developers, those lines of code must be in Javascript. Unless you are using Vaadin:

1. How to get PWA features in your Vaadin app

Enable PWA in Vaadin is easy. Vaadin framework comes with @PWA annotation that enables the PWA functionalities. Place it on top of your entry point route, and you are all set. It injects a manifest file and generates a service worker for you.

@PWA(name = "Beverage Buddy", shortName = "BevBuddy")
public class MainLayout {
  // --
Install App

Things delivered by default with the @PWA annotation are a default manifest compatible with the Lumo theme, and functionality that allows app installation on desktop and mobile devices.

Now try to disconnect your application server, and reload the page. You are greeted by the default offline page:

Offline App

You can change this default page, by creating your own custom offline.html page and place it in src/main/webapp/offline.html.

This offline file can be customized, and you can specify which parts of your application need to be cached. Let’s take an example:

Create a file with name offline.html and contains:

<!DOCTYPE html>
<html lang="en">
    <script src="offline.js"></script>
    <span id="un_placeholder"></span>

Create another file offline.js with contents as following:

window.addEventListener('load', () => {

function getUsername() {
    = localStorage.getItem("username")
    + " is the stored username.";

Now include them both, offline.js and offline.html inside src/main/webapp/ folder.

The code assumes there is a value stored in the browser’s local storage with key username and tries to retrieve it when offline.

To get this to work, let’s store a real username from our Vaadin app, in the main UI:

  public MainLayout() {
      "localStorage.setItem('username', 'Joey')");

    // --

Also update your annotation to include the new offline.js file:

@PWA(name = "Beverage Buddy", shortName = "BevBuddy",
  offlineResources = {"offline.js"})

Now run your Vaadin app one more time, then cut the connection and reload the page. You should see something similar to:

Offline Storage

The offline capabilities you can do when there is no internet connection are not limited. Depending on your business needs, it can range from just a static informative page, telling your users that the app can not work offline. Alternatively, implementing offline functionalities and read cached files and stored data in the local storage. The parameter offlineResources described earlier can take an array of all possible files that you want to cache and make them available offline.

2. How to override the default settings and customize the service worker

You may also want to customize the manifest file. There is no need to remember all the manifest file parameters, there are many online services that can help you customize and generate a manifest file, with the colors and app description you need. To use the custom manifest file, specify the new file with the parameter manifestPath:

@PWA(name = "Beverage Buddy", shortName = "BevBuddy", manifestPath = "manifest.json")

You can also override the default service worker by creating a new one with the exact name sw.js and place it in the src/main/webapp/ folder. However, at this point, you are about to write your custom Javascript code for the service worker. Currently, there is no Java APIs available to customize the service worker.


Vaadin framework comes with the default functionalities to make your web app installable and rich with PWA features. Depending on your business needs, you can do a lot with one single annotation @PWA, or you might want to make low-level customization and specific front-end code. What other features do you need in your web app that should be part of the default setup?

Vaadin is an open-source framework offering the fastest way to build web apps on Java backends

Comments (0)