Aggregated Javadoc with APIviz in Gradle
Gradle is a relatively new Java build system, which mixes some of the ideas from Maven and Ant: the well-defined structure, multi-module support and dependency management from Maven, but also the customizability from Ant.
I recently switched to using it for one of my projects, which was using Maven, when I needed to implement some rather project-specific behaviour in the build and was fairly impressed with it. Unfortunately, it still lacks some things which are easier to do in other build systems, and this post describes how I added code to my build script to generate aggregated Javadoc with APIviz UML diagrams.
There is an open ticket in the Gradle bug tracker about built-in aggregated Javdoc support, so it might be possible that this will be built into Gradle in the future. However, as I lack a time machine, I decided to base my implementation on the ‘workaround’ code in that ticket, with changes to support APIviz.
To avoid cluttering the classpath of my actual application with APIviz, I
created a new configuration for doclet JARs, and then added APIviz as a
dependency in this configuration to the root project (you’ll need to have added
the Maven central repository to your repositories
section for this to work:)
configurations {
doclet
}
dependencies {
doclet group: 'org.jboss.apiviz', name: 'apiviz', version: '1.3.2.GA'
}
The aggregateJavadoc task itself inherits from the standard Javadoc task. Mostly
it consists of configuration, however, to workaround some APIviz projects I also
had to introduce some code which runs before the task - APIviz expects all the
-sourceclasspath
directories passed to it to actually exist, whereas Gradle
does not create these directories unless a file is placed in them.
You can see the workaround in the start of task, which simply ensures these
directories actually exist to stop APIviz from complaining. This is implemented
by adding the code in the doFirst
section, which is executed before Javadoc
is.
task aggregateJavadoc(type: Javadoc) {
group 'Documentation'
description 'Generates aggregated Javadoc API documentation for the main source code of all projects.'
doFirst {
subprojects.each { project ->
project.sourceSets.main.output.each { dir ->
dir.mkdirs()
}
}
}
The next piece of code is what I borrowed from the ticket I mentioned earlier. It merges the source and classpaths of all submodules into a single path containing them, and sets these as options in the Javadoc task:
source subprojects.collect { project ->
project.sourceSets.main.allJava
}
classpath = files(subprojects.collect { project ->
project.sourceSets.main.compileClasspath
})
APIviz also expects another option to be passed to it called -sourceclasspath
,
which is the location where the compiled .class
files are placed for your
project’s .java
files. This is the code I used to set that option:
options.addStringOption('sourceclasspath', files(subprojects.collect { project ->
project.sourceSets.main.output
}).getAsPath())
I chose to make the destination directory match the directory non-aggregated Javadocs are placed in:
destinationDir file("$project.buildDir/docs/javadoc/")
The remainder of the options are mostly down to your preference. The
-nopackagediagram
is an APIviz-specific option, which I
decided to use as the package diagram tends to look messy when your project has
more than a handful of packages. The other options are all fairly standard
Javadoc options, which are explained well in the official Javadoc
documentation.
options.showAll()
options.addBooleanOption('nopackagediagram', true)
configure(options) {
windowTitle '<super secret project name here>'
docTitle '<super secret project name here>'
links 'http://docs.oracle.com/javase/7/docs/api/'
The final part to mention is the options to set the class name of the APIviz doclet, and the path to it, which can be done like so (notice the use of the configuration created earlier:)
doclet 'org.jboss.apiviz.APIviz'
docletpath file(configurations.doclet.asPath)
}
}
and that’s it! Running gradle aggregateJavadoc
should create Javadocs for all
of your sub-modules in the build/docs/javadoc
directory, including the UML
diagrams APIviz draws.