jsfprettyfacesflash-scope

Can the Flash data be persisted after redirection?


Using JSF 2.1.29

In list.xhtml

<p:commandLink id="ownerViewLinkId" value="#{petOwner.firstName} #{petOwner.lastName} " 
action="#{ownerAndPetListBean.viewPetOwnerFrmList(petOwner.id,petOwner.userId,0)}"
        onclick="PF('progrees_db').show()"
        oncomplete="PF('progrees_db').hide()"
        style="color:#0080FF;">
</p:commandLink>

In listBean (viewscoped),

public void viewPetOwnerFrmList(String ownerIdStr, String userIdStr,
            String petIdStr) {
    try {
        FacesContext.getCurrentInstance().getExternalContext().getFlash().put("ownerId",ownerIdStr);
            FacesContext.getCurrentInstance().getExternalContext().getFlash().put("userId",userIdStr);
            FacesContext.getCurrentInstance().getExternalContext().getFlash().put("petId",petIdStr);

            FacesContext.getCurrentInstance().getExternalContext()
                    .redirect("/ownerandpets/view");

    } catch (Exception e) {
            log.warn("FL Warning", e);
    }
}

pretty-config.xml

  <url-mapping id="ownerandpetsview"> 
      <pattern value="/ownerandpets/view" />          
      <view-id value="/WEB-INF/views/ownerAndPet/OwnerAndPetsView.xhtml" />
      <action onPostback="false">#{ownerAndPetViewBean.fillPage}</action> 
  </url-mapping>

In viewbean (viewscoped),

String petIdStr;
String userIdStr;
String ownerIdStr;
String firstName;
//include getters and setters
public void fillPage() {

    petIdStr = (String) FacesContext.getCurrentInstance().getExternalContext().getFlash().get("petId");
    userIdStr = (String) FacesContext.getCurrentInstance().getExternalContext().getFlash().get("userId");
    ownerIdStr = (String) FacesContext.getCurrentInstance().getExternalContext().getFlash().get("ownerId");

    System.out.println(ownerIdStr+" "+userIdStr+" "+petIdStr);
    firstName = getFromDBByOwnerId(ownerIdStr); 
}

In view page,

<h:outputText value="#{ownerAndPetViewBean.firstName}"/>

firstName is displayed after redirect. On refreshing the view page (by pressing f5), the string firstName becomes null and id strings printed in viewBean's fillPage is null. What i need is on refresh, i need to refetch firstName for which the ids must not be null. Had gone through this link Anyway to persist the flash data in request?

Tried the below but was not successful :

1.

FacesContext.getCurrentInstance().getExternalContext()
                    .redirect("/ownerandpets/view?faces-redirect=true");

2.

FacesContext.getCurrentInstance()
    .getExternalContext().getFlash().keep("ownerId");
FacesContext.getCurrentInstance()
    .getExternalContext().getFlash().keep("userId");
FacesContext.getCurrentInstance()
    .getExternalContext().getFlash().keep("petId");

3.

FacesContext.getCurrentInstance().getExternalContext()
    .getFlash().setKeepMessages(true);
FacesContext.getCurrentInstance().getExternalContext()
    .getFlash().setRedirect(true);

On Refresh debugging, the ids are there in the flash scope map on watching FacesContext.getCurrentInstance().getExternalContext().getFlash() , but the same is not displayed in watching FacesContext.getCurrentInstance().getExternalContext().getFlash().get("petId"); (see fig 2).

Values in Flash Map on Refresh - Fig 1 Fig 2

Update 1 (Answer):

As suggested by Xtreme Biker, added preRenderView to the view page.

<f:event type="preRenderView" listener="#{ownerAndPetViewBean.fillPage}"/> .

From the pretty-config.xml, remove or comment

<action onPostback="false">#{ownerAndPetViewBean.fillPage}</action>

Put a not postback checking in fillPage method and added flash.keep in managed bean.

FacesContext.getCurrentInstance().getExternalContext().getFlash().keep("ownerId");

The above method will not work with pretty-faces action tag (if used instead of preRenderview) and we will get page with no values.


Solution

  • The prettyfaces action is probably out of the scope of the current flash state. Don't know exactly how the pretty action works, but you need to set flash.keep in the same request cycle where the redirection is performed (If using pretty, that's done by a POST-REDIRECT-GET pattern).

    Anyway, as the docs example for pretty action shows a @RequestScoped bean, don't know its compatibility with the View Scope and with the flash state, consequently. I personally prefer to use the f:event='preRenderView' checking for postbacks if you still in JSF 2.1. If JSF 2.2, use f:viewAction, without having to check for postbacks.

    See also: