Tutorials » Make Struts Development Even Faster Using XDoclet

XDoclet is an extended Javadoc Doclet engine, which enables Attribute-Oriented Programming for Java. It's a generic Java tool that lets you create custom Javadoc @tags and based on those @tags generate source code or xml deployment descriptors using a template engine that it provides. XDoclet is a metadata driven code generation engine for Java. It generates deployment descriptors, interfaces, framework classes, and other utility classes your project requires from simple Javadoc style comments (@tags).

XDoclet parses source files and generates many artifacts like XML descriptors and source code from it. You don't have to worry about out dating deployment metadata whenever you touch the code. The deployment metadata is continuously integrated. If you have written an Enterprise Java Bean, a single EJB can consist of more than one file. With XDoclet you only maintain one of them, and rest of them are generated. In short, you dramatically reduce your development time and only concentrate on business logic by using the XDoclet utility. The focus of this article is to demonstrate how XDoclet is useful in making Struts development even faster.

XDoclet functions as a collection of Ant tasks, each with a nested set of subtasks that perform a specific type of generation.

XDoclet and Struts fit perfectly with each other. I will start explaining how; with a simple example. It's out of this article's scope to explain Struts in detail. Prior knowledge of Struts is required in order to understand this article.

You have a GUI form which has a few input fields. When you use Struts, you will need a form bean with getter and setter methods for each input field, a JSP page which uses Struts tag libraries to build an UI (HTML form), and action which routes the submitted form.

The heart of the Struts framework, which binds all of the above components together, is the struts-config.xml file. Struts-config.xml is nothing but a deployment descriptor that includes classname mappings of all the form beans in the software, the mappings of URI's to Struts Action classes and also forwarding JSP pages. Following is the snippet of how struts-config.xml will look like:

<form-beans>
    <form-bean name="searchForm" type="com.ui.actionform.SearchForm" />
</form-beans>

You must be thinking this is damn easy to create manually. (Remember anything manual is not error-prone in software industry). They're are more than a few issues to consider when you create above code by hand. What happens if beans are removed from software? You would have to remove them manually from the struts-config.xml file. What happens when you add new forms to the software? You would have to add them manually in struts-config.xml. What happens if you move SearchForm to a different package? You will end up editing struts-config.xml manually and specify new path. Here where XDoclet comes into picture. Following is the code for SearchForm.java

import org.apache.struts.validator.ValidatorForm;

/**
 * Search query entry form.
 *
 * @struts.form name="searchForm"
 */
public class SearchForm extends ValidatorForm{
    private String query;
    /**
     * Sets the query attribute of the SearchForm object
     *
     * @struts.validator type="required" msgkey="query.required"
     */
    public void setQuery(String query){
        this.query = query;
    }
    public String getQuery(){
        return query;
    }
}

We just put the custom @tag in the class-level Javadoc comments like the one shown in the above example. Just by simply putting the @tag Javadoc comment, our code now tells XDoclet engine to generate form bean definition and XDoclet does the remaining.

Also, make a note of the @tag Javadoc comment before setQuery() method in the class. @struts.validator type="required" msgkey="query.required". This tag will generate validation.xml validation file for struts. Which saves your time even in generating validation.xml file.

Now let's see how it generates Action mappings automatically in struts-config.xml from @tags of Action subclasses.

import java.io.IOException;

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

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


/** @struts.action name="searchForm" path="/searchUser"
 * scope="request"
 * validate="false" parameter="action" input="mainMenu"
 *
 * @struts.action-forward name="success" path="/next.jsp"
 */

 

public class SearchAction extends Action{

    public ActionForward execute(ActionMapping mapping,ActionForm       form,HttpServletRequest request, HttpServletResponse response) throws       IOException,ServletException{
        return mapping.findForward("success");
    }
}

Above Java code explains how to put @tag at class-level in Action file to generate action mappings automatically while XDoclet generates struts-config.xml.

Now you will need to know what modification you need to make in your build file build.xml, in order to use XDoclet tasks. First of all download XDoclet from www. XDoclet.org and also Ant version 1.5.3 or later (In attached code I have used ant version 1.6).

Following section will explain how XDoclet generates struts-config.xml and validation.xml files.

<path id="xdocpath">
    <fileset dir="WEB-INF/lib">
        <include name="*.jar"/>
    </fileset>
</path>

You have to specify directory path for required jar files while executing build file.

<taskdef name="webdoclet" classname="Xdoclet.modules.web.WebDocletTask" classpathref="xdocpath">

    </taskdef>
    <webdoclet destdir="WEB-INF" mergedir="metadata/web"       excludedtags="@version,@author" verbose="true">
        <fileset dir="WEB-INF/src">
            <include name="**/*Form.java" />
            <include name="**/*Action.java" />
            <include name="**/*Servlet.java" />
        </fileset>
        <deploymentdescriptor validatexml="true"
          servletspec="2.3" sessiontimeout="60"
          destdir="WEB-INF" distributable="false">
        </deploymentdescriptor>
        <strutsconfigxml validatexml="true" version="1.1"/>
        <strutsvalidationxml/>
    </webdoclet>


<webdoclet/>: This task allows you to generate various web-related files using nested subtasks and template files. In above snippet I am also generating web.xml for Servlet.

<strutsconfigxml />: The <strutsconfigxml /> subtask is a subtask of the <webdoclet/> task. It parses the source directories for Action and Form classes that contain @struts: tags and generates a struts-config.xml based on that data. It also relies on merging for additional global config options.

Also with <strutsform/> subtask you can generate form beans from entity beans.

The same information is coded in the source code and deployment descriptors, requires developers to perform maintenance on multiple files, which is completely not acceptable in software industry. In this article I exemplified how DRY (Don't Repeat Yourself) principle can be implemented. Now contentedly you can say that you have dramatically reduced your development time and rationalized development process.

About the Author

Vikas Pandya is a Sun-certified Java software engineer. He has several years of extensive hands-on experience on Java, XML,
Webservices technologies. He currently works as J2EE,XML/XSL engineer for Framework Inc. in New York.He writes articles on Java, XML and related technologies for different web-sites. He has a passion of exploring new technologies. Contact him at vikasdp@yahoo.com.
Vikas Pandya