3

I am trying to evaluate if it is possible to add Progressive Web App support to a JavaServerFaces web application. Our JSF app is has grown over the years and a possible future requirement might be to make parts of the application available for offline use. Besides the other nice features offered by PWA functionality (notifications, full screen web app, add to homescreen, etc), we would be primarily interested in the offline capabilities that PWA in conjunction with a service worker and caching seems to offer.

Our clients have to work in areas where sometimes there is no internet connection available. In such a situation, they should ideally be able to have access the app, authenticate themselves and navigate to the part of the app they need to use on-sight. In this part of the app they would manipulate or create new datasets. If I am informed correctly, one can - in theory - use the PWA service worker to cache data and even to store newly created or updated data for a later synchronisation with the server. Is this the case?

While the idea of PWA support seems nice, I have serious doubts that it is possible to implement especially the offline mode capabilities in a JSF application, since all the application logic is basically on the server side and the client does not make direct API calls to GET/POST/PUT/etc (and hence cache and synchronize) the data.

My research so far has produced nothing substantial (JSF & PWA) which is the reason why I am posting this question. It would be great if someone could point me into the right direction or give me an answer if JSF apps can make use of the PWA technologies, especially the offline/caching/synchronisation functionality.

Thank you.

Kukeltje
  • 12,223
  • 4
  • 24
  • 47
Lms24
  • 57
  • 7

3 Answers3

3

Since version 3.7, OmniFaces adds PWA support to a certain degree via the built-in PWAResourceHandler. The usage is well documented and demonstrated in the showcase.

  1. First create a class which extends from WebAppManifest

    public class YourWebAppManifest extends WebAppManifest {
    }
    
  2. Give it a CDI scope annotation matching its state, e.g. @ApplicationScoped.

    @ApplicationScoped
    public class YourWebAppManifest extends WebAppManifest {
    }
    
  3. Override/implement properties conform their Javadoc and rules in W3 spec.

    @ApplicationScoped
    public class YourWebAppManifest extends WebAppManifest {
    
        @Override
        public String getName() {
            return "Your Application";
        }
    
        @Override
        public Collection<ImageResource> getIcons() {
            return Arrays.asList(
                ImageResource.of("logo.svg"),
                ImageResource.of("logo-120x120.png", Size.SIZE_120),
                ImageResource.of("logo-180x180.png", Size.SIZE_180),
                ImageResource.of("logo-192x192.png", Size.SIZE_192),
                ImageResource.of("logo-512x512.png", Size.SIZE_512)
            );
        }
    
        @Override
        public String getOfflineViewId() {
            return "/offline.xhtml";
        }
    }
    
  4. Reference it in your HTML head as follows, with the exact library name omnifaces and resource name manifest.json:

    <link rel="manifest" href="#{resource['omnifaces:manifest.json']}" />
    

That's basically it. The PWAResourceHandler will automatically generate the desired manifest.json and sw.js files and serve the /offline.xhtml template as offline view.

By default, all <welcome-file> entries in web.xml are registered as "cacheable resources", i.e. they are also available offline. You can override this in your custom WebAppManifest as follows:

@Override
public Collection<String> getCacheableViewIds() {
    return Arrays.asList("/index.xhtml", "/contact.xhtml", "/support.xhtml");
}

You'll probably also want to make all JSF forms in these pages stateless by using <f:view transient="true"> so that they don't throw a ViewExpiredException.

The major advantage of this PWAResourceHandler is primarily that you don't need to manually fabricate the sw.js, but can just control its contents/configuration via a simple CDI bean.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • That does indeed seem like agreat solution for PWA support in JSF applications. While I am anymore not involved with the project or the technology stack I described in my post, I would still - out of curiosity - ask for additional clarification: Would I be able to declare API calls (e.g. GET or even POST) as resources that should be cached or does this only work for `xhtml` pages? The objective would be to have a PWA that does not only have a fallback page but is actually usable offline if the needed resources were cached beforehand. – Lms24 Apr 23 '21 at 14:01
2

I am evaluating the same technologies and as far as is have seem jsf is really not a good fit for offline capability. Additional hurdles are that (especially on ios) the sometimes decides that the cookies/localstorage should be cleaned because if inactivity, which breaks the views when a user tries to resume. We are trying to move the code to jax-rs endpoints.

Birki
  • 21
  • 3
0

I've been looking at something similar. (although I am pretty new to PWAs at the moment) It should be relatively simple, JSF is ultimately a taglib that first filters through a servlet. You can easily define tags to render whatever you need.

But my sense is that the various addons theme and component libraries may not have been made in a way that is compatible with PWA ideas. My suspicion is that I need to start with plan JSF and make a prototype.

So I have actually gone back as far as JSTL. Once I get a sense of the patterns enough to make some taglibs, I should be able understand how it works in JSF. (now for full disclosure last time i was into web development JSTL was new, but the fundamentals are still fundamentals)

Chris
  • 194
  • 6