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.

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 < 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>
Thought...
JSF 2 conditional navigation rule, ... quite similar with the Spring Web Flow, right? :)

Download Source Code

About the Author

author image
mkyong
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

avatar
14 Comment threads
2 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
15 Comment authors
valleyAhmedSachin SinghAntonioGuest Recent comment authors
newest oldest most voted
Ahmed
Guest
Ahmed

#{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
Guest
valley

thanks

Sachin Singh
Guest
Sachin Singh

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

Antonio
Guest
Antonio

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?… Read more »

Guest
Guest
Guest

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
Guest
majda

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
Guest
hai nam

great thank sir

kamlesh
Guest
kamlesh

Hi

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

sudheer
Guest
sudheer

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

pradeep
Guest
pradeep

Hi

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

kumar
Guest
kumar

change the following line:

public int orderQty = 99

TO

public int orderQty = 111

wallace
Guest
wallace

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
Guest
Nalina

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.

trackback
Conditional navigation in JSF2.0 | PHP Developer Resource

[…] take a look at this Conditional Navigation Rule in JSF 2.0 […]

Sridhar
Guest
Sridhar

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
Guest
Tomasz

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

Is not possible to write it like that:

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

?