BUY THIS BOOK
Add to Cart

Print Book $44.95


Add to Cart

Print+PDF $58.44

Add to Cart

PDF $35.99

Safari Books Online

What is this?

Add to UK Cart

Print Book £31.95

What is this?

Looking to Reprint or License this content?


Jakarta Struts Cookbook
Jakarta Struts Cookbook By Bill Siggelkow
February 2005
Pages: 526

Cover | Table of Contents | Colophon


Table of Contents

Chapter 1: Getting Started: Enabling Struts Development
The popularity of the Struts framework has grown tremendously in the last year. Since the release of Struts 1.1 in June 2003, Struts has become one of the most popular frameworks for developing complex JSP-based web applications. Traffic on the Strut's user's mailing list is heavy, typically 70 messages a day.
Despite its popularity, figuring out how to get started developing with Struts is still a common topic of conversation. The recipes in this first chapter should help you jump-start your development with Struts.
Good commercial tools have been built around Struts, the primary focus here is on tools and frameworks that are open source and free (as in "free beer"). By focusing on freely available tools, developers should be more encouraged to experiment with these tools than if they had to pay to use them.
You want to start developing applications using Struts.
Download the Struts binary and source distributions from http://struts.apache.org/acquiring.html and deploy the example applications to your web container.
A common question among developers new to Struts is which release to use. Without question, any new Struts project should use the latest best available release. At the time this was written, Struts 1.2.4 (referred to in this book as Struts 1.2) had just gone GA (General Availability).
For developers looking to gain experience with the latest and greatest Struts features, the Struts Nightly Build will provide a peek into Struts 1.3.
You will find it useful to have the binary and source distributions available. The binary distribution includes the Struts JARs and associated dependent JARs. The source distribution, on the other hand, contains the source code for the Struts framework itself, as well as the Java source for the Struts tag libraries. Just as important, the source distribution contains the Java source, deployment descriptors, HTML pages, and JSP pages for all of the supplied sample applications.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Introduction
The popularity of the Struts framework has grown tremendously in the last year. Since the release of Struts 1.1 in June 2003, Struts has become one of the most popular frameworks for developing complex JSP-based web applications. Traffic on the Strut's user's mailing list is heavy, typically 70 messages a day.
Despite its popularity, figuring out how to get started developing with Struts is still a common topic of conversation. The recipes in this first chapter should help you jump-start your development with Struts.
Good commercial tools have been built around Struts, the primary focus here is on tools and frameworks that are open source and free (as in "free beer"). By focusing on freely available tools, developers should be more encouraged to experiment with these tools than if they had to pay to use them.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Downloading Struts
You want to start developing applications using Struts.
Download the Struts binary and source distributions from http://struts.apache.org/acquiring.html and deploy the example applications to your web container.
A common question among developers new to Struts is which release to use. Without question, any new Struts project should use the latest best available release. At the time this was written, Struts 1.2.4 (referred to in this book as Struts 1.2) had just gone GA (General Availability).
For developers looking to gain experience with the latest and greatest Struts features, the Struts Nightly Build will provide a peek into Struts 1.3.
You will find it useful to have the binary and source distributions available. The binary distribution includes the Struts JARs and associated dependent JARs. The source distribution, on the other hand, contains the source code for the Struts framework itself, as well as the Java source for the Struts tag libraries. Just as important, the source distribution contains the Java source, deployment descriptors, HTML pages, and JSP pages for all of the supplied sample applications.
The exact content of these distributions varies depending on whether you are getting the latest Release Build or the Struts Nightly Build.
The Struts 1.2 Release Build binary distribution includes a basic README file, an installation document, and release notes. The lib folder contains the Struts JAR file, as well as the dependent JAR files from the Jakarta Commons project. The contrib folder contains contributions to the Struts distribution that aren't considered part of the Struts core. In particular, this folder contains the JAR files and sample web applications for Struts-EL. Struts-EL allows you to use JSTL (JSP Standard Tag Library) style expression language in the Struts tags. It includes, by necessity, the JSTL tag libraries.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Deploying the Struts Example Application
You want to deploy the Struts MailReader example application to Tomcat.
If you don't already have the Tomcat running on your box, you can download it from http://jakarta.apache.org/tomcat. This recipe assumes that you are using Tomcat 5. Set environment variables for Struts and Tomcat, copy the Struts example WAR file to Tomcat, and start Tomcat.
If you are using Struts 1.2, the WAR file for the Struts example application has been changed from struts-example.war to struts-mailreader.war.
The commands for a Windows machine are shown here:
C:\>set STRUTS_HOME=c:\jakarta-struts-1.1

C:\>set CATALINA_HOME=c:\tomcat5

C:\>copy %STRUTS_HOME%\webapps\struts-example.war %CATALINA_HOME%\webapps
        1 file(s) copied.

C:\>%CATALINA_HOME%\bin\startup
Using CATALINA_BASE:   c:\tomcat5
               Using CATALINA_HOME:   c:\tomcat5
               Using CATALINA_TMPDIR: c:\tomcat5\temp
               Using JAVA_HOME:       c:\j2sdk1.4.2
            
The last command shown, %CATALINA_HOME%\bin\startup, starts Tomcat. On Windows, you will see Tomcat startup in a separate terminal window. The output in this terminal window displays information about the applications deployed and the state of Tomcat:
               Jun 22, 2004 12:23:34 AM org.apache.catalina.core.StandardHostDeployer install
               INFO: Installing web application at context path /struts-example from URL file:c
               :/tomcat5/webapps/struts-example
Jun 22, 2004 12:23:38 AM org.apache.struts.util.PropertyMessageResources <init>
INFO: Initializing, config='org.apache.struts.util.LocalStrings', returnNull=tru
e
Jun 22, 2004 12:23:38 AM org.apache.struts.util.PropertyMessageResources <init>
INFO: Initializing, config='org.apache.struts.action.ActionResources', returnNul
l=true
Jun 22, 2004 12:23:40 AM org.apache.struts.util.PropertyMessageResources <init>
INFO: Initializing, config='org.apache.struts.webapp.example.AlternateApplicatio
nResources', returnNull=true
Jun 22, 2004 12:23:40 AM org.apache.struts.util.PropertyMessageResources <init>
INFO: Initializing, config='org.apache.struts.webapp.example.ApplicationResource
s', returnNull=true
Jun 22, 2004 12:23:40 AM org.apache.struts.webapp.example.memory.MemoryDatabaseP
lugIn init
INFO: Initializing memory database plug in from '/WEB-INF/database.xml'
Jun 22, 2004 12:23:40 AM org.apache.struts.validator.ValidatorPlugIn initResourc
es
INFO: Loading validation rules file from '/WEB-INF/validator-rules.xml'
Jun 22, 2004 12:23:41 AM org.apache.struts.validator.ValidatorPlugIn initResourc
es
INFO: Loading validation rules file from '/WEB-INF/validation.xml'
...
Jun 22, 2004 12:23:44 AM org.apache.coyote.http11.Http11Protocol start
INFO: Starting Coyote HTTP/1.1 on port 80
Jun 22, 2004 12:23:45 AM org.apache.jk.common.ChannelSocket init
INFO: JK2: ajp13 listening on /0.0.0.0:8009
Jun 22, 2004 12:23:45 AM org.apache.jk.server.JkMain start
INFO: Jk running ID=0 time=20/50  config=c:\tomcat5\conf\jk2.properties
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Migrating from Struts 1.0 to Struts 1.1
You need to migrate a Struts 1.0-based application to Struts 1.1.
Replace the Struts 1.0 JAR files, tag library descriptor (TLD) files, and XML DTD files with the corresponding files from Struts 1.1. If you have JSP pages that use the absolute URI from the Struts tag libraries, you'll need to change these. Recompile your application using the new libraries and address any compilation errors.
Finally, you'll want to modify your code that is using deprecated APIs to use the new Struts 1.1 APIs.
While Struts 1.1 was a significant change to Struts 1.0, functionally speaking, applications based on Struts 1.0 can be migrated without much difficulty by replacing the Struts 1.0 JARs and TLDs with the corresponding files for Struts 1.1. You will need to change your use of the tag library URIs, as they have changed in Struts 1.1; this generally means changing your web.xml deployment descriptor. If you use the absolute URIs in your JSP pages, these values will need to be changed as well. Table 1-3 shows the changes to the tab library URIs.
Table 1-3: Struts tag library URIs
Struts 1.0.2 Taglib URI
Struts 1.1 Taglib URI
http://jakarta.apache.org/struts/tags-bean-1.0.2
http://jakarta.apache.org/struts/tags-bean
http://jakarta.apache.org/struts/tags-html-1.0.2
http://jakarta.apache.org/struts/tags-html
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Upgrading from Struts 1.1 to Struts 1.2
You want to upgrade an application based on Struts 1.1 to Struts 1.2.
  1. Download the Struts 1.2 binary distribution from http://struts.apache.org/acquiring.html.
  2. Copy the JAR files and Tag Library Descriptor (TLD) files from the Struts lib folder to your application's WEB-INF/lib folder.
  3. If you use absolute URIs for the taglib directives in your JSP pages, change these to use the new URIs shown in Table 1-4.
Table 1-4: Struts 1.1 and 1.2 Taglib URIs
Struts 1.1 Taglib URI
Struts 1.2.4 Taglib URI
http://jakarta.apache.org/struts/tags-bean
http://struts.apache.org/tags-bean
http://jakarta.apache.org/struts/tags-html
http://struts.apache.org/tags-html
http://jakarta.apache.org/struts/tags-logic
http://struts.apache.org/tags-logic
http://jakarta.apache.org/struts/tags-template
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Converting JSP Applications to Struts
You want to convert an existing JSP-based web application to a Struts application.
Take a refactoring-style approach by applying Struts as you add new features to your application. As you increase your Struts knowledge, you can re-architect the existing code to use Struts. If no new development is planned for the application, refactor the existing JSPs a page at a time.
The level of difficulty to migrate an existing JSP application depends greatly on the complexity and architectural soundness of the application. If the application uses a Model 1 architecture—that is, all logic is contained in the JSP page—it could be quite a challenge. You may find that you need to redesign the application from scratch to separate out the business logic from the presentation before you begin.
If you are new to Struts, then learn Struts on development of a new application instead of attempting to retrofit Struts to an application well into development. Struts is not a technology that can easily be "bolted on" late in the development process. However, some projects have altered their architectural underpinnings in midstream. If you are in this situation, steer the project plan so Struts is applied to new development first and preferably to features not on the critical path. Once you increase your Struts knowledge, it will be easier to convert existing code.
To make this more concrete, consider a simple example consisting of three JSP pages. The first page is the main welcome page that displays a link to the second page. The second page displays two form input fields. When the user submits the form, the result of adding the values is displayed on the third JSP page.
First, Example 1-3 shows the index.jsp page that provides a link to the input page.
Example 1-3. Linking to an input page
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
   <head>
      <title>Simple Calculator</title>
   </head>
   <body>
      <a href="get_input.jsp">Calculator</a>
   </body>
</html>
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Managing Struts Configuration Files
You want to avoid typographical errors in the various Struts configuration files and make editing and maintenance of these files easier.
Use a tool like Struts Console for viewing and editing the Struts configuration files.
One of the most common causes of errors in web applications is typographical mistakes. In general, most modern software applications—Struts included—rely on configuration files and deployment descriptors in some form of ASCII text, typically XML. Using a validating XML editor can help alleviate mistakes; however, it does not eliminate the mistyped path, form-bean name, or class name.
The Struts Console, available for download at http://www.jamesholmes.com, provides a graphical editor for the Struts (struts-config.xml), Validator (validation.xml and validator-rules.xml), and Tiles (tiles-defs.xml) configuration files. Instead of hand-editing these files, you use the Swing-based editor provided by Struts Console. In addition to reducing the typos, Struts Console gives you a birds-eye view of these files for easier browsing. You will find this feature invaluable when your configuration files start to get large.
Struts Console provides "smart" graphical editors for the XML-based configuration files used in Struts development. Figure 1-2 is the view of the struts-config.xml file for the struts-example application.
Figure 1-2: Struts Console viewing the Struts sample application
The Editor tab presents two panes. The left pane contains a tree view of the elements that make up the configuration file. The right pane contains a graphical editor window. Different editors are shown depending on the element selected in the tree view. In Figure 1-2, the /saveSubscription action mapping is selected in the tree view and the Action editor displays all the details.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Using Ant to Build and Deploy
You want to be able to build and deploy your Struts web application in a repeatable and portable manner.
Create an Ant (http://ant.apache.org) build script and use Ant (or your IDE's Ant integration) to compile, test, package, and deploy your application. Example 1-8 is a boilerplate Ant build file that can compile, build, and deploy a Struts application.
Example 1-8. Boilerplate Ant build file
<project name="jsc-ch01-r02" default="dist" basedir=".">
  <description>
      Jakarta Struts Cookbook - Ant Template
  </description>

  <!-- Enable access to environment variables -->
  <property environment="env"/>

  <!-- Set to use JDK 1.4 -->
  <property name="build.compiler" value="javac1.4"/>

  <!-- set global properties for this build -->
  <property name="src.dir" location="src"/>
  <property name="build.dir" location="build"/>
  <property name="dist.dir"  location="dist"/>
  <property name="server.dir" location="${env.CATALINA_HOME}"/>
  <property name="servlet.jar" 
     location="${server.dir}/common/lib/servlet-api.jar"/>
  <property name="jsp.jar" location="${server.dir}/common/lib/jsp-api.jar"/>
  <property name="struts.dist.dir" location="c:/jakarta-struts-1.1/lib"/>

  <!-- Struts -->
  <fileset id="struts.lib.files" dir="${struts.dist.dir}">
       <include name="**/*.jar"/>
  </fileset>
  <path id="struts.classpath">
       <fileset refid="struts.lib.files"/>
  </path>

  <path id="project.class.path">
    <pathelement location="${servlet.jar}"/>
    <pathelement location="${jsp.jar}"/>
    <path refid="struts.classpath"/>
  </path>

  <!-- Deployment Properties -->
  <property name="deploy.dir" location="${server.dir}/webapps"/>

  <target name="clean"
        description="clean up" >
    <!-- Delete the ${build.dir} and ${dist.dir} directory trees -->
    <delete dir="${build.dir}"/>
    <delete dir="${dist.dir}"/>
  </target>

  <target name="init">
    <!-- Create the build directory structure used by compile -->
    <mkdir dir="${build.dir}"/>
  </target>

  <target name="compile" depends="init"
        description="compile the source " >
    <!-- Compile the java code from ${src.dir} into ${build.dir} -->
    <javac srcdir="${src.dir}" destdir="${build.dir}" debug="on">
      <classpath>
          <path refid="project.class.path"/>
      </classpath>
    </javac>

    <copy todir="${build.dir}">
      <fileset dir="${src.dir}">
        <include name="**/*.properties"/>
      </fileset>
    </copy>
  </target>

  <target name="dist" depends="compile"
        description="generate the distribution" >

    <!-- Create the distribution directory -->
    <mkdir dir="${dist.dir}"/>

    <!-- Copy the build dir to WEB-INF/classes -->
    <mkdir dir="web/WEB-INF/classes"/>
      
    <copy todir="web/WEB-INF/classes">
        <fileset dir="${build.dir}"/>
    </copy>

    <!-- Put everything in ${build} into the war file -->
    <war destfile="${dist.dir}/${ant.project.name}.war" 
         webxml="web/WEB-INF/web.xml">
      <fileset dir="web" excludes="**/web.xml"/>
        <webinf dir="web/WEB-INF">
          <include name="*.xml"/>
          <exclude name="web.xml"/>
        </webinf>
      <lib dir="web/WEB-INF/lib">
        <include name="${struts.dist.dir}/**/*.jar"/>
        <include name="${struts.dist.dir}/**/*.tld"/>
      </lib>
      <classes dir="build"/>
    </war>
  </target>

  <!-- Deploy the application by copying it to the deployment directory -->
  <target name="deploy" depends="dist"
           description="deploy to server" >
      <unjar src="${dist.dir}/${ant.project.name}.war"
          dest="${deploy.dir}/${ant.project.name}"/>
  </target>

</project>
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Generating Struts Configuration Files Using XDoclet
When you make changes to or create a new Action or ActionForm, you have to make the corresponding changes to Struts configuration files.
Use the XDoclet tool, in conjunction with Ant, to process annotations in your Java code for automatic generation of the struts-config.xml file.
Modern software applications are commonly composed of executable code as well as text configuration files. This approach makes it easier to port your application between environments and reduces the amount of code you have to change for different deployments. However, it adds an additional burden: keeping the code and the configuration files consistent with each other.
The XDoclet tool, originally developed for use in Enterprise JavaBean development, addresses this problem. With XDoclet, the developer places annotations, similar to JavaDoc tags, in the code that describes configuration attributes related to the code. At build time, you employ custom Ant tasks that use XDoclet to process these tags and generate the corresponding XML configuration files.
For Struts, XDoclet can generate the following elements for the struts-config.xml file:
  • action elements
  • form-bean elements
In addition, XDoclet can create the field-level Struts Validator configuration, typically found in the validation.xml file. Finally, if you are mapping properties of EJB Entity Beans to Struts ActionForms, XDoclet can generate the ActionForm Java source code.
XDoclet can be downloaded from http://xdoclet.sourceforge.net. Follow the installation instructions provided to install it. You will need to have Ant installed as well.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 2: Configuring Struts Applications
Struts provides a flexible framework. It can be used in many different ways and supports customizations and extensions at several levels. As a result of this flexibility, many developers have difficulty understanding how to configure Struts to suit their purposes. Struts can be configured using the web application's web.xml file as well as one or more Struts configuration files (struts-config.xml). In addition, the Struts Validator is configured through an additional set of XML files.
This chapter goes over some of the more common and not-so-common scenarios that utilize Struts configurability. The coverage includes creating plug-ins and is a simple, yet powerful mechanism that can be used to solve a number of problems. We will cover the use of multiple configuration files, for facilitating team development as well as structuring and partitioning the web application. Finally, we will review Struts' built-in support for extensibility and the use of custom configuration properties.
You want to load initial data into the application context when your application starts up.
Create a class that implements the org.apache.struts.action.PlugIn interface and specify the plug-in element in the struts-config.xml. The following XML fragment shows a plug-in declaration and a nested set-property element for setting a custom property:
<plug-in className="com.oreilly.strutsckbk.CustomPlugin" >


  <set-property property="customData"


                   value="Hello from the plugin"/>


</plug-in>
Struts provides a PlugIn interface you can use to create custom services that are initialized on application startup. The Java source for the PlugIn interface is shown in Example 2-1. (For clarity, the JavaDoc documentation has been removed from this listing.)
Example 2-1. The Struts PlugIn interface
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Introduction
Struts provides a flexible framework. It can be used in many different ways and supports customizations and extensions at several levels. As a result of this flexibility, many developers have difficulty understanding how to configure Struts to suit their purposes. Struts can be configured using the web application's web.xml file as well as one or more Struts configuration files (struts-config.xml). In addition, the Struts Validator is configured through an additional set of XML files.
This chapter goes over some of the more common and not-so-common scenarios that utilize Struts configurability. The coverage includes creating plug-ins and is a simple, yet powerful mechanism that can be used to solve a number of problems. We will cover the use of multiple configuration files, for facilitating team development as well as structuring and partitioning the web application. Finally, we will review Struts' built-in support for extensibility and the use of custom configuration properties.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Using Plug-ins for Application Initialization
You want to load initial data into the application context when your application starts up.
Create a class that implements the org.apache.struts.action.PlugIn interface and specify the plug-in element in the struts-config.xml. The following XML fragment shows a plug-in declaration and a nested set-property element for setting a custom property:
<plug-in className="com.oreilly.strutsckbk.CustomPlugin" >


  <set-property property="customData"


                   value="Hello from the plugin"/>


</plug-in>
Struts provides a PlugIn interface you can use to create custom services that are initialized on application startup. The Java source for the PlugIn interface is shown in Example 2-1. (For clarity, the JavaDoc documentation has been removed from this listing.)
Example 2-1. The Struts PlugIn interface
package org.apache.struts.action;

import javax.servlet.ServletException;
import org.apache.struts.config.ModuleConfig;

public interface PlugIn {

    public void destroy( );

    public void init(ActionServlet servlet, ModuleConfig config)
        throws ServletException;
}
To implement a plug-in, you only need to implement this interface and declare the plug-in implementation in the struts-config.xml file. The two methods that must be implemented, init() and destroy( ), are called during the lifecycle of the plug-in. Struts calls the init( ) method after it instantiates the plug-in on startup of the ActionServlet. Struts calls the destroy() method when the ActionServlet is destroyed, usually on shutdown of the application server. At first, this plug-in feature may seem simplistic and limited. However, by utilizing another feature of Struts, the set-property element, you can pass ad hoc information to the plug-in. This capability enhances the flexibility of these classes.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Eliminating Tag Library Declarations
You want to avoid having to add taglib elements to the web.xml file every time you want to use a new tag library.
Create a JSP file containing taglib directives that refer to the absolute URIs for the tag libraries you are using. Example 2-4 (taglibs.inc.jsp) shows a JSP file containing the taglib declarations for the Struts bean, html, and logic tag libraries as well as the JSTL core and formatting tag libraries.
Example 2-4. Common tag library declarations
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean" %>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html" %>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix="logic" %>
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt" %>
Then include this file in all of your JSP pages using the include directive:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<!-- start taglib -->
<%@ include file="/includes/taglibs.inc.jsp" %>
<!-- end taglib -->

<html:html>
  <body>
    ...
Since you are using the absolute URIs in the taglib directive, you aren't required to enter a corresponding taglib element in the application's web.xml file.
If you are using a JSP 1.2/Servlet 2.3 compliant container, such as Tomcat 4.x or later, you can use an absolute URI in the taglib directive on the JSP page and you don't have to specify taglib elements in the web.xml.
Prior to the Servlet 2.3 specification, you were required to declare any JSP tag libraries you used in your applications web.xml deployment descriptor. The following snippet from a web.xml deployment descriptor shows the typical taglib descriptors used for a Struts application:
<!-- Struts Tag Library Descriptors -->
<taglib>
  <taglib-uri>/tags/struts-bean</taglib-uri>
  <taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
</taglib>
<taglib>
  <taglib-uri>/tags/struts-html</taglib-uri>
  <taglib-location>/WEB-INF/struts-html.tld</taglib-location>
</taglib>
<taglib>
  <taglib-uri>/tags/struts-logic</taglib-uri>
  <taglib-location>/WEB-INF/struts-logic.tld</taglib-location>
</taglib>
<taglib>
  <taglib-uri>/tags/struts-nested</taglib-uri>
  <taglib-location>/WEB-INF/struts-nested.tld</taglib-location>
</taglib>
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Using Constants on JSPs
Without resorting to scriptlets, you want to use application constants— public static fields defined in Java classes—on a JSP page.
Use the bind tag provided by the Jakarta Taglibs unstandard tag library to create a JSTL variable containing the value of the constant field:
<%@ taglib uri="http://jakarta.apache.org/taglibs/unstandard-1.0" prefix="un" %>
<un:bind var="constantValue"
        type="com.foo.MyClass"
       field="SOME_CONSTANT"/>
<bean:write name="constantValue"/>
A lot of teams put hard work into avoiding hard-coded String literals in their Java classes by using public static fields (constants). Unfortunately, neither Struts nor JSP provide a means to access these constants from a JSP page without resorting to JSP scriptlet like the following:
<%= com.foo.MyClass.SOME_CONSTANT %>
However, many development teams ban, or at least frown on scriptlet use on JSP pages.
Scriptlets (<% . . . %>) and runtime expressions (<%= . . . %>) place Java code directly onto a JSP page. They are not inherently evil, but they can lead your development down a slippery slope by turning your JSP pages into a tangled brittle mass of intermixed HTML, JSP, and Java code. Find solutions that don't require you to use scriptlets. You'll find—particularly with the introduction of JSTL—that you can always find a way around the dreaded scriptlet.
The Solution provides a way around this quandary through the use of a custom JSP tag, the un:bind tag. This tag is part of the unstandard tag library, part of the Jakarta Taglibs distribution. The unstandard tag library contains custom JSP tags that have been or are being considered for use in the standard tab library. The standard tag library is the Jakarta Taglibs implementation of the JSTL specification.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Using Multiple Struts Configuration Files
You want to break apart a large struts-config.xml file into smaller files for improved organization and easier maintenance, particularly in a team environment.
Split your monolithic struts-config.xml into multiple configuration files. Each file must be well-formed and valid according to the struts-config XML DTD. Reference these files as the value for the config initialization parameter of the ActionServlet in the web.xml file as shown in Example 2-9.
Example 2-9. Multiple config files (single module)
<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,
      /WEB-INF/struts-config-2.xml
    </param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
</servlet>
When the ActionServlet is loaded, Struts will merge the results of the specified configuration files into a single in-memory configuration.
For anything other than the most trivial applications, the struts-config.xml file tends to get large and unwieldy. Many applications may have action elements numbering in the hundreds. Combine this with the use of a locking source control system, and soon you will have developers in constant contention for the same file.
Struts 1.1 introduced support for multiple configuration files. Each configuration file must be a valid XML file and conform to the struts-config XML Document Type Definition (DTD). You declare the set of files as the parameter value for the config ActionServlet initialization parameter in your web.xml file. You specify the files as a comma-separated list of file paths. At runtime, the files are merged in memory into a single configuration set. If duplicate elements exist—for example, a form bean declaration with the same value for the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Factoring Your Application into Modules
You want to segregate portions of a web application into distinct subapplications, or modules, each with its own separate configuration.
Create a Struts configuration file for each module in addition to a Struts configuration file for the default module. Then declare each module using initialization parameters for the ActionServlet in the web.xml, as shown in Example 2-11.
Example 2-11. ActionServlet configuration for modules
<!-- 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>
  <init-param>
    <param-name>config/module1</param-name>
    <param-value>/WEB-INF/struts-config-module1.xml</param-value>
  </init-param>
  <init-param>
    <param-name>config/module2</param-name>
    <param-value>/WEB-INF/struts-config-module2.xml</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
</servlet>
Struts 1.1 introduced the ability to define separately configurable sub-applications known as modules. Modules were incorporated into Struts to address the need for subdividing a web application into distinct, manageable portions. Each module is defined with its own configuration file(s). Every Struts application implicitly has a default module. The default module has no module name.
To provide backward compatibility with Struts 1.0 applications, the actual name of the default module is the empty string.
Additional modules are defined by specifying a module prefix. The prefix is the value following config/ in the initialization parameter for the Struts' ActionServlet. In Example 2-11, three modules are defined. The first init-param element defines the default module. The second and third init-param
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Using Multiple Resource Bundles
You want to break apart your application resources properties file into multiple files for improved organization and easier maintenance, particularly in a team environment.
Create separate properties files and declare a message-resources element for each file in your struts-config.xml file:
<message-resources
  parameter="com.oreilly.strutsckbk.MessageResources"/>
<message-resources 
  parameter="com.oreilly.strutsckbk.LabelResources"
  key="labels">
</message-resources>
<message-resources 
  parameter="com.oreilly.strutsckbk.HeaderResources"
  key="headers">
</message-resources>
Struts uses a concept known as message resources to provide a mechanism for storing error messages, field labels, and other static text. With the default Struts implementation, you store the messages as name/value pairs in a .properties file. A message resources set is basically the same as a Java ResourceBundle.
You make your message resources properties file available to Struts using the message-resources element. The parameter attribute identifies the classpath-relative name of the properties file. You derive the value for this attribute by replacing the path separator in the file's path with a dot (".") and removing the .properties extension from the filename. For example, if the properties file was located in /WEB-INF/classes/com/oreilly/strutsckbk/MessageResources.properties, you would set up the message resources element as follows:
<message-resources
  parameter="com.oreilly.strutsckbk.MessageResources"/>
On application startup, Struts creates a runtime representation of the message resources and stores it in the servlet context.
You are not limited to one set of message resources. However, unlike using multiple Struts configuration files, if you use multiple message resource files, they are not combined or merged. Instead, you define distinct sets of message resources. Each set is identified with a unique value specified using the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Accessing Message Resources from a Database
You want to store all labels, messages, and other static text in a database rather than a properties file, while still being able to access the values using the bean:message tag.
  1. Download the OJBMessageResources distribution from http://prdownloads.sourceforge.net/struts/ojb-message-resources.zip?download.
  2. Extract the ZIP file into a directory on your computer.
  3. Copy the ojb-msg-res.jar file from the ojb-message-resources/dist folder into your application's WEB-INF/lib folder.
  4. Copy the properties, XML, and DTD files from the ojb-message-resources/config folder to your application's src folder. When you build your application, these files must be copied to the WEB-INF/classes folder.
  5. Create the tables to hold the Objec Relational Bridge (OJB) metadata tables. OJB uses these tables to keep internal mapping information. Example 2-12 shows the data definition SQL that creates these tables for the MySQL database. These statements for other databases are included with the OJB distribution.
Example 2-12. OJB metadata DDL (MySQL)
CREATE TABLE ojb_dlist (
  ID int NOT NULL default '0',
  SIZE_ int default NULL,
  PRIMARY KEY  (ID)
) TYPE=MyISAM;

CREATE TABLE ojb_dlist_entries (
  ID int NOT NULL default '0',
  DLIST_ID int NOT NULL default '0',
  POSITION_ int default NULL,
  OID_ longblob,
  PRIMARY KEY  (ID)
) TYPE=MyISAM;

CREATE TABLE ojb_dmap (
  ID int NOT NULL default '0',
  SIZE_ int default NULL,
  PRIMARY KEY  (ID)
) TYPE=MyISAM;

CREATE TABLE ojb_dmap_entries (
  ID int NOT NULL default '0',
  DMAP_ID int NOT NULL default '0',
  KEY_OID longblob,
  VALUE_OID longblob,
  PRIMARY KEY  (ID)
) TYPE=MyISAM;

CREATE TABLE ojb_dset (
  ID int NOT NULL default '0',
  SIZE_ int default NULL,
  PRIMARY KEY  (ID)
) TYPE=MyISAM;

CREATE TABLE ojb_dset_entries (
  ID int NOT NULL default '0',
  DLIST_ID int NOT NULL default '0',
  POSITION_ int default NULL,
  OID_ longblob,
  PRIMARY KEY  (ID)
) TYPE=MyISAM;

CREATE TABLE ojb_hl_seq (
  TABLENAME varchar(175) NOT NULL default '',
  FIELDNAME varchar(70) NOT NULL default '',
  MAX_KEY int default NULL,
  GRAB_SIZE int default NULL,
  PRIMARY KEY  (TABLENAME,FIELDNAME)
) TYPE=MyISAM;

CREATE TABLE ojb_lockentry (
  OID_ varchar(250) NOT NULL default '',
  TX_ID varchar(50) NOT NULL default '',
  TIMESTAMP_ decimal(10,0) default NULL,
  ISOLATIONLEVEL int default NULL,
  LOCKTYPE int default NULL,
  PRIMARY KEY  (OID_,TX_ID)
) TYPE=MyISAM;

CREATE TABLE ojb_nrm (
  NAME varchar(250) NOT NULL default '',
  OID_ longblob,
  PRIMARY KEY  (NAME)
) TYPE=MyISAM;

CREATE TABLE ojb_seq (
  TABLENAME varchar(175) NOT NULL default '',
  FIELDNAME varchar(70) NOT NULL default '',
  LAST_NUM int default NULL,
  PRIMARY KEY  (TABLENAME,FIELDNAME)
) TYPE=MyISAM;
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Selectively Disabling Actions
You want to disable an action using a custom property that can be set on the action element in your struts-config.xml file; forwarding any requests to the disabled action to an "under construction" page.
Create a custom ActionMapping extension (as shown in Example 2-16) that provides a boolean property indicating if the action is disabled or not.
Example 2-16. Custom ActionMapping
import org.apache.struts.action.ActionMapping;

public class DisablingActionMapping extends ActionMapping {

    private String disabled;
    private boolean actionDisabled = false;
    
    public String getDisabled( ) {
        return disabled;
    }

    public void setDisabled(String disabled) {
        this.disabled = disabled;
        actionDisabled = new Boolean(disabled).booleanValue( );
    }
    
    public boolean isActionDisabled( ) {
        return actionDisabled;
    }
}
This action mapping class can now be specified in the struts-config.xml file. You set the disabled property to true if an action is to be disabled:
<action-mappings type="com.oreilly.strutsckbk.DisablingActionMapping">

  <!-- Edit mail subscription -->
  <action    path="/editSubscription"
             type="org.apache.struts.webapp.example.EditSubscriptionAction"
        attribute="subscriptionForm"
            scope="request"
         validate="false">
    <set-property property="disabled" value="true"/>
    <forward name="failure"              path="/mainMenu.jsp"/>
    <forward name="success"              path="/subscription.jsp"/>
  </action>
Then create a custom RequestProcessor, such as the one shown in Example 2-17, that handles the DisablingActionMapping.
Example 2-17. Processing requests for disabled actions
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.RequestProcessor;

public class CustomRequestProcessor extends RequestProcessor {
    
    protected ActionForward processActionPerform(HttpServletRequest request, 
           HttpServletResponse response, Action action,ActionForm form, 
            ActionMapping mapping) throws IOException, ServletException {
        ActionForward forward = null;
        if (!(mapping instanceof DisablingActionMapping)) {
            forward = super.processActionPerform( request, response, 
                                                    action, form, mapping);
        }
        else {
            DisablingActionMapping customMapping = 
                  (DisablingActionMapping) mapping;
            if (customMapping.isActionDisabled( )) {
                forward = customMapping.findForward("underConstruction");
            }
            else {
                forward = super.processActionPerform( request, response,
                                                         action, form, mapping);
            }
        }
        return forward;
    }
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 3: User Interface
Face it: you can create the most architecturally pure, elegant, and robust web application, but if the users don't like the looks of the interface, you are doomed to failure. Some Java developers consider themselves above the use of such mundane technologies as HTML and JavaScript. Whether you like it or not, however, knowledge of these technologies—particularly HTML—can make all the difference when it comes to presentation and usability. If you don't know how to use them to your advantage, you will find it challenging for your application to be endorsed by the user community.
This chapter will introduce some recipes to help you get the most out of your application's presentation. The recipes here don't eliminate the need for a good graphics/user interface designer. However, they do go a long way in helping you leverage HTML via the dynamic capability of Struts. In addition, this chapter will provide alternative solutions based on complementary technologies, such as JSTL.
Some scenarios when working with HTML forms are always challenging. Checkboxes, for example, cause no end of headaches because of the way that unchecked controls are handled. This chapter includes a recipe that specifically tackles this problem. Another common issue in form processing is how to handle date fields. There are many ways to do them and they all have their pros and cons. A recipe that highlights these different approaches is included in this chapter as well.
You'll find various other recipes that address issues such as setting form tab order, generating URLs for use in JavaScript, and working with frames. All in all, if you've got a user interface problem, there is a good chance that you'll find some help in these pages.
You want to use the JSP Standard Tag Library (JSTL) tags in your Struts application.
Download the Jakarta Taglibs JSTL reference implementation from http://jakarta.apache.org/taglibs. Copy the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Introduction
Face it: you can create the most architecturally pure, elegant, and robust web application, but if the users don't like the looks of the interface, you are doomed to failure. Some Java developers consider themselves above the use of such mundane technologies as HTML and JavaScript. Whether you like it or not, however, knowledge of these technologies—particularly HTML—can make all the difference when it comes to presentation and usability. If you don't know how to use them to your advantage, you will find it challenging for your application to be endorsed by the user community.
This chapter will introduce some recipes to help you get the most out of your application's presentation. The recipes here don't eliminate the need for a good graphics/user interface designer. However, they do go a long way in helping you leverage HTML via the dynamic capability of Struts. In addition, this chapter will provide alternative solutions based on complementary technologies, such as JSTL.
Some scenarios when working with HTML forms are always challenging. Checkboxes, for example, cause no end of headaches because of the way that unchecked controls are handled. This chapter includes a recipe that specifically tackles this problem. Another common issue in form processing is how to handle date fields. There are many ways to do them and they all have their pros and cons. A recipe that highlights these different approaches is included in this chapter as well.
You'll find various other recipes that address issues such as setting form tab order, generating URLs for use in JavaScript, and working with frames. All in all, if you've got a user interface problem, there is a good chance that you'll find some help in these pages.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Using JSTL
You want to use the JSP Standard Tag Library (JSTL) tags in your Struts application.
Download the Jakarta Taglibs JSTL reference implementation from http://jakarta.apache.org/taglibs. Copy the jstl.jar and standard.jar files from the lib folder into your applications WEB-INF/lib folder. Then copy the c.tld, fmt.tld, sql.tld, and x.tld files from the tlds folder into your applications WEB-INF/lib folder.
Use the appropriate taglib directives on JSP pages where you want to use JSTL:
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
Table 3-1 lists the JSTL tag libraries and the corresponding URIs.
Table 3-1: