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 &lt; 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.

Note
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 &lt; 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 &lt; 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>
Thought…
JSF 2 conditional navigation rule, … quite similar with the Spring Web Flow, right? 🙂

Download Source Code

15 comments on “Conditional Navigation Rule in JSF 2.0

  1. #{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}

    Reply
  2. when i m executing the example it is only always executing the top most navigation rule and not checking the rest condition

    Reply
  3. 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

    Reply
  4. 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

    Reply
  5. 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)?

    Reply
  6. Hi

    Its not working correctly, always redirect to first navigation case.
    Please provide the solution.

    Reply
  7. Yes,Conditional navigation is not working as expected here.It is always accessing first navigation case.

    Reply
  8. Hi

    It always redirect to payment.xhtml. Page navigation is not happening from faces-config.xml.
    Kindly make it clear..

    Reply
    1. change the following line:

      public int orderQty = 99

      TO

      public int orderQty = 111

      Reply
  9. 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

    Reply
  10. 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.

    Reply
  11. 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

    Reply
  12. “#{paymentController.orderQty < 100} && #{paymentController.xxx}”

    Is not possible to write it like that:

    “#{paymentController.orderQty < 100 && paymentController.xxx}”

    ?

    Reply

Leave a Comment

Your email address will not be published. Required fields are marked *