Conditional Navigation Rule in JSF 2.0
JSF 2 comes with a very flexible conditional navigation rule to solve the complex page navigation flow, see the following conditional navigation rule example :
1. JSF Page
A simple JSF page, with a button to move from this page to the payment page.
start.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<h:body>
<h2>This is start.xhtml</h2>
<h:form>
<h:commandButton action="payment" value="Payment" />
</h:form>
</h:body>
</html>
2. Managed Bean
A managed bean to provide sample data to perform the conditional checking in the navigation rule.
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import java.io.Serializable;
@ManagedBean
@SessionScoped
public class PaymentController implements Serializable {
private static final long serialVersionUID = 1L;
public boolean registerCompleted = true;
public int orderQty = 99;
//getter and setter methods
}
3. Conditional Navigation Rule
Normally, you declared the simple navigation rule in the “faces-config.xml” like this :
<navigation-rule>
<from-view-id>start.xhtml</from-view-id>
<navigation-case>
<from-outcome>payment</from-outcome>
<to-view-id>payment.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
With JSF 2, you can add some conditional checking before it move to the payment page, see following :
faces-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<faces-config
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
version="2.0">
<navigation-rule>
<from-view-id>start.xhtml</from-view-id>
<navigation-case>
<from-outcome>payment</from-outcome>
<if>#{paymentController.orderQty < 100}</if>
<to-view-id>ordermore.xhtml</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>payment</from-outcome>
<if>#{paymentController.registerCompleted}</if>
<to-view-id>payment.xhtml</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>payment</from-outcome>
<to-view-id>register.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
</faces-config>
This is equal to the following Java code :
if (from-view-id == "start.xhtml"){
if(from-outcome == "payment"){
if(paymentController.orderQty < 100){
return "ordermore";
}else if(paymentController.registerCompleted){
return "payment";
}else{
return "register";
}
}
}
The code should be self explanatory enough.
In the conditional navigation rule, the sequence of the navigation rule does affect the navigation flow, always put the highest checking priority in the top.
4. Testing
Different data sets for testing :
Example 1
public class PaymentController implements Serializable {
public boolean registerCompleted = true;
public int orderQty = 99;
...
When the button is clicked, it hits the “paymentController.orderQty < 100” criteria and move to the “ordermore.xhtml” page.
Example 2
public class PaymentController implements Serializable {
public boolean registerCompleted = true;
public int orderQty = 200;
...
When the button is clicked, it hits the “paymentController.registerCompleted” criteria and move to the “payment.xhtml” page.
Example 3
public class PaymentController implements Serializable {
public boolean registerCompleted = false;
public int orderQty = 200;
...
When the button is clicked, it failed all the checking criteria and move to the “register.xhtml” page.
Suggestion
In JSF 2.0, there is no “else” tag in the conditional navigation rule, wish JSF team can include the “else” tag in the future release. For example,
<navigation-rule>
<from-view-id>start.xhtml</from-view-id>
<navigation-case>
<from-outcome>payment</from-outcome>
<if>#{paymentController.orderQty < 100}</if>
<to-view-id>ordermore.xhtml</to-view-id>
<else if>#{paymentController.registerCompleted}</else if>
<to-view-id>payment.xhtml</to-view-id>
<else>
<to-view-id>register.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
Moreover, It should include the multiple conditional checking as well, like this
<navigation-rule>
<from-view-id>start.xhtml</from-view-id>
<navigation-case>
<from-outcome>payment</from-outcome>
<if>#{paymentController.orderQty < 100} && #{paymentController.xxx}</if>
<to-view-id>ordermore.xhtml</to-view-id>
<else if>#{paymentController.registerCompleted}</else if>
<to-view-id>payment.xhtml</to-view-id>
<else>
<to-view-id>register.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
JSF 2 conditional navigation rule, … quite similar with the Spring Web Flow, right? 🙂
#{paymentController.orderQty < 100} didn't work for me, after some search it worked with "lt" instead of "<".
Working expression for me : #{paymentController.orderQty lt 100}
thanks
when i m executing the example it is only always executing the top most navigation rule and not checking the rest condition
hi,when using conditional navigation it happens that navigation cases are matched disregarding the from-action and from-outcome rules and navigation case is evaluated to only the expression contained in the “if”. The result of this is that the “return null” which I used for reloading the same page (for instance when I wanted to display validation errors, or to display the result of user search) is not working anymore, and instead of staying on the same page, the first clause that matches the if case is evaluated and thus I navigate wrongly to another page. Is this an issue of JSF2? please help, I cannot find a solution!
thanks Antonio
Hello Sir,
I wanted to use JSF Redirect to new tab as we can do by
but i want it by JSF Navigation rule
Like:
start.xhtml
payment
#{paymentController.orderQty < 100}
ordermore.xhtml
I have faced the same problem like some other users who let a comment..I have resolved it, I see that I have omitted in start.xhtml page (it’s necessary for <h:commandButton )
But I don’t know why I need to clean and restart the server everytime I need to test(Set different values in the managed bean)?
great thank sir
Hi
Its not working correctly, always redirect to first navigation case.
Please provide the solution.
Yes,Conditional navigation is not working as expected here.It is always accessing first navigation case.
Hi
It always redirect to payment.xhtml. Page navigation is not happening from faces-config.xml.
Kindly make it clear..
change the following line:
public int orderQty = 99
TO
public int orderQty = 111
Hi, I have a problem with my web application, I have JSF 2.0 with prime faces and everything is working fine, but today I created a new folder and inside a new web page (.xhtml). But when a tried to navigation thought the page using a managerBean with implicit navigation doesn’t works. The interesting thing is that when a change this web page to one especific folder works if I put in other one doesn’t works. Every new web pages not work with implicit navigation only using faces-config.
Have any idea ?
Thks
Hi .
Thank you for the examples written. But I found Conditional navigation is not working means irrespective values for attributes of managed bean it is navigating to payment.xhtml page only.. not to any other pages. Could you pls check it out.
The navigation rule defined in the above faces-config.xml, is not working.
As its hardcoded in start.jsp to navigate to particular jsp, its forwarding the request to particular jsp.
can anyone help me to navigate to corresponding jsps by changing the quantity in java code?
Thanking you,
M.Sridhar
“#{paymentController.orderQty < 100} && #{paymentController.xxx}”
Is not possible to write it like that:
“#{paymentController.orderQty < 100 && paymentController.xxx}”
?