miércoles, 4 de agosto de 2010

Facelets Essentials: Guide To JavaServer Faces View Definition Framework


1. Definition.
2. Facelets Vs JSP.
3. Features.
4. Creating an application with facelets.
    4.1. Downloading Facelets.
    4.2. Adding Dependency.
    4.3. Creating a Project Structure.
    4.4. Configuring the Web descriptor (web.xml)
    4.5. Configuring the Faces descriptor (faces-config.xml)
    4.6. Creating JSF Views
    4.7. Unified Expression Language
    4.8. Tag Libraries
    4.9. Facelets Templating and Template Clients
    4.10. Facelets Tags

1. Definition

Facelets is a templating language that provides a highly performant, JSF-centric view technology.

2. Facelets Vs JSP
  • JSP and JSF don't naturally complement each other.
  • JSP is used to create static and dynamic web content but not to create component trees.
  • Its elements are processed in a page from top to bottom with the basic objective of creating a response to a request. JSF has a more complex life cycle, component generation and rendering happen in clearly separated phases.
  • When use together, JSP and JSF both write output to the response, but they do so differently: the JSP container creates output as soon as it finds JSP content, whereas JSF component dictate its own rendering. This difference can cause some problems.
  • Problems found between JSP and JSF can frustate developers using JSF for the first time who does not know the implementation details of both JSP and JSF.
  • Facelets fills the gap between JSP and JSF.
  • Facelets is a view technology focused on building component trees and interweaving content with the complex JSF life cycle.
  • Facelets replace JSP with a very simple API that is a reflection of its simple principles, and it incorporate numerous developer-friendly features.

3. Features
  • Facelets does not depend on a web container. We can use JSF 1.2 without having to use JEE5 or a container that already has JSP 2.1.
  • Facelets can work with any implementation and version of JSF.
  • As mentioned previously, interweaving JSP and JSF can cause difficulties.
  • JSTL cannot be used with JSF. Facelets provides a solution to this incompatibility.
  • Facelets provides a compilation process that is much faster than JSP's, because no Java bytecode is actually generated and compiled behind the scenes when you first visit your page.
  • Facelets provides templating, so you can reuse your code extensively to simplify the development and maintenance of large-scale applications.
  • Facelets allows the creation of lightweight components.
  • Facelets has Unified Expression Language (EL) support.
  • Facelets does not require any special render kits.

4. Creating an application with facelets

4.1 Downloading Facelets
  • You can download a release binary from
    http://facelets.dev.java.net/servlets/ProjectDocumentList
  • The Facelets artifact can be found in the Maven Central Repository

    (http://www.ibiblio.org/maven2/) and in the Java.net Maven Repository (https://maven- repository.dev.java.net/repository/). You can include the artifact in your project by adding the following dependency to your Project Object Model (POM):

    <dependency>

      <groupId>com.sun.facelets</groupId>

      <artifactId>jsf-facelets</artifactId>

      <version>1.1.13</version>

    </dependency>


    Version 1.1.13 is the current one at the time of this writing. You should use a newer version if possible.

4.2. Adding Dependency

PROJECT

BUILD

INCLUDED

DESCRIPTION

Apache MyFaces

No

No

Implements JSF 1.1 and JSF 1.2.

JavaServer Faces RI

No

No

The reference implementations of JSF 1.1 and JSF 1.2 are available for use with your application.

JavaServer Faces API

Yes

Yes

JSF 1.2 API that works with the new EL specification. (Optionally, MyFaces Core API could be used.)

EL API

Yes

Yes

The stand-alone EL utilized by both JSP and JSF.

EL RI

No

Yes

The reference implementation that is used by Facelets for handling EL.

Servlet API

Yes

Yes

Servlet API

XML SAX

Yes

No

This dependency should not be an issue for most deployments, as it's astandard part of web containers and JREs.


4.3. Creating a Project Structure

Including the correct list of libraries can be one of the trickiest parts when starting a project. Missing libraries or incompatibilities between its versions can lead to obscure exceptions and increase developer frustration. Moreover, the diversity of web containers, each of them with its own libraries and particularities, makes this task even more complex.

In a project that uses Facelets and MyFaces, a common directory structure would look like this:

$PROJECT
+- /WEB-INF
+- /lib
+- /commons-beanutils.jar
+- /commons-collections.jar
+- /commons-digester.jar
+- /commons-logging.jar
+- /el-api
+- /el-impl
+- /jsf-facelets.jar
+- /myfaces-api.jar
+- /myfaces-impl.jar
+- /web.xml
+- /faces-config.xml
+- /[xhtml documents]

The EL libraries (el-api and el-impl) need to be excluded if the container is JSP 2.1 compliant. JSP 2.1 already contains an EL implementation, and you would have a conflict when starting the application.
If you are using the Reference Implementation (RI), replace myfaces-api.jar and myfaces-impl.jar with jsf-ri.jar and jsf-api.jar.
Note: if you’re using Maven, you do not need to worry about the dependencies, as Maven will get them for you. You need to declare the JSF implementation in your POM file, though.
4.4. Configuring the Web descriptor (web.xml)

We need to include the context parameter javax.faces.DEFAULT_SUFFIX, which defines the suffix of the documents for your views. By convention, the default extension for pages built using Facelets is *.xhtml.

<web-app>
..............
<!-- Use Documents Saved as *.xhtml -->
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>
</web-app>

4.5. Configuring the Faces descriptor (faces-config.xml)

Facelets replaces the default JavaServer Faces ViewHandler with its own implementation represented by the class com.sun.facelets.FaceletViewHandler.

<faces-config>
<application>
<view-handler>
com.sun.facelets.FaceletViewHandler
<!-- Icefaces => com.icesoft.faces.facelets.D2DFaceletViewHandler-->
</view-handler>
</application>
</faces-config>

4.6. Creating JSF Views
  • Create a template and define the different areas
  • Create a project structure like the following

    $PROJECT
    +- /WEB-INF
    +- /lib [with dependencies]
    +- web.xml
    +- faces-config.xml
    +- template.xhtml
    +- index.xhtml
    +- parrot.xhtml
    +- eagle.xhtml
    +- menu.xhtml
  • Create documents with the extension *.xhtml
  • One of them is the template.xhtml used by the other pages
  • menu.xhtml will be used to navigate through the application.
  • With the Facelets UI tag “ui:insert” we define areas in the page (template) that can be overwritten
  • We need to use the http://java.sun.com/jsf/facelets namespace to use the Facelets tags. By convention, we define “ui” as the prefix for the UI Facelets library tags.
  • We can define default content for the areas just by nesting this content in the “ui:insert” tag.
  • We are using three new Facelets tags: “ui:composition”, “ui:define”, and “ui:include”.
    • We use the “ui:composition” tag’s template attribute to reference the template we want to use for the page. Everything inside the “ui:composition” tag will be evaluated by Facelets when compiling the document. All elements outside the “ui:composition” tag will be ignored.
    • Use the “ui:define” tag to define the content that will go in the areas declared in the template. The name attribute of the ui:define tag must match the one of the ui:insert tag in the template.
    • “ui:include” tag allows us to include the content from another document.
  • We use “h:commandLink” with action attributes defined to trigger the navigation in our application . It builds a link that will take the user to the page indicated in the navigation rule. We define this rule in the faces-contig.xml with the following tag,

    <navigation-rule>
    <navigation-case>
    <from-outcome>action_name</from-outcome>
    <to-view-id>/view_page.xhtml</to-view-id>
    </navigation-case>
    </navigation-rule>

4.7. Unified Expression Language
  • The Unified Expression Language was successfully created in an attempt to align the Expression Languages (ELs) used in JSP 2.0 and JSF 1.1.
    • JSP EL uses ${. . .}
    • JSF EL uses #{. . .}
  • Thanks to the Unified EL, JSTL tags, such as the iteration tags, can now be used intuitively with JSF components .
  • Facelets uses the new Unified EL. It supports the use of ${. . .} and #{. . .} syntax , so you can use either one, depending on the developer’s particular tast e.
  • With Facelets, you can insert an EL expression anywhere in the page

    <p>The Happy Birds Directory
    contains #{directoryBean.totalCount} birds.
    </p>

4.8. Tag Libraries
  • To use a tag library in our page, we must declare it by using its namespace. We can do that by mapping the library’s URI (or URL) to a prefix.
  • Facelets uses a couple of strategies to load tag libraries.
    • It searches the classpath trying to find libraries in the /META-INF folder of the JAR files. It will try to load any file that has the extension *.taglib.xml.
    • Facelets will check the libraries defined in the web.xml file with the initialization parameter facelets.LIBRARIES.
  • Tag libraries included in the Facelets binaries
    • Templating library: This contains the tags using for templating.
    • JSF libraries: The two tag libraries for the JavaServer Faces specification are supported by default by Facelets.
    • JSTL: Facelets provides partial support for JavaServer Pages Standard Tag Library (JSTL) tags. While the Function library is fully supported, the Core tags are only partially so. The Core tags supported by Facelets are: c:if, c:forEach, c:catch, and c:set.
  • If you want to use other libraries that do not have a Facelets tag library, you will need to create the tag library file yourself and register it in your web.xml file, if the tag library was not already included in a JAR . Add the library under the parameter facelets.LIBRARIES, and separate multiple libraries with semicolons.

4.9. Facelets Templating and Template Clients
  • Facelets templates can be created from both JSF components and HTML tags. Templates can be interwoven thanks to the fact that they are compiled during the render phase.
  • We distinguish in Facelets between templates and template clients. The latter use the templates to create variations of the same pattern.
  • A template defines spots where the content can be replaced. Which content is used in those spots is defined by the clients. The template defines the different areas using the ui:insert tag, and the clients use the templates with ui:component, ui:composition, ui:fragment, or ui:decorate tags.
  • Templating in Facelets is not just limited to one level. It is possible to have multilevel templating, as a client for one template can be a template for other client templates. Hence, Facelets powerful templating support allows you to create complex composite applications.
  • Facelets will interpret the EL expressions within the HTML comments (<!-- -->) unless the context parameter facelets.SKIP_COMMENTS is set to true in the web.xml file.

4.10. Facelets Tags
  • <ui:component/>: inserts a new UIComponent instance as the root of JavaServer Faces tree.
  • <ui:composition/>: it is used to encapsulate content that can be included in other Facelets pages.
  • <ui:debug/>: When launched using the combination Ctrl + Shift + (D, by default), it will display a pop-up window that shows the component tree and the scoped variables.
  • <ui:decorate/>: is similar to the ui:composition tag, the only difference being that the decorate tag does not remove everything outside of it. You can use this tag to add some content around the decorated section by using a template.
  • <ui:define/>: can be used to insert named content into a template. It can be used within tags that allow templating, such as the ui:composition and ui:decorate tags. The names used in the define tag must match the names used in the ui:insert tags in the target template.
    : is similar to the ui:component tag, but the fragment tag does not trim the content outside itself.
  • <ui:include/>: can be used to include another Facelets file into your document. It simply includes whatever source file you specify.
  • <ui:insert/>: is used to specify in a template those parts that can be replaced by ui:define tags declared in the client template.
  • <ui:param/>: This tag is used to pass objects as named variables between Facelets.
  • <ui:remove/>: The ui:remove tag is used to remove blocks of code at compilation time. It has no attributes, though you can use this tag in conjunction with the jsfc attribute.
  • <ui:repeat/>: The ui:repeat tag is used to iterate over a list of objects, and we always recommend its use instead c:forEach from the JSTL Code tag library.
  • Note: ui:repeat and c:forEach are different. ui:repeat is a render-time evaluation, whereas c:forEach is a build-time evaluation. c:forEach does not represent a component in Facelets (it is a TagHandler) and will never become part of the component tree. It is used to create the tree when the page is first referenced (when the request is not a postback), but after that, c:forEach will not do anything else. On the other hand, ui:repeat is implemented as a component in Facelets and is part of the component tree. As an example, you could develop a list of elements with a button to add more elements. If you used forEach for the iteration, the new elements would never be added when the button is clicked (which is a postback).