jsfrestoreview-scopehttp-request-parametersviewexpiredexception

Restoring request parameters in @ViewScoped bean after session expires


I have a page that has the setup as below with url like my.page.com/table.xhtml?id=123:

+----------------------------------------------+
|Meta information                              |
|----------------------------------------------|
|           Search Fields           Submit btn |
|----------------------------------------------|
|                                              |
|                                              |
|            Big p:dataTable                   |
|                with rowExpansion             |
|                                              |
|----------------------------------------------|
|                   Pager                      |
+----------------------------------------------+

id=123 is the request parameter that controls the content on the result table. All actions only reload the data table using AJAX.

id is loaded throught this :

<f:metadata>
    <o:viewParam name="id" value="#{dataTable.id}" />
    <f:viewAction action="#{dataTable.initialize}" />
</f:metadata>

This all works fine, until the session expires. At this point, nothing works. I cannot get data since I no longer have access to the id in question and the call to the DAO classes fetching the data do not have this.

By "no longer have access to the id" I mean that :

FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("id")

returns null. Also, the int id from my backing bean (which is loaded through the o:viewParam in the f:metadata suffers the same fate.

I know there are methods to catch a ViewExpiredException, but this is not what I want. I need the page to simply reload all values using the request parameter (in this case id) without the user knowing.

I (think I) need a @ViewScoped manage bean to control this complex table and all parameters, etc.

I am at a lost with regards to this. I have tried building my own ViewHandler to try to get it to simply rebuild (mimic a refresh) of the page, and tried to use the PrimeFaces ajaxExceptionHandler among other solutions. But all these get an error and display it. I just want to have access to my request parameter my.page.com/table.xhtml?id=123 from the backing bean.

Any help would be appreciated.

I am running on:


Solution

  • As to bypassing the expired view by just completely recreating it, add <o:enableRestorableView> to the metadata:

    <f:metadata>
        ...
        <o:enableRestorableView />
    </f:metadata>
    

    As to retaining the request parameter, either add a plain HTML hidden input field to the form:

    <h:form>
        ...
        <input type="hidden" name="id" value="#{dataTable.id}" />
    </h:form>
    

    or use <o:form> with includeViewParams="true",includeRequestParams="true" or useRequestURI="true", depending on whether you'd like to submit to the JSF view ID with all view params, or to the JSF view ID with the entire request query string, or to the entire request URI (including query string):

    <o:form includeViewParams="true">
        ...
    </o:form>
    

    As to reinitializing the bean's state on postback before it going through all phases of the JSF lifecycle, you'd need to replace the <o:viewParam> by manually grabbing it and the <f:viewAction> by @PostConstruct:

    @PostConstruct
    public void initialize() {
        id = Faces.getRequestParameter("id");
        // ...
    }