Search code examples
javadocmaven-javadoc-plugintaglet

with maven-javadoc-plugin, how to load the class that taglet reference is contained within?


I've developed a custom javadoc taglet that uses reflection through an API to get information about the class the taglet is referenced within. It loads the class with "Class.forName(String)".

I was able to get this to work in the project for the taglet itself, even to the point of running integration tests using "ToolProvider.getSystemDocumentationTool()" and verifying the resulting content.

I've now installed this artifact in our nexus server, and I'm trying to reference it from a class built with Maven and the maven-javadoc-plugin.

When I first ran the build where my tag was referenced in "Foo.java", I saw a ClassNotFound exception in my taglet code, saying it couldn't find the specified class.

This tells me that it's getting into my taglet code, but it's unable to load the class file for the class in question. This is sort of ironic, as the only way it could get here is by finding and parsing the source file associated with the class.

So, I then edited the maven-javadoc-plugin configuration, adding a "additionalDependencies" block, specifying the artifact containing the class file that references the tag.

I also set the "verbose" flag, and I saw that in the resulting output, when it printed the "search path for class files", I found the artifact jar with the class in question at the end of that list.

However, I'm still getting the error.

What else could be going wrong here?

Here's some excerpts of relevant code:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-javadoc-plugin</artifactId>
            <version>2.10.4</version>
            <configuration>
                <verbose>true</verbose>
                <additionalDependencies>
                    <additionalDependency>
                        <groupId>our.group.id</groupId>
                        <artifactId>our.artifact.id</artifactId>
                        <version>${current.pom.version}</version>
                    </additionalDependency>
                </additionalDependencies>
                <additionalparam>-Xdoclint:none</additionalparam>
                <taglets>
                    <taglet>
                        <tagletClass>packagepath.taglet.ValidationConstraintsTaglet</tagletClass>
                    </taglet>
                    <taglet>
                        <tagletClass>packagepath.taglet.ValidationConstraintsCombinedTaglet</tagletClass>
                    </taglet>
                </taglets>
                <tagletArtifact>
                    <groupId>our.group.id.taglets</groupId>
                    <artifactId>validationJavadocTaglet</artifactId>
                    <version>0.0.1-SNAPSHOT</version>
                </tagletArtifact>
            </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>
            </executions>
        </plugin>

Here's part of the code in the Taglet class that shows the loading of the containing class:

@Override
public String toString(Tag tag) {
    String  className   = tag.holder().toString();
    
    StringBuilder   sb  = new StringBuilder();
    sb.append("<dt><b>Validation Constraints</b></dt>");
    sb.append("<dd>");
    sb.append("<table border=1><thead><tr><th>Property</th><th>Message</th></tr></thead>");
    sb.append("<tbody>");
    
    try {
        Class<?>    clazz   = Class.forName(className);

When I run the build, I see this output:

Generating C:\...\...\target\apidocs\help-doc.html...
[done in 2593 ms]
[WARNING] Javadoc Warnings
[WARNING] java.lang.ClassNotFoundException: ...Foo
[WARNING] at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
[WARNING] at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
[WARNING] at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
[WARNING] at java.lang.Class.forName0(Native Method)
[WARNING] at java.lang.Class.forName(Class.java:264)
[WARNING] at ....taglet.ValidationConstraintsTaglet.toString(ValidationConstraintsTaglet.java:69)

And I noticed the following line in the output (verbose is on):

[search path for class files: C:\Program Files\Java\jdk1.8.0_102\jre\lib\resources.jar,...,C:\...\our.artifact.id\target\our.artifact.id-2.7.0-SNAPSHOT.jar]

I inspected the jar at the end of the list and verified that the class in question is there.


Solution

  • I determined that adding an "additionalDependency" seems to do nothing that I can see.

    What does matter, which I didn't expect, was to add the dependency as another "tagletArtifact". I suppose if you think about it, it is a dependency needed by the taglet. When I added the GAV for the artifact the POM itself is producing, this finally worked.