Hi, I recently tried to get xdoclet to generate my struts-config.xml, web.xml, and validation.xml files and thanks to Erik Hatcher, my JSP's, etc.
After a lot of searching I couldnt find a Maven article for this, only Ant ones. Because of this, I tried to keep a record of way I did and so on. I have tried to turn this into an article/roadmap of sorts (attached). I have decided to post it to list for two reasons. First, to get comments from those (and I am sure there are lots of you) that know infinately more than me about this kind of thing and secondly to add it to the archive and pass it on to maven-users for anyone (like me) that might find it useful. I happy to take comments, suggestion and even critisizm regarding this, as am sure that it can only make the end result better. I am also more than happy for anyone to use/abuse or publish this at their will (peril :-D). Regards, Corey
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Untitled Document</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> </head> <body> <p><strong>Maven / Struts / XDoclet Roadmap </strong><br /> <br /> <strong>Intro:</strong> <br /> Let me just say, all of these tools are fantastic and I believe the creators and maintainers have all done a wonderful job. Keep up all the great work.<br /> Next, article is NOT an intro into <a href="http://maven.apache.org/" target="_new">Maven</a>, <a href="http://struts.apache.org/" target="_new">Struts</a> or <a href="http://xdoclet.sourceforge.net/xdoclet/maven-plugin.html" target="_new">xDoclet</a>, if you are after these there are a great number of links available from the respective web sites, and the user mailing lists are all quite helpful. I firmly suggest you join the mailing lists, they are great source of information and you may even be able to help out others with your experience.</p> <p><strong>Why:</strong><br /> The main intention (and on of my pet hates) of using tools is to allow you, the programmer, to concentrate on the task at hand and not get bogged down maintaining config files and doing unnecessary work. Why do something manually when there are tools to do it for you? This is the basis of the DRY (Don't Repeat Yourself principle) <a href="http://c2.com/cgi/wiki?DontRepeatYourself" target="_new">[LINK]</a></p> <p><strong>Assumptions:</strong><br /> 1) You have downloaded and configured Maven and are using it to build your project<br /> 2) You have a struts project that you are currently working on. </p> <p><strong> General setup (required for all steps):</strong> <br /> Firstly add the following to your project.xml <br /> (Note: I am currently using xdoclet 1.2.1, version 1.2.2 has been released but I have not upgraded yet.)</p> <table width="100%" border="1"> <tr> <td valign="top"> <code><!-- Required for xdoclet generation only --><br /> <dependency><br /> <groupId>xdoclet</groupId><br /> <artifactId>maven-xdoclet-plugin</artifactId><br /> <version>1.2.1</version><br /> <type>plugin</type><br /> <url>http://xdoclet.sourceforge.net/</url><br /> </dependency><br /> <br /> <dependency><br /> <groupId>xdoclet</groupId><br /> <artifactId>xdoclet-web-module</artifactId><br /> <version>1.2.1</version><br /> <url>http://xdoclet.sourceforge.net/</url><br /> </dependency><br /> <br /> <dependency><br /> <groupId>xdoclet</groupId><br /> <artifactId>xdoclet-apache-module</artifactId><br /> <version>1.2.1</version><br /> <url>http://xdoclet.sourceforge.net</url><br /> </dependency><br /> <br /> <dependency><br /> <groupId>xdoclet</groupId><br /> <artifactId>xdoclet-ejb-module</artifactId><br /> <version>1.2.1</version><br /> <url>http://xdoclet.sourceforge.net/</url><br /> </dependency><br /> <br /> <dependency><br /> <groupId>xdoclet</groupId><br /> <artifactId>xdoclet-jmx-module</artifactId><br /> <version>1.2.1</version><br /> <url>http://xdoclet.sourceforge.net/</url><br /> </dependency></code></td> </tr> </table> <p><strong> Adding a pregoal:</strong><br /> Add the following code to your maven.xml file. Adding this will cause maven to run the xdoclet:webdoclet target before it runs the war:webapp goal. <br /> This will ensure that the config files are up-to-date whenever a war is generated. This is not necessary, but recommended for obvious reasons.<br /> You can also run the goal separately if you prefer, the command would be: <code>maven xdoclet:webdocet</code><br /> (Note: I have displayed the entire maven.xml file, this is not needed, if you already have a maven.xml file, then you only need to add the line in italics)</p> <table width="100%" border="1"> <tr> <td> <p><code><?xml version="1.0"?><br /> <br /> <project xmlns:ant="jelly:ant"><br /> <br /> <preGoal name="war:webapp"><br /> <em><attainGoal name="xdoclet:webdoclet" /></em><br /> </preGoal><br /> <br /> </project></code></p> </td> </tr> </table> <br /> <strong>Define the necessary properies for the plug-in:</strong><br /> These properties define the general xdoclet properties including the files to use. For more information regarding these values, please refer to the xdoclet site <a href="http://xdoclet.sourceforge.net/xdoclet/ant/xdoclet/modules/web/WebDocletTask.html" target="_new">[LINK]</a> <br /> These properties can be set in your build.properties file (project or user) or the project.properties file. Mine are in the project.properties for a couple of reasons, mainly they are project specific and there are a lot of them, so separating them from the rest of my build.properties is useful for me. <br /> (Special Note: Before you panic, the destDir property looks wrong and arguably it is. I always override it as I have my files going to different destinations, it is only set, just in case) <br /> <table width="100%" border="1"> <tr> <td><code># xdoclet general props<br /> maven.xdoclet.webdoclet.verbose=true <br /> maven.xdoclet.webdoclet.force=true </code> <p><code># define the files to use<br /> maven.xdoclet.webdoclet.fileset.0=true <br /> maven.xdoclet.webdoclet.fileset.0.include=**/*.java <br /> maven.xdoclet.webdoclet.jsptaglib.0=false<br /> maven.xdoclet.webdoclet.destDir=${maven.build.dir}</code></p> </td> </tr> </table> <br /> <strong>Now on to the fun stuff .....</strong> <br /> <br /> <br /> <strong>Generating the deployment descriptor (web.xml)</strong>: <br /> To generate the web.xml, we need to add a few more properties to our project.properties file. <br /> I have italicized the settings that you are most likely to change. For more information regarding these values, please refer to the xdoclet site. <a href="http://xdoclet.sourceforge.net/xdoclet/ant/xdoclet/modules/web/WebXmlSubTask.html" target="_new">[LINK]</a> <br /> You will notice that I write the web.xml back into the src directory. This is not necessary, but I find that it simplifies things. <br /> The only thing that you might want to consider is if you also take this approach, is if you are using a CVS you will most likely want to add the generated web.xml file to your .cvsignore (remove it from CVS coverage. This will of course go for the other generated files as well. <br /> <table width="100%" border="1"> <tr> <td><code># xdoclet / web.xml props<br /> maven.xdoclet.webdoclet.deploymentdescriptor.0=true<br /> [EMAIL PROTECTED],@date,@version<br /> maven.xdoclet.webdoclet.deploymentdescriptor.0.distributable=false<br /> maven.xdoclet.webdoclet.deploymentdescriptor.0.validateXML=false<br /> maven.xdoclet.webdoclet.deploymentdescriptor.0.mergeDir=<em>src/resources/merge/web</em><br /> maven.xdoclet.webdoclet.deploymentdescriptor.0.destDir=<em>src/webapp/WEB-INF/</em></code></td> </tr> </table> <p><br /> The xdoclet plugin provides for the ability to include external files into the generated file, they are referred to as 'merge points'. <br /> For a full list of all the merge points please refer to the xdoclet site. <a href="http://xdoclet.sourceforge.net/xdoclet/ant/xdoclet/modules/web/WebXmlSubTask.html" target="_new">[LINK]</a><br /> I have found the most common ones I use are:</p> <table width="100%" border="1"> <tr> <td width="19%"> servlets.xml </td> <td width="81%"> An XML unparsed entity containing the servlet elements for any additional servlets not processed by XDoclet. </td> </tr> <tr> <td> servlet-mappings.xml </td> <td> An XML unparsed entity containing the servlet-mapping elements for any additional servlets not processed by XDoclet.</td> </tr> <tr> <td> welcomefiles.xml </td> <td> An XML document containing a welcome-file-list element, used instead of welcomeFiles config parameters. </td> </tr> <tr> <td> taglibs.xml </td> <td> An XML unparsed entity containing taglib elements, for tag libraries not defined in tagLibs config parameters. </td> </tr> <tr> <td>web-resource-env-refs.xml</td> <td> An XML unparsed entity containing resource-env-ref elements for any resources not specified by web.resource-env-ref tags. </td> </tr> </table> <p>Now when you run your war:webapp goal or xdoclet:webdoclet goal your web.xml should be compiled for you.<br /> <br /> <br /> <strong>Generating the struts config file (struts-config.xml)</strong>: <br /> You may find that generating your web.xml doesn't achieve much for you as all/most of the settings end up your merge files. This has case for me, but I still use it. I find that working in a team environment it is easier to have separate files as it clears up tracking the changes, particularly in the CVS, but this is a personal preference. <br /> You will however find that generating your struts-config.xml is not a nice thing to do, it is ABSOLUTELY NECESSARY. (My opinion of course, you don't have to agree with me, but if you try it, I reckon you will)<br /> First thing we need to do add some more properties to our project.properties.<br /> Again, I have italicized the settings that you are most likely to change. For more information regarding these values, please refer to the xdoclet site. <a href="http://xdoclet.sourceforge.net/xdoclet/ant/xdoclet/modules/apache/struts/StrutsConfigXmlSubTask.html" target="_new">[LINK]</a></p> <table width="100%" border="1"> <tr> <td><code># xdoclet / struts.xml props<br /> maven.xdoclet.webdoclet.strutsconfigxml.0=true<br /> [EMAIL PROTECTED],@date,@version<br /> maven.xdoclet.webdoclet.strutsconfigxml.0.validateXML=false<br /> maven.xdoclet.webdoclet.strutsconfigxml.0.Version=1.2<br /> maven.xdoclet.webdoclet.strutsconfigxml.0.ofType=org.apache.struts.action.Action<br /> maven.xdoclet.webdoclet.strutsconfigxml.0.mergeDir=<em>src/resources/merge/struts/</em><br /> maven.xdoclet.webdoclet.strutsconfigxml.0.destDir=<em>src/webapp/WEB-INF/conf/</em></code></td> </tr> </table> <p>Now you need to add some custom javadoc-style comments to your source code, the complete list of these are available at xdoclet. <a href="http://xdoclet.sourceforge.net/xdoclet/tags/apache-tags.html" target="_new">[LINK]</a> <br /> Below you will find a simple example of the type of comments you should add to your actions and forms.</p> <table width="100%" border="1"> <tr> <td>For actions you will most likely get away with adding the following code <strong>(bold)</strong> to the <em>class's</em> javadoc comment:<br /> <code>/**<br /> * @author corsc<br /> <strong>* @struts.action<br /> * path="/AddTaskInternal"<br /> * validate="false"<br /> *<br /> * @struts.action-forward<br /> * name="success"<br /> * path="/WEB-INF/pages/Main/AddTaskInternal.jsp"<br /> </strong>*/<br /> public class AddTaskInternalAction extends Action</code></td> </tr> <tr> <td>For forms you will most likely get away with adding the following code <strong>(bold)</strong> to the <em>class's</em> javadoc comment:<br /> <code>/**<br /> * @author corsc<br /> <strong>* @struts.form<br /> * name="AddTaskInternalForm"</strong><br /> */<br /> public class AddTaskInternalForm extends ValidatorForm</code></td> </tr> </table> <p> Like the web.xml, there are merge files available for any definitions that are not (and probably can't/shouldn't be) in your source code.<br /> For a full list please refer to the xdoclet site <a href="http://xdoclet.sourceforge.net/xdoclet/ant/xdoclet/modules/apache/struts/StrutsConfigXmlSubTask.html" target="_new">[LINK]</a> <br /> I have found the most common ones I use are:</p> <table width="100%" border="1"> <tr> <td width="16%"> global-exceptions.xml</td> <td width="84%"> An XML document containing the optional global-exceptions element.</td> </tr> <tr> <td> global-forwards.xml </td> <td> An XML document containing the optional global-forwards element. </td> </tr> <tr> <td> struts-actions.xml </td> <td> An XML unparsed entity containing action elements, for additional non-XDoclet actions. </td> </tr> <tr> <td> struts-message-resources.xml</td> <td> An XML unparsed entity containing any message-resources elements.</td> </tr> <tr> <td> struts-plugins.xml </td> <td> An XML unparsed entity containing any plug-in elements. </td> </tr> </table> <p> Now when you run your war:webapp goal or xdoclet:webdoclet goal your struts-config.xml should be compiled for you.<br /> <br /> <br /> <strong>Generating struts validation file (struts-validation.xml):</strong><br /> If you wish to use the struts validation, then generating it using xdoclet (IMHO) will save you a heap of time and trouble. You would do this for much the same reasons you would generate your struts-config.xml<br /> Again we need to add some more properties (and again I have italicized those you are likely to want to change. For more information regarding these values, please refer to the xdoclet site. <a href="http://xdoclet.sourceforge.net/xdoclet/ant/xdoclet/modules/apache/struts/StrutsValidationXmlSubTask.html" target="_new">[LINK]</a></p> (Note: I am using normal forms in this example, if you are using DynaForms, there is a task for this as well. <a href="http://xdoclet.sourceforge.net/xdoclet/ant/xdoclet/modules/apache/struts/StrutsDynaFormValidationXmlSubTask.html" target="_new">[LINK]</a>) <br /> (Note2: Although it may seem obvious, for the tags to be picked up your forms MUST extend the ValidatorForm and not ActionForm) <br /> <table width="100%" border="1"> <tr> <td><code>maven.xdoclet.webdoclet.strutsvalidationxml.0=true<br /> [EMAIL PROTECTED],@date,@version<br /> maven.xdoclet.webdoclet.strutsvalidationxml.0.validateXML=false<br /> maven.xdoclet.webdoclet.strutsvalidationxml.0.version=1.1.3<br /> maven.xdoclet.webdoclet.strutsvalidationxml.0.ofType=org.apache.struts.validator.ValidatorForm<br /> maven.xdoclet.webdoclet.strutsvalidationxml.0.mergeDir=<em>src/resources/merge/validation/</em><br /> maven.xdoclet.webdoclet.strutsvalidationxml.0.destDir=<em>src/webapp/WEB-INF/conf/</em></code></td> </tr> </table> <br /> As you may have come to expect by now there are merge points for this task as well, well actually only one. <br /> <table width="100%" border="1"> <tr> <td width="16%"> validation-global.xml </td> <td width="84%"> An XML unparsed entity containing the global elements for the validation descriptor.</td> </tr> </table> <p>Now you need to add some tags to your ActionForms:<br /> </p> <table width="100%" border="1"> <tr> <td>You will most likely get away with adding the following code <strong>(bold)</strong> to the <em>setter method's</em> javadoc comment:<br /> <code>/**<br /> * Set the txtInitialTaskDesc.<br /> * @param string The txtInitialTaskDesc to set<br /> <strong>* @struts.validator<br /> * type="required"<br /> </strong>*/<br /> public void setTxtInitialTaskDesc(String string)<br /> {<br /> this.txtInitialTaskDesc = string;<br /> }</code></td> </tr> </table> <p> <br /> <br /> Now when you run your war:webapp goal or xdoclet:webdoclet goal your struts-validation.xml should be compiled for you.<br /> <br /> <br /> <strong>Extra: Generating JSP pages and corresponding Message Resources properties for your forms:</strong><br /> Now I must give credit where credit is due, there are 3 fantastic articles by Erik Hatcher on Struts and Xdoclet <a href="http://www.ftponline.com/javapro/2003_07/online/ehatcher_07_18_03/" target="_new">here</a>, <a href="http://www.fawcette.com/javapro/2003_07/online/ehatcher_07_21_03/" target="_new2">here</a> and <a href="http://www.ftponline.com/javapro/2003_07/online/ehatcher_07_25_03/" target="_new3">here</a>. Unfortunately for Maven fans, this is article is written for Ant.<br /> Not to worry, we will see that it runs just fine on Maven as well.<br /> <br /> Firstly you need to download the <a href="http://www.ftponline.com/javapro/codepage.asp?loccode=JPEP030718EH" target="_code">code</a> attached to Erik's third article <a href="http://www.ftponline.com/javapro/2003_07/online/ehatcher_07_25_03/" target="_new3">[LINK]</a>.<br /> Second, add the XDT files to your templates directory and the single java file to your project. <br /> Third, that's right, you guessed it, more properties for our project.properties </p> <table width="100%" border="1"> <tr> <td><code># Generation of JSP pages props<br /> maven.xdoclet.xdoclet.force=true<br /> maven.xdoclet.xdoclet.verbose=true<br /> maven.xdoclet.xdoclet.additionalClasspath=${maven.build.dir}/classes<br /> maven.xdoclet.xdoclet.destDir=${maven.build.dir}/generated-jsps/</code> <p>maven.xdoclet.xdoclet.fileset.0=true<br /> maven.xdoclet.xdoclet.fileset.0.include=**/*Form.java</p> <p>maven.xdoclet.xdoclet.template.0=true<br /> maven.xdoclet.xdoclet.template.0.templateFile=<em>src/resources/templates/FormKeys.xdt</em><br /> maven.xdoclet.xdoclet.template.0.ofType=org.apache.struts.action.ActionForm<br /> maven.xdoclet.xdoclet.template.0.acceptAbstractClasses=false<br /> maven.xdoclet.xdoclet.template.0.prefixWithPackageStructure=false<br /> maven.xdoclet.xdoclet.template.0.destinationFile={0}.properties</p> <p>maven.xdoclet.xdoclet.template.1=true<br /> maven.xdoclet.xdoclet.template.1.templateFile=<em>src/resources/templates/StrutsForm_jsp.xdt</em><br /> maven.xdoclet.xdoclet.template.1.ofType=org.apache.struts.action.ActionForm<br /> maven.xdoclet.xdoclet.template.1.acceptAbstractClasses=false<br /> maven.xdoclet.xdoclet.template.1.prefixWithPackageStructure=false<br /> maven.xdoclet.xdoclet.template.1.destinationFile={0}.jsp</p> </td> </tr> </table> <p>Now comes the tricky part. There is (IMHO) a bug in the current maven-xdoclet plugin (yes I have raised this with the appropriate people, but it is not resolved yet).<br /> Because the first line of both of the XDT files we use have a reference to a class inside our current project (the one from Erik's article).<br /> If you were to run maven's xdoclet:xdoclet goal now, you would would get a class not defined error.<br /> There may another way to overcome this problem, but for me I used the following technique (WARNING this is a major kludge).<br /> Inside your maven directory there should be a cache subdirectory, inside this directory there should be a maven-xdoclet-1.2.1 directory.<br /> Inside this directory you should find a plugin.jelly file, for those that are not so familiar with the internals of maven, this is the file which defines the xdoclet goals and hence allows you to run goals we have been using for this article.<br /> On lines 1359-1376 you should find the definition of the xdoclet:xdoclet goal and the classpath for this goal (see below)</p> <table width="100%" border="1"> <tr> <td> <p> <code><goal<br /> description="xdoclet"<br /> name="xdoclet:xdoclet"><br /> <br /> <taskdef name="xdoclet" classname="xdoclet.DocletTask"><br /> <classpath><br /> <br /> <path refid="maven.dependency.classpath"/><br /> <br /> <pathelement path="${plugin.getDependencyPath('xdoclet:xdoclet')}"/><br /> <pathelement path="${plugin.getDependencyPath('xdoclet:xjavadoc')}"/><br /> <pathelement path="${plugin.getDependencyPath('xdoclet:xdoclet-xdoclet-module')}"/><br /> <pathelement path="${plugin.getDependencyPath('commons-collections:commons-collections')}"/><br /> <pathelement path="${plugin.getDependencyPath('commons-logging:commons-logging')}"/><br /> <pathelement path="${plugin.getDependencyPath('log4j:log4j')}"/><br /> <br /> </classpath><br /> </taskdef></code><br /> </p> </td> </tr> </table> <br /> Now to add the classes from our current project and therefore the class from Erik's example we need to add another pathelement statement. So your code should look like (below) when completed, changes in <strong>bold</strong>. <br /> <table width="100%" border="1"> <tr> <td> <p> <code><goal<br /> description="xdoclet"<br /> name="xdoclet:xdoclet"><br /> <br /> <taskdef name="xdoclet" classname="xdoclet.DocletTask"><br /> <classpath><br /> <br /> <path refid="maven.dependency.classpath"/><br /> <br /> <pathelement path="${plugin.getDependencyPath('xdoclet:xdoclet')}"/><br /> <pathelement path="${plugin.getDependencyPath('xdoclet:xjavadoc')}"/><br /> <pathelement path="${plugin.getDependencyPath('xdoclet:xdoclet-xdoclet-module')}"/><br /> <pathelement path="${plugin.getDependencyPath('commons-collections:commons-collections')}"/><br /> <pathelement path="${plugin.getDependencyPath('commons-logging:commons-logging')}"/><br /> <pathelement path="${plugin.getDependencyPath('log4j:log4j')}"/><br /> <br /> <strong><pathelement location="${maven.xdoclet.xdoclet.additionalClasspath}"/></strong><br /> <br /> </classpath><br /> </taskdef></code><br /> </p> </td> </tr> </table> <p><br /> You may have notices a property that we added to our project.properties file earlier that you couldn't find in the xdoclet documentation, <code><strong>maven.xdoclet.xdoclet.additionalClasspath</strong></code>, this is because we just finished adding it.<br /> <br /> Now if you run the xdoclet:xdoclet goal, your JSP's and corresponding properties files have been generated and placed in the directory we specified in a line similar to this (see above).<br /> <code>maven.xdoclet.xdoclet.destDir=${maven.build.dir}/generated-jsps/<br /> </code><br /> If you take a look at the generated files, you will see the brilliance of Erik's example, all text has been externalized into property files and these display names have been 'humanized' so you are automatically ready for both translation and possibly shipping the pages of to the design team (if you are lucky enough to have one). You may want to experiment/modify Erik's class for passing the comments depending on your coding style and naming convention, I had to do this, but this because I started life as a C++ programmer and haven't lost the habit of hungarian notation. <br /> <br /> As always, I hope this has helped you and if you have any questions, suggestions or corrections, please feel free to email me.<br /> <br /> Corey Scott<br /> <a href="mailto:[EMAIL PROTECTED]">[EMAIL PROTECTED]</a><br /> </p> </body> </html>
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
