Omnifaces Faces.redirect loses conversation scope
Asked Answered
A

1

1

I have problem with org.omnifaces.util.Faces#redirect and conversation scoped bean:

there is a button

<p:commandButton action="#{navigationHandler.gotoCreateCar}"
  actionListener="#{createHandler.init(searchHandler.search())}
  value="#{msg.search}" update=":articleSearchForm">
  <f:param name="cid" value="#{javax.enterprise.context.conversation.id}"/>
</p:commandButton>

which must do a navigation to createCar page within the same conversation scope after init of my conversation scoped bean: createHandler.

In the NavigationHandler#gotoCreateCar is just a call of Faces.redirect(createCarPage).

If I do like this the parameter cid is not transfered and I lose my conversation.

If I define a navigation rule in faces-config.xml:

<navigation-case>
  <from-outcome>createCar</from-outcome>
  <to-view-id>/portal/createCar.xhtml</to-view-id>
  <redirect />
</navigation-case>

and in the NavigationHandler#gotoCreateCar just return the needed outcome - then it works fine.

Maybe I do not understand every detail in the difference between this two navigation approaches. I would be appreciated if somebody could help me to understand the problem.

Thanks!

Alkene answered 17/6, 2014 at 8:34 Comment(0)
T
3

The conversation propagation is handled by the navigation handler. The Faces#redirect() delegates to ExternalContext#redirect() which does not use the navigation handler. You'd better use Faces#navigate() instead which delegates to NavigationHandler#handleNavigation().

public void gotoCreateCar() {
    // ...

    Faces.navigate("/portal/createCar.xhtml?faces-redirect=true");
}

(note: no <navigation-case> is needed in this case)

Alternatively, just return exactly that string from the action method.

public String gotoCreateCar() {
    // ...

    return "/portal/createCar.xhtml?faces-redirect=true";
}    

The Faces#navigate() is only useful when you're inside a (listener) method which doesn't support returning a navigation case outcome, such as @PostConstruct or preRenderView.

Trodden answered 17/6, 2014 at 8:52 Comment(6)
Ok, thanks! Can you also explain what the difference between ExternalContext#redirect and navigation handler redirect?Alkene
The one doesn't use JSF navigation handler, while the other does.Trodden
So the navigation handler handles the conversation additionally to redirecting and ExternalContext just do the plain redirecting? Sorry, I just try to clarify the question for me.Alkene
Yes. As answered, the conversation propagation is handled by the JSF navigation handler. The ExternalContext#redirect() doesn't use the JSF navigation handler. It just sets "plain vanilla" a HTTP Location header on the response without any manipulation of the given path. The JSF navigation handler supports more fine grained control over this, e.g. it can interpret the given path as a (relative) JSF view ID and perform some additional actions based on e.g. the current conversation state, or the additional specific parameters such as faces-redirect, includeViewParams, etc.Trodden
Note that the blueish texts in my answer are actually links to docs (as usual). Click them to see and read the docs. It's also explained over there.Trodden
Thank you very much. I must read the source code to see all the details :) and documentation also...Alkene

© 2022 - 2024 — McMap. All rights reserved.