Wednesday, December 28, 2011

JavaServer Faces 2.0 Resources Framework and CSS StyleSheets

By: Derek Berube, Wildstar Technologies, LLC.
Last Update: December 30, 2011

Back in 2008, when I read Ryan Lubke's "JSF 2.0 New Feature Preview Series (Part 2.1): Resources", "JSF 2.0 New Feature Preview Series (Part 2.2): Resources", and "JSF 2.0 New Feature Preview Series (Part 2.3): Resources" articles, I was excited to learn about the new mechanisms for managing resources coming with the JavaServer Faces 2.0 specification. This article guides web application developers with information on how to leverage the JSF 2.0 resource management framework in Cascading Style Sheet definitions.

Background

First and foremost, the 2.0 revision of the JavaServer Faces specification provides two standard locations for resources relative to the context root of your web application.
  • /resources
  • /META-INF/resources
Which of the locations you intend to use in your web application is really a matter of personal preference. The /resources directory is accessible to users of your web application whereas the /META-INF/resources directory is considered private and is only directly-accessible to your web application.

In developing the new resource management framework, the architects of the JSF 2.0 platform took inspiration from the convention over configuration aspects of some of the more popular web application frameworks available at the time. By doing this, they provide automatic localization and version management as long as developers adhere to the following structural pattern for the files in the /resources directory.

[localePrefix/][libraryName/][libraryVersion/]resourceName[/resourceVersion]

NOTE: The elements surrounded by brackets ( [ ] ) are considered optional. Only the resourceName is required.

In keeping with the "ease-of-use" theme for JSF 2.0, a standardized expression language syntax is provided for accessing resources regardless of which directory in which they reside:

#{resource['libraryName/fileName']}

The resource object is explained in greater detail in Ryan Lubke's "JSF 2.0 New Feature Preview Series (Part 2.3): Resources" article.

Shortly after working with the resource management framework in my JSF 2 applications, I wondered how I could leverage this framework for images declared in my CSS stylesheets. Ryan Lbuke's first article on the new resource management framework outlines the following URL pattern which will be used in the HTML generated by the framework.

/javax.faces.resource/[?ln=][&loc=][&v=]

NOTE: The elements surrounded by brackets ( [ ] ) are considered optional. Only the resource-name element is required.

By leveraging the notation of a Uniform Resource Locator prescribed in section "6.4 URL" of the "Cascading Style Sheets, Level 1" standard and incorporating the URL format shown above, we have the pattern shown below for identifying resources in our CSS files.

url('/javax.faces.resource/.jsf[?ln=][&loc=][&v=')

ParameterDescription
lnThe name of the library which is a sub-directory found in either the /resources or /META-INF/resources directory relative to your web application's context root. If the library is locale-specific, then the directory identified by the ln parameter will actually be a sub-directory found in a sub-directory corresponding to the two-character country-code identifying the locale.

For example, say you wanted to use a graphic image (background.png) that is in the images resource library as the background for a web page. You would use the following URL:

url('/javax.faces/resource/background.png.jsf?ln=images');
locIdentifies a specific local that should be used when the resource management framework returns the specified resource. If this parameter is omitted, the default locale specified by the client will be used.

NOTE: The supported codes for countries are defined in the ISO 3166 standard.

Continuing with the example used from the ln parameter, say you wanted to use a locale-specific background image for France. The following would be the URL used in your stylesheet.

url('/javax.faces/resource/background.png.jsf?ln=images&loc=FR');
vIdentifies a specific version of a resource that should be used to satisfy the resource request. If this parameter is omitted, the highest available of the identified resource will be returned.

In the context of our background.png image, the CSS file would contain the following line to identify version 1.1 of the image file:

url('/javax.faces/resource/background.png.jsf?ln=images&loc=FR&v=1_1');

NOTE: Web developers should be aware of the fact that per the Cascading Style Sheets, level 1 specification, the following characters should be escaped with a backslash.

CharacterEscaped Value
(\(
)\)
,\,
'\'
"\"

In addition, whitespace characters should also be escaped with a backslash.

Faces Servlet Configuration Consideration

In the URL example provided above, it is assumed that you have configured your web application to map the .jsf extension to the Faces Servlet (as shown below).

<servlet-mapping>

<servlet-name>Faces Servletservlet-name>

<url-pattern>*.jsfurl-pattern>

