It is obvious that most of us question why we go for JavaServer Faces when a similar MVC framework, which is most popular, exists? The answer is simple. Try before commit. Use the framework, discover the benefits and then decide which is best suites your need.
JavaServer Faces is view-centric which is best suited in applications where rich GUI required. But that doesn't mean it is not suitable for the flow-based applications, where Struts is majorly being used. It can be ported on such applications as well without doing heavy work.
Below are some comparisions between both the MVC frameworks.
Standard
JavaServer Faces follows the JCP specification standard where as Struts is being developed under Apache Community.
Customization
JavaServer Faces specification provides the standards needs to be followed in implementing the specification. Any vendor can provide their own implementation which follows the JSR specification of JSF. Few vendors are actively involved in implementing the JSF framework. Oracle ADF Faces, ICEFaces, jBoss Rich Faces, Apache MyFaces are few implementations of the JSF specification. Since all vendors follow the same standard, any vendor can develop the components that can easily pluggable into the JSF applications.
Controller
The controller logic of JavaServer Faces is implemented in POJOs and hense no need to implement any specific implementations required. In struts the controller logic can be written in processAction and execute method. The controller logic is simplified by directly providing the method to be called from the JSF page. This can be achieved by using the Unified Expression Language (EL).
Rich UI Components for the View Tier
The JSF implementations provides easy to use and easily pluggable rich UI components. By using the rich UI component model the view tier of the web application will be enhanced. Also the component model can be easily extended from the standard set of components.
Event Driven
The JSF framework is event driven and the component framework is fully sensitive to the events generated from the client tier. Using this we can easily handle the events generated from the client side and can provide extended features to the web applications.
Six phases in the life cycle of a JSF application
- Restore View Phase
- Apply Request Values Phase and Process Events
- Process Validations Phase and Process Events
- Update Model Values Phase and Process Events
- Invoke Application Phase and Process Events
- Render Response Phase
Figure: JavaServer Faces Standard Request-Response Life Cycle
The life cycle of a JSF requests starts when the user invokes any action on the JSF page. The action could be a standard event like clicking on the button or changing the value of a text box etc. When the request is submitted to the server, the Faces Servlet gets the handle and starts processing the request.
Restore View Phase
When an event, like button click, happens the JavaServer Faces implementations starts the life cycle with the first phase i.e. the Restore View Phase. In this phase, it builds the view, attach the validators, converters and event handlers and stores in the FacesContext instance. FacesContext will have access to all these components and the information to process the request.
The UIView component forms the root of the view tree and all other components like Text Boxes, Command Button etc (UIInput), the form (UIForm) will be under the root as childs. While restoring the view, the implementation builds the exact tree, starting with the root, and attach all the validators etc., to the corresponding components in the tree.
Apply Request Values Phase
- During this phase the request values of the components will be extracted by calling the decode method of the components and the new values retrieved will be stored locally to process further validations and conventions, if any. If the conversion of the new value fails, the error message will be queued in the FacesContext instance.
- If any events attached to any component, the corresponding event listener will get invoked during this phase. If the immediate flag set on any particular component, the associated event listener, validations and conversions will get executed during this phase itself. If any validation or conversion failed during the phase, the corresponding message will be queued in the FacesContext instance and the message will gets displayed during the Render Response phase.
- If the renderResponse method called on the current FacesContext instance during this phase, the implementation skips to the Render Response phase. This will be helpful in situations like when you want to skip executing the business logic when the data entered is invalid etc.
Process Validations Phase
- In this phase all validations attached to the components will get executed. Error messages for all failed validations will gets queued in the FacesContext instance and will get displayed during the Render Response phase.
- Any events that are queued for this phase will be processed and the corresponding event listener gets invoked. Similar to the Apply Request Values Phase, if any method during this phase (like validate, event handler methods) call the renderResponse method on the FacesContext instance, the executions will skips to the Render Response phase. This is true with the next phase as well.
- If you want to skip the current execution during any phase and render a different page (no jsf page) on a different web application, you can simply call the responseComplete method on the FaceContext instance.
Update Model Values Phase
- If the execution of the applications successfully completes the third phase means that the request data is valid and can be assigned to the model. So the data will be applied to the model and if any conversion fails, the application will skips to Render Response phase.
- Again, if any updateModes method or event listener method calls the renderResponse method, the executions skips to the last phase. Also any events registered will be broadcasted to the corresponding event listeners.
Invoke Application Phase
- This is the phase where you execute the actual business logic. The JavaServer Faces controller will invoke the application to to handle the form submissions. The component values validated, converted and applied to the model and you can use the model in your business logic.
- You can specify the next view to be rendered in this phase by returning the corresponding view mapping. See the navigation rules declaration in faces-config.xml file.
Render Response Phase
- This is the last phase of the JSF page execution life cycle. In this phase the result view will be rendered with the generated components and their corresponding values existing with the model.
Pre-Requisites
-
J2SE 1.4 or higher (Depending on the version used)
-
Servlet 2.x
-
JSP 2.x
Refer your web-server documentation for the JSP and Servlet API version information.
Libraries
The Sun JSF implementation comes with two libraries one for API and other for Implementation. Just drop the libraries into the WEB-INF\lib folder of your web application.
Configuration Files
Create the faces-config.xml configuration file and configure it in the web.xml file. Below is the sample configuration of web.xml to plugin the JSF implementation.
<listener><listener-class>com.sun.faces.config.ConfigureListener</listener-class></listener><context-param><param-name>javax.faces.CONFIG_FILES</param-name><param-value>/WEB-INF/faces-config.xml</param-value></context-param><servlet><servlet-name>Faces Servlet</servlet-name><servlet-class>javax.faces.webapp.FacesServlet</servlet-class><load-on-startup>0</load-on-startup></servlet><servlet-mapping><servlet-name>Faces Servlet</servlet-name><url-pattern>*.jsf</url-pattern></servlet-mapping>
Create properties files
Create the properties files and define the locale based messages. You can use the messages defined in the properties files directly in the JSF pages with simple declaration in the faces-config.xml file. Below is the sample declaration of the properties file.
<application><resource-bundle><base-name>com.yourcompany.app.resources.messages</base-name><var>msg</var></resource-bundle></application>
Create JSF Pages
Write the jsp pages which will present the results of the web application. Use the tag libraries provided by the JSF implementation to design rich UI. Use the expression language of JSF (EL) to put the power of JSF into your application.
Below is the way of including the tag libraries in to your JSP page.
<%@taglib uri="http://java.sun.com/jsf/core" prefix="f" %><%@taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
Create Managed-Beans
Managed Beans, also called as backing-beans, are standard Java POJO bean whose methods and properties are available to the JSF pages using the JSF Unified Expression Language(EL). Using managed beans, which are generally used as controllers in JSF, you can easily manage the communication between client and server. All the public methods and properties (using standard getter and setter methods) can be accessible using the EL in JSF pages.
Define the managed beans that are required for the controller logic of your application. And configure the beans in the faces-config.xml file. Below is the sample configuration of the managed beans.
<managed-bean><managed-bean-name>BeanName</managed-bean-name><managed-bean-class>com.yourcompany.yourapp.beanpackage.BeanName</managed-bean-class><managed-bean-scope>request</managed-bean-scope></managed-bean>
Define Navigation Rules
Navigation rules tells the container to choose the specified page. The controller, i.e. the backing bean will return the name of the navigation rule which specifies the page to be rendered. This can be achieved by making the managed bean operation return the string containing the name of the navigation rule and the navigation rule with that name is defined in the faces-config.xml file. Here is the sample configuration.
<navigation-rule><navigation-case><from-outcome>NavigationRuleName</from-outcome><to-view-id>/path/pageName.jsf</to-view-id></navigation-case></navigation-rule>
John has written the following program which prints the below message.
"I am developer 1
You are developer 2"
requirements has changed and he has to print the below message.
"I am developer 2
You are developer 1"
The specifications/rules are given as below:
1) The solution should be done with minimal changes
2) No modifications are allowed to the Main, Developer1 and Developer2 classes
Try if you can do it. Else watch this space for the answer soon...
"I am developer 1
You are developer 2"
public class Main {
public static void main(String[] args){
System.out.println("I am --> "+Programmers.Developer1.getMyName());
System.out.println("You are --> "+Programmers.Developer2.getMyName());
}
}
class Programmers{
static class Developer1{
static String getMyName(){
return "Developer 1";
}
}
static class Developer2{
static String getMyName(){
return "Developer 2";
}
}
}
requirements has changed and he has to print the below message.
"I am developer 2
You are developer 1"
The specifications/rules are given as below:
1) The solution should be done with minimal changes
2) No modifications are allowed to the Main, Developer1 and Developer2 classes
Try if you can do it. Else watch this space for the answer soon...