Main Tutorials

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

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
15 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Ahmed
8 years ago

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

valley
6 years ago
Reply to  Ahmed

thanks

Sachin Singh
8 years ago

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

Antonio
9 years ago

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

Guest
9 years ago

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

majda
9 years ago

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)?

hai nam
11 years ago

great thank sir

kamlesh
11 years ago

Hi

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

sudheer
11 years ago

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

pradeep
11 years ago

Hi

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

kumar
10 years ago
Reply to  pradeep

change the following line:

public int orderQty = 99

TO

public int orderQty = 111

wallace
11 years ago

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

Nalina
11 years ago

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.

Sridhar
12 years ago

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

Tomasz
12 years ago

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

Is not possible to write it like that:

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

?