<url-pattern>/faces/*url-pattern>

</servlet-mapping>


Should you elect to use some other file extension, you will have to replace .jsf in the example above with the extension defined in your servlet-mapping for the Faces servlet.

Putting Everything into Action

The goal for this article is to produce the web page depicted in the screenshot below using standard cascading style sheets and the new resource management capabilities provided by the JavaServer Faces 2.0 web application framework. The image of Duke waving is a scaled down version of wave.png taken from the Duke Images archive found at http://duke.kenai.com/wave/index.html. It has been loaded as the background for the element in the HTML page. The stylesheet tells the browser to place the waving Duke image in the top right corner of the web page. It also tells the browser that the image should NOT be repeated.



The reference page shown above is publicly accessible at the http://jsf2gae.wildstartech.com/resourceManagerCSSExample/resourceManagerCSSExample.jsf URL. The following is the contents of the resourceManagerCSSExample.jsf file.

<!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" xml:lang="en" lang="en"

xmlns:f="http://java.sun.com/jsf/core"

xmlns:h="http://java.sun.com/jsf/html"

xmlns:ui="http://java.sun.com/jsf/facelets">

<h:head id="head">

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

<title>Resource Manager CSS Example</title>

</h:head>

<h:body id="body">

<h:outputStylesheet name="resourceManagerCSSExample.css"

library="resourceManagerCSSExample"

target="head" />

<p>Example of using JSF 2.0 resource management framework with CSS.</p>

</h:body>

</html>


In the example page above, the following snippet of code is used to instruct the browser to load the resourceManagerCSSExample.css stylesheet.

<h:outputStylesheet name="resourceManagerCSSExample.css"

library="resourceManagerCSSExample"

target="head" />


The <h:outputStylesheet> tag is something Ryan Lubke talks about in his "JSF 2.0 New Feature Preview Series (Part 4) Resource Re-location" article. The official JavaDoc for the <h:outputStylesheet> tag is also available.

The following is the complete content of the resourceManagerCSSExample.css file.

body {
background-image: url('/javax.faces.resource/wave.png.jsf?ln=resourceManagerCSSExample');
background-repeat: no-repeat;
background-position: right top;
}

The value used for the background-image style identifies a uniform resource locator (URL) that leverages the JSF 2.0 resource management framework to obtain the wave.png file from the /resources/resourceManagerCSSExample directory of the jsf2gae web application.

References

The following documents or web sites were referenced in the process of composing this article.

Developing JSF 2 Applications on Google App Engine 1.6.1

I have taken advantage of some free time I had while on vacation to update the "Configuring JavaServer Faces 2.0 to run on the Google App Engine Using Eclipse" using the 1.6.1 release of the App Engine platform.

In the course of updating this article, my testing shows that it is no longer necessary to set the com.sun.faces.enableThreading context parameter equal to a value of false. As described in the JSF 2.0 release notes, this context parameter impacts resource handling for the JSF framework.
When enabled, the runtime initialization and default ResourceHandle implementation will use threads to perform their functions. Set this value to false if threads aren't desired (as in the case of running within the Google Application Engine).

Note that when this option is disabled, the ResourceHandler will not pick up new versions of resources when ProjectStage is development.
In addition, it appears that one may now freely use the javax.faces.PROJECT_STAGE context parameter with a value of "Development" without issue. Ryan Lubke provides an excellent description of the purpose of this context parameter in his "JSF 2.0 New Feature Preview Series (Part 1): ProjectStage" blog entry.

The "JavaServer Faces 2.0 and Google App Engine Compatibility Issues" article has been updated accordingly.

Sunday, February 14, 2010

A Brief Introduction

I am an ardent fan of the Java(TM) platform and have been developing applications in both my spare time and as an occasional part of my day job since it was made publicly available. By the time the first iteration of the JavaServer Faces framework was formalized in 2004, I had been creating web applications using Servlets/JSPs, ColdFusion, and Apache Struts. I was excited about JSF's potential and thought it would be a good opportunity to further immerse myself in the Java EE world.

I am someone who tends to learn and retain things better when I have some practical way of applying the theories and techniques I am studying. So it was fortunate that about the time I decided to take a serious dive into JSF, I knew someone who was looking to construct a web-based work order management solution for their privately held logistics company.

As a firm believer in the Open Source movement and a fan of the Apache Software Foundation, I decided to work with the MyFaces project and leverage the Tomahawk component library. I became intimately familiar with David Geary and Cay Horstmann's "Core JavaServer Faces" book (both the first and second editions and I am anxiously awaiting the release of the third edition). The experience was immensely rewarding and extremely educational!

It was equally frustrating and tiresome. My frustrations primarily arose from from two sources:
  • backing beans and database persistence
  • XML configuration files
The first point was a pain I brought on myself by electing to not use Seam and Hibernate. In my defense, this project was intended to be a learning experience and as such I wanted to stay as close to the metal as I could. I also subscribe to the notion that if you are forced to do things the hard way, you are in a better position to appreciate all the benefits that frameworks such as Seam and Hibernate have to offer.

Dealing with XML configuration files was not hard, it was just tedious. While I cannot cite specific sources, I recall reading that the architects of JSF did not intend for programmers to deal directly with these files. The intent was that the Integrated Development Environments (kudos to the Java Studio Creator team) developers would use as they dragged and dropped their way to building and deploying amazing JSF-based applications would be responsible for maintaining configuration files in the background.

However, my enthusiasm for the JSF framework remained steadfast and I followed the developments of the 2.0 iteration of the spec with great interest and anticipation. I frequently read Ed Burns, Jim Driscoll and Ryan Lubke's weblogs as the reference implementation was developed under the Mojarra Open Source project. Andy Schwartz has a great summary of the new features included in the JSF 2 platform.

I hope to use this blog as a way to share my experiences developing applications with the JavaServer Faces framework. If you have made it this far and are interested in reading a little more, I wrote a tutorial guiding one through the process of getting the JSF 2 framework running on the Google App Engine platform.