jsfomnifaces

@PreDestroy method not called when leaving page of bean annotated with OmniFaces "ViewScoped"


I am trying to invoke a method annotated with @PreDestroy in a @ViewScoped bean when the user leaves the page associated with that bean in a rather large JSF powered web application.

After reading https://stackoverflow.com/a/15391453/5467214 and several other questions and answers on SO as well as https://showcase.omnifaces.org/cdi/ViewScoped, I came to the understanding that the OmniFaces ViewScoped annotation provides exactly that behavior by utilizing the unload page event as well as sendBeacon on modern browsers.

So I used the @ViewScoped annotation from OmniFaces in my bean:

import javax.annotation.PreDestroy;
import org.omnifaces.cdi.ViewScoped;

@Named("DesktopForm")
@ViewScoped
public class DesktopForm implements Serializable {
   ...
}

and annotated the method I want to invoke with the PreDestroy annotation:

@PreDestroy
public void close() {
    System.out.println("Destroying view scoped desktop bean");
    ...
}

Unfortunately, this "close" method is not called when I click some link or leave the page by entering an entirely new URL. Instead, the network analysis of my browser (a current Firefox) shows me that a POST request is send when leaving the page that returns with an 403 http error code: enter image description here

As you can see in the screenshot, the "Initiator" of the POST request seems to be an unload.js.jsf script with a beacon mentioned in parentheses, which I assume is part of the OmniFaces library. So presumably the functionality described in the OmniFaces ViewScoped documentation is somehow triggered, but does not result in the expected behavior for me.

The browser still navigates to the new page, but the PreDestroy annotated method was not triggered. When I switch to the standard version of ViewScoped (javax.faces.view.ViewScoped instead of org.omnifaces.cdi.ViewScoped), naturally the method still does not get invoked, but there is also no POST method resulting in a 403 error status when leaving the page in the network analysis of my browser (because the standard ViewScoped annotation of Java does not try to invoke any bean side action on unload events, I guess)

I am using MyFaces 2.3.10 in combination with OmniFaces 2.7.18 (and PrimeFaces 8.0.5, I don't know if that is relevant), Spring Security 5.7.3 and Java 11.

Since "403" is the http status for "forbidden", could this have something to do with using "http" instead of "https" in my local development environment? Does this "send beacon" only work with secure connections?

Any help appreciated!

Edit: I also consulted the official documentation of the OmniFaces ViewScoped annotation under https://omnifaces.org/docs/javadoc/2.7/index.html?org/omnifaces/cdi/ViewScoped.html but could not find a reason for the problem I encounter.


Solution

  • With the help of BalusC's comment to my question above, I was able to solve my problem. What it came down to was that unload events were not processed correctly by our filter chain. Specifically, they were denied access in the doFilter method of our class extending org.springframework.web.filter.GenericFilterBean.

    Therefore I added

    if (ViewScopeManager.isUnloadRequest(httpServletRequest)) {
        chain.doFilter(request, response);
    }
    

    to the doFilter method of the mentioned class and then it worked.

    On a side note, I had to update my OmniFaces library from 2.7.18 to 3.13.3, because the ViewScopeManager class of OmniFaces 2 only has one isUnloadRequest method that accepts an FacesContext as parameter, which I did not have available in the our GenericFilterBean extension. OmniFaces 3.1 on the other hand provides another method with the same name that works with an HttpServletRequest instance instead, which I had access to and therefore resolved the issue