SyntaxHighlighter

Friday, April 30, 2010

Introducing SpringDoclet

As the Spring Framework evolves, one of the areas that gets better with each release is annotation-based application configuration and wiring. Using Spring annotations in Java classes along with component scanning helps fight the XML bloat that can make some applications difficult to work with.

However, one downside to annotation-based configuration is that there is no central place to find all Spring-managed beans in an application. With XML Spring configuration, all the bean definitions and their injected dependencies can be seen in one or more XML files (if you have the patience to wade through all the XML required for a larger system).

Reducing the XML bloat and moving the wiring closer to the code is worth the loss of visibility in my opinion.

IDEs can help with the visibility issue. SpringSource Tool Suite (or STS, available as a stand-alone Eclipse distribution or as a set of Eclipse plugins) provides a Spring Explorer view which shows components, MVC request mappings, AOP advices, auto-wired dependencies, and more. IntelliJ IDEA has some nice Spring-related features, including navigation between beans and their auto-wired dependencies via gutter icons, but (as far as I know) it doesn't have one view to show all Spring-managed components and mappings in an application.

On the Spring Framework community forums, the user @petrp suggested a tool to generate documentation for controllers and request mappings in a Spring MVC application. The more I thought about this idea the more I liked it. Generating an HTML report from the source code would be another good way to mitigate the visibility issue.

And so, SpringDoclet was born. SpringDoclet is a Javadoc doclet designed to generate an HTML report as part of a project's build process. The report lists all classes decorated with any of the annotations from the org.springframework.stereotype package (@Component, @Service, @Repository, @Controller). It also lists all @RequestMappings with the HTTP method, URL template, and implementing class. Classes listed on the report can be cross-linked to standard Javadoc HTML reports or other source code reports like JXR.

I decided to implement this as doclet so I could get the source code scanning for free, along with integration with Maven, Ant, and other tools that already support Javadoc.

I also chose to implement the doclet in Groovy. I knew the code would need to generate HTML, and Groovy's MarkupBuilder makes that chore a breeze compared to Java. I'm still fairly new to Groovy, and using a new language on a real project (even if it is a small one) is the best way for me to really learn it. I tried to do everything the Groovy way, learned a few tricks along the way, and became much more comfortable with the language.

The code for SpringDoclet is at http://github.com/scottfrederick/springdoclet. For now, you will have to build the doclet before using it. Instructions for building and using SpringDoclet are in the README file on GitHub.

Give it a try, and let me know what you think. Please comment on this post with any feedback, suggestions for enhancements, or (gasp!) bugs.

20 comments:

  1. Hi Scott,

    I asked a question on the spring forums about a month ago regarding generating docs from annotations and javadoc which you kindly answered, telling me about your springdoclet project. Anyway I have finally found some time to test drive it. Firstly nice work, its an interesting use of groovy.

    A few questions/comments I had were:
    1. From what I can tell only the @RequestMapping and @Controller annotations are supported. Are there plans for the rest of the Spring web annotations? This would really add value I feel.
    2. If I have a class level @RequestMapping and method level @RequestMapping the "URL Template" value looks a little wierd as each value is quoted. e.g. "/classLevel""/methodLevel"

    cheers,
    Ben

    ReplyDelete
  2. Nice work Scott, I'm still trying to understand hows this all implemented ?
    Meanwhile, how about supporting @RequestParams as well, that would help us a lot for our project.

    Cheers
    Srikanth

    ReplyDelete
  3. Srikanth,

    Is there any particular part of the implementation that you have questions on?

    I put this out there a while ago to see how much interest there was, and didn't get much feedback. Adding support for @RequestParam, @PathVariable, @RequestBody/@ResponseBody etc. would be the next logical enhancements to the tool. If this would be useful for you I can find some time to do some enhancements.

    Scott

    ReplyDelete
  4. Nice work! @RequestParam, @PathVariable, @RequestBody and @ResponseBody would be nice additions.

    ReplyDelete
  5. This looks like a great start; I agree - @RequestParam, @PathVariable, @RequestBody and @ResponseBody are important additions.

    ReplyDelete
  6. Hi Scott, I could probably help you out with the @RequestParam etc. additions, I already coded them for my own plugin which does the exact same thing.

    ReplyDelete
  7. Michael,

    Sounds good. You can fork my repository on GitHub and send a pull request if you'd like. The first thing I was going to do was to change the page generation from using the DSL to using a templating language, as I think the DSL is going to get hard to maintain as the pages get more complex.

    Alternatively, if you have another plugin that is doing more than mine, you can just point people to that via a comment here.

    Thanks,
    Scott

    ReplyDelete
  8. Hi Scott,

    We are trying to using Spring doclet but it in turn refers the another jar org.codehaus.mojo:mant-maven-plugin:jar:1.0-beta-2-SNAPSHOT. It's not get downloading from Maven repository. And we are not able to find the jar any where else :-( . Please help us, we should configure it ASAP.

    Thanks in advance.

    -Sankar

    ReplyDelete
  9. Sankar,

    I'm not sure where this dependency is coming from, but I don't think it is from springdoclet. When I run "mvn depdency:tree", this jar is not in the list of direct or transitive dependencies:

    [INFO] org.springdoclet:springdoclet:jar:0.0.1
    [INFO] +- org.codehaus.gmaven.runtime:gmaven-runtime-1.7:jar:1.2:compile
    [INFO] | +- org.slf4j:slf4j-api:jar:1.5.10:compile
    [INFO] | +- org.codehaus.gmaven.feature:gmaven-feature-support:jar:1.2:compile
    [INFO] | | \- org.codehaus.gmaven.feature:gmaven-feature-api:jar:1.2:compile
    [INFO] | +- org.codehaus.gmaven.runtime:gmaven-runtime-support:jar:1.2:compile
    [INFO] | | +- org.codehaus.gmaven.runtime:gmaven-runtime-api:jar:1.2:compile
    [INFO] | | +- org.sonatype.gshell:gshell-io:jar:2.0:compile
    [INFO] | | | \- org.sonatype.gossip:gossip:jar:1.0:compile
    [INFO] | | +- org.codehaus.plexus:plexus-utils:jar:1.5.5:compile
    [INFO] | | \- com.thoughtworks.qdox:qdox:jar:1.8:compile
    [INFO] | \- jline:jline:jar:0.9.94:compile
    [INFO] +- org.codehaus.groovy:groovy-all:jar:1.7.2:compile
    [INFO] +- com.sun:tools:jar:1.5.0:system
    [INFO] +- org.springframework:spring-context:jar:3.0.2.RELEASE:test
    [INFO] | +- org.springframework:spring-aop:jar:3.0.2.RELEASE:test
    [INFO] | +- org.springframework:spring-beans:jar:3.0.2.RELEASE:test
    [INFO] | +- org.springframework:spring-core:jar:3.0.2.RELEASE:test
    [INFO] | | \- commons-logging:commons-logging:jar:1.1.1:test
    [INFO] | +- org.springframework:spring-expression:jar:3.0.2.RELEASE:test
    [INFO] | \- org.springframework:spring-asm:jar:3.0.2.RELEASE:test
    [INFO] +- org.springframework:spring-web:jar:3.0.2.RELEASE:test
    [INFO] | \- aopalliance:aopalliance:jar:1.0:test
    [INFO] +- org.aspectj:aspectjweaver:jar:1.6.8:test
    [INFO] \- junit:junit:jar:4.6:test (scope not updated to compile)

    Are you trying to use springdoclet with Ant? If so, what version of Ant are you using?

    ReplyDelete
  10. Hi Scott,

    Thank you very much for your reply, we are trying to use spring doclet with maven.

    please find below the maven plugin code in pom.xml


    org.apache.maven.plugins
    maven-javadoc-plugin
    2.9

    org.springdoclet.SpringDoclet

    org.springdoclet
    springdoclet
    0.0.1

    false





    and we are getting error like this

    "Failed to execute goal org.codehaus.mojo:springdoclet-maven-plugin:1.0-b
    eta-1:springdoclet (default-cli) on project springdoclet: Execution default-cli
    of goal org.codehaus.mojo:springdoclet-maven-plugin:1.0-beta-1:springdoclet fail
    ed: Plugin org.codehaus.mojo:springdoclet-maven-plugin:1.0-beta-1 or one of its
    dependencies could not be resolved: Failure to find org.codehaus.mojo:mant-maven
    -plugin:jar:1.0-beta-2-SNAPSHOT in http://snapshots.maven.codehaus.org/maven2 wa
    s cached in the local repository, resolution will not be reattempted until the u
    pdate interval of snapshots has elapsed or updates are forced"

    The springdoclet-maven-plugin requires mant-maven-plugin jar.

    ReplyDelete
  11. Tags are not publishing I replaced with [ ]

    [plugin]
    [groupId]org.apache.maven.plugins[/groupId]
    [artifactId]maven-javadoc-plugin[/artifactId]
    [version]2.9[/version]
    [configuration]
    [doclet]org.springdoclet.SpringDoclet[/doclet]
    [docletArtifact]
    [groupId]org.springdoclet[/groupId]
    [artifactId]springdoclet[/artifactId]
    [version]0.0.1[/version]
    [/docletArtifact]
    [useStandardDocletOptions]false[/useStandardDocletOptions]
    [/configuration]
    [/plugin]

    ReplyDelete
  12. I'm confused by part of the error message here:

    Plugin org.codehaus.mojo:springdoclet-maven-plugin:1.0-beta-1 or one of its dependencies could not be resolved: Failure to find org.codehaus.mojo:mant-maven-plugin:jar:1.0-beta-2-SNAPSHOT

    Where is springdoclet-maven-plugin coming from? That's not part of the SpringDoclet project in my GitHub account or the samples there. My samples just use the standard maven-javadoc-plugin with SpringDoclet configured into it. Is that plugin coming from somewhere else?

    ReplyDelete
  13. Scott,
    Still I was getting below mentioned error if I run mvn javadoc:javadoc in command promt

    [ERROR] Failed to execute goal org.apache.maven.plugins:maven-javadoc-plugin:2.6
    .1:javadoc (default-cli) on project org.springframework.samples.petclinic: An er
    ror has occurred in JavaDocs report generation:Unable to find artifact:groupId =
    'org.springdoclet.SpringDoclet'
    [ERROR] artifactId = 'org.springdoclet'
    [ERROR] version = '1.0.0-SNAPSHOT': Could not find artifact org.springdoclet.Spr
    ingDoclet:org.springdoclet:pom:1.0.0-SNAPSHOT
    [ERROR]
    [ERROR] org.springdoclet.SpringDoclet:org.springdoclet:pom:1.0.0-SNAPSHOT

    I think springdoclet jar is not downloading. Can you please help me on this ?

    ReplyDelete
    Replies
    1. The SpringDoclet jar is not in the public maven repository. You need to build and install it locally, using "mvn install" from the root of the springdoclet project (not in the samples directory).

      Delete
  14. Scott,

    If I use mvn install , springdoclet jar is not downloading. Any other command I want to use ?

    ReplyDelete
    Replies
    1. OK, let's try this again... springdoclet.jar cannot be downloaded, because it does not exist in any public repository. You have to build it locally and install it into your local maven repository before you can use the "mvn javadoc:javadoc" in target in any project.

      Look at the instructions here: http://scottfrederick.github.io/springdoclet/using.html. Clone the github repository (https://github.com/scottfrederick/springdoclet) into a local directory, go into that directory, and run "mvn install" from there. That will build the springdoclet.jar file and install it into your local maven repository.

      Only then can you go to your project directory and run "mvn javadoc:javadoc", "mvn site", or any other maven target that runs javadoc with springdoclet.

      Delete
  15. Thanks for information. I have installed jar file using mvn install. But I am able to generate spring-summary.html file and not able generate java docs. I was getting as mentioned below INFO] --- maven-javadoc-plugin:2.9:javadoc (default-cli) @ org.springframework.samples.petclinic ---
    [WARNING] Source files encoding has not been set, using platform encoding Cp1252, i.e. build is platform dependent!
    [INFO]
    Loading source files for package com.spring.sample...
    Loading source files for package org.springframework.samples.petclinic.aspects...
    Loading source files for package org.springframework.samples.petclinic...
    Loading source files for package org.springframework.samples.petclinic.hibernate...
    Loading source files for package org.springframework.samples.petclinic.jdbc...
    Loading source files for package org.springframework.samples.petclinic.jpa...
    Loading source files for package org.springframework.samples.petclinic.util...
    Loading source files for package org.springframework.samples.petclinic.validation...
    Loading source files for package org.springframework.samples.petclinic.web...
    Constructing Javadoc information...
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS




    Can you please help me on this ?

    ReplyDelete
    Replies
    1. The spring-summary.html file is what you should expect to see as output from this tool. What else are you expecting? The output you showed looks exactly as expected also. "BUILD SUCCES" - what more could you want?

      Delete
  16. Thanks for your reply scott.
    As per your sample report spring-summary.html should be generated and also individual html files for all java classes. For example, I opened spring-summary.html and clicked one form. But I was not able to find html file for that particular java class.

    Thanks in advance.

    ReplyDelete
  17. Hi Scott!

    Thanks for the great tool!

    I tried building this with gradle. The config looks fine. When I run the task I get this error:
    Successfully started process 'command '/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/bin/javadoc''
    javadoc: error - invalid flag: -doctitle

    On looking around I found this article: http://stackoverflow.com/questions/11034326/javadoc-does-not-recognize-doctitle-option-flag/11048833#11048833

    From this it looks like an issue with the doclet itself and not gradle. If that's the case, how does it work with mavnen?

    Thanks

    ReplyDelete