Navigation rules in JSF

In the previous chapter we have discussed the fundamentals of JSF. We also made the basic set up to develop a JSF application.In this chapter we are looking in to another concept – navigation rules in JSF

Navigation rules in JSF

In JSF , developers can mention the page navigation  in multiple ways  . At run time ,page  navigation happens based on  these navigation rules. So these navigation rules decides which view needs to be shown based on an outcome.

There are multiple ways to define the navigation rules.They are:

1)Implicit Navigation:-In JSF 2.0 , developer can specify the navigation rule in  the page itself.The outcome view name can be specified as the action in the JSF page. JSF will  search for the correct view from the list of deployed views and will be displayed if found.(As in the previous example)

2)Navigation Rule in Managed Bean : In this case  the  managed bean action methods returns the view name . JSF will search for the correct view among all the deployed list of views and will be shown if found.

3)Navigation rule in faces-config.xml file :-In faces-config file , we can define the navigation rule for each action and for each outcome.

Example

Now we can look into an example.We have a login page and a success page. Once the user enters both the credentials(user name & password) and press the login button , success page will be shown. Otherwise the login page will be shown again.We are defining our navigation rules in faces-config.xml file.We  are using the same setup made for the previous example. Source file locations are also same .

We have two managed beans in this example.We have a LoginController.java which  has a method to handle the login request from the page.We also have UserBean.java ,which holds the user reference.The LoginController has a reference of the UserBean.java for holding the user object.

So it is possible to refer a managed bean from another managed bean as a managed property.To set a bean as a managed property of another bean , the child should have a scope which is equal to or less than the scope of the parent bean.Also the parent bean should have a setter of the child bean.

loginPage.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:f="http://java.sun.com/jsf/core"
	xmlns:h="http://java.sun.com/jsf/html">

<h:head>
	<title>Login Page</title>
</h:head>
<h:body>
	<h2>Please Provide the Details</h2>
	<h:form>
		<h:panelGrid>
			<h:outputLabel for='userName' value="Username: "
				style="font-weight:bold" />
			<h:inputText id='userName' value="#{loginController.userBean.userName}"></h:inputText>
			<h:outputLabel for='password' value="Password: "
				style="font-weight:bold" />
			<h:inputSecret id='password' value="#{loginController.userBean.password}"></h:inputSecret>
			<h:commandButton value="Login" action="#{loginController.doLogin}" ></h:commandButton>			
		</h:panelGrid>
	</h:form>
</h:body>
</html>

This is the source page.It has the text widgets to enter the user name and password.It also has the command button to trigger the action

LoginController.java

It has the action method.It returns either success or failure responses based on the user input.

import java.io.Serializable;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;

@ManagedBean(name = "loginController")
@SessionScoped
public class LoginController implements Serializable {

	private static final long serialVersionUID = 1L;

	@ManagedProperty(value = "#{userBean}")
	private UserBean userBean;

	public LoginController() {

	}

	public void setUserBean(UserBean user) {
		this.userBean = user;
	}

	public UserBean getUserBean() {
		return userBean;
	}

	public String doLogin() {
		System.out.println("User details : " + userBean);
		String status = "failure";
		if (null != userBean.getUserName() && !userBean.getUserName().isEmpty()
				&& !userBean.getUserName().equalsIgnoreCase(" ")
				&& null != userBean.getPassword()
				&& !userBean.getPassword().isEmpty()
				&& !userBean.getPassword().equalsIgnoreCase(" ")) {
			status = "success";
		}
		return status;
	}

}

UserBean.java

import java.io.Serializable;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean(name="userBean")
@SessionScoped
public class UserBean implements Serializable {

	private static final long serialVersionUID = 1L;
	private String userName;
	private String password;

	public UserBean() {

	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}
	
	public String toString(){
		return "User Name = "+userName + " ;  Password = "+password;
	}

}

It holds the user object

faces-config.xml

It has the navigation rules for both the outcome.For success outcome from manged bean , the result view is successPage and for failure outcome , the result will be loginPage

<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
	version="2.2">	

 <navigation-rule>
	<from-view-id>loginPage.xhtml</from-view-id>
	<navigation-case>
		<from-action>#{loginController.doLogin}</from-action>
		<from-outcome>success</from-outcome>
		<to-view-id>loginSuccess.xhtml</to-view-id>
	</navigation-case>
	<navigation-case>
		<from-action>#{loginController.doLogin}</from-action>
		<from-outcome>failure</from-outcome>
		<to-view-id>loginPage.xhtml</to-view-id>
	</navigation-case>
    </navigation-rule>	
</faces-config>

loginSuccess.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:head>
	<title>Success Page</title>
</h:head>
<h:body>
	<h2>Login Success</h2>
	<h2>Hello #{userBean.userName}</h2>
</h:body>
</html>

Now build the project and run the loginPage.xhtml. A successful login will render the success view. Otherwise the login page will be shown again.

See Related Topics

1)JSF Overview