
Voyage among the XDoclet lepers, a struggling group of Struts developers.
Last year some of my fellow developers came back from a Florida conference to recover from all the fun, sun, and to mull over the many new technologies they had been exposed to. The big topics of the conference were brought back into the office and put on display like polished shells and interesting pieces of driftwood. Some of the smaller ones however were quickly forgotten, left in the bottom of the sack, or shaken into the rug like sand in the bottom of your shoe. XDoclet was one of the latter. It wasn't until this month that I got around to investigating this technology. As promising as it seemed, my final report is, sadly, that it isn't of much use to a struts developer.
The main argument for using XDoclet is that it can reduce the number of artifacts that the developer is responsible for creating and maintaining, which when I was first learning Struts was one of my biggest complaints. In Struts (just in case you don't know) every Action class (the code that makes a web application so much more than just a plain web page) relates to several XML artifacts (files) that have significant impact on how that Action interacts with the application. The XML is basically the glue that holds your individual Actions and templates together. The big three of these artifacts are validation.xml, struts-config.xml, and web.xml. The premise behind XDoclet is that life would be better if we could just write code without juggling all the XML files. From what you read on the XDoclet site you might think that you have just stumbled across the ultimate organizing tool. It slices, it dices, one size fits all. It sounds like a Struts developer's dream.
Sadly there is a very ugly 499 pound gorilla waiting for you at the end of this rainbow. Think carefully about struts-config.xml and the other artifacts. What could possibly be wrong with moving the information from a seperate file to individual actions? Well don't some of the sections of your struts-config.xml have nothing to do with an individual action? Take plugins for example. What are you going to do with the plugin initialization information? You can't just lump it with a random Action. That wouldn't make sense. XDoclet's solution to that is to create a seperate XML file for that plugin information. Great, but now what about the global exceptions stuff. Again, it goes in a seperate XML file. Global forwards? You guessed it, seperate file. So now instead of having that one painful boil of a configuration file on your forehead you have a rash of little ones. We now have MORE artifacts to maintain with XDoclet than without it. Crazy! I feel like I just consolidated my credit cards only to find out that the company I am consolidating with is going to send me an individual bill for every dollar I owe.
There are still 3 good arguments for using XDoclet. First, it looks really nice to have the Action specific parts of your struts-config moved into the java-docs. You don't have to look at a different file to see if you are using the validator or what the name of your forward is. Second, most of the XML artifacts that you create for XDoclet will not change much throughout the life of your project, so you set them up once and then forget about it. Third, you can tell your friends how special you feel every time you run Maven when it creates your struts-config.xml on the fly for you. It is with this last one in mind that I stuck with it and built an entire project using XDoclet. It was a difficult task and an uphill battle. The documentation was poor, the community unresponsive, and the Struts support was out of date. The following is a bunch of code snippets, files, bits and pieces that I had lying around my desk. I thought they might come in handy if you are adventerous and want to give this crazy thing called XDoclet a go. (These instructions are for Maven users only.)
- You need to get Xdoclet installed. Download it Here
- Configure the maven plugin. [code]maven plugin:download -DartifactId=maven-xdoclet-plugin -DgroupId=xdoclet -Dversion=1.2.3[/code]
- You need to add a task in your maven.xml file. This will cause maven to create the struts configuration files from comment tags in your code before a build. [code lang="xml"]
[/code]
- add the following dependencies to your project.xml file. NOTE ejb-1.0.jar is actually just ejb.jar, but I couldnât figure out how to specify a jar without a version number, so I just made it version 1.0 as a workaround. Also note that as of this writing the ibiblio repository was screwed up and the ejb jar directory was empty. [code lang="xml"]
ejb:ejb
jar
1.0
xdoclet
xdoclet-web-module
1.2.3
http://xdoclet.sf.net/
xdoclet
xdoclet-ejb-module
1.2.3
http://xdoclet.sf.net/
[/code]
xdoclet
xdoclet-apache-module
1.2.3
http://xdoclet.sf.net/
- You need a project.properties file. This goes in the same directory as your project.xml. It should look something like this: [code]# set up xdoclet to process this subset of files
maven.xdoclet.webdoclet.fileset.0=true
maven.xdoclet.webdoclet.fileset.0.include=**/*Form.java
maven.xdoclet.webdoclet.fileset.1=true
maven.xdoclet.webdoclet.fileset.1.include=**/*Action.java
# Generate a webapp descriptor pulling in merge data from metadata/web
maven.xdoclet.webdoclet.deploymentdescriptor.0=true
maven.xdoclet.webdoclet.deploymentdescriptor.0.validateXML=true
maven.xdoclet.webdoclet.deploymentdescriptor.0.distributable=false
maven.xdoclet.webdoclet.deploymentdescriptor.0.displayname=${pom.name}
maven.xdoclet.webdoclet.deploymentdescriptor.0.destDir=${basedir}/target/${pom.artifactId}/WEB-INF
maven.xdoclet.webdoclet.strutsconfigxml.1.subTaskName=Generating web.xml
maven.xdoclet.webdoclet.deploymentdescriptor.0.mergeDir=${basedir}/merge
# Generate a struts config descriptor pulling in extra data from metadata/struts
maven.xdoclet.webdoclet.strutsconfigxml.1=true
maven.xdoclet.webdoclet.strutsconfigxml.1.validateXML=true
maven.xdoclet.webdoclet.strutsconfigxml.1.Version=1.2
maven.xdoclet.webdoclet.strutsconfigxml.1.destDir=${basedir}/target/${pom.artifactId}/WEB-INF
maven.xdoclet.webdoclet.strutsconfigxml.1.subTaskName=Generating struts-config.xml
maven.xdoclet.webdoclet.strutsconfigxml.1.mergeDir=${basedir}/merge
# Generate a struts validation descriptor
maven.xdoclet.webdoclet.strutsvalidationxml.1=true
maven.xdoclet.webdoclet.strutsvalidationxml.1.destDir=${maven.build.dir}/${pom.artifactId}/WEB-INF
maven.xdoclet.webdoclet.strutsvalidationxml.1.subTaskName=Generating struts-validation.xml[/code] - Here is an example of how to add attributes to an Action class [code lang="java"]package org.renew.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
/**
* The IndexAction Class sets up the index page.
*
* @author Josh Cronemeyer
* @struts.action
* name="IndexAction"
* path="/index"
* type="org.renew.action.IndexAction"
* scope="request"
*
* @struts.action-forward
* name="login"
* path="login.page"
* redirect="false"
*
*/
public class IndexAction extends Action {
/**
* setup the variables to display on the index page.
*/
public ActionForward execute2(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
return mapping.findForward("login");
}
}[/code] - Here is how to generate a form definition in struts-config [code lang="java"]/**
* @struts.dynaform name="loginForm"
* type="org.apache.struts.validator.DynaValidatorActionForm"
* validate="true"
*/
public class LoginForm {
String ssn;
String certNum;
String certLevel;
/**
* @struts.dynaform-field
*/
public String getCertLevel() {
return certLevel;
}
/**
* @struts.validator type="required"
* @struts.validator-args arg0resource="login.certLevel"
*/
public void setCertLevel(String certLevel) {
this.certLevel = certLevel;
}
/**
* @struts.dynaform-field
*/
public String getCertNum() {
return certNum;
}
/**
* @struts.validator type="required"
* @struts.validator-args arg0resource="login.certNum"
*/
public void setCertNum(String certNum) {
this.certNum = certNum;
}
/**
* @struts.dynaform-field
*/
public String getSsn() {
return ssn;
}
/**
* @struts.validator type="required"
* @struts.validator-args arg0resource="login.ssn"
*/
public void setSsn(String ssn) {
this.ssn = ssn;
}
}[/code]
Yuck. I got all that setup and all the XML artifacts going, and even got XDoclet to generate my struts-config.xml, but when I tried to build my project I realized that XDoclet was creating an old version of struts-confg (v 1.0). Modern versions of struts have a newer dtd(v 1.2) which is required. Another problem I encountered was that it wouldn't generate the validation.xml at all. I took these problems up with the mailing list since thier documentation web site was difficult to navigate and very oddly organized.
The responses I got were funny to me at first, because instead of answers I got questions. The thread I started immediately got hijacked by another person trying to get XDoclet and Struts to work together. He was having the same problems that I was having, and he pointed out a few problems that I was having that I hadn't even discovered yet. It was sad I couldn't help the guy because he was as desperate for answers as I. It was at that moment that I swore off XDoclet. EJB programmers may find use in that tool, but for Struts you would do well to steer clear of the snake oil they are selling. Don't become one of the lost souls I encountered on their mailing list, desperately looking for that configuration symbol or switch that will suddenly make all the effort worthwhile.
It ain't worth it.
References
No comments:
Post a Comment