O'Reilly logo

Jakarta Struts Cookbook by Bill Siggelkow

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

1.8. Generating Struts Configuration Files Using XDoclet

Problem

When you make changes to or create a new Action or ActionForm, you have to make the corresponding changes to Struts configuration files.

Solution

Use the XDoclet tool, in conjunction with Ant, to process annotations in your Java code for automatic generation of the struts-config.xml file.

Discussion

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.

Tip

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.

First, you will need to add a task to your Ant build script to call the XDoclet tasks. Example 1-9 shows an Ant target that can generate the struts-config.xml file for the struts-example web application.

Example 1-9. Webdoclet Ant target

<target name="webdoclet" depends="init">
  <taskdef 
      name="webdoclet"
      classname="xdoclet.modules.web.WebDocletTask"
      classpathref="project.class.path"/>
  <webdoclet
      mergedir="${merge.dir}"
      destdir="${generated.xml.dir}"
      excludedtags="@version,@author"
      force="${xdoclet.force}">
    <fileset dir="${src.dir}">
      <exclude name="**/*Registration*.java"/>
      <include name="**/*.java"/>
    </fileset>
    <strutsconfigxml
            version="1.1"/>
  </webdoclet>
</target>

This target calls the webdoclet custom Ant task, provided by XDoclet. This task can generate several web-related artifacts including the web.xml file, the struts-config.xml file, and the validation.xml file. For Struts applications, you probably won't need to generate the web.xml file; for Struts applications, this file doesn't change often. In Example 1-9, the webdoclet task is being used to generate the struts-config.xml file.

Not all elements of a struts-config.xml file can or should be based on annotated source code. Elements such as global forwards, global exception handlers, message resources, and plug-ins are not associated with a specific Action or ActionForm class. XDoclet handles this by letting you place this static configuration in files located in a special directory. At build time, XDoclet merges these files with elements generated in your source code. You use the mergedir attribute to specify the location of these static files. The destdir attribute specifies the directory where the generated files will be created. Generally, you want to create a separate directory for these files and copy the files into the appropriate directory for packaging and deployment after they are generated. The excludedtags attribute specifies JavaDoc tags that are to be excluded from processing by XDoclet.

Tip

It is common to exclude the @author and @version tags.

Finally, the force attribute forces XDoclet to generate new configuration files. If this attribute's value is false, new files are generated only if the corresponding annotated Java source files have changed.

The fileset element tells XDoclet which Java source files to process. You can use this element to indicate which source files contain XDoclet annotations. For example, the struts-example application uses two Struts configuration files: struts-config.xml and struts-config-registration.xml. As Example 1-9 shows, you can exclude the elements that go into the struts-config-registration.xml by setting the fileset element to exclude classes that contain the name "Registration".

The strutsconfigxml element instructs XDoclet to generate the struts-config.xml file. XDoclet generates a Struts Version 1.0-compliant file by default. Therefore, you must specify the version as "1.1" if you are using Struts 1.1. It is anticipated that XDoclet will provide support for Struts 1.2 via this attribute as well.

Once you have created this target in your build file, you can add annotations to your Action and ActionForm classes. For an ActionForm, XDoclet provides the @struts.form tag for generation of a form-bean element. The following code shows how this class-level tag is used in the SubscriptionForm of the struts-example application:

/**
 * Form bean for the user profile page...
 *
 * @struts.form 
 *    name="subscriptionForm"
 */

public final class SubscriptionForm extends ActionForm  {
  ...
}

When the webdoclet target is executed, the following form-beans element will be created in the generated struts-config.xml file:

  <!-- ========== Form Bean Definitions =================================== -->
  <form-beans>
    <form-bean
      name="subscriptionForm"
      type="org.apache.struts.webapp.example.SubscriptionForm"
    />

    <!--
         If you have non XDoclet forms, define them in a file called
         struts-forms.xml and place it in your merge directory.
    -->
  </form-beans>

XDoclet generates the form-bean element using the name you specified and creates the type attribute using the fully qualified class name of the ActionForm. This feature is one of the greatest benefits of XDoclet. Attributes of your classes, such as class names, packages, and method names are available to XDoclet just as they would be when you generate Javadocs for your application. XDoclet then uses these values where appropriate for the files being generated.

Tip

If you change the class name or package of a class, XDoclet will generate the correct configuration element without any other intervention. While IDE refactoring tools can be used to handle these types of changes, using XDoclet yields a solution that can be integrated with your existing Ant build process.

You can use XDoclet to generate action elements from your Action classes. XDoclet uses the @struts.action custom tag to allow for specification of the action element. In addition, the @struts.action-forward tag can specify nested forward elements. Likewise, @struts.action-exception tag can be used to generate action-specific declarative exception handling. The LoginAction.java class of the struts-example application is shown below with the annotations required to generate the complete action element:

/**
 * Implementation of <strong>Action</strong> that validates a user logon.
 * 
 * @struts.action
 *    path="/logon"
 *    name="logonForm"
 *    scope="session"
 *    input="logon"
 * 
 * @struts.action-exception
 *    key="expired.password"
 *    type="org.apache.struts.webapp.example.ExpiredPasswordException"
 *    path="/changePassword.jsp"
 */
public final class LogonAction extends Action {
  ...
}

The syntax of the custom tags closely matches the syntax of the corresponding XML elements. If you have your struts-config.xml defined, a good approach for using XDoclet is to cut and paste the XML elements from the struts-config.xml file into the Action class. Make the changes necessary for XDoclet to recognize the tags. The following are the annotated class comments in the LogoffAction.java file that show how the @struts.action-forward tag is used:

/**
 * Implementation of <strong>Action</strong> that processes a
 * user logoff.
 *
 * @struts.action
 *    path="/logoff"
 * 
 * @struts.action-forward
 *    name="success"
 *    path="/index.jsp"
 */

public final class LogoffAction extends Action {
  ...
}

Though XDoclet can go a long way to generating your struts-config.xml file, it can't do everything. Some action elements do not correspond to Action classes that you create. For example, the struts-example application includes the following action mapping:

<action path="/tour"
     forward="/tour.htm">
</action>

The struts-config.xml file may contain global forwards, global exceptions, a controller element, message resource elements, and plug-in elements. XDoclet doesn't generate these elements. However, it can merge files containing these elements with the generated file to produce a complete struts-config.xml file. Table 1-5 lists the files that XDoclet expects to find in the directory specified by the mergedir attribute when creating the struts-config.xml file.

Table 1-5. Files for merging into the generated struts-config.xml

Merge file

Used for

struts-data-sources.xml

An XML document containing the optional data-sources element

struts-forms.xml

An XML unparsed entity containing form-bean elements, for additional non-XDoclet forms

global-exceptions.xml

An XML document containing the optional global-exceptions element

global-forwards.xml

An XML document containing the optional global-forwards element

struts-actions.xml

An XML unparsed entity containing action elements, for additional non-XDoclet actions

struts-controller.xml

An XML document containing the optional controller element

struts-message-resources.xml

An XML unparsed entity containing any message-resources elements

struts-plugins.xml

An XML unparsed entity containing any plug-in elements

Most developers would agree that XDoclet doesn't do as much for Struts development as it does for EJB development. For example, if you are primarily using dynamic action forms declared in your struts-config.xml, then form-bean generation from ActionForm classes doesn't buy you anything. However, if you have a large application with lots of action elements and your application uses Ant, then XDoclet is certainly worth considering. XDoclet also supports generation of other types of configuration documents such as Hibernate mappings.

See Also

Recipe 1.7 provides a boilerplate Ant build script to which you can add the XDoclet targets.

Complete information for XDoclet can be found at http://xdoclet.sourceforge.net.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required