Recipe14.8.Integrating JavaServer Faces with Struts


Recipe 14.8. Integrating JavaServer Faces with Struts

Problem

You want to migrate an existing Struts application to JavaServer Faces without having to rewrite the entire application.

Solution

Use the Struts-Faces integration library.

Discussion

It's reasonable to consider JavaServer Faces (JSF) to be the "son of Struts." In fact, the creator of Struts, Craig McClanahan, serves as co-lead for the JSF specification. Unlike Struts, JSF specifies a component model for the user interface of applications. Theoretically, that model can be rendered by any type of user interface, and not just a web-based interface. But in its current release, JSF targets web application development. There are two implementations of JSF available. The reference implementation (RI) has been developed and is distributed by Sun. MyFaces, an open source Apache project, implements the JSF specification and adds additional components not contained in the reference implementation.

Struts-Faces, initially developed by Craig McClanahan, allows you to use JSF technology in a Struts application. Using this library, you can continue to use your actions and action forms as written, but you use the JSF custom tags instead of the Struts tags for the user interface. Struts-Faces allows you to migrate your existing Struts applications to JSF a page at a time.

This recipe will help you get started with Struts-Faces. It applies this technology to a three-page application having an index page, a login page, and a welcome page displayed upon login.

Struts-Faces is under active development. For the latest documentation and code, download the nightly build of Struts-Faces from http://svn.apache.org/builds/struts/nightly/struts-faces/, extracting the archive into a directory on your system:

  1. Copy the struts-faces.jar and struts-faces.tld from the struts-faces/lib directory to your WEB-INF/lib directory.

  2. Download and extract Sun's JSF reference implementation from http://java.sun.com/jsf. At the time of this writing, Version 1.1 was the latest available.

  3. Copy the jsf-api.jar and jsf-impl.jar from the jsf-1.1/lib directory to your WEB-INF/lib directory.

  4. If your application doesn't use JSTL, copy the jstl.jar and standard.jar files from the jakarta-struts-1.2.x/lib directory to your WEB-INF/lib directory.

  5. Add the servlet declaration and mapping for the JavaServer Faces servlet to your web.xml file. Set the load-on-startup value for the FacesServlet so it starts up before the Struts ActionServlet:

    <!-- Faces Servlet Configuration --> <servlet>     <servlet-name>faces</servlet-name>     <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>     <load-on-startup>1</load-on-startup> </servlet> <!-- Action Servlet Configuration --> <servlet>     <servlet-name>action</servlet-name>     <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>     <init-param>         <param-name>config</param-name>         <param-value>/WEB-INF/struts-config.xml</param-value>     </init-param>     <load-on-startup>2</load-on-startup> </servlet> <!-- Servlet Mappings --> <servlet-mapping>     <servlet-name>faces</servlet-name>     <url-pattern>*.faces</url-pattern> </servlet-mapping> <servlet-mapping>     <servlet-name>action</servlet-name>     <url-pattern>*.do</url-pattern> </servlet-mapping>

The servlet mapping for the Faces servlet directs all requests with a .faces extension through the JSF FacesServlet for standard JSF processing. You will need to configure Struts to use a custom request processor for handling JSF integration. Example 14-21 shows the struts-config.xml, which specifies the controller declaration for the FacesRequestProcessor, that includes the action mappings for this example application.

Example 14-21. Struts configuration file that uses Struts-Faces
<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE struts-config PUBLIC           "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"           "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"> <struts-config>     <form-beans>         <form-bean name="logonForm" type="org.apache.struts.action.         DynaActionForm">             <form-property name="username" type="java.lang.String"/>             <form-property name="password" type="java.lang.String"/>         </form-bean>     </form-beans>     <global-forwards>         <forward name="welcome" path="/welcome.faces"/>         <forward name="logon" path="/logon.faces"/>         <forward name="home" path="/index.jsp" redirect="true"/>     </global-forwards>     <!-- ========== Action Mapping Definitions =========================== -->     <action-mappings>         <action    path="/Logon"                    name="logonForm"                   scope="request"                    type="com.oreilly.strutsckbk.ch14.LogonAction">             <forward name="success" path="welcome.faces"/>         </action>     </action-mappings>     <controller>         <set-property property="processorClass"             value="org.apache.struts.faces.application.FacesRequestProcessor"/>     </controller>     <message-resources parameter="ApplicationResources"/> </struts-config>

The first page of the application, shown in Example 14-22 (index.jsp), provides a link to the "logon" page. This conventional JSP page doesn't contain any JSF or Struts-Faces components.

Example 14-22. Regular Struts-based index page
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %> <%@ taglib prefix="html" uri="http://struts.apache.org/tags-html" %> <html> <head>   <title>Struts Cookbook - Integrating Struts and JSF</title> </head> <body>   <h2>Struts Cookbook - Integrating Struts and JSF</h2>   <html:link forward="logon">Try out Struts and JSF</html:link> </body> </html>

The second page, logon.jsp shown in Example 14-23, contains the logon form submitted to the /Logon action.

Example 14-23. Logon page using Struts-Faces components
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %> <%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %> <%@ taglib prefix="s" uri="http://struts.apache.org/tags-faces" %> <f:view> <s:html locale="true"> <head>   <title>Struts Cookbook - Integrating Struts and JSF</title> </head> <body>   <p />   <s:form  action="/Logon"       focus="username" style>     <h:outputLabel for="username" style value="Username:"/>     <h:inputText  value="#{logonForm.username}"             required="true" size="10"/> <p />     <h:outputLabel for="password" style value="Password:"/>     <h:inputSecret  value="#{logonForm.password}"              required="true" size="10"/> <p />     <h:commandButton  type="SUBMIT" value="Logon" />   </s:form> </body> </s:html> </f:view>

If you've never used JavaServer Faces, this page probably looks funky. The page starts conventionally and declares the taglib directives for the JSF core and html tag libraries, as well as the Struts-Faces tag library.

To prevent collision with the JSTL core tag library, the taglib declaration for the JSF core tag library commonly uses "f" instead of "c" as the prefix. You can think of "f" as standing for "faces" or "framework."


On this page, the f:view tag contains the entire content of the view. All JSF pages must contain a f:view tag that encapsulates the custom JSF tags. The s:form tag, from the Struts-Faces library, creates an HTML form that can be submitted to a Struts action. The h:outputLabel tags display label text for input fields declared with the h:inputText tags. The h:inputSecret tag creates a password input field. The h:commandButton tag creates the form's submit button.

When this page was first written, yours truly inadvertently left off the value attribute for the h:inputText and h:inputSecret tags. As Struts developers, the best practice is to eschew specifying the value attribute for tags like html:text since the values are automatically retrieved from the form based on name. When this application was tested, data entered on the form wasn't populated to the action form. Because JavaServer Faces uses a different binding convention than Struts, you must explicitly bind each field to a form-bean property. Adding the value attributes to the form as shown solved the problem.

The Struts-Faces tags resemble the Struts html tag library. By design, Struts developers will find it easy to learn the Struts-Faces tags. The s:form tag, for example, closely matches the Struts html:form tag. However, with the s:form tag, you use the JSF html tags instead of the Struts html tags. Table 14-2 provides a complete list of tags included with Struts-Faces.

Table 14-2. Struts-Faces tags

Tag name

Description

base

Creates a <base> element, similar to the Struts html:base tag

commandLink

Creates a hyperlink that can be used to submit a form

errors

Displays accumulated action errors, similar to the Struts html:errors tag

form

Creates an HTML form that submits to a Struts action, similar to the Struts html:form tag

html

Generates an <html> element with optional locale-sensitivity, similar to the Struts html:html tag

javascript

Generates the JavaScript for client-side validation using the Validator, similar to the Struts html:javascript tag

loadMessages

Loads messages resources into a map for access by JSF tags such as h:outputText

message

Displays a localized message, similar to the bean:message tag

stylesheet

Generates a link to a stylesheet

write

Renders a property value from a model object, similar to the bean:write tag


The FacesRequestProcessor processes the submitted logon form and executes the LogonAction. This action doesn't have to do anything special related to JSF. The Struts-Faces library integrates Struts and JSF so your action classes and action forms require no modification when using JSF. Example 14-24 shows the LogonAction for this application. A "real" action would authenticate the user.

Example 14-24. Action for logon
package com.oreilly.strutsckbk.ch14; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.beanutils.PropertyUtils; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; public class LogonAction extends Action {     public ActionForward execute(ActionMapping mapping, ActionForm form,             HttpServletRequest request, HttpServletResponse response)             throws Exception {         String name = (String) PropertyUtils.getSimpleProperty(form,                                                              "username");         User user = new User( );         user.setUsername(name);         request.getSession( ).setAttribute("user", user);         return mapping.findForward("success");     } }

The application culminates by rendering a "welcome" page that includes text from the message resources bundle as well as the username entered on the preceding form. The welcome.jsp page, accessed through the welcome.faces path, is shown in Example 14-25.

Example 14-25. Rendering HTML with JSF and Struts-Faces tags
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %> <%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %> <%@ taglib prefix="s" uri="http://struts.apache.org/tags-faces" %> <f:view> <s:loadMessages var="messages"/> <s:html locale="true"> <head>   <title>Struts Cookbook - Integrating Struts and JSF</title> </head> <body>   <h2>Struts Cookbook - Integrating Struts and JSF</h2>   <h3><s:message key="index.welcome"/></h3>   <h:outputText value="#{messages['msg.loggedIn']}"/>    <b><h:outputText value="#{user.username}"/></b>. </body> </s:html> </f:view>

At this point, you have a working application, which uses Struts and JSF together, that preserves your custom action classes and action forms and allows you to take advantage of the rich components afforded by JavaServer Faces.

See Also

For the latest documentation on Struts-Faces, consult the documentation included with the Struts-Faces nightly build. If you're unsure about using JSF or Struts, Craig McClanahan presents a fair assessment on his blog at http://java.net/craigmcc.

You'll find a good article on integrating Struts, JSF, and Tiles on IBM's Developer Works at http://www-106.ibm.com/developerworks/java/library/j-integrate/.

The source for information on JavaServer Faces, including the specification and the reference implementation, can be found at http://java.sun.com/jsf.

You can use Struts-Faces with any JSF compliant implementation. The MyFaces project (http://incubator.apache.org/projects/myfaces.html) implements the JSF specification and provides an alternative to the reference implementation.

You'll find the quick reference for the standard JSF tags at http://www.horstmann.com/corejsf/jsf-tags.html to be quite handy.



    Jakarta Struts Cookbook
    Jakarta Struts Cookbook
    ISBN: 059600771X
    EAN: 2147483647
    Year: 2005
    Pages: 200

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