Can the Flash data be persisted after redirection?

2019-08-06 04:30发布

问题:

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).

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.

回答1:

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:

  • How to keep JSF flash scope parameters on page reload?