1) Introduction
In this article, let us see the different types of Navigation mechanisms available in JSF. The JSF Navigation Model is both declarative and programmatic, i,e, Navigation can be configured either statically in the deployment time or dynamically during the run-time of a Web Application. We will see how to configure such navigation models in a Web Application with code snippets. This article is not an introductory article for JSF and hence readers with no or little JSF knowledge are advised to go through the Introductory article on JSF in javabeat.
2) Navigation
Navigation happens in a Web Application when a user tries to switch from one page to another page either by clicking a button after entering some input values, clicking a hyperlink, or directly entering the target URL of the Web Application in a browser. Whatever be the case, the next page to be displayed or the response for the current page has to be handled by the Web Application. Take the case of Java Servlets Technology. When a Web Browser invokes the Servlet by typing the Servlet URL in the Address bar, the method doGet()
(the default method) will get invoked and the response is shown in the Browser window.
also read:
Imagine that the response delivered from the Servlet is prompting the user to enter some other input forcing the current page to navigate to the next output page. Here the Navigation mechanism is totally handled only by the Web Application. The Navigation Handling Servlet should look for the current display page, then depending on the output of the current page the next page (or the next view) to be displayed is selected. The output of the current page may logically fall into success, failure, need more input, etc and all these cases have to be handled separately.
The designers of JSF soon recognized the need for Navigation handling since it is almost common in all Web Applications. The Navigation model in JSF is highly configurable and it is very simple to understand and use. The subsequent sections will detail the different types of Navigation models along with code samples.
3) Types of Navigation
JSF supports two kinds of Navigation models which are,
- Static Navigation
- Dynamic Navigation
Static Navigation is recommended when the output of one page is known well in Advance and it is always easier to predict the output of the current page. Whereas, it is better to use Dynamic Navigation when the output of the current page is highly unpredictable and the output depends mainly on the execution of some Business logic.
4) Static Navigation
As mentioned earlier, if the response of the current page is known well in advance, then this type of Navigation can be chosen. Let us take an example to illustrate this. Let us display a Web Page (a login page) that prompts for user input like the username and the password. Once the values are entered and the form is submitted, then a welcome page is displayed. Here it is known that the outcome of the login page is always the welcome page.
4.1) The Login Page
The Login page containing the user input fields for username
and password
is shown below. A command button is attached at the end of the form for submitting the request information to the server. Note the usage of the 'action'
attribute with the value 'loginWelcome'
. Later on we will see that the logical name 'loginWelcome'
will resolve to a JSF Page called 'loginWelcome.jsp'
.
login.jsp
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %> <%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %> <html> <head> <title>Login Application</title> </head> <body> <h1>Login Application</h1> <f:view> <h:form> <p>Enter your username: <h:inputText value="#{LoginBean.username}" id="usernameTextField" required="true"/> <h:message for="usernameTextField" /> <p>Enter your password: <h:inputSecret value="#{LoginBean.password}" id="passwordTextField" required="true"/> <h:message for="passwordTextField" /> <h:commandButton value="Submit Values" action="loginWelcome"/> </h:form> </f:view> </body> </html>
4.2) Login Bean class
LoginBean.java
package net.javabeat.articles.jsf.navigation; public class LoginBean { private String username; private String password; public LoginBean() { } 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; } }
The UserBean
class encapsulates the properties username
and password
for holding the request information. The username
and the password
values entered by the user will be directly mapped to UserBean.username
and UserBean.password
because of the expressions '#{UserBean.username}'
and’#{UserBean.password}’.
4.3) Faces Configuration File
faces-config.java
<?xml version='1.0' encoding='UTF-8'?> <faces-config version="1.2" 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_1_2.xsd"> <managed-bean> <managed-bean-name>LoginBean</managed-bean-name> <managed-bean-class> net.javabeat.articles.jsf.navigation.LoginBean </managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean> <navigation-rule> <description></description> <from-view-id>/login.jsp</from-view-id> <navigation-case> <from-outcome>loginWelcome</from-outcome> <to-view-id>/loginWelcome.jsp</to-view-id> </navigation-case> </navigation-rule> </faces-config>
The Faces Configuration file contains a managed bean definition entry for the LoginBean through the element 'managed-bean'
. Next comes the important section which is related to navigation Handling. We have defined a navigation rule for the login.jsp
page through the elements 'navigation-rule'
and 'from-view-id'
. The presence of the 'from-view-id'
manifests that the rule will be applicable for the outcome from the page 'login.jsp'
. Next we have defined an inner element called 'navigation-case'
which defines a single possibly output for the current page. Note the presence of the elements 'from-outcome'
and 'to-view-id'
. The value 'loginWelcome'
represents one of the logical outcomes of the page 'login.jsp'
. The value for the 'to-view-id'
points to the next response page to be displayed. To summarize, if the current page is login.jsp
and the outcome of the page is 'loginWelcome'
, then the next page to be displayed is 'loginWelcome.jsp'
.
5) Dynamic Navigation
Let us see how to control the Navigation behavior dynamically in this section. Let us extend the above example to do this. In this time, let us display a login success page when the username and password values are matching 'guest'
, else a login failure page is displayed. Since the values are entered by the user only at the run-time, the next view to be displayed cannot be predicted. This means that the next view to be selected depends on the execution of some business logic in code.
5.1) User Bean updated
Add the following method definition in the UserBean class,
public String nextPage() { if (username.equals("guest") && password.equals("guest")) { return "loginSuccess"; } return "loginFailure"; }
The method nextPage()
determines the next page to be displayed based on the values of the username and the password. If both the username and password is given as 'guest'
, then a login success page will be displayed. Note that we are returning logical strings 'loginSucess'
(for login success) and 'loginFailure'
(for login failure). In the later section, we will see how this logical string will resolve to a JSP Page.
5.2) Faces Configuration file
<navigation-rule> <description></description> <from-view-id>/login.jsp</from-view-id> <navigation-case> <from-outcome>loginSuccess</from-outcome> <to-view-id>/loginSuccess.jsp</to-view-id> </navigation-case> <navigation-case> <from-outcome>loginFailure</from-outcome> <to-view-id>/loginFailure.jsp</to-view-id> </navigation-case> </navigation-rule>
We have added two navigation cases for the login page, one for success and the other one for failure. The configuration file tells that for the view login.jsp
, if the logical outcome is 'loginSuccess'
, then display the page 'loginSuccess.jsp'
. Else, if the logical outcome is 'loginFailure'
, then the page 'loginFailure.jsp'
should get displayed.
We will see the files 'loginSuccess.jsp'
and 'loginFailure.jsp'
in the next sections.
5.3) Login Success
The loginSuccess.jsp
page just displays the successful login message along with the username which is taken from the managed bean LoginBean.
loginSuccess.jsp
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %> <%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %> <html> <head> <title>Login Successful</title> </head> <body> <h2>Login Successful</h2> <P> <f:view> <h:form> <P>You have succesfully logged in.<P/> <P>Welcome <h:outputText value = "#{LoginBean.username}" /> <P/> </h:form> </f:view> </body> </html>
5.4) Login Failure
loginFailure.jsp
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %> <%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %> <html> <head> <title>Login Failure</title> </head> <body> <h2>Login Failure</h2> <P> <f:view> <h:form> <P>The Login id <h:outputText value = "#{LoginBean.username}" /> is not found.<P/> <P>Please try again. </h:form> </f:view> </body> </html>
The loginFailure.jsp
page displayed a message telling that the login was not successful.
6) Miscellaneous
In this section, we will see the left-over details of JSF Navigation Mechanisms. We will cover the usage of the 'redirect'
element as well as specifying wild-card strings.
6.1) Re-direct
Normally, when a Redirect is encountered by the Server, then the current request is terminated, the control is directed back to the browser and the Browser makes the request (which will be available as a URL in the Redirect instruction). The same happens here also. For example, consider the following code snippet,
<navigation-case> <from-outcome>loginFailure</from-outcome> <to-view-id>/loginFailure.jsp</to-view-id> <redirect/> </navigation-case>
Suppose, say that the outcome of the page login.jsp
is loginFailure.jsp
. If the redirect element is not present in the configuration file, then the Browser URL will still show login.jsp
and not loginFailure.jsp
(though the contents displayed in the Browser will be of loginFailure.jsp). The presence of the redirect element will move the control from the Server to the Browser and a request is made to the target page 'loginFailure.jsp'
.
6.2) Specifying wild-cards
It is also possible to specify wild-card character (*) in the 'from-view-id'
element. For example, say that we want to handle the navigation mechanism for all jsf files within the folder 'registration'
, then we can have something like the following,
<navigation-rule> <from-view-id>/registration/*</from-view-id> <navigation-case> ... </navigation-case> </navigation-rule>
7) Conclusion
In this article, we saw how JSF simplifies things in handling Navigations in a typical Web Application. We happened to cover the different mechanisms of JSF Navigations along with code snippets. The Miscellaneous section that was presented in the final section of the article explained the usage of the redirect element as well specifying ‘wild-cards’ in the JSF Navigation elements.