1) Introduction
In Fact, JSF is nothing but an abstraction over the existing Web Framework. JSF is implemented as a Servlet which is called the Faces Servlet. Before the advent of JSF, Servlets and JSP are the predominant ones that form the core components in the development of a Web Application. Let us see the traditional interaction that takes place in a Web Application is developed only with the Servlet and the JSP components that follows the MVC-2 Architecture. A client who is normally a HTML Browser sends a request to the server. The Web Server receives the request, encapsulates the request and then populates this request object with the various parameter values from the client and will send it to the Servlet. The Servlet which acts as a Controller, analyses the request, then will interact with the Model (Java Beans) that executes the various application business logic and then chooses which View to be shown to the User.
2) What is JSF?
Java Server Faces which provides a Component-Based Architecture for developing reusable User Interface Components hides most of the complex stuffs that are happening in the View portion of the MVC-2 Architecture. The framework is not only limited to developing customized User Interface Components but also provides support for various Advanced Features like Event handling Mechanism, Validating User Inputs that are sent by the clients, Easy Page Navigation Mechanism etc. The good thing about Java Server Faces is that the degree of coupling between the UI Components that represent the various behaviour/properties and its Rendering is very low. In fact it is almost nill. So, HTML browsers are not the only target client applications. JSF Applications works even well with WML Browsers.
3) Basic Elements of JSF
Let us examine the various core basic elements in a JSF application. The most significant components in a JSF application are explained as follows.
- User Interface Components
- Managed Beans
- Validators
- Convertors
- Events and Listeners
- Page Navigation
- Renderers
All the above-mentioned components can be found in separated packages in the API. For example, the User Interface Components are available in javax.faces.component package, Validation API is available in javax.faces.validator package and so on.
3.1) User Interface Components
If Java Swings represent the UI components for a Desktop Java Application, then JSF UI Components are meant for the Web Applications. The JSF User Interface Components are developed with Java Beans Specifications and Standards in mind. It means that JSF Components have properties, methods and events as they are normally found for a traditional Java Bean. One of the peculiar features of the JSF UI Components is that they can manage the state of the component. So many built-in UI components are bundled with the JSF API, the most commonly used ones are Label, Text-Field, Form, Check-Box, Drop-Down Box etc. JSF also provides a framework for creating Customized UI Components.
It is very important to note that JSF UI Components only represent the attributes, behaviors and events for a component and not the actual display. For example in a Text-Field Control, the attributes may be the value of the text-field, the maximum number of characters that can be entered etc. Modifying the existing value and setting the maximum number of characters forms the behaviour for the Text-Field. Change in the value of the Text-Field may cause the Text-Field to cause some kind of Event to be emitted.
The manner is which text-field is displayed in the client is separated from the UI Data Representation itself. It means that there are separate components called Renderers which will take care of displaying the UI components in Different Client Surfaces, one client may be the HTML Browser running in a PC and the other may be the WML Browser running within a mobile phone. Each and every JSF component is uniquely identified by a Component Identifier.
3.2) Managed Beans
Managed Beans are standard Java classes that follow the Java Beans Specification.Generally, Managed Beans are used to represent the user inputs. They may even act as Listeners and can handle the appropriate Actions. Assume that there is an Encryption Application, which is presented with a Text-Field, wherein which user can enter a string that is to be encrypted. Below that is a Encrypt Button, which when clicked calls the server code that does the actual job of Encryption.
The following code snippet shows how to represent the Text-Field and the command button,
<html:inputText id = "strToBeEncryptedTextField" value = "#{EncryptionBean.strToBeEncrypted}"> </html:inputText> <html:commandButton id = "encryptButton" actionListener = "#{EncryptionBean.doEncryption}"> </html:commandButton>
Don’t worry about the declaration of the Text-Field and the Command Button here. The syntax for their declaration in covered in the later sections. The first noticeable thing is that the Text-Field has two attributes namely id and value. The id attribute uniquely identifies the Text-Field component from other Components in the View.
The value for the attribute value is #{EncryptionBean.strToBeEncrypted}. This expression is a JSF EL Expression. The EL expression can be interpreted as follows, Take the value of the string to be encrypted from the UI Component and map it to the property called strToBeEncrypted which is inside the class called EncryptionBean.
It means that the declaration of the Managed Java Bean class may look something like the following,
class EncryptionBean{ private String strToBeEncrypted; public String getStrToBeEncrypted(){ return strToBeencrypted; } public void setStrToBeEncrypted(String strToBeEncrypted){ this.strToBeEncrypted = strToBeEncrypted; } // Other things goes here }
From the declaration of the command button object, we can interpret that, ‘encryptButton’ is uniquely used to identify the command button object, the attribute actionListener is used to provide the listener method that will get invoked as a result of someone clicking the button. So, actionListener = “#{EncryptionBean.doEncryption}” essentially says that there is a method called doEncryption() within the EncryptionBean class. Following code snippet may prove this,
class EncryptionBean{ … public void doEncryption(javax.faces.event.ActionEvent event){ } … }
3.3) Validator
Validation is a must for almost any application. Data entered by the clients have to be validated before being sent to the Server for processing. JSF already have the Common Validation API being implemented for almost all controls in the javax.faces.validator package and also through various Custom Tags. The Validator Framework that is available with JSF is pluggable, i.e it also allows the developers to provide their own Custom Validation Classes through the help of Configuration Files.
Suppose say, there is a Text-Field Component in the form which inputs the age from the user to get some benefit from the organization. We can have a Simple Validation Rule telling that only Employees who are above 35 and below 45 are eligible for such a benefit. This can easily achieved through the use of Custom Validation Tags like the following one,
<html:inputText identifier = "employeeAgeTextField"> <f:validateLongRange minimum = "25" maximum = "35"> </f:validateLongRange> </html:inputText>
JSF will immediately report a Default Error Message whenever the value of the age entered by the user crosses the boundary range of 25-35.
Two types of Validation are possible in JSF. They are,
- Direct Validation
- Delegated Validation
i). Direct Validation:
Assume that there is a Customized UI component called E-Mail Text Field which allows the user to enter only email-ids in the appropriate format. Whenever a user enters some email-id, the UI component has to validate whether the given email-id is in the right format, something like [email protected]. It is wise to embed the Validation Logic within the component itself. Such Validation Code which is found within the UI component and can be used only by that Component is called Direct Validation.
ii). Delegated Validation:
Delegation Validation comes into picture when the Validation Logic is about to be re-used across so many Components. Common Validation stuffs are ideal candidates for Delegated Validation. For example, consider in a form where we have a Text-Field representing the name of a customer and a Radio-Button for Marital Status with values ‘Married’ and ‘Single’. If both are required fields, then before the submission of the form, both the input fields (text-field and the radio-button) have to be validated for empty (or null) values. So, in such a case we can have a Validator called NullCheckValidator and then bind both the input components to this Validator.
3.4) Convertors
Every piece of request that is passed from the client to the server is interpreted as a String value only. Manual conversion of the String object to the appropriate Data-type has to be done in the Application Code before carrying on with the application logic. Suppose in a form, there are fields like name, age and date. Corresponding to this form, we would have constructed a Managed Bean representing name, age and date as properties with String, integer and Date respectively. Certain amount of code has to be written for the conversion of the age and date values to their corresponding int and Date types.
But because of the availability of JSF Convertors functionality, this becomes easy. In the declaration of the UI Component itself within the form, we can mention which data-type the value for this control has to be converted. The Conversion API is available in javax.faces.convert.
For example, consider the following piece of code,
<html:inputText identifier = "numberTextField"> <f:convertNumber pattern = "###,###"> </f:convertNumber> </html:inputText>
In the above, we have a Number Converter which converts the number given by the user to the specified format. For example, if the original value entered by the user is 123456, then the after the conversion process the value becomes ‘123,456’.
3.5) Events and Listeners
JSF UI Event Mechanism is very similar to the one found in Swing UI Components. The Architecture remains the same in both the cases. In JSF, all the UI Components can emit any number of events. For example, a Button Component, when clicked by the user can emit an ActionEvent. Those which take appropriate actions after a component has emitted some kind of Events are called Event Listeners. In JSF, Java Managed Beans also acts as Listeners for the Events emitted by the components.
For example, consider the following code snippet,
<html:inputText identifier = "submitButton" value = "Click Me" actionListener = "#{SomeBean.submitButtonClicked}" </html:inputText>
In the above code, we can see that how a UI Component can be associated with an Event-Handler with the help of actionListener attribute. The code essentially says that whenever an ActionEvent is emitted by the button (which will happen usually when the user clicks the button or presses the Enter key over the button) call the Event Listener’s method submitButtonClicked inside the SomeBean class.
3.6) Navigation
An user of a Web Application doesn’t restrict himself in viewing one single Web Page. He/She will navigate from one page to another page. Technically the navigation of a user from one page to another page results in the generation of request and response for that page. Most of the boiler-plate work that is related to navigation stuffs in a web-application is handled by the Default JSF Navigation Handler itself. The Navigation Handler provides a simple yet a powerful framework for controlling the navigation.
For any single request page, there may be a number of response pages. Assuming that in a data-entry application, if the request page, say ‘enterdata.jsp’, is a view showing all the input controls to get data from the user, then the following responses may be available.
The user has entered all the data and the result is a ‘success’ so that a page called
- ‘success.jsp’ page is displayed
- The user has entered a mix of correct and incorrect data in which case, the result or theresponse is a ‘partialsuccess’ and some jsp page called ‘partialsuccess.jsp’ is displayed.
- The user hasn’t entered any correct values which means that result is a ‘failure’ whichresults in the display of a page called ‘failure.jsp’.
If we look at a very high-level, almost all of the pages will have this kind of Navigation Rule which will have N number of Navigational Cases. As such, we can define the Navigational Rules along with Navigational Cases for handling the navigational logic for the entire JSF application in the JSF Configuration File.
For example, the following is a simple navigation rule for the above sample scenario,
<navigation-rule> <from-view-id>/dataentry/enterdata.jsp</from-view-id> <navigation-case> <from-outcome>success</from-outcome> <to-view-id>/dataentry/success.jsp</to-view-id> </navigation-case> <navigation-case> <from-outcome>partialsuccess</from-outcome> <to-view-id>/dataentry/partialsuccess.jsp</to-view-id> </navigation-case> <navigation-case> <from-outcome>failure</from-outcome> <to-view-id>/dataentry/failure.jsp</to-view-id> </navigation-case> </navigation-rule>
The above code within the Configuration File states for the jsp file ‘enterdata.jsp’ (where ‘/dataentry/’ is the context path), if the outcome is ‘success’, navigate to ‘success.jsp, if the outcome is ‘partialsuccess’, then navigate to ‘partialsuccess.jsp’, else if the outcome is ‘failure’, then take the user to ‘failure.jsp’.
4) Different Phases in a JSF Application
It is very important to understand how a JSF application is initiated by a typical client such as a Web Browser along with the set of phases involved. Most of the different phases in a JSF Web Application is taken care by the JSF framework and only a minimal amount of burden is imposed on the application developers. The six different phases that are involved in a
JSF application are as follows,
- View Restoration
- Applying the Request Values
- Validation of User Inputs
- Updating the Model objects
- Execution of Application Logic
- Rendering the Response to the Clients
Let us have a brief discussion about the several phases one by one.
4.1) View Restoration
Before getting into details of the various set of actions that happens in this phase, let us define what a View is in JSF terms. In JSF terminology, a View represents the tree of UI components. Assume a typical e-mail application, which is asking the user to enter the details like email-id and the password. Also there is a submit button which is there to carry the request information from the client to server after the user has filled-in the necessary details.
Technically, there is a form in the page with 3 controls, 2 for the Text-Field holding the email-id and the password and 1 for the Action button. In this context, a View represents the tree of components that are available in the page. The view along with the components is stored in the server so that the state of the UI components is automatically managed.
In our case, the View may look like this,
Representation of View which points to a Tree of UI Components
Before understanding what the view restoration phase will do, let us see the various components and interactions involved in a JSF Web-Application. In a Web Application, thousands and thousands of requests may come from the clients. Each and every different request may display different page to the user. Every page often has an entirely different View (Tree of UI Components) associated with it. And each view within the page may have separated UI Components which may have Validators, Converters, Listeners and Managed Beans.
Every JSF Request is often associated with a context called JSF Context. The JSF Context stores the entire graph of view. The primary responsibility of this View Restoration phase is to identify the Current View and to restore this current view from the JSF Context. If no such view is found in the JSF Context, then this phase will create a new View which hold all the related UI components and associates all the different elements and then places it in the JSF Context.
Upon client request, the View may either be newly created or it can be restored from the current JSF Context, so this phase has been termed as View Restoration phase.
4.2) Applying the Request Values
View Restoration Phase has ended and the client has been presented with a nice view wherein which he/she is ready to input the appropriate values. After the client has entered the input data, the data is set or it is mapped to corresponding UI Component. Taking the sample example that we had in the View Restoration Phase, The First component is the Text-Field component with some unique identifier, say “emailIdTextField” and the next Text-Field component is represented by the identifier “passwordTextField”.
Whenever the user submits the values by clicking the submit button, JSF will iterate over the tree of components, pick up every component and sets the corresponding values to the right component that are submitted by the User. So, after the end of this phase, all the values that are submitted by the client will be set to the appropriate UI Components taken from the View with the help of the Faces Context.
4.3) Validation of User Inputs
In this phase, all the inputs that are submitted by the client user will be validated for their correctness. JSF will iterate over all the UI components in the UI Tree and will call the Default Validators as well as any of the Custom Validators that have been provided to the component. Assume that in the email-id text field, user is allowed to enter only in the following format, [email protected].
For this type of application specific validation, we can define something called EMailValidator to check whether the user input matches the correct email format. Either kind of validation is possible, Direct validation which is dedicated only for the particular component as well as Delegated Validation. The result of this phase may end up in the next phase Updating the Model Objects being called or it may direct JSF to the last phase which is the Rendering Response Phase. Assume that the user has entered an invalid email-id in which a case, the application will display appropriate Error Messages back to the user. It means that some kind of Error-Response has been given back to the user which is nothing but the Render Response Phase.
It is worthwhile to mention that two possible set of actions can occur in this phase apart from validations. One is Pre-Conversion Operation and the other one is the Post-Event Operation. As mentioned, all the input values from the client are sent to the server only as string values. Some kind of objects called Converters must be there to convert whatever input the client sent. Say a date value in the client UI has to be converted into a Date object before proceeding with the processing. Even there is a possibility that Events may be triggered as a result of values being changed; in such a case Value-Changed Events will be fired.
4.4) Updating the Model objects
Managed Beans form the Model Objects in a JSF application. Assume that in the mail application, we have represented a form containing two text-fields namely email-id and password. For this, we may have written a Bean class called UserInfoBean encapsulating the values of email-id and password.
The next question that arises in mind immediately is who will take care of mapping the two Text-Field values to the two String properties inside the UserInfo bean. The answer has become very simple because of EL expressions. An UI component can be mapped directly against a Java Bean Property declaratively in the definition of the UI component.
For example, consider the code following code snippet,
<html:inputText id = "emailIdTextField" value = "#{UserInfoBean.emailId}"> </html:inputText>
The above code declares an input component of type ‘Text-Field’ with an identifier ’emailIdTextField’. It has one more important attribute called value. This attribute is populated with a string called #{“UserInfoBean.emailId”}. This is essentially an EL Expression which tells to associate the value of the email-id text-field to the property name called emailId in the class UserInfoBean. Synchronizing an UI Component Value with that of a Bean Property is as simple like this.
4.5) Execution of Application Logic
If you remember that in the second phase Apply Request Values, we saw that as soon as the values from the input fields are applied to the corresponding UI components events will be generated. Only the events will be generated in that phase. The generated event won’t be notified to all the listeners who have registered for the events. The events in the second phase will be notified to all the listeners (if any) in this phase only. Remember that in JSF, all the UI components often have their Default Listeners associated with them.
Take the example of a Button Control. This UI component, by default will have an ActionListener associated with it. Whenever user clicks this button control, an event called action event will be generated. For example, if the model Bean Object has been registered to receive the events, then the corresponding event handler will be called in this phase
Consider the following snippet code,
<html:commandButton id = "submitButton" value = "Submit the Form" actionListener = "#{UserInfoBean.submitButtonClicked}"> … </html:commandButton>
In the above example, a button control with the display names ‘Submit the Form’ has an attribute called actionListener with value #{UserInfoBean.submitButtonClicked}. As mentioned before, this is a JSF EL Expression, which will resolve to a method called submitButtonClicked inside a bean class UserInfoBean as follows
class UserInfoBean{ public void submitButtonClicked(javax.faces.event.ActionEvent event){ // Process code here. } }
As we can see from the above snippet code, the submitButtonClicked() method is passed an ActionEvent (note, the event is of type javax.faces.event.ActionEvent and not the AWT ActionEvent found in java.awt.event.ActionEvent). One useful method in the ActionEvent class is the getComponent() method which will return the component that generated this event.
4.6) Rendering the Response
Now, it’s time to render (display) the response back to the client application in the Rendering the Response phase and this is the last phase in the life-cycle. One more thing to note is that before sending the response data to the client, JSF implementations store the View (which represents the Tree of UI components) in the Faces Context object, so that it can be restored back by the View Restore back when the request comes to the same page.
In JSF, there is a clear separation between the data representation and the display of the UI Components. More specifically, the UI components that we talked about don’t have the implementation of how they can be displayed. They will just represent the properties and the behaviors of the control. The rendering is handled separately by Renderer Components in JSF in the form of Renderer Kits.
Assume that there are two types of client application, one is the traditional HTML Browser which can understand and interprets HTML, and the other is the WML Browser which can interpret only WML. So, they will be two separate rendering kits namely the HTML Rendering Kit and the WML Rendering Kit. Sun’s JSF implementation comes with the Standard HTML Rendering Kit. The entire API for HTML rendering is available in the javax.faces.component.html.
Third party vendors can seamlessly plug-in the rendering Kits for WML (or for any other kind of display).
Events in Life-cycle phases
It is not that only UI Components can fire Events. Even events are emitted by the Request Processing Life-cycle Phases. To be precise 6 different life-cycle phases comes into the picture as soon as a client request comes to a JSF application. During every life-cycle phase, events are emitted by the JSF during the beginning and the ending of that particular phase. Following code snippet will demonstrate this,
class MyViewRestorePhaseListener extends PhaseListener{ public void beforePhase(PhaseEvent event){ //Do application specific initialization code here. } public void afterPhase(PhaseEvent event){ //Release the object resources here. } public PhaseId getPhaseId(){ return PhaseId. RESTORE_VIEW; } } LifecycleFactory factory = (LifecycleFactory) FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY); Lifecycle lifecycle = factory.getLifecycle(DEFAULT_LIFECYCLE); lifecycle.addPhaseListener(new MyViewRestorePhaseListener());
5) JSF Tag Libraries
Tags in JSP terms often represent a kind of task or an action that can do a small piece of work. Repeated Actions can be encapsulated within a tag and can be used in various places. A set of tags represent a Tag library. In JSF, two categories of tag libraries are available. They are
- JSF Core Tag Libraries
- JSF HTML Tag Libraries
Let us see the two different Tag Libraries one by one.
5.1) JSF Core Tag Libraries
These are set of libraries that provide tags which are responsible for categorizing the various UI elements in the form, to provide validation and conversion stuffs, tor manage set of event listeners for a particular UI component and so on. The declaration of the JSF Core Tag library is given below,
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="face" %>
In the above snippet, the prefix can be anything like ‘face’ or ‘f’ or anything that doesn’t matter. Some of the commonly used tags inside the core tag library are given as follows, (they have been categorized based on their functionality)
- View
- actionListener, valueChangeListener
- validateRange, validateLongRange, validateDoubleRange
- convertDateTime, convertNumber
The view tag is the top level view and it acts as a container for all the UI components in a form. The entire tree of UI components are logically contained in this view tag. actionListener and valueChangeListener are kind of Event-Listener tags. They can be associated with UI components. Whenever an action is made on a UI component an event is triggered by a UI component and the event will be notified to all Registered Listeners. Tags that are related to validations are validateRange, validateLongRange and validateDoubleRange. They can be used to restrict the number of characters that are typed in an input component and also can be used to check whether the given number is between certain range. convertDateTime and convertNumber represent the conversion tags which are used to convert the user input values to some object representation.
5.2) JSF HTML Tag Libraries
These set of tags are used to display the UI components in a HTML-aware Browser. Do remember that HTML Browser is not the only target client for a JSF application. It can even be a WML Browser for a mobile phone in which case they will be a need for a separate WML Renderer Kit. The HTML Tag Libraries can be classified as follows,
- input and output tags (text-field and text-area)
- Command tags (Buttons and Hyper-links)
- Selection tags (check-box, radio-button, drop-down box)
The input tags may represent the normal Text-Field or Text-Area to get the input data and it can even be a password text-field. The command tags represent the Actionable Tags like the click of the Button or the Hyperlink. Multiple inputs for a UI component can be represented by Check-Box and Radio-Button controls.
6) Configuration File
A JSF Configuration File is a XML File which can be used to configure the various components like the Managed Beans, Validators, Converters, Navigation Rules etc. A sample configuration file is given below,
<!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN" "http://java.sun.com/dtd/web-facesconfig_1_1.dtd"> <faces-config> <managed-bean> <managed-bean-name>testBean</managed-bean-name> <managed-bean-class>test.TestBean</managed-bean-class> </managed-bean> <navigation-rule> <description>Navigation for the test page.</description> <from-view-id>/test/test.jsp</from-view-id> <navigation-case> <from-outcome>test</from-outcome> <to-view-id>/test/response.jsp</to-view-id> </navigation-case> </navigation-rule> <validator> <validator-id>TestValidator</validator-id> <validator-class>test.TestValidator</validator-class> </validator> <converter> <converter-id>TestConverter</converter-id> <converter-class>test.TestConverter</converter-class> </converter> </faces-config>
7) Sample Application
Let us write a sample application called User Registration system. The system will provide a User Interface that will collect various values from the user such as name, username, password, birthday and phone-number.
7.1) JSF Configuration File
The following is the faces-config.xml file used in the sample application which will contain all the necessary configurations that are related to the declaration of managed beans, Custom Validators for validating the user inputs and a Simple Navigation Rule for Page Navigation.
<?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>UserBean</managed-bean-name> <managed-bean-class>user.registration.UserBean</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean> <navigation-rule> <description></description> <from-view-id>/UserRegistration.jsp</from-view-id> <navigation-case> <from-outcome>success</from-outcome> <to-view-id>/Success.jsp</to-view-id> </navigation-case> </navigation-rule> <validator> <validator-id>PhoneNumberValidator</validator-id> <validator-class> user.registration.validator.PhoneNumberValidator </validator-class> </validator> </faces-config>
7.2) Web.xml file
Following is the web.xml which has to be located in the WEB-INF directory of the application root. As we can see from the servlet-mapping element, whatever Request Uri’s which follows the pattern /faces/* will be directed to the FacesServlet available in the javax.faces.webapp package.
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" 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-app_2_5.xsd"> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/faces/*</url-pattern> </servlet-mapping> </web-app>
7.3) UserRegistration.jsp file
The UserRegistration.jsp page represents the user interface wherein which the user is allowed to enter the various inputs like name, username/password, and birthday and phone number. All the HTML UI Components have to be embedded with the <f:view> and the </f:view> tags. Text-Field, password field and the button object are represented by <h:inputText>, <h:inputSecret> and <h:commandButton> respectively. Every individual control has been assigned a unique identifier and all the input values for the components are made mandatory by setting the required attribute to ‘true’. The element is used to display an Error Message if the user didn’t provide any value for the field. The for attribute in the message element identifies for which element the error message has to be displayed.
The various input components are tied directly to the properties of the managed Java Bean called the UserBean. Since the birthday is a Date field, the string entered by the user is converted to a Date object with the help of the converter tag <f: convertDateTime>. Also a simple validation is provided for the phone number field with the help of the <f:validator> tag. The logical output of this page is ‘success’ which is represented by the action attribute of the ‘commandButton’ element. This value has to be used to define the from-outcome element that is present within the navigation-case element.
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %> <%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %> <html> <head> <title>User Registration</title> </head> <body> <h1>User Registration</h1> <f:view> <h:form> <p>Enter your name: <h:inputText value="#{UserBean.name}" id="nameTextField" required="true"/> <h:message for="nameTextField"/> <p>Choose a username: <h:inputText value="#{UserBean.userName}" id="userNameTextField" required="true"/> <h:message for="userNameTextField" /> <p>Enter the password: <h:inputSecret value="#{UserBean.password}" id="passwordTextField" required="true"/> <h:message for="passwordTextField" /> <p>Enter your birthday: <h:inputText value="#{UserBean.birthday}" id="birthdayTextField" required="true"> <f:convertDateTime pattern="MMM-dd-yyyy" /> </h:inputText> (MMM-dd-yyyy) <h:message for="birthdayTextField" /> <p>Enter your phone-number <h:inputText value="#{UserBean.phoneNumber}" id="phoneNumberTextField" required="true"> <f:validator validatorId="PhoneNumberValidator" /> </h:inputText> <h:message for="phoneNumberTextField"/> <h:commandButton value="Submit Values" action="success"/> </h:form> </f:view> </body> </html>
7.4) Success.jsp
This success.jsp is the response page for the ‘UserRegistration.jsp’ page. The page is just meant to display the values that are entered by the user along with a confirmation message telling that the user has been successfully registered. Displaying of message is done with the help of <h:outputText> tag.
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %> <%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %> <html> <head> <title>Registration Successful</title> </head> <body> <h2>Registration Successful</h2> <P> <f:view> <h:form> <P>The following information has been saved succesfully<P/> <P>Name: <h:outputText value = "#{UserBean.name}" /> <P/> <P>User Name: <h:outputText value = "#{UserBean.userName}"/> <P/> <P>Birthday: <h:outputText value = "#{UserBean.birthday}"/> <P/> <P>Phone Number: <h:outputText value = "#{UserBean.phoneNumber}"/> <P/> </h:form> </f:view> </body> </html>
7.5) UserBean.java
Following is the code for the UserBean class which is the managed Java Bean as being defined in by the managed-bean element in the faces-config.xml. This class is used to just hold the various input values with the properties and the behaviours according to the Java Bean Specification.
package user.registration; import java.util.Date; public class UserBean { private String name; private String userName; private String password; private Date birthday; private String phoneNumber; /** Creates a new instance of UserBean */ public UserBean() { } public String getName() { return name; } public void setName(String name) { this.name = name; } 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 Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getPhoneNumber() { return PhoneNumber; } public void setPhoneNumber(String PhoneNumber) { this.PhoneNumber = PhoneNumber; } }
7.6) PhoneNumberValidator.java
Validation for the input component phone-number Text-Field is taken care by this class. This class provides a Simple Validation Rule to check the validity of the phone number. It first checks whether the input entered by the user is a number by parsing the string object. If the parsing fails because the user has entered some character or invalid data, then a ValidationException is thrown. Then it just checks whether the number of digits is 10. If not, then also a ValidationException is thrown.
package user.registration.validator; import javax.faces.application.FacesMessage; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.validator.Validator; import javax.faces.validator.ValidatorException; public class PhoneNumberValidator implements Validator{ public PhoneNumberValidator() { } public void validate( FacesContext context, UIComponent component, Object value) throws ValidatorException { String strValue = (String)value; checkForNumbersOnly(strValue); if (strValue.length() != 10){ throwException("Number of phone digits must be 10"); } } private void checkForNumbersOnly(String strValue){ try{ long phoneNumber = Long.parseLong(strValue); }catch (Exception exception){ throwException("All Phone Digits must be of numbers only."); } } private void throwException(String errMessage){ FacesMessage message = new FacesMessage(); message.setDetail(errMessage); message.setSummary(errMessage); message.setSeverity(FacesMessage.SEVERITY_ERROR); throw new ValidatorException(message); } }
7.7) Running the Application
Following are the pre-requisite softwares needed to run the application.
- A web container like Tomcat(http://www.ip97.com/apache.org/tomcat/tomcat-6/v6.0.13/bin/apache-tomcat-6.0.13.zip)
- Java Development Kit(http://java.sun.com/javase/downloads/index_jdk5.jsp)
Create a directory called UserRegistration and copy all the JSP files (UserRegistration.jsp and success.jsp) into it. Next, create a directory within UserRegistration with name WEB-INF and then copy the web.xml and JSF Configuration file (faces-config.xml). Create a sub-directory called ‘classes’ under WEB-INF directory and copy all the class files (‘UserBean.class’ and ‘PhoneNumberValidator.class’) along with the directory structure. Make sure that ‘jsf-impl.jar’ is placed inside the lib directory which is inside the WEB-INF directory.
Javabeat has published many of the good articles related to Java Server Faces (JSF). This list will help you to learn the basic concepts on JSF and how to start using in your projects, please have a look on these articles when time permits. Don’t forget to leave your feedback on the comments section. This helps us to provide better content for you.
The above article would provide the higher level of understanding on each concept. If you would like to know all the features in detail, please buy any of the JSF books listed in the book recommendations for Java Server Faces (JSF). Hope this helps you!!
If you would like to receive future mails on Java articles, please subscribe here.