Frage

I have an issue with understanding how flash works in the jsf lifecycle.

I am trying to redirect to a different page from a phase listener through a normal get request and at the same time adding a flash message(of course i have set the flah.keepmessage) to be displayed on the new page. But the message fails to show up. I know that something is wrong and will be grateful if anyone can kindly assist in implementing a better way (without filters please).

phaseredirect1.html

    <h:body>
    <f:view>
        <f:phaseListener binding="#{testphase.testPL}"/>
        <div>Testing Phases Redirect 1</div>
    </f:view>
    </h:body>

TestPhaseRedirect.java

   @SessionScoped
   @ManagedBean(name="testphase")
   public class TestPhaseRedirect {
   private PhaseListener testPL;

   @PostConstruct
   private void initializeVar(){
    testPL = new PhaseListener() {
        @Override
        public void afterPhase(PhaseEvent event) {
        }
        @Override
        public void beforePhase(PhaseEvent event) {
            getFacesContext().addMessage(null, new FacesMessage("Faces Message: redirecting to page 2..."));
            getExternalContext().getFlash().setKeepMessages(true);
            ConfigurableNavigationHandler nav = (ConfigurableNavigationHandler)getFacesContext().getApplication().getNavigationHandler();
            nav.performNavigation("redirect-to-page2");
            getFacesContext().responseComplete();
            return;
        }
        @Override
        public PhaseId getPhaseId() {
            return PhaseId.RENDER_RESPONSE;
        }
    };
}    
public PhaseListener getTestPL() {
    return testPL;
}
}

phaseredirect2.html

    <h:body>
    <f:view>
        <div style="width:400px;">
            <p:messages autoUpdate="true" closable="true"/>
            <p>Testing Phases Redirect 2</p>
            <p> Did it display the message? </p>
        </div>
    </f:view>
    </h:body>

faces config

    <navigation-case>
        <from-outcome>redirect-to-page2</from-outcome>
        <to-view-id>/phaseredirect2.html</to-view-id>
        <redirect />
    </navigation-case>

Kindly correct me. Thank you so much.

War es hilfreich?

Lösung

During the render response phase, it's too late to create the flash scope. You need to do it at latest during invoke application phase. Basically, this problem has the same grounds as when doing so in a <f:event type="preRenderView"> as already answered in the following related questions:

In your particular case, you need a dummy view parameter so that the invoke action phase is triggered and then use the <f:event type="postInvokeAction"> (after having created the custom event yourself or having installed OmniFaces as per the answers on the abovelinked questions):

<f:metadata>
    <f:viewParam name="dummy" />
    <f:event type="postInvokeAction" listener="#{bean.init}" />
</f:metadata>

with

public void init() {
    FacesContext context = FacesContext.getCurrentInstance();
    context.addMessage(null, new FacesMessage("Faces Message: redirecting to page 2..."));
    context.getExternalContext().getFlash().setKeepMessages(true);
    ConfigurableNavigationHandler nav = (ConfigurableNavigationHandler)  context.getApplication().getNavigationHandler();
    nav.performNavigation("redirect-to-page2");
}

or if you've chosen for OmniFaces

public void init() {
    Messages.addFlashGlobalInfo("Faces Message: redirecting to page 2...");
    Faces.navigate("redirect-to-page2");
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top