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!

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
golinko
  • 327
  • 2
  • 3
  • 14

1 Answers1

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.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Ok, thanks! Can you also explain what the difference between ExternalContext#redirect and navigation handler redirect? – golinko Jun 17 '14 at 09:04
  • The one doesn't use JSF navigation handler, while the other does. – BalusC Jun 17 '14 at 09:04
  • 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. – golinko Jun 17 '14 at 09:08
  • 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. – BalusC Jun 17 '14 at 09:10
  • 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. – BalusC Jun 17 '14 at 09:11
  • Thank you very much. I must read the source code to see all the details :) and documentation also... – golinko Jun 17 '14 at 09:12