Tuesday, May 08, 2007

JavaServer Faces Part 1 - Introduction

This is first in the series of blogs on JSF.

JSF = JavaServer Faces.

It’s a web framework. The 3 independent elements that make up a usable JSF component in a page are:

  1. UIComponent class – defines behavior of component. Eg. UISelectOne
  2. Renderer class – provides specific renderings of component. For eg, a UISelectOne can be rendered in HTML as either a group of radio buttons or a select menu.
  3. A JSP tag – which associates a Renderer with a UIComponent and makes them usable in JSP as a single tag, eg <h:selectOneMenu>

JSF UI components are bound to server-side Java beans (which are registered as Managed Beans in faces-config.xml). In the JSP pages, the UI components are bound to Managed Beans using the JSF Expression Language (which in JSF 1.2 is same as JSTL 2.1’s EL and is now called Unified EL). Once bound, updating bean properties or invoking bean methods from a web interface is handled automatically by JSF request processing lifecycle. This ability to automatically synchronize server-side Java Bean properties to a hierarchical set of components that are based on UI presented to the client user is a major advantage of JSF over other web frameworks like Struts.

JSF Request Processing Lifecycle

  1. When a JSP page with JSF components is requested first time, then JSF runtime creates an in-memory components tree on server side.
  2. In between requests, when nothing is happening in application, the component tree is cached on server.
  3. Upon a subsequent request, the component tree is reconstituted, and if form input values are sent in request, they are processed and validations are executed.
  4. Upon successful validation, server-side managed bean properties are updated.
  5. Once all event processing and updates are over, the response is sent to client.

To enable JSF support in a Java EE web application, following needs to be done:

  1. An entry for Faces Servlet in web.xml and mapping of this servlet to *.faces or /faces/* etc. (A request that uses the appropriate faces URL pattern can be considered a faces request and when received by faces controller, it processes the request by preparing an object known as the JSF context, which contains all accessible application data and routes the client to appropriate view page based on the navigation rules as defined in the faces-config.xml.)
  2. A JSF configuration file – faces-config.xml in WEB-INF/ path.
  3. Following jar files in WEB-INF/lib path:
    1. JSF jars – jsf-api.jar and jsf-impl.jar
    2. Apache commons jars – commons-beanutils.jar, commons-collection.jar, commons-digester.jar, and commons-logging.jar.
    3. JSTL jars – standard.jar and jstl.jar

For a JSP page to be JSF enabled,

  • we need to include at least the following taglibs from Sun’s JSF RI (you may also use Apache MyFaces implementation of JSF spec):
   1: <%@taglib uri=”http://java.sun.com/jsf/core” prefix=”f”%>
   2: <%@taglib uri=”http://java.sun.com/jsf/html” prefix=”h”%>

  • In the JSP page body, we must add <f:view> tag which becomes the base UI component of component tree in memory on server side when the page is requested for viewing.

  • If page processes form input, then we can add <h:form> tag.

Example code:

inputname.jsp – shows a form to user to enter name

If outcome is “greeting” then show greeting.jsp to user

The input name between the two pages is stored in memory in PersonBean’s personName field. The personName is registered as managed bean and JSF’s EL is used in the JSP pages to access the PersonBean’s personName field values.

   1: inputname.jsp:
   3: <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
   4: <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
   5: <f:loadBundle basename="jsfks.bundle.messages" var="msg"/>
   7: <html>
   8:  <head>
   9:   <title>enter your name page</title>
  10:  </head>
  11:  <body>
  12:    <f:view>
  13:      <h1>
  14:       <h:outputText value="#{msg.inputname_header}"/>
  15:      </h1>
  16:      <h:form id="helloForm">
  17:       <h:outputText value="#{msg.prompt}"/>
  18:       <h:inputText value="#{personBean.personName}" />
  19:       <h:commandButton action="greeting" value="#{msg.button_text}" />
  20:      </h:form>
  21:    </f:view>
  22:  </body>
  23: </html>

Where, message bundle is defined in a message.properties file (which needs to be put in WEB-INF/classes path in your web applications WAR) as,


   1: inputname_header=JSF KickStart
   2: prompt=Tell us your name:
   3: greeting_text=Welcome to JSF
   4: button_text=Say Hello
   5: sign=!

We bind a PersonBean to the inputText filed in helloForm. To do so we also need to register the PersonBean as managed bean in faces-config.xml. We also need to define the navigation rule from :

   1: <?xml version="1.0"?>
   2: <!DOCTYPE faces-config PUBLIC
   3:   "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN"
   4:   "http://java.sun.com/dtd/web-facesconfig_1_1.dtd">
   6: <faces-config>
   7:   <navigation-rule>
   8:    <from-view-id>/pages/inputname.jsp</from-view-id>
   9:     <navigation-case>
  10:      <from-outcome>greeting</from-outcome>
  11:      <to-view-id>/pages/greeting.jsp</to-view-id>
  12:    </navigation-case>
  13:   </navigation-rule>
  15:   <managed-bean>
  16:     <managed-bean-name>personBean</managed-bean-name>
  17:     <managed-bean-class>jsfks.PersonBean</managed-bean-class>
  18:     <managed-bean-scope>request</managed-bean-scope>
  19:   </managed-bean>
  20: </faces-config>

And here’s what the greeting.jsp is:

   1: <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
   2: <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
   3: <f:loadBundle basename="jsfks.bundle.messages" var="msg"/>
   5: <html>
   6:   <head>
   7:    <title>greeting page</title>
   8:   </head>    
   9:   <body>
  10:      <f:view>
  11:          <h3>
  12:       <h:outputText value="#{msg.greeting_text}" />,
  13:       <h:outputText value="#{personBean.personName}" />
  14:          <h:outputText value="#{msg.sign}" />
  15:         </h3>
  16:      </f:view>
  17:  </body>    
  18: </html>

And the managed bean PersonBean.java:

   1: package jsfks;
   3: public class PersonBean {
   5:    String personName;
   7:    /**
   8:    * @return Person Name
   9:    */
  10:    public String getPersonName() {
  11:       return personName;
  12:    }
  14:    /**
  15:    * @param Person Name
  16:    */
  17:    public void setPersonName(String name) {
  18:       personName = name;
  19:    }
  20: }

This completes the short introduction to JSF 1.1.

No comments: