1) What is JSF? JSF stands for Java Server Faces. JSF has set of pre-assembled User Interface (UI). By this it means complex components are pre-coded and can be used with ease. It is event-driven programming model. By that it means that JSF has all necessary code for event handling and component organization. Application programmers can concentrate on application logic rather sending effort on these issues. It has component model that enables third-party components to be added like AJAX.
2) What is required for JSF to get started? Following things required for JSF: • • • •
JDK (Java SE Development Kit) JSF 1.2 Application Server (Tomcat or any standard application server) Integrated Development Environment (IDE) Ex. Netbeans 5.5, Eclipse 3.2.x, etc.
Once JDK and Application Server is downloaded and configured, one can copy the JSF jar files to JSF project and could just start coding. :-) If IDE is used, it will make things very smooth and will save your time.
3) What is JSF architecture? JSF was developed using MVC (a.k.a Model View Controller) design pattern so that applications can be scaled better with greater maintainability. It is driven by Java Community Process (JCP) and has become a standard. The advantage of JSF is that it’s both a Java Web user – interface and a framework that fits well with the MVC. It provides clean separation between presentation and behavior. UI (a.k.a User Interface) can be created by page author using reusable UI components and business logic part can be implemented using managed beans.
4) How JSF different from conventional JSP / Servlet Model? JSF much more plumbing that JSP developers have to implement by hand, such as page navigation and validation. One can think of JSP and servlets as the “assembly language� under the hood of the high-level JSF framework.
5) How the components of JSF are rendered? An Example In an application add the JSF libraries. Further in the .jsp page one has to add the tag library like:
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%> Or one can try XML style as well:
<jsp:root version="2.0" xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"> Once this is done, one can access the JSF components using the prefix attached. If working with an IDE (a.k.a Integrated Development Environment) one can easily add JSF but when working without them one also has to update/make the faces-config.xml and have to populate the file with classes i.e. Managed Beans between
tags
6) How to declare the Navigation Rules for JSF? Navigation rules tells JSF implementation which page to send back to the browser after a form has been submitted. For ex. for a login page, after the login gets successful, it should go to Main page, else to return on the same login page, for that we have to code as:
/login.jsp login /main.jsp fail /login.jsp from-outcome to be match with action attribute of the command button of the login.jsp as:
Secondly, it should also match with the navigation rule in face-config.xml as
<managed-bean> <managed-bean-name>user <managed-bean-class>core.jsf.LoginBean <managed-bean-scope>session In the UI component, to be declared / used as:
value attribute refers to name property of the user bean.
7) How do I configure the configuration file? The configuration file used is our old web.xml, if we use some IDE it will be pretty simple to generate but the contents will be something like below:
<web-app version="e;2.4"e; xmlns="e;http://java.sun.com/xml/ns/j2ee"e; xmlns:xsi="e;http://www.w3.org/2001/XMLSchema-instance"e; xsi:schemaLocation="e;http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"e;>
<param-name>com.sun.faces.verifyObjects <param-value>false <param-name>com.sun.faces.validateXml <param-value>true <param-name>javax.faces.STATE_SAVING_METHOD <param-value>client <servlet> <servlet-name>Faces Servlet <servlet-class>javax.faces.webapp.FacesServlet
1 <servlet-mapping> <servlet-name>Faces Servlet
/faces/* <session-config> <session-timeout> 30 <welcome-file-list> <welcome-file> index.jsp The unique thing about this file is ?servlet mapping?. JSF pages are processed by a servlet known to be part of JSF implementation code. In the example above, it has extension of .faces. It would be wrong to point your browser to http://localhost:8080/MyJSF/login.jsp, but it has to be http://localhost:8080/MyJSF/login.faces. If you want that your pages to be with .jsf, it can be done with small modification :-),
<servlet-mapping> <servlet-name>Faces Servlet
*.jsf <servlet-mapping>
8) What is JSF framework? JSF framework can be explained with the following diagram:
As can be seen in Figure 1, JSF interacts with Client Devices which ties together with presentation, navigation and event handling and business logic of web tier model. Hence JSF is limited to presentation logic / tier. For Database tier i.e. Database and Web services one has to rely on other services.
9) How does JSF depict the MVC (a.k.a Model View Controller) model? The data that is manipulated in form or the other is done by model. The data presented to user in one form or the other is done by view. JSF is connects the view and the model. View can be depicted as shown by:
JSF acts as controller by way of action processing done by the user or triggering of an event. For ex.
, this button event will triggered by the user on Button press, which will invoke the login Bean as stated in the faces-config.xml file. Hence, it could be summarized as below: User Button Click -> form submission to server -> invocation of Bean class -> result thrown by Bean class caught be navigation rule -> navigation rule based on action directs to specific page.
10) What does it mean by rendering of page in JSF? Every JSF page as described has various components made with the help of JSF library. JSF may contain h:form, h:inputText, h:commandButton, etc. Each of these are rendered (translated) to HTML output. This process is called encoding. The encoding procedure also assigns each component with a unique ID assigned by framework. The ID generated is random.
11) What is JavaServer Faces? JavaServer Faces (JSF) is a user interface (UI) framework for Java web applications. It is designed to significantly ease the burden of writing and maintaining applications that run on a Java application server and render their UIs back to a target client. JSF provides ease-of-use in the following ways: • • • • •
Makes it easy to construct a UI from a set of reusable UI components Simplifies migration of application data to and from the UI Helps manage UI state across server requests Provides a simple model for wiring client-generated events to server-side application code Allows custom UI components to be easily built and re-used
Most importantly, JSF establishes standards which are designed to be leveraged by tools to provide a developer experience which is accessible to a wide variety of developer types, ranging from corporate developers to systems programmers. A "corporate developer" is characterized as an individual who is proficient in writing procedural code and business logic, but is not necessarily skilled in object-oriented programming. A "systems programmer" understands object-oriented fundamentals, including abstraction and designing for re-use. A corporate developer typically relies on tools for development, while a system programmer may define his or her tool as a text editor for writing code. Therefore, JSF is designed to be tooled, but also exposes the framework and programming model as APIs so that it can be used outside of tools, as is sometimes required by systems programmers.
12) How to pass a parameter to the JSF application using the URL string? if you have the following URL: http://your_server/your_app/product.jsf?id=777, you access the passing parameter id with the following lines of java code:
FacesContext fc = FacesContext.getCurrentInstance(); String id = (String) fc.getExternalContext().getRequestParameterMap().get("id"); From the page, you can access the same parameter using the predefined variable with name param. For example,
Note: You have to call the jsf page directly and using the servlet mapping.
13) How to add context path to URL for outputLink? Current JSF implementation does not add the context path for outputLink if the defined path starts with '/'. To correct this problem use #{facesContext.externalContext.requestContextPath} prefix at the beginning of the outputLink value attribute. For example:
14) How to get current page URL from backing bean? You can get a reference to the HTTP request object via FacesContext like this:
FacesContext fc = FacesContext.getCurrentInstance(); HttpServletRequest request = (HttpServletRequest) fc.getExternalContext().getRequest(); and then use the normal request methods to obtain path information. Alternatively,
context.getViewRoot().getViewId();
will return you the name of the current JSP (JSF view IDs are basically just JSP path names).
15) How to access web.xml init parameters from java code? You can get it using externalContext getInitParameter method. For example, if you have:
<param-name>connectionString <param-value>jdbc:oracle:thin:scott/tiger@cartman:1521:O901DB
You can access this connection string with:
FacesContext fc = FacesContext.getCurrentInstance(); String connection = fc.getExternalContext().getInitParameter("connectionString");
16) How to access web.xml init parameters from jsp page? You can get it using initParam pre-defined JSF EL valiable. For example, if you have:
<param-name>productId <param-value>2004Q4 You can access this parameter with #{initParam['productId']} . For example:
Product Id:
17) How to terminate the session? In order to terminate the session you can use session invalidate method. This is an example how to terminate the session from the action method of a backing bean:
public String logout() { FacesContext fc = FacesContext.getCurrentInstance(); HttpSession session = (HttpSession) fc.getExternalContext().getSession(false); session.invalidate(); return "login_page"; } The following code snippet allows to terminate the session from the jsp page:
<% session.invalidate(); %>
18) How to implement "Please, Wait..." page? The client-side solution might be very simple. You can wrap the jsp page (or part of it you want to hide) into the DIV, then you can add one more DIV that appears when user clicks the submit button. This DIV can contain the animated gif you speak about or any other content. Scenario: when user clicks the button, the JavaScript function is called. This function hides the page and shows the "Wait" DIV. You can customize the look-n-fill with CSS if you like. This is a working example:
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> Input Name Page <script> function gowait() { document.getElementById("main").style.visibility="hidden"; document.getElementById("wait").style.visibility="visible"; }
If you want to have an animated gif of the "Wait" Page, the gif should be reloaded after the form is just submitted. So, assign the id for your image and then add reload code that will be called after some short delay. For the example above, it might be:
<script> function gowait() { document.getElementById("main").style.visibility="hidden"; document.getElementById("wait").style.visibility="visible"; window.setTimeout('showProgress()', 500); } function showProgress(){ var wg = document.getElementById("waitgif"); wg.src=wg.src; } .... .... ....
19) How to reload the page after ValueChangeListener is invoked? At the end of the ValueChangeListener, call FacesContext.getCurrentInstance().renderResponse()
20) How to download PDF file with JSF? This is an code example how it can be done with action listener of the backing bean. Add the following method to the backing bean:
public void viewPdf(ActionEvent event) { String filename = "filename.pdf"; // use your own method that reads file to the byte array byte[] pdf = getTheContentOfTheFile(filename); FacesContext faces = FacesContext.getCurrentInstance(); HttpServletResponse response = (HttpServletResponse) faces.getExternalContext().getResponse(); response.setContentType("application/pdf"); response.setContentLength(pdf.length); response.setHeader( "Content-disposition", "inline; filename=\""+fileName+"\""); try { ServletOutputStream out; out = response.getOutputStream(); out.write(pdf); } catch (IOException e) { e.printStackTrace(); } faces.responseComplete();
} This is a jsp file snippet:
21) How to show Confirmation Dialog when user Click the Command Link? h:commandLink assign the onclick attribute for internal use. So, you cannot use it to write your own code. This problem will fixed in the JSF 1.2. For the current JSF version you can use onmousedown event that occurs before onclick. <script language="javascript"> function ConfirmDelete(link) { var delete = confirm('Do you want to Delete?'); if (delete == true) { link.onclick(); } } . . . .
22) What is the different between getRequestParameterMap() and getRequestParameterValuesMap() getRequestParameterValuesMap() similar to getRequestParameterMap(), but contains multiple values for for the parameters with the same name. It is important if you one of the components such as .
23) Is it possible to have more than one Faces Configuration file? Yes. You can define the list of the configuration files in the web.xml. This is an example:
<param-name>javax.faces.CONFIG_FILES <param-value>/WEB-INF/faces-config-navigation.xml,/WEB-INF/facesbeans.xml Note: Do not register /WEB-INF/faces-config.xml file in the web.xml . Otherwise, the JSF implementation will process it twice. Hi there, I guess the Note: column should have been meant or intended for "faces-config.xml" file as thats the default configuration file for JSF (which is similar to struts-config.xml for Struts!!). faces-context.xml file sounds like the user defined config file similar to the aforementioned two xml files.
24) How to mask actual URL to the JSF page? You'll need to implement your own version of javax.faces.ViewHandler which does what you need. Then, you register your own view handler in faces-config.xml. Here's a simple abstract ViewHandler you can extend and then implement the 3 abstract methods for. The abstract methods you override here are where you'll do your conversions to/from URI to physical paths on the file system. This information is just passed right along to the default
ViewHandler for JSF to deal with in the usual way. For example, you could override these methods to add and remove the file extension of an incoming view id (like in your example), for extensionless view URIs.
import java.io.IOException; import java.util.Locale; import import import import
javax.faces.FacesException; javax.faces.application.ViewHandler; javax.faces.component.UIViewRoot; javax.faces.context.FacesContext;
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory;
the
/** * A facade view handler which maps URIs into actual physical views that * underlying implementation can deal with regularly. * Therefore, all internal references to view ids, for example in faces-
config,
* will use the path to the physical files. Everything publicized, however,
will
* see a "converted" / facade url. */ public abstract class SimpleConverterViewHandler extends ViewHandler { private static final Log LOG = LogFactory.getLog(SimpleConverterViewHandler.class); private final ViewHandler base; public SimpleConverterViewHandler(ViewHandler base) { this.base = base; } /** * Distinguishes a URI from a physical file view. * Tests if a view id is in the expected format -- the format corresponding * to the physical file views, as opposed to the URIs. * This test is necessary because JSF takes the view ID from the * faces-config navigation, and calls renderView() on it, etc. */ public abstract boolean isViewFormat(FacesContext context, String viewId); /** * Convert a private file path (view id) into a public URI. */ public abstract String convertViewToURI(FacesContext context, String viewId); /** * Convert a public URI into a private file path (view id) * note: uri always starts with "/"; */
uri);
public abstract String convertURIToView(FacesContext context, String public String getActionURL(FacesContext context, String viewId) { // NOTE: this is used for FORM actions.
}
String newViewId = convertViewToURI(context, viewId); LOG.debug("getViewIdPath: " + viewId + "->" + newViewId); return base.getActionURL(context, newViewId);
private String doConvertURIToView(FacesContext context, String requestURI) { if (isViewFormat(context, requestURI)) { return requestURI; } else { return convertURIToView(context, requestURI); } } public void renderView(FacesContext context, UIViewRoot viewToRender) throws IOException, FacesException { if (null == context || null == viewToRender) throw new NullPointerException("null context or view"); String requestURI = viewToRender.getViewId(); String newViewId = doConvertURIToView(context, requestURI); LOG.debug("renderView: " + requestURI + "->" + newViewId); viewToRender.setViewId(newViewId); }
base.renderView(context, viewToRender);
public UIViewRoot restoreView(FacesContext context, String viewId) { String newViewId = doConvertURIToView(context, viewId); LOG.debug("restoreView: " + viewId + "->" + newViewId); return base.restoreView(context, newViewId); } public Locale calculateLocale(FacesContext arg0) { return base.calculateLocale(arg0); } public String calculateRenderKitId(FacesContext arg0) { return base.calculateRenderKitId(arg0); } public UIViewRoot createView(FacesContext arg0, String arg1) { return base.createView(arg0, arg1); } public String getResourceURL(FacesContext arg0, String arg1) { return base.getResourceURL(arg0, arg1); } public void writeState(FacesContext arg0) throws IOException { base.writeState(arg0); }
}
25) How to print out html markup with h:outputText? The h:outputText has attribute escape that allows to escape the html markup. By default, it equals to "true". It means all the special symbols will be replaced with '&' codes. If you set it to "false", the text will be printed out without ecsaping.
For example, will be printed out like: This is a text In case of you will get: This is a text
26) h:inputSecret field becomes empty when page is reloaded. How to fix this? Set redisplay=true, it is false by default
Event Driven Programming with JSF 1) Introduction This article discusses theories and concepts related to JSF Event Model. It details the supporting high level classes and interfaces that are involved in JSF Event Handling Mechanism. The logical categorization of JSF Events is also explained along with code snippets. Then, the tags available in the core JSF Framework are also discussed. This article doesn't provide an introduction so first-time readers of JSF are advised to read Introduction to Java Server Faces in JavaBeat before beginning this article.
2) JSF Event Model
2.1) Introduction The model that JSF implements for handling Events is based on the standards defined in Java Beans Specification. The basic model goes like this. JSF User Interface Components are sources that can emit some kind of signals based on user actions. These signals are often termed as Events. Applications who want to process the Events can attach any number of Event Listeners to Event Sources. This simple model is also followed in Swing Components. However, the difference here is, the Event Sources (i.e, the UI Components) reside in the Client whereas the Listeners (Application Logic that does something in response to Events) will reside on the Server.
2.2) Event Classes The classes/interfaces related to JSF Events are contained in the package 'javax.faces.event'. All Events (standard Events or User-defined Events) in JSF should extend the javax.faces.event.FacesEvent. The constructor for this class has an argument of type UIComponent which specifies for which UI Component the Event is for.
UIComponent someComponent = new UIComponent(); MyFacesEvent event = new MyFacesEvent(someComponent); UIComponent sourceCompoenent = event.getComponent();
If the above code, the source component that generated a particular Event can be obtained by calling the method event.getComponent(). This class has a method called queue() which is used to queue the Event at the end of the current request processing life-cycle. If we want the Event to be queued and occur at a particular request processing phase, then this can be achieved by the following lines of code,
MyFacesEvent event = new MyFacesEvent(); event.setPhaseId(PhaseId.PROCESS_VALIDATIONS);
In the above code, the event MyFacesEvent will occur at the end of the 'Process Validations' life-cycle phase. JSF defines two concrete set of Events namely ActionEvent and ValueChangeEvent and they both extend the base Event class FacesEvent. They are discussed in greater depth in the subsequent sections.
2.3) Listener Classes There is a corresponding Listener Class for each type of Event in JSF. For example, consider the case of ActionEvent, in which there exists an equivalent Listener class called ActionListener. Same is the case of ValueChangeEvent, in which case the corresponding Listener class is ValueChangeListener. The JavaBeans Specification mandates the support for the following methods for registering a Listener to a particular Event. For example, if the Event name is MyCustomEvent and the corresponding Listener class is MyCustomListener and we want this Event to happen for a component called MyCustomComponent, then the following methods shall be defined in the MyCustomComponent class for registering the Listeners.
public void addMyCustomListener(MyCustomListener listener) public void removeMyCustomListener(MyCustomListener listener) public MyCustomListener[] getMyCustomListeners()
3) Types of JSF Events
3.1) Introduction The logical categorization of JSF Events fall under three categories and they are listed as follows, • • •
Action Events Value Change Events Phase Events
We will discuss about these Events in the following sections along with code snippets.
3.2) Action Events Action Events are emitted for UI Command objects like Command Button or a Hyper-link. Whenever a user presses a Command Button or clicks a hyper-link these Events get generated. It is possible to attach any number of Listeners to these Sources. For example, consider the following code snippet,
We have defined an attribute called 'actionListener' pointing to a method expression. This method expression will resolve to a method called doSomeAction() which is defined in the Managed Bean with identifier 'testActionListener'. The signature of the method for the 'actionListener' attribute must be,
public void anyMethod(ActionEvent actionEvent)
Given below is the definition of the Managed Bean in the Faces Configuration file,
<managed-bean> <managed-bean-name>testActionListener <managed-bean-class> net.javabeat.articles.jsf.events.actions.TestActionListener <managed-bean-scope>request
It is also possible to programmatically register any number of Listeners for a particular UI Component. Say for example, the following code snippet attached two listeners to the component identified by myComponent,
UIComponent myComponent = new UIComponent(); myComponent.addActionListener(new TestActionListener()); myComponent.addActionListener(new CustomActionListener());
Given below is the definition for the class TestActionListener, TestActionListener.java
package net.javabeat.articles.jsf.events.actions; import import import import
javax.faces.component.UIComponent; javax.faces.event.AbortProcessingException; javax.faces.event.ActionEvent; javax.faces.event.ActionListener;
public class TestActionListener implements ActionListener { public TestActionListener() { } public void processAction(ActionEvent event) throws AbortProcessingException { System.out.println("Test Action Listener called.."); UIComponent source = event.getComponent(); System.out.println("Source of the Event is " + source.getClass().getName()); } }
Whenever the Button is clicked, the method processAction(ActionEvent event) will be called and the business logic will be executed. Same is the case with the following CustomActionListener class, CustomActionListener.java
package net.javabeat.articles.jsf.events.actions; import import import import
javax.faces.component.UIComponent; javax.faces.event.AbortProcessingException; javax.faces.event.ActionEvent; javax.faces.event.ActionListener;
public class CustomActionListener implements ActionListener { public CustomActionListener() { } public void processAction(ActionEvent event) throws AbortProcessingException { System.out.println("Custom Action Listener called.."); UIComponent source = event.getComponent(); System.out.println("Source of the Event is " + source.getClass().getName()); }
}
The order of execution of Action Events follows this way. If the attribute 'actionListener' is defined for the Component, then it is executed first, followed by the Event Listeners that are registered programmatically by calling the method addActionListener(ActionListener actionListener).
3.3) Value Change Events Value Change Events are applicable for UI Components like Text Field, Check-Box, List and Radio Buttons. The Value Change Event is fired as soon as the value that is displayed in the view is modified. Listeners that are attached to this Value Change Event usually perform some sort of validation to check whether the new input is acceptable. For example, consider the following code snippet,
Note the use of the attribute 'valueChangeListener'. In the above code, whenever the value of the country name is changed, then the PIN value for the country name is auto-populated in the relevant text-field. CountryValueChangeListener.java
package net.javabeat.articles.jsf.events.actions; import javax.faces.event.AbortProcessingException; import javax.faces.event.ValueChangeEvent; import javax.faces.event.ValueChangeListener; public class CountryValueChangeListener { public CountryValueChangeListener() { } public void populatePinNumber(ValueChangeEvent event) { Object oldValue = event.getOldValue(); Object newValue = event.getNewValue(); if (oldValue != newValue) { // Get the country name and populate the pin value. String countryName = (String)newValue; } }
}
In the above code, an attempt is made to fetch the PIN number for the corresponding country name. If we wish to add Value Change Listeners to a particular UI Component, then make use of the method addValueChangeListener(ValueChangeListener valueChangeListener). The Custom ValueChangeListener class must define a processValueChange() with a single argument of type ValueChangeEvent.
3.4) Phase Events As we are aware that the Request processing life-cycle in JSF includes six phases and any JSF implementation will fire Phase Events during the start and end of each phase. If we want to capture the Phase Events, then can define a Phase Listener class as follows, CustomPhaseListener.java
package net.javabeat.articles.jsf.events.actions; import javax.faces.event.PhaseEvent; import javax.faces.event.PhaseId; import javax.faces.event.PhaseListener; public class CustomPhaseListener implements PhaseListener { public CustomPhaseListener() { } public void afterPhase(PhaseEvent event) { System.out.println("After Phase->" + event.getPhaseId()); } public void beforePhase(PhaseEvent event) { System.out.println("Before Phase->" + event.getPhaseId()); } public PhaseId getPhaseId() { return PhaseId.ANY_PHASE; } }
Note that the Application specific Phase Listener class implements the interface PhaseListener. The methods afterPhase() will be called once a Phase gets ended. And the method beforePhase() will be called even before a phase begins. To register this Phase Listener to our Application, we have to define an entry in the Faces Configuration file like this,
net.javabeat.articles.jsf.events.actions.TestActionListener
It is possible to define any number of Phase Listeners for an Application as follows,
PhaseListener1 PhaseListener2
The following code will now list down all the phase listeners that are defined in the Faces Configuration file,
public void listAllPhaseListeners() { LifecycleFactory lifecycleFactory = (LifecycleFactory)FactoryFinder.getFactory( FactoryFinder.LIFECYCLE_FACTORY); Lifecycle applicationLifecycle = lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
}
PhaseListener phaseListeners[] = applicationLifecycle.getPhaseListeners(); for (PhaseListener phaseListener : phaseListeners) { System.out.println(phaseListener.getPhaseId()); }
4) Conclusion This article discussed about the Event Driven Modeling in JSF Framework. More specifically, it dealt with the JSF Events and the JSF Listener Classes for supporting Event Handling. Then the final sections concentrated on the various types of JSF Events like Action Events, Value Change Events and Phase Events and how they can be configured and registered to the source components.
Navigation model in JSF 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. 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" %>
Login Application Login Application
Enter your username:
Enter your password:
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
<managed-bean> <managed-bean-name>LoginBean <managed-bean-class> net.javabeat.articles.jsf.navigation.LoginBean <managed-bean-scope>request <description> /login.jsp loginWelcome /loginWelcome.jsp
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 <description> /login.jsp loginSuccess /loginSuccess.jsp loginFailure /loginFailure.jsp
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" %> Login Successful Login Successful
You have succesfully logged in.
Welcome
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" %> Login Failure
Login Failure
The Login id is not found.
Please try again.
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,
loginFailure /loginFailure.jsp
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,
/registration/*
...
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.
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 <description> /login.jsp loginSuccess /loginSuccess.jsp
loginFailure /loginFailure.jsp
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" %> Login Successful Login Successful
You have succesfully logged in.
Welcome
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" %>
Login Failure Login Failure
The Login id is not found.
Please try again.
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,
loginFailure /loginFailure.jsp
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,
/registration/* ...
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.
Request Processing Lifecycle phases in JSF 1) Introduction This article will explain the sequence of activities that will take place while processing the Request in a typical Web Application. The various phases like the Restore View Phase, Apply Request Values Phase, Process Validations Phase, Update Model Values Phase, Invoke Application Phase and Render Response Phase are covered briefly. First-time readers of JSF are requested to read the introductory article Introduction to Java Server Faces in JavaBeat.
2) Life-cycle Phases As soon as a JSF Application in initiated by calling the Faces Servlet (which is configured in the web.xml file), series of activities will take place. These activities come under the category of JSF Request Processing Life-cycle Phases. The phases are, • • • • • •
Restore View Apply Request Values Process Validations Update Model Values Invoke Application Render Response
The above Life-cycle Phases are not sequential. For example, the control may be re-directed to Render Response Phase from Process Validation phase in case of any Conversion or Validation Errors.
3) Restore View A JSF View or Simple View is nothing but a collection of UI Components. For example, consider the following login form,
Enter your username:
Enter your password:
The above form has a root UI Component called 'view'. It is having three child components namely a text-field (with identifier 'usernameTextField'), a password-field (with identifier 'passwordTextField') and a command button with name 'Submit Values'. So, this whole setup represents a view. It is also possible to have any number of sub-views as represented by a 'sub-view' tag in a single form. The state of the view can either be stored in the Server or in the Client Browser. If it is stored in Server, then it might be cached in the HttpSession object, else it may be represented as hidden text-fields in the client end. The strategy whether the view state is stored in Server or Client is determined by the property called 'javax.faces.STATE_SAVING_METHOD'. The default value for this property is 'server' which means that the view state is restored in the Server. The other permitted value is 'client'. This property is specified in the Configuration file (web.xml) as follows,
<param-name>javax.faces.STATE_SAVING_METHOD <param-value>client
Now, let us see the activities happening in this phase. If the request is made to a URL for the first time, then a new View object is created and rendered to the Client. Else (because the view state is already found in the cache), the view is restored and displayed. In our example case, we saw three child components. Any Custom Convertors, Validators, Renderers, if attached for the UI components, will be restored in this phase. In case, if the UI Component values are directly mapped to the property defined in a Managed Bean, then the value for the property is restored and it is associated with the View. Most of the works are handled by the ViewHandler class through its method restoreView().
4) Apply Request Values
In this phase, the values that are entered by the user will be updated on each and every individual component defined in the View graph. More specifically, the processDecodes() on the UIComponentBase method will be called for all components. Here, the process of applying the Request values to the UI Components is called Decoding. For example, in the above sample login form that we have taken, the user input values will be applied on the components (text-field and password). The outcome of this phase may either end in Process Validations Phase or the Render Response Phase. If the child components include Action components (such as command button or a hyper-link), and the immediate property is set to true, then any Action Events associated with it will be queued by calling the UIComponentBase.queueEvent(FacesEvent) method. Since the immediate property is set to true, the Action Event will be immediately fired at then end of this Phase. On the other hand, if the immediate property is set to false, then the Action Events are queued and fired only at the end of Invoke Application phase, and for editable components (more specifically, components that implement the EditableValueHolder interface), all the conversions and the validations will take place if the property 'immediate' is set to 'true'. If any of the Conversions or the Validations fail, then the current processing is terminated and the control directly goes to the Render Response for rendering the conversion or the validation errors to the Client.
5) Process Validations This Phase will process any Validations that are configured for UI Components. For example, consider the following code snippet,
Enter your phone-number
The above code defines a Custom Validator called PhoneNumber Validator which will validate the given string against some standard format. It is possible to define and attach any number of Validators to a Component. In this phase, JSF Implementation will traverse over the UIViewRoot to fetch all the child components and ask the child components to validate themselves by calling the method UIComponentBase.processValidators(). So, the child components will get a list of Validators that are defined for them and then invoke the Validation logic defined on them. These validations will only happen for the UI Components only if the property 'rendered' property is set to 'true'. If the property is set to false, then Validations would not take place. It is important to understand that even before Validations occur on UI Components, conversions will happen. For example, consider the following code snippet,
Enter your birthday:
(MMM-dd-yyyy)
The above code attaches a Date Time Converter to the component 'birthdayTextField'. So, the user entered request value is made to get converted to the pattern 'MMM-dd-yyyy'. If any Conversion error happens here, then the current Process Validations Phase is terminated and the control is directed to the 'Render Response' Phase for reporting any errors.
6) Updating Model Values If the Application has reached this phase, then it is obvious that the user entered request values are syntactically valid. The values that are stored in UI Components will be made to synchronize with the Model objects, which are usually Backing Beans. For example, consider the following code snippet,
Enter your username:
Enter your password:
In the above code snippet, we have defined two UI Components namely a text-field and a password field. The corresponding model object for this form is the LoginBean class. Since the LoginBean is treated as a Backing Bean (else, it can't be used in Method Expressions), the Application should have defined this in the Faces Configuration file as follows,
<managed-bean> <managed-bean-name>UserBean <managed-bean-class>user.registration.UserBean <managed-bean-scope>request
In this phase, the processUpdates() method in the UIComponentBase will be called, which in turn will call all the processUpdates() method that are defined in the child components. Setting the request value to the Model object may also result in Events to get queued and fired.
7) Invoke Application In this phase, all the Listeners that are registered for the UI Components will get invoked and the Listeners will usually contain the Application specific logic. Note that for all Action Components (like the Command Button or the Hyper-link), there always exists Default Action Listeners which when invoked will display the current page. Consider the code snippet which defines an Action Listener for the Button click,
In this phase, JSF Implementation will call the method UIComponentBase.processApplications() method which can immediately call the Render Response Phase.
8) Render Response And finally, we have reached the Render Response whose job is to render the response back the Client Application. Before rendering the response, the state of View is stored in the cache by calling the method UIViewRoot.saveState() method.
9) Conclusion This article provided an overview about the various phases that are involved in JSF Request Processing. It should be noted that, not at all times, phases will occur in a sequential manner. A phase encountering Errors (like Conversion or Validation Errors) or Events may redirect the control to the final phase without passing through any of the intermediatary phases.