EJB Integration-Seam

Alternate View Technologies Facelets

In the early days of enterprise Java, developers dealt in HTML directly, by emitting HTML from servlets. Over the years, we have moved to eradicate HTML from our views with the advent of JSP and, especially, JSP custom tags, which do a neat job of encapsulating Java code and removing it from JSP pages.

Everything is a trade-off, but overall the trend toward JSP tags has made JSP pages more readable, maintainable, and extensible.

However, JSP has a dark side: When software developers and graphic designers work independently, the JSP model breaks down badly. Graphic designers are typically not familiar with JSP or the set of custom JSP tags that software developers use on any given project.

Software developers, on the other hand, can have a devil of a time incorporating a look and feel into a web application laden with custom tags that ultimately generate HTML, as is the case for a typical JSF application. If JSP is used on a project in which software developers and graphic designers work separately, only rigid discipline provides any hope of success. Fortunately, there is an alternative.

XHTML Views

Now we cut to the chase. We are going to use Facelets, an open source display technology for JSF, to implement our views in XHTML (Extensible HTML) instead of JSP. In our XHTML files, we will have mock-up HTML that is edited by a graphic designer, but at runtime, Facelets will swap out that mock-up HTML with JSF components. This will allow graphic designers to create a look and feel with mock-up markup that developers can replace with JSF components at runtime. And here is the clincher: The JSF components absorb the mock-up's look and feel.

Feel free to take a moment to ponder the ramifications.

This sort of chicanery, first pioneered in the Java web application space by Tapestry, truly borders on magic. Now we see how it works. First, an XHTML page, shown in Figure 12-4.

Figure 12-4. A simple XHTML page


Here is the listing for that page:

   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"            "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">    <html xmlns="http://www.w3.org/1999/xhtml">       <head>            <link href="styles.css" rel="stylesheet" type="text/css"/>            <title>An plain-vanilla XHTML file</title>       </head>       <body>          <form >             <table cellpadding="2px;">                <tr>                   <td>                      <label for="name" >                         Name                      </label>                    </td>                    <td>                       <input type="text"                                                    style="background: #ffa"/>                    </td>                </tr>                <tr>                   <td>                      <label for="password" >                         Password                      </label>                   </td>                   <td>                      <input type="password"                                                  size="8"                         />                   </td>                </tr>                <tr>                   <td></td>                   <td>                      <input type="submit"                         value="Log In"/>                   </td>                </tr>             </table>          </form>       </body>    </html>     

You cannot get much more vanilla than that. Next we wire those HTML elements to JSF components.

Replacing Markup with JSF Components: The jsfc Attribute

We are going to use JSF components to turn our nonfunctional markup into a thriving web page, as shown in Figure 12-5.

Figure 12-5. Replacing XHTML markup at runtime with JSF components


Here is the transformation of our XHTML file:

   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">    <html xmlns="http://www.w3.org/1999/xhtml"       xmlns:f="http://java.sun.com/jsf/core">       <head>          <link href="styles.css" rel="stylesheet" type="text/css"/>          <f:loadBundle basename="com.corejsf.messages" var="msgs"/>          <title>#{msgs.windowTitle}</title>       </head>       <body>          <form jsfc="h:form" >             <table cellpadding="2px;">                <tr>                   <td>                      <label for="name"                                                  jsfc="h:outputLabel">                         #{msgs.namePrompt}                      </label>                   </td>                   <td>                     <input type="text"                                                value="#{user.name}"                        style="background: #ffa;"                        jsfc="h:inputText"/>                   </td>                </tr>                <tr>                   <td>                      <label for="password"                                                  jsfc="h:outputLabel">                         #{msgs.passwordPrompt}                      </label>                    </td>                    <td>                      <input type="password"                         jsfc="h:inputSecret"                                                  value="#{user.password}"                         size="8"                         />                    </td>                 </tr>                 <tr>                   <td> </td>                   <td>                      <input type="submit"                         jsfc="h:commandButton"                         value="#{msgs.loginButtonText}"                         action="login"/>                   </td>                </tr>             </table>          </form>       </body>    </html>     

Three things about this example:

  • Notice the address bar URLs in Figure 12-4 on page 586 and Figure 12-5 on page 587. The former URLs end in .xhtml, whereas the latter end in .jsf. This means that Figure 12-4 shows what the graphic designer sees and Figure 12-5 shows what software developers, and ultimately end users, see.

  • We use an XML namespace to enable Facelet tags that mimic the JSF core tag library. Subsequently, we use the f:loadBundle tag from that namespace to load a resource bundle. Finally, we use value expressions, such as #{msgs.namePrompt}, directly in the page no h:outputText is required to access keys in the resource bundle.

  • We have added jsfc attributes to our form, labels, text fields, and button. When you run this souped-up XHTML page through Facelets, it swaps the markup for components of the specified type.

You might wonder what the graphic designer sees when she views this souped-up XHTML file. Figure 12-6 provides the answer.

Figure 12-6. What the graphic designer sees


The browser does not know what to do with JSF value expressions. So it just uses them as is, which is convenient for translators, who can glean the context of a translation just by looking at the XHTML.

Note

What does the browser, or any other tool that lets you view XHTML, do with those jsfc attributes? Nothing! So graphic designers can continue to iterate over your XHTML files to refine the look and feel, while you work on the components that will ultimately be used at runtime.


Note

Shale has something similar to Facelets, called Clay. Like Facelets, Clay gives you clean separation of graphic design and software development concerns with HTML views. One advantage Clay has over Facelets is that it works with ill-formed HTML, whereas Facelets requires XHTML.


Using JSF Tags

Fundamentally, Facelets, like Tapestry, cleanly separates graphic design from software development. But if you are both a graphic designer and a software developer, there are still viable reasons to prefer the more traditional JSP-based approach. For example, XHTML is more verbose than JSP and therefore can be harder to maintain over the long run. If you yearn for the more traditional approach with JSP tags, Facelets can easily accomodate. It's just that you are not really using JSP at all.

Facelets recognizes tags that look identical to their JSP counterparts, but it is Facelets, not JSP, that processes the tags. As Facelets parses the XHTML, it creates the resulting component tree.

Figure 12-7 shows the login application from page 587 with Facelet JSF tags.

Figure 12-7. A Facelets view that uses JSF tags


Now our XHTML page looks like this:

   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">    <html xmlns="http://www.w3.org/1999/xhtml"       xmlns:ui="http://java.sun.com/jsf/facelets"       xmlns:f="http://java.sun.com/jsf/core"       xmlns:h="http://java.sun.com/jsf/html">        <head>           <link href="styles.css" rel="stylesheet" type="text/css"/>           <f:loadBundle basename="com.corejsf.messages" var="msgs"/>           <title>#{msgs.facesTagsWindowTitle}</title>        </head>        <body>           <h:form >              <h:panelGrid columns="2" cellpadding="3px">                 <h:outputLabel for="name"                    value="#{msgs.namePrompt}"/>                 <h:inputText type="text"                                        value="#{user.name}"                    />                 <h:outputLabel for="password"                                        value="#{msgs.passwordPrompt}"/>                 <h:inputSecret                                        value="#{user.password}"                    size="8"                    />                 <h:outputText value=""/>                 <h:commandButton value="#{msgs.loginButtonText}"                    action="login"/>              </h:panelGrid>           </h:form>        </body>     </html>     

Notice that with the preceding code, we have purposely chosen to forego the jsfc approach, which, as we have seen, lets software developers and graphic designers work separately, in parallel.

In the end of course, it is your call whether to separate graphic design and software development. Either way, Facelets adds some very appealing features to this fundamental replacement of JSF's default display technology.

Page Composition with Templates

Facelets lets you compose web pages from individual XHTML fragments, similar to the popular Tiles framework. Figure 12-8 shows such a web page.

Figure 12-8. Using Facelets composition


Here is the XHTML page shown in Figure 12-8:

   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">    <html xmlns="http://www.w3.org/1999/xhtml"       xmlns:ui="http://java.sun.com/jsf/facelets">       <body>           <ui:composition template="/layout.xhtml">              <!-- Header -->              <ui:define name="header">                 <img src="/books/2/24/1/html/2/images/facelets.jpg"/>              </ui:define>               <!-- Menu -->               <ui:define name="menu">                  <img src="/books/2/24/1/html/2/images/whatisit.jpg"/>                  <img src="/books/2/24/1/html/2/images/demos.jpg"/>                  <img src="/books/2/24/1/html/2/images/downloads.jpg"/>                  <img src="/books/2/24/1/html/2/images/bestpractices.jpg"/>               </ui:define>               <!-- Content -->               <ui:define name="content">               <ui:include src="/books/2/24/1/html/2/login-composition.xhtml"/>              </ui:define>           </ui:composition>       </body>    </html>     

In the preceding code, we define a page composition that has a template, and we define content that is displayed by the template. Since the word "template" is so overloaded, it might help to think of the template as a layout instead. Here is the template for the preceding composition.

   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">    <html xmlns="http://www.w3.org/1999/xhtml"       xmlns:ui="http://java.sun.com/jsf/facelets"       xmlns:f="http://java.sun.com/jsf/core"       xmlns:h="http://java.sun.com/jsf/html"       xmlns:c="http://java.sun.com/jstl/core">       <link href="styles.css" rel="stylesheet" type="text/css"/>       <f:loadBundle basename="com.corejsf.messages" var="msgs"/>       <head>          <title>Facelets</title>       </head>        <body>          <div >             <ui:insert name="header"/>          </div>          <div >             <ui:insert name="menu"/>          </div>          <div >             <ui:insert name="content"/>          </div>       </body>    </html>     

Admittedly, there is not much layout there, other than three DIVs. The rest of the layout is encapsulated in CSS for a further separation of concerns. But the result is the same: the template, in this case an XHTML file and its stylesheet, represent the layout for the composition.

Notice the three ui:define tags in the code beginning on page 592. The first ui:define tag, representing the header of the page, contains a lone image. The next tag, representing the menu, contains four images. The most interesting tag is the third ui:define tag, which includes content from another XHTML file with the ui:include tag. That XHTML file looks like this:

   <ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"       xmlns:h="http://java.sun.com/jsf/html"       xmlns:c="http://java.sun.com/jstl/core">       <!-- the contents of this tag are the same as the body of the          listing on page  586 -->    </ui:composition>

The body of the preceding ui:composition is the same as the body of the XHTML file that begins on page 586.

Note

Why bother to use Facelets composition, when we can just neatly encapsulate the layout and its content in one file? Because if we have multiple views that share layout, we want to define that layout in only one place and reuse it for multiple views, much the same as you include content with JSP's jsp:include, or Facelets' ui:include. Realize that in the preceding example, any composition that defines header, menu, and content regions can reuse the same layout. That is pretty powerful.


Facelets Custom Tags

Facelets has many more features than we have covered here, so at this point we refer you to the Faclets documentation, but before we do, we will show you one more feature: Facelets custom tags.

You can easily create your own XHTML tags and use them in your Facelets views. For example, Figure 12-9 shows the application discussed in "Page Composition with Templates" on page 592, equipped with a custom tag that shows the HTTP headers for the current request, but only when there is a request parameter named debug whose value is true.

Figure 12-9. A debug tag that is triggered by a request attribute


A severely abbreviated listing of Figure 12-9 follows:

   <html xmlns="http://www.w3.org/1999/xhtml"       xmlns:ui="http://java.sun.com/jsf/facelets"       xmlns:debug="http://corejsf/facelets/debug">       ...          <debug:headers/>       ...    </html>

We must include our namespace declaration and then we are free to use the tag. The tag is defined in an XML file:

   <facelet-taglib>       <namespace>http://corejsf/facelets/debug</namespace>       <tag>          <tag-name>headers</tag-name>          <source>tags/corejsf/debug/headers.xhtml</source>       </tag>    </facelet-taglib>

We specify the name of the tag, headers, and the file it represents: tags/corejsf/debug/headers.xhtml. Here is that file:

   <ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"       xmlns:h="http://java.sun.com/jsf/html"       xmlns:c="http://java.sun.com/jstl/core">       <c:choose>          <c:when test="#{not empty param.debug and param.debug == 'true'}">             <h:outputText value="#{msgs.debugHeaders}"/>             <p><h:outputText value="#{header}" style="color: red;"/></p>          </c:when>       </c:choose>    </ui:composition>

That's it. A Facelets custom tag in three easy steps.



Core JavaServerT Faces
Core JavaServer(TM) Faces (2nd Edition)
ISBN: 0131738860
EAN: 2147483647
Year: 2004
Pages: 84

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net