Maven javadoc Search redirects to “/undefined/..”

2020-07-03 04:00发布

问题:

I have generated javadoc with javadoc maven plugin 3.0.1 and Java 9. However, when I use the new Search capability and pick a class, it redirects to "File not found"...

There is undefined in the url (e.g. "../target/site/apidocs/undefined/com/mycompany/MyClass.html"), which if removed, loads the page correctly.

Could you please help me with the right configuration to generate java doc (get rid of this undefined), so the search capability load the html page fine?

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-javadoc-plugin</artifactId>
    <version>${version.maven-javadoc-plugin}</version>
        <executions>
            <execution>
                <id>javadoc</id>
                <goals>
                    <goal>javadoc</goal>
                </goals>
                <phase>prepare-package</phase>
                <configuration>
                    <doclint>none</doclint>
                    <dependencySourceIncludes>
                       <dependencySourceInclude>com.some:some</dependencySourceInclude>
                    </dependencySourceIncludes>
                    <doctitle>Title - ${project.version}</doctitle>
                    <includeDependencySources>true</includeDependencySources>
                    <windowtitle>Title</windowtitle>
                </configuration>
            </execution>
        </executions>

回答1:

Got this working with the help of the following option in the java doc maven plugin configuration

<additionalJOption>--no-module-directories</additionalJOption>


回答2:

Each .html file generated by Javadoc contains the following variable definition:

var useModuleDirectories = true;

which affects the behavior of the getURLPrefix() function in search.js:

function getURLPrefix(ui) {
    var urlPrefix="";
    if (useModuleDirectories) {
        ...
    }
    return urlPrefix;
}


Therefore, we can work around this issue by overriding the value of useModuleDirectories with false, which is possible by specifying the following script tag in the -bottom option:

<script>
if (typeof useModuleDirectories !== 'undefined') {
  useModuleDirectories = false;
}
</script>

Note that you must specify the --allow-script-in-comments option as well so that Javadoc does not complain about using the <script/> tags in comments.


Using the Javadoc maven plugin

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-javadoc-plugin</artifactId>
    <version>${javadoc.pluginVersion}</version>
    <executions>
        <execution>
            <id>javadoc</id>
            <goals>
                <goal>javadoc-no-fork</goal>
                <goal>jar</goal>
            </goals>
            <phase>process-resources</phase>
            <configuration>
                <bottom>
                <![CDATA[
                    <script>
                    if (typeof useModuleDirectories !== 'undefined') {
                      useModuleDirectories = false;
                    }
                    </script>
                ]]>
                </bottom>
                <additionalJOption>--allow-script-in-comments</additionalJOption>


回答3:

This indeed resolves the «Search» linking to ../undefined/... problem. There is however a nasty side effect: Links to standard classes or interfaces directing towards e.g. https://docs.oracle.com/en/java/javase/12/docs/api/... will be broken due to missing module names.

Consider e.g. links to java.lang.String now incorrectly pointing to https://docs.oracle.com/en/java/javase/12/docs/api/java/lang/String.html rather than towards https://docs.oracle.com/en/java/javase/12/docs/api/java.base/java/lang/String.html.



回答4:

This is a bit of a hack, but as @Martin Goik has mentioned in his answer, specifying --no-module-directories breaks any external links to standard classes due to missing module names. As the OP has mentioned in a comment, getURLPrefix(ui) of search.js is what generates the module names. So after some digging around, I found that the problem can be fixed by appending this to the end of search.js:

getURLPrefix = function(ui) {
    return "";
};

which essentially overwrites the definition of getURLPrefix to return an empty string no matter what. As it only needs to be appended to the end of a file, it should be easy enough to automate with any build tool by code or a command.

For example, if you're using Gradle, the following can be added to build.gradle:

// Needed to fix Javadoc search
// See comments below
final JAVADOC_FIX_SEARCH_STR = '\n\n' +
'getURLPrefix = function(ui) {\n' +
'    return \'\';\n' +
'};\n'

tasks.withType(Javadoc) {
    // Link to external docs
    options.with {
        // Example: Java 11 API documentation
        links 'https://docs.oracle.com/en/java/javase/11/docs/api/'
    }

    doLast {
        // Append the fix to the file
        def searchScript = new File(destinationDir.getAbsolutePath() + '/search.js')
        searchScript.append JAVADOC_FIX_SEARCH_STR
    }
}