JSF : Basics

JavaServer Faces (JSF) is a Java-based web application framework intended to simplify development of web-based user interfaces. JavaServer Faces is a standardized display technology which was formalized in a specification through the Java Community Process. JSF facilitates Web application development by :

  • proving reusable UI components
  • making easy data transfer between UI components
  • managing UI state across multiple server requests
  • enabling implementation of custom components
  • wiring client side event to server side application code

In our example we will have registration web app. We will be buiding it step by step in this and following posts.

Make a ‘Dynamic web Project’ in Eclipse. Right click the project -> Configure – > Convert to Maven project

The project is now maven web project. Add dependencies in your pom.xml:


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>MyNotes_JSF</groupId>
 <artifactId>MyNotes_JSF</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>war</packaging>
 <dependencies>
 <dependency>
 <groupId>com.sun.faces</groupId>
 <artifactId>jsf-api</artifactId>
 <version>2.2.7</version>
 </dependency>
 <dependency>
 <groupId>com.sun.faces</groupId>
 <artifactId>jsf-impl</artifactId>
 <version>2.2.7</version>
 </dependency>
 <dependency>
 <groupId>javax.servlet.jsp</groupId>
 <artifactId>jsp-api</artifactId>
 <version>2.1</version>
 </dependency>
 <dependency>
 <groupId>javax.servlet</groupId>
 <artifactId>servlet-api</artifactId>
 <version>2.5</version>
 </dependency>
 <dependency>
 <groupId>javax.servlet</groupId>
 <artifactId>jstl</artifactId>
 <version>1.2</version>
 </dependency>
 </dependencies>
</project>

Maven will add these jars for you. Notice 2 specific jars – jsf-api and jsf-impl. 

The jsf-api-xxx.jar contains classes that are under packages java package javax.faces. The classes in this jar are implementation of standard API defined by JSF specification. The jsf-impl-xxx.jar contains classes that are under java package com.sun.faces, which as the java package indicates, is Sun’s own class for JSF implementation. If you want a different implementation , then use that impl jar. The javax.faces-xxx.jar actually merges the previous two jar files together. So what should you use for your development? Ideally, your own application does not  need to depend on any classes under com.sun.faces package to achieve the portability to other JSF implementations. If you are using an application such as GlassFish, the container should already provide the JSF implementation at runtime ( maven scope – provided). You should not package the above JSF jar files with your war or ear file, as server will provide all of them. If you use a container that does not come with a JSF implementation by default such as Tomcat, you need to package javax.faces-xxx.jar or (jsf-api-xxx.jar + jsf-impl-xxx.jar) in the WEB-INF/lib.

Our final project structure will be:

jsf_basic_projectStructure

Lets create manage bean for our form. Managed Bean is a regular Java Bean class registered with JSF. The managed bean contains the getter and setter methods, business logic. Managed beans works as Model for UI component and can be accessed fron jsf pages. From JSF 2.0 onwards, Managed beans can be easily registered using annotations.


package mynotes.jsf.bean;

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

@ManagedBean(name="registrationForm", eager=true)
@SessionScoped

public class RegistrationForm {
 
 private String name;
 private String email;
 public String getName() {
 return name;
 }
 public void setName(String name) {
 this.name = name;
 }
 public String getEmail() {
 return email;
 }
 public void setEmail(String email) {
 this.email = email;
 }

}


@ManagedBean marks a bean to be a managed bean with the name specified in name attribute. If the name attribute is not specified, then the managed bean name will default to class name. Another important attribute is eager. If eager=”true” then managed bean is created before it is requested for the first time otherwise “lazy” initialization is used in which bean will be created only when it is requested.

Scope annotations set the scope into which the managed bean will be placed. If scope is not specified then bean will default to request scope. Each scope is briefly discussed below

Scope Description
@RequestScoped Bean lives as long as the HTTP request-response lives. It get created upon a HTTP request and get destroyed when the HTTP response associated with the HTTP request is finished.
@NoneScoped Bean lives as long as a single EL evaluation. It get created upon an EL evaluation and get destroyed immediately after the EL evaluation.
@ViewScoped Bean lives as long as user is interacting with the same JSF view in the browser window/tab. It get created upon a HTTP request and get destroyed once user postback to a different view.
@SessionScoped Bean lives as long as the HTTP session lives. It get created upon the first HTTP request involving this bean in the session and get destroyed when the HTTP session is invalidated.
@ApplicationScoped Bean lives as long as the web application lives. It get created upon the first HTTP request involving this bean in the application (or when the web application starts up and the eager=true attribute is set in @ManagedBean) and get destroyed when the web application shuts down.
@CustomScoped Bean lives as long as the bean’s entry in the custom Map which is created for this scope lives.

Lets create another managed bean to handle form action (button clicks etc.). Though this cann be written in previous bean also, nut its a good practice to have different form and action classes. Also you need to map your form class to this action class. RegistrationAction.java


package mynotes.jsf.actionBean;

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

import mynotes.jsf.bean.RegistrationForm;

@ManagedBean
public class RegistrationAction {
 
 @ManagedProperty(value="#{registrationForm}")
 RegistrationForm myRegistrationForm;
 
 public String register(){
 System.out.println("Inside register"); 
 System.out.println("Name=>"+myRegistrationForm.getName());
 System.out.println("Email=>"+myRegistrationForm.getEmail());
 return "registrationSuccess";
 }

public RegistrationForm getMyRegistrationForm() {
 return myRegistrationForm;
 }

public void setMyRegistrationForm(RegistrationForm myRegistrationForm) {
 this.myRegistrationForm = myRegistrationForm;
 }

}


JSF is a simple static Dependency Injection(DI) framework.Using @ManagedProperty annotation a managed bean’s property can be injected in another managed bean. Must have getters and setters. register() is the method that will be called from button.

In JSF 1.2,a managed bean had to register it in JSF configuration file such as faces-config.xml. Initialization of one bean in another was also done here. For ex.


<managed-bean>
 <managed-bean-name>registrationForm</managed-bean-name>
 <managed-bean-class>mynotes.jsf.bean.RegistrationForm</managed-bean-class>
 <managed-bean-scope>session</managed-bean-scope>
 </managed-bean>

Lets create 2 views. registration.xhtml


<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Registration</title>
</head>
<h:body>
<h3>Registration Page</h3>
<h:form>
<h:outputLabel for="id" value="Name: "></h:outputLabel>
<h:inputText value="#{registrationForm.name}" id="name"></h:inputText>
<h:outputLabel for="email" value="Email: "></h:outputLabel>
<h:inputText value="#{registrationForm.email}" id="email"></h:inputText>
<h:commandButton value="Register" action="#{registrationAction.register}"></h:commandButton>
</h:form>
</h:body>
</html>

Notice the tag lib for jsf here. The text field are mapped to ‘registrationForm’ bean and the submit method is mapped to ‘registrationAction’ bean register() method.
Make a success page – registrationSuccess.xhtml


<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Registration Success</title>
</head>
<body>
<h4>Registration Success</h4>
</body>
</html>

web.xml:


<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>MyNotes_JSF</display-name>
<!-- JSF mapping -->
<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>/</url-pattern>
</servlet-mapping>

</web-app>

jsf_basic_registration

jsf_basic_registrationSuccess

Navigation rules are those rules provided by JSF Framework which describe which view is to be shown when a button or link is clicked. JSF 2.0 provides auto view page resolver mechanism named “implicit navigation”. In this case you only need to put view name in action attribute and JSF will search the correct view page automatically in the deployed application. Thats why your action method must return a string. Also, you can hardcode the string in the action attribute in view also.

In JSF 1.2, all the page navigation are required to declare in the “faces-config.xml” file like this :

<pre class="xml"><navigation-rule>
   <from-view-id>page1.xhtml</from-view-id>
   <navigation-case>
       <from-outcome>page2</from-outcome>
       <to-view-id>/page2.xhtml</to-view-id>
   </navigation-case>
</navigation-rule></pre>

To solve the complex page navigation flow you should still use above type called Conditional Navigation Rule in faces-config.

As said previousle, JSF is a Component based MVC. Many MVC frameworks (such as Struts, Spring MVC in Java world, Asp.Net MVC) are Request-based.
In request (action) based MVC, a single front controller servlet will delegate to action models based on request URL/params. You works directly with raw HttpServletRequest and HttpServletResponse objects in the action model. You’ve to write code yourself to gather, convert and validate the request parameters and if necessary update the model values before you can ever invoke the business action.
In component based MVC, a single front controller will gather, convert and validate request parameters and update the model values itself so that you only need to worry about the business action yourself. How the controller needs to gather/convert/validate/update the values is definied in a single place, the view. Since that’s not possible with “plain” HTML, a specific markup language is required to achieve the goal. In case of JSF 2.0, that’s XML (XHTML) based. You use XML to define UI components which in turn contain information about how the controller should gather/convert/validate/update the values and itself generate the necessary HTML representation.
With a request based MVC framework you need to write more code yourself to achieve the goal. However you end up with much more fine grained control over the process and the HTML/CSS/JS output. With a component based MVC framework you don’t need to write much code yourself. However you have less fine grained control over the process and the HTML/CSS/JS output. So if you’d like to do things a bit differently than the standard describes, you’ll waste a lot more time in a component based MVC framework.

JSF versions

  • JSF 2.2 (2013-05-21) — Introduced new concepts like stateless views, page flow and the ability to create portable resource contracts.
  • JSF 2.1 (2010-11-22) — Maintenance release 2 of JSF 2.0. Only very minor amount of spec changes.
  • JSF 2.0 (2009-07-01) — Major release for ease of use, enhanced functionality, and performance. Coincides with Java EE 6.
  • JSF 1.2 (2006-05-11) — Many improvements to core systems and APIs. Coincides with Java EE 5. Initial adoption into Java EE.
  • JSF 1.1 (2004-05-27) — Bug fix release. No specification changes.
  • JSF 1.0 (2004-03-11) — Initial specification released.
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: