Skip to main content

Developing applications with Facelets, JSF, and JSP

August 29, 2006

{cs.r.title}







JavaServer Faces (JSF) along with Facelets and JavaServer Pages (JSP) 2.0+ promotes a new way of Java web programming. This article introduces a rich list of useful tips to help developers smoothly transition from the old-fashioned JSP/servlet programming to the new JSF-style programming. It clarifies the issues and confusion developers may encounter, and promotes best practices and methodologies to simplify web development, improve code reuse, and make source code more designer-friendly, as well as easy-to-maintain.

JSF, an Innovative Style of Java Web Programming

JavaServer Faces (JSF) is a server-side user interface component framework for Java-based web applications. As a standard web development technology, JSF 1.2 is encapsulated as part of the latest Java EE 5 specification. JSF promotes a component-based, event-driven UI development methodology, independent from any mark-up language, protocol, or client device. Inspired by MVC frameworks like Struts, the JSF API has built-in support for internationalization, localization, data type conversion, and validation. Developing scriptlet-free web pages becomes possible in collaboration with JSTL tags. Recently, AJAX-JSF UI components have gained a lot of attention in Java communities, because they deliver a rich user experience similar to desktop applications and can be used off-the-shelf without requiring deep knowledge of remote scripting in JavaScript. As a view-tier MVC solution, JSF with dependency injection and pluggable APIs can be easily integrated with business-tier technologies like Spring, JBoss Seam, and EJB 3.0. Evidently, the JSF community endeavors to interface JSF with a variety of exciting new technologies. To benefit fully from the great features that JSF and JSP 2.0+ offer, developers must give up their stale JSP/servlet programming style and migrate to the new world of JSF. The following sections are presented to facilitate this process.

Write JSP Pages as Strict XML Documents

A JSP document is a JSP page written in XML syntax, which is more readable, flexible, and maintainable than the old JSP syntax. For a protocol-independent JSP document, you need to declare <jsp:root> as the root element in conjunction with the xml namespaces for JSP tags, JSTL tags, JSF tags, and custom tags if there are any:

<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" 
    xmlns:ui="http://java.sun.com/jsf/facelets" 
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:c="http://java.sun.com/jstl/core"
    xmlns:fn="http://java.sun.com/jsp/jstl/functions"
    xmlns:t="http://myfaces.apache.org/tomahawk"
    xmlns:bp="http://java.sun.com/blueprints/ui/14"
    version="2.0">

Because the <jsp:root> isn't rendered into any element in the output, you need to add an authentic root element like <html>, or <wml> inside the document. Another choice introduced since JSP 2.0 is to make JSP pages strict XHTML documents:

<html xmlns="http://www.w3.org/1999/xhtml"  
    xmlns:jsp="http://java.sun.com/JSP/Page"
    xmlns:ui="http://java.sun.com/jsf/facelets" 
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:c="http://java.sun.com/jstl/core"
    xmlns:fn="http://java.sun.com/jsp/jstl/functions"
    xmlns:t="http://myfaces.apache.org/tomahawk"
    xmlns:bp="http://java.sun.com/blueprints/ui/14">

This approach makes HTML designers happy, as they can read and edit the code through their visual editor tools. It is even possible for web developers and HTML designers to work concurrently on the same source base using version management systems like CVS and Subversion.

Handle Image References in CSS and JavaScript Files and Avoid Hard-coded Context Paths

A context path in URLs uniquely identifies a web application in a shared web server environment. From a maintenance standpoint, developers should avoid hard-coded context paths in any URL in JSP source, CSS, and JavaScript files. Like Struts, JSF UI component tags have built-in URL-rewriting capability, which automatically appends the runtime value of the context path as well as a session ID (if cookies are disabled) to any relative URL as tag attributes. Meanwhile, for URLs referenced in ordinary HTML tags, like anchor points and image tags, a good approach to remove hard-coded context paths is to append the following tag in front of the relative URLs: <c:out value="${pageContext.request.contextPath}"/>, or to apply the JSTL <c:url> tag for URL-rewriting. Similarly, hard-coded context paths in CSS and JavaScript files should be eliminated to reduce coupling. The usual approach is to change your CSS and JavaScript files into JSP pages, so that you can apply the same tricks. Here is a sample CSS JSP document:

<?xml version="1.0" encoding="UTF-8"?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
    xmlns:c="http://java.sun.com/jsp/jstl/core"
    xmlns:fmt="http://java.sun.com/jsp/jstl/fmt"
    version="2.0">
       
    <jsp:directive.page session="false"
        contentType="text/css;charset=UTF-8"/>

    .alertBox {background: #FFE0C1
        url(<c:url value="/images/icon_warning.gif"/>)
        no-repeat 5px 5px;}

</jsp:root>

For JavaScript files, the value of the contentType attribute in the page directive needs to be set as "text/javascript;charset=UTF-8".

Tag Files

A new feature introduced in JSP 2.0 is tag files. A tag file is a JSP fragment that is reusable as a custom tag. Tag files allow developers to create custom tags using JSP syntax without writing any tag handler class. Tag files have many advantages:

  • They follow JSP syntax, which is easy to write and maintain.
  • They promote high productivity and rapid development.
  • They can be used to refactor existing pages.
  • They can reference other custom tags in their bodies.
  • Common screen areas can be consolidated into tag files that are shared between application views.

Tag files are preferred over the conventional tag handlers, although the former won't completely replace the latter.

Choose between HTML Tags and JSF Tags, Avoid Over-engineering JSP Pages

JSF offers a set of standard HTML component tags, which are normally rendered as HMTL tags at runtime by the JSF implementation. JSF HTML tags cover the most useful HTML tags with a big benefit: they prevent developers from using the old, deprecated HTML style attributes. Developers build web pages by replacing static HTML content in mockups with JSF tags, which display the dynamic content on a web site. The question is what level of reengineering is necessary for the HTML mockups. Should you replace a static HTML <img> tag with the JSF <h:graphicImage>? The protocol-independent nature of the JSF API suggests that the same JSF UI component tag may be rendered differently into an HTML tag(s) or a WML tag(s) depending on the renderkit configured. You may be attracted to this feature initially but the decision to replace all HTML tags with JSF tags in the first JSF project resulted in extra coding work. It didn't take us long to realize that it is nearly impossible to make the same JSF page serve different types of clients, due to the discrepancies in requirements and hardware specifications, such as screen size. In reality, the client type is always determined in the first place before a project is even launched. Moreover, over-engineering JSP pages makes them no longer readable to HTML designers. To keep it productive and designer-friendly, web developers should leave as many HTML tags in JSP pages as possible.

Internationalization, Localization, and Beyond

JSF has rich support for internationalization (I18N) and localization (L10N). To develop a completely internationalized web site, all literals including labels, date fields, number fields, text fields, error messages, as well as texts displayed as images must be externalized from web pages to .properties files. The JSF runtime determines the locale of a user based on that user's browser's setup. Web applications may sometimes dictate the locale for a user. The JSF runtime uses ResourceBundle to load text messages from the locale-affiliated .properties files and displays them on the screen. As a reminder, over-engineering a web site not meant for internationalization is a waste of resources. In fact, ResourceBundle helps developers in many aspects beyond I18N/L10N. A good practice to reduce coupling of remote URLs is to place the base URL in a .properties file:

remotestorage.httpsever.uri
    =http://test.httpserver.com
#remotestorage.httpsever.uri
    =https://production.httpserver.com

Inside a JSP page:

<h:graphicImage id="companyLogo"
    alt="my company"
    url="#{bundle['remotestorage.httpsever.uri']}
        /common/images/companyLogo.gif"/>

You may also declare UTF special characters in a .properties file to avoid the hassle of escaping them in JSP pages:

text.specialchar.copyright=\u00A9
text.specialchar.checkmark=\u2713
text.specialchar.numbersign=\u0023
text.specialchar.nbsp=&nbsp;
text.specialchar.amp=&

Build Scriplet-free Web Pages with JSTL Tags

Scriptlets (embedded Java code in JSP) are considered to be hazardous from a maintenance standpoint. Especially in JSF development, they should be dumped. The JSP 2.0 specification allows developers to explicitly ban the use of scriptlets by making the following declaration in web.xml:

<jsp-config>
    <jsp-property-group>
        <url-pattern>*.jsp</url-pattern>
        <scripting-invalid>true</scripting-invalid>
        <is-xml>true</is-xml>
    </jsp-property-group>        
</jsp-config>

The JavaServer Pages Standard Tag Library (JSTL) was introduced to help developers build scriplet-free web pages. The JSTL core contains a list of logic tags for manipulating testing and iteration logic, among which the most frequently used are <c:forEach> and <c:if>. The expression language defined in JSTL makes it really powerful. On the other hand, JSF as a higher-level UI component API defines its own expression language, which doesn't align well with the JSTL expression language. As an example, JSTL tags can't reference JSF backing beans directly but have to go through the four scope objects. Therefore, the following code doesn't work!

<c:forEach var="orderItem" 
    items="#{orderBackingBean.orderItems}">

The article Getting around JSF: The role of JSP has a deep discussion on how to make JSP, JSTL, and JSF tags work collaboratively. Another approach not mentioned in the article is to declare normal JavaBeans through the <referenced-bean> tag in face-config.xml file, and have referenced JavaBeans and JSF-managed beans wiring their properties through dependency injection.

<referenced-bean>
    <description>A JSP scoped Java Bean</description>
    <referenced-bean-name>nameJavaBean
    </referenced-bean-name>
    <referenced-bean-class>servlet.NameJavaBean
    </referenced-bean-class>
</referenced-bean>

<managed-bean>
    <managed-bean-name>personBackingBean
    </managed-bean-name>
    <managed-bean-class>jsf.PersonBackingBean
    </managed-bean-class>
    <managed-bean-scope>session</managed-bean-scope>
    <managed-property>
        <description>Java Bean Reference</description>
        <property-name>personName</property-name>
        <value>#{nameJavaBean}</value>
    </managed-property>
</managed-bean>

Consequently, developing web pages in JSF is not very efficient because of the clumsy and verbose alignment code. The Unified Expression Language available only on JSP 2.1-compliant web severs will save you from this inconvenience.

Unified Expression Language: Distinguishing between ${} and #{} Syntaxes

As a primary new feature in JSP 2.1, the Unified Expression Language is a union between the expression language (EL) used by JSTL tags and the expression language defined in JSF. Due to the different lifecycles between JSP and JSF components, expressions to be evaluated immediately use the ${} syntax, which was introduced with the JSP expression language, while expressions whose evaluation is deferred use the #{} syntax, which was introduced by JSF technology. With deferred expressions, JSTL tags can now access JSF backing beans just like JSF tags do:

<c:forEach var="orderItem" 
    items="#{orderBackingBean.orderItems}">
    <tr>
        <td>#{orderItem.id}</td>
        <td>#{orderItem.name}</td>
        <td>#{orderItem.count}</td>
    </tr>
</c:forEach>

From the example above, you notice a nice feature of the Unified Expression Language; it may be used everywhere in JSP pages, and is no longer limited to being used only inside tags as attribute values. Without this, developers have to use JSTL or JSF tags like <c:out> or <h:outputText> to output any dynamic values on the server. Immediate expressions give developers access to normal JavaBeans and the implicit variables, which are also available through deferred expressions. Therefore, it is safe and simple to stick with deferred expressions in JSF applications. Bear in mind that the dominant web servers in the market like Tomcat still conform to the JSP 2.0 specification without the Unified Expression Language feature, and that is where Facelets comes into play.

Facelets Makes JSF Easier

Facelets is a lightweight, Tapestry-like web framework backed by JSF technology. It solves all the ugliness of using JSF with JSP 2.0. The first and the most important thing is that it makes the future JSP 2.1 features, especially the Unified Expression Language, available on any JSP 2.0 platform. An immediate benefit is the significant reduction on JSP page size after the removal of the alignment code between JSF and JSP. Facelets makes JSP pages more designer friendly through a Tapestry-style attribute "jsfc," which enables you to declare JSF UI components as ordinary HTML tags:

<input type="text" jsfc="h:inputText" id="lastName" 
    value="#{personBackingBean.personName.lastName}"/>                  
<input type="submit" jsfc="h:commandButton"
    id="submit" action="success" value="Submit"/>

A designer's visual editor will render the above tags as a normal HTML form input text and a button, but they will be translated into JSF UI components just like JSF tags, after being compiled by Facelets. Facelets offers a templating solution, namely composition components, that works in a similar way as tiles. Without Facelets, JSP source code has never been so concise, readable, and designer friendly. More important, Facelets as a portable solution works with both JSF 1.1 and JSF 1.2, including Sun's reference implementation (RI) and Apache MyFaces.

Choosing between MyFaces and Reference Implementation

Sun's RI essentially guarantees the JSF source code will be completely portable across different JSF implementations. If developers choose to use MyFaces' Tomahawk UI components, the portability has to be sacrificed. Anyway, it is not a significant drawback, as the MyFaces runtime can be deployed as part of a web application on almost any popular web server.

The extended rich list of validators and custom UI components in Tomahawk may potentially simplify page development. Especially when an application has UI component-level security requirements, the Tomahawk UI components with the extended user-role awareness feature are really handy. The two extra attributes on UI component tags, visibleOnUserRole and enableOnUserRole, make the UI components displayed or enabled for certain security configurations. In addition, the extra forceId attribute makes the client-side component IDs more JavaScript friendly; as you know, JSF by default appends the ID of a naming container like <h:form id="myForm"> to the IDs of all enclosed UI components. For example, when you name the ID of an input text field "lastName," it ends up with id="myForm:lastName" in the HTML output. MyFaces also has the tiles framework integrated as an optional page templating solution.

Develop Web Pages without HTML Mockups

Under certain circumstances, web developers are required to build web screens without assistance from HTML designers. This can be accomplished with Oracle ADF Faces Components, which ensure a consistent look and feel for the application, and allow developers to focus more on user interface interaction and backend functions rather than look and feel compliance. The ADF components support multi-language and translation implementation as well as accessibility features. More important, the ADF components are portable across multiple JSF implementations like Sun's RI and Apache's MyFaces. This rich set of UI components essentially enables Java developers to build web pages in a consistent and professional look and feel from scratch without HTML mockups.

Integrate Facelets, JSF, and the Spring Framework

The Spring framework is a lightweight application container built on top of the concepts of Aspect Oriented Programming (AOP) and Dependency Injection or inversion-of-control (IoC). It works as a middle-layer integration framework for different Java and Java EE technologies and services. Resources and services are made available to JavaBeans through bean wiring (IoC) and aspect weaving (AOP). Essentially, Spring allows you to develop applications using Plain Old Java Objects (POJOs). The AppFuse project provides webapp templates for "kick starting" web application development. It demonstrates a simple integration approach between JSF and Spring. As a result, developers can wire Spring beans to JSF backing beans in faces-config.xml through dependency injection:

<managed-bean>
    <managed-bean-name>backingBean</managed-bean-name>
    <managed-bean-class>jsf.BackingBean
    </managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
    <managed-property>
        <description>SpringBean Reference</description>
        <property-name>springBean</property-name>
        <value>#{springBean}</value>
    </managed-property>      
</managed-bean>

The #{springBean} is declared inside a Spring XML configuration file. Programmatically, you may use facesContext.getApplication().createValueBinding("#{springBean}") to get a Spring bean reference within JSF backing beans. Meanwhile, developers shouldn't have any trouble integrating Facelets with JSF and Spring. As a little reminder, if you choose MyFaces as the JSF implementation and apply the Tomahawk UI components in these web pages, you must add a Facelets-specific taglib declaration file "tomahawk.taglib.xml" to register the Tomahawk custom tags on Facelets. Similar files are required for any of these home-brew custom JSF tags. These taglib declaration files need to be declared as a context parameter "facelets.LIBRARIES" in web.xml.

Conclusion

The new Java web technologies make our development journey more pleasant and productive. This article should help web developers make an easy transition from the old-fashioned JSP programming to the new JSF-styled web programming. There is one more thing worth mentioning for enthusiasts of servlet filters like myself: JSF phase listeners are preferred and should replace servlet filters. Apart from the discussions, topics like exception handling and security management, including single-sign on (SSO), should also be considered carefully from an enterprise architecture standpoint.

Resources

width="1" height="1" border="0" alt=" " />
Dr. Xinyu Liu is a Sun Microsystem certified enterprise architect working in a healthcare corporation.
Related Topics >> Web Development Tools   |