1

I have a largish multimodule Maven build. I need to generate the javadoc for all of the modules and produce an "aggregated" javadoc result that I can deploy to a box for consumption by users.

I did have this working perfectly fine for quite a while, until I tried implementing a custom taglet with specific features and requirements, which makes this more complicated to produce.

All of the submodules inherit a parent pom that is not the aggregator pom. In that parent pom I define the maven-javadoc-plugin. This is what it looked like before I added the custom taglet:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-javadoc-plugin</artifactId>
            <version>2.10.4</version>
            <configuration>
                <additionalparam>-Xdoclint:none</additionalparam>
                <bottom>Unified Service Layer - bottom</bottom>
                <doctitle>Unified Service Layer - title</doctitle>
                <footer>Unified Service Layer - footer</footer>
                <groups></groups>
                <header>Unified Service Layer - header</header>
                <level>public</level>
                <packagesheader>Unified Service Layer - packagesheader</packagesheader>
                <top>Unified Server Layer - top</top>
                <windowtitle>Unified Service Layer - windowtitle</windowtitle>
            </configuration>
            <executions>
                <execution>
                    <id>module-javadoc-jar</id>
                    <phase>package</phase>
                    <goals>
                        <goal>jar</goal>
                    </goals>
                    <configuration>
                        <show>protected</show>
                        <detectLinks>false</detectLinks>
                    </configuration>
                </execution>
                <execution>
                    <id>aggregated-documentation</id>
                    <phase>package</phase>
                    <inherited>false</inherited>
                    <goals>
                        <goal>aggregate-jar</goal>
                    </goals>
                    <configuration>
                        <show>protected</show>
                        <detectLinks>false</detectLinks>
                    </configuration>
                </execution>
            </executions>
        </plugin>

With this, I could build all all of the modules, which will generate their own javadoc (which I now know is just a validation step, as aggregate-jar doesn't use this output). I have a separate step I call from jenkins that runs "javadoc:aggregate-jar" in the root project, which produces the aggregated javadoc jar that I deploy.

Again, this has been working fine until now.

I implemented a custom javadoc taglet which requires getting access to the Class object associated with the source file it is contained within. I got this to work, at least in the individual module builds by adding the following to the configuration above:

                <taglets>
                    <taglet>
                        <tagletClass>com.att.det.taglet.ValidationConstraintsTaglet</tagletClass>
                    </taglet>
                    <taglet>
                        <tagletClass>com.att.det.taglet.ValidationConstraintsCombinedTaglet</tagletClass>
                    </taglet>
                </taglets>
                <tagletArtifacts>
                    <tagletArtifact>
                        <groupId>com.att.detsusl.taglets</groupId>
                        <artifactId>validationJavadocTaglet</artifactId>
                        <version>0.0.1-SNAPSHOT</version>
                    </tagletArtifact>
                </tagletArtifacts>

In order to have the taglet get access to the class file, I had to add a minimal plugin configuration to each subproject pom.xml, which looks like this:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-javadoc-plugin</artifactId>
            <configuration>
                <tagletArtifacts combine.children="append">
                    <tagletArtifact>
                        <groupId>com.att.detsusl</groupId>
                        <artifactId>artifact-name</artifactId>
                        <version>${current.pom.version}</version>
                    </tagletArtifact>
                </tagletArtifacts>
            </configuration>
        </plugin>

With these minimal changes, I could run the build in each module, generating the javadoc, and examining the generated javadoc output in each module, verifying that it all worked.

However, the problem is, when I run "javadoc:aggregate-jar" in the root project, all of that already built output is ignored. It reruns the javadoc generation for all of the subprojects, also ignoring the appended tagletArtifacts list in each subproject pom.xml file. As a result, I get ClassNotFound errors when it tries to get the class file.

I could "fix" this by putting all of the subproject GAVs into the top-level "tagletArtifacts" list, but I definitely do not want to do that. I liked the ability to specify this in the subproject pom.xml (with combine.children="append") to make it work.

What I need is an overall javadoc package for all of the subprojects, with the taglet able to get access to the class file, without forcing the parent pom to know about all of its subprojects. How can I do this?

David M. Karr
  • 14,317
  • 20
  • 94
  • 199

1 Answers1

1

I'm facing the same problem with all aggregate goals. I checked the source code to maven-javadoc-plugin and it turns out that aggregate work by traversing submodules and collecting source files and nothing more, thus completely ignoring any form configurations specified in the submodules.

During execution every submodule is completely ignored: source

if ( isAggregator() && !project.isExecutionRoot() ) {
    return;
}

And during collection of source files submodules are traversed: source

if ( isAggregator() && project.isExecutionRoot() ) {
    for ( MavenProject subProject : reactorProjects ) {
        if ( subProject != project ) {
            List<String> sourceRoots = getProjectSourceRoots( subProject );

So at the moment, there is no way to do this.

This is not easy to fix either since the whole plugin works by composing a single call to the actual javadoc tool. If you would like to respect settings in the submodules as well, you'll have to merge the configuration blocks of them. While this would work in your case with tagletArtifacts, it does not work for all the settings you can specify, e.g. any form of filter, and can therefore not be done in a generic way.

wazz3r
  • 472
  • 4
  • 15