August 30, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Code Smarter, Not Harder, With XDoclet

  • October 31, 2003
  • By David Thurmond
  • Send Email »
  • More Articles »

Example Application

To demonstrate more fully how XDoclet templates can be used to generate code, we will examine a sample JSP tag application. Using XDoclet, we will generate a taglib.tld file for the custom tags within the application, a TagExtraInfo class for each tag, and HTML tag documentation for each tag. Luckily, XDoclet will do most of the work for us. The only source code that is manually written in the application is the code for the JSP tags themselves. Everything else, except for the demonstration index.jsp file, is derived using doclet tags, templates, and predefined XDoclet tasks in Ant.

Coding the Doclet Tags

Before any templates can be written, we must first document the code using doclet tags. Below is a sample SHOWING HOW TO USE DOCLET TAGS.

/**
* This JSP tag produces a greeting based on the parameters passed
* in.
* <ul>
* <li>formal - true|false If true, the greeting is
* "Greetings"; otherwise, it is "Hi"</li>
* <li>name - A non-empty string containing the name of the person
*            to be greeted</li>
* <li>times - An integer value from one to three that determines
*             how many greetings appear.  Default is one.
* </ul>
*
* @jsp:tag name="hello"
* tag-class="com.dlt.XDocletexamples.taglib.HelloTag.class"
* tei-class="com.dlt.XDocletexamples.taglib.HelloTagExtraInfo.class"
* body-content="empty"
*  description="This tag generates a formal or informal greeting
*               based on the parameters passed in."
*/
public class HelloTag extends TagSupport {
...
  /**
  Set the formal or informal greeting.
  * @param boolean formalGreeting If true, greeting is
  * "Greetings"; otherwise, "Hi"
  * @jsp:attribute name="formal" required="true" rtexprvalue="true"
  * type="boolean" description="If true, sets the greeting to
  * 'Greetings', otherwise, to 'Hi'."
  */
  public void setFormal(boolean formalGreeting) {
...
}
..
}

There are several things to note about this code listing. First, normal Javadoc procedures should be used. Adding doclet tags to your code will not affect Javadoc generation. Second, note the @jsp:tag doclet tag at the top of the listing. This is called a class tag because it only occurs at the class level, rather than occurring multiple times within a source file. Finally, note the @jsp:attribute and @jsp:attribute-validation doclet tags. These are method tags. They can appear on any method within the class that might be relevant to the code being generated. While the @jsp:attribute tag is a predefined doclet tag that can be processed by the XDoclet template engine, the @jsp:attribute-validation tag is a custom-defined tag created specifically for this application. To create your own doclet tags, simply define them in the source code and use them within a template, as we will see later.

Generating the Taglib.tld File

To generate the taglib.tld file required to use the custom JSP tags defined as part of the application, we will use an XDoclet task that is predefined for Ant. An example follows.

<target name="generate-tld" depends="prepare,resources">
          <taskdef
             name="webdoclet"
             classname="XDoclet.web.WebDocletTask"
          >
             <classpath refid="compile.classpath"/>
          </taskdef>

          <webdoclet destDir="${taglib.tld.dir}"
          sourcePath="${java.dir}"
          classpathref="compile.classpath"
               excludedtags="@version,@author"
               mergedir="${merge.dir}">
               <fileset dir="${java.dir}">
                  <include name="**/*Tag.java"/>
               </fileset>
          <jsptaglib xmlencoding="UTF-8"
          description="This taglib contains the greeting tags that
                       demonstrate how to use XDoclet to generate
                       code."/>
          </webdoclet>
</target>

When Ant executes this task, XDoclet will parse the source code in the java.dir directory, looking for @jsp:tag and @jsp:attribute tags. The taglib.tld file will contain the information specified in the parameter values for these tags. There is one interesting thing to note about this task. The mergedir= attribute specifies the location of a file called taglib-settings.xml, which contains information about the taglib version, JSP version, icons, and other information that will go into the taglib descriptor file. This merge file allows the deployment information to be kept separate from the build information, while still including the deployment information in the build process. Thus, a different taglib-settings.xml file could be used to specify information for test and production builds.

Besides the webdoclet task demonstrated above, Xdoclet contains many other predefined Ant tasks for generating code. For details on these tasks, and the doclet tags used during task processing, consult the Xdoclet documentation. Most notably, there are predefined tasks for EJB code generation, Struts code generation, and configuration file generation for many common application servers.

Generating the TagExtraInfo Classes

A TagExtraInfo class provides extra information about validating tag attributes to the JSP container at translation time. The template shown below validates strings whose length falls within a particular range, and integers whose value falls between a minimum and maximum value. Based on the doclet tags in the source code, XDoclet can generate a TagExtraInfo class for each tag class we create. Below is a partial listing of the template code found in the tei.j template file.

/**
 * Generated File - Do Not Edit!
 */

package <XDtPackage:packageOf><XDtClass:fullClassName/>
        </XDtPackage:packageOf>;

import javax.servlet.jsp.tagext.TagExtraInfo;
import javax.servlet.jsp.tagext.TagData;

public class <XDtClass:className/>ExtraInfo extends TagExtraInfo {
/**
* Validates the parameters sent to the JSP tag.
* @param TagData data The tag attributes passed to the JSP tag.
* @return true if all validation checks pass.
*/
public boolean isValid(TagData data) {
boolean valid = true;
<XDtMethod:forAllMethods>
<XDtMethod:ifHasMethodTag tagName="jsp:attribute">
<XDtMethod:ifHasMethodTag tagName="jsp:attribute-validation">
// Validate the <XDtMethod:methodTagValue
                 tagName="jsp:attribute"
                 paramName="name"/> tag attribute
if (valid && data.getAttribute("<XDtMethod:methodTagValue
                                 tagName="jsp:attribute"
                                 paramName="name"/>") != null) {

<XDtMethod:ifMethodTagValueEquals tagName="jsp:attribute"
                                  paramName="type"
                                  value="java.lang.String">
String value = (String)data.getAttribute("<XDtMethod:methodTagValue
                                           tagName="jsp:attribute"
                                           paramName="name"/>");
valid = isValidString(value, <XDtMethod:methodTagValue
                              tagName="jsp:attribute-validation"
                              paramName="minLength"/>,
                             <XDtMethod:methodTagValue
                              tagName="jsp:attribute-validation"
                              paramName="maxLength"/>);
</XDtMethod:ifMethodTagValueEquals>
<XDtMethod:ifMethodTagValueEquals tagName="jsp:attribute"
                                  paramName="type" value="int">
Integer value = (Integer)data.getAttribute(
                "<XDtMethod:methodTagValue
                  tagName="jsp:attribute" paramName="name"/>");
valid = isValidInt(value.intValue(),
        <XDtMethod:methodTagValue
         tagName="jsp:attribute-validation"
         paramName="minValue"/>,
        <XDtMethod:methodTagValue
         tagName="jsp:attribute-validation" paramName="maxValue"/>);
</XDtMethod:ifMethodTagValueEquals>
} // if
</XDtMethod:ifHasMethodTag>
</XDtMethod:ifHasMethodTag>

</XDtMethod:forAllMethods>
return valid;
} // isValid()

private boolean isValidString(String value, int minLength,
                              int maxLength) {
...
} // isValidString()

private boolean isValidInt(int value, int minValue, int maxValue) {
...
} // isIntegerValid()
} //  <XDtClass:className/>ExtraInfo

The template consists of XDoclet template tags and Java code. Within this template, everything that is not enclosed within <XDtxxx> and </XDtxxx> tags will appear in the generated source code as-is. When the template engine encounters a content template tag, it will fill in the content referenced within the tag. For the <XdtClass:className> tag, the content returned by the template tag will be the name of the current class being processed by the template engine. Thus, <XDtClass:className/>ExtraInfo becomes HelloTagExtraInfo when the HelloTag source file is processed, and GoodbyeTagExtraInfo for the GoodbyeTag class.





Page 2 of 3



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel