maven-javadoc-plugin:如何动态更新模块路径

maven-javadoc-plugin: How to update the module path dynamically

我有一个 Java (11.0.7) Maven (3.0.6) 多模块项目,其中包含以下模块声明:

<modules>
    <module>jdrum-commons</module>
    <module>jdrum-datastore-base</module>
    <module>jdrum-datastore-simple</module>
    <module>jdrum</module>
</modules>

这些 Maven 模块中的每一个都包含一个 module-info,它定义了必要的要求和导出以限制访问和可见性。

因此,jdrum-datastore-simple 有一些我在 jdrum 的测试中重复使用的测试实用程序 类。通过下面的代码片段在 jdrum 的配置中配置 surefire 插件,我可以毫无问题地打包整个项目。

<build>
    <plugins>
        <plugin>
            <artifactId>maven-surefire-plugin</artifactId>
            <configuration>
                <argLine>
                    <!-- Allow the unnamed module access to the tests at test-time -->
                    --add-opens jdrum/at.rovo.drum.impl=ALL-UNNAMED
                    --illegal-access=deny
                </argLine>
            </configuration>
        </plugin>
    </plugins>
</build>

在父 POM 中,我还通过 site 参数配置了报告的生成,该参数还生成了各个项目的 Javadoc。包含 javadoc 的 JAR 的配置以及作为报告一部分的 Javadoc 生成的配置都是相同的,如下所示:

<!-- Generate Javadoc while reporting -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-javadoc-plugin</artifactId>
    <version>3.2.0</version>
    <inherited>true</inherited>
    <configuration>
        <verbose>true</verbose>
        <source>${maven.compiler.source}</source>
        <show>protected</show>
        <failOnWarnings>false</failOnWarnings>
        <release>${maven.compiler.release}</release>
        <stylesheet>java</stylesheet>
    </configuration>
    <reportSets>
        <reportSet>
            <id>html</id>
            <reports>
                <report>javadoc</report>
            </reports>
        </reportSet>
    </reportSets>
</plugin>

Javadoc 生成作为 package 步骤的一部分,它生成 project-version-javadoc.jar 作为输出,因为 jdrum-datastore-simple 依赖项及其测试,仅在测试时包含:

<!-- Test data store to use for testing -->
<dependency>
    <groupId>at.rovo</groupId>
    <artifactId>jdrum-datastore-simple</artifactId>
    <version>${project.parent.version}</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>at.rovo</groupId>
    <artifactId>jdrum-datastore-simple</artifactId>
    <version>${project.parent.version}</version>
    <scope>test</scope>
    <type>test-jar</type>
</dependency>

如果我将范围从 test 更改为 compileprovided,Javadoc 生成也会失败并出现错误,例如

Exit code: 1 - javadoc: error - The code being documented uses packages in the unnamed module, but the packages defined in https://github.com/RovoMe/JDrum/jdrum-datastore-simple/apidocs/ are in named modules.

据我了解,这里的问题是 jdrum-datastore-simple 模块没有添加到 Javadoc 的模块路径中。因此,下一个合乎逻辑的步骤是add that module to the configuration

<reporting>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-javadoc-plugin</artifactId>
            <configuration>
                <additionalOptions>
                    <option>--add-modules</option>
                    <option>jdrum.datastore.simple</option>
                </additionalOptions>
            </configuration>
        </plugin>
    </plugins>
</reporting>

这会将 jdrum-datastore-simple 模块添加到 Javadoc 配置字符串,可以在现在包含

jdrum/target/site/apidocs/options 文件中看到
...
--add-modules
jdrum.datastore.simple
...

条目。在进一步分析生成的 options 文件时,很明显模块路径缺少对实际 JAR 文件的引用,因此缺少 Javadoc 生成,因此 Maven 进程因 Javadoc 无法找到定义的模块。如果我更新该选项文件并将路径添加到丢失的 JAR 文件,然后只执行 mvn package site 整个过程成功并且一切正常(因为 javadoc.bat 的纯调用位于 target/site/apidocs 文件夹也是如此)。

现在,为了使整个过程更加动态,我想添加或更新模块路径。然而,maven-javadoc-plugin 并没有直接允许这样做。因此,我想出了添加 --module-path 的进一步 maven-javadoc-plugin 选项和包含整个路径的进一步选项条目。我所说的整个路径是指每个依赖项的路径,所以不仅仅是 jdrum-datastore-simple 的路径。这也有效,但由于对各自 JAR 文件的路径进行硬编码,该项目现在不能被其他用户使用,除非他们具有我使用的相同系统和路径结构。为了解决这个问题,我迅速用模块路径中各个模块的 ${settings.localRepository}${project.parent.basedir} 属性替换了各自的路径结构。不幸的是,Javadoc 对它接受的路径结构相当挑剔,事实证明在我的 Windows 机器上 Maven 做了 return 一个以 C:\Users\... 开头的路径结构,Javadoc 无法处理。如果路径结构看起来像 C:/Users/...,但是 Javadoc 的值没问题。

在进一步的研究中,我偶然发现了 this thread,它建议使用 Maven 的 build-helper-maven-plugin 来定义新属性,即 M2 存储库,并使用内置的 reg-ex 功能来替换 \ 个字符 /。但是,添加配置如

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>build-helper-maven-plugin</artifactId>
    <version>3.1.0</version>
    <executions>
        <execution>
            <id>replace-local-repo-characters</id>
            <goals>
                <goal>regex-property</goal>
            </goals>
            <configuration>
                <name>tag.m2repo</name>
                <value>${settings.localRepository}</value>
                <regex>\</regex>
                <replacement>/</replacement>
                <failIfNoMatch>false</failIfNoMatch>
            </configuration>
        </execution>
        <execution>
            <id>replace-local-path-characters</id>
            <goals>
                <goal>regex-property</goal>
            </goals>
            <configuration>
                <name>tag.basedir</name>
                <value>${project.parent.basedir}</value>
                <regex>\</regex>
                <replacement>/</replacement>
                <failIfNoMatch>false</failIfNoMatch>
            </configuration>
        </execution>
    </executions>
</plugin>

并且使用引入的标签根本不起作用,因为 Maven 抱怨提供的值无效。如果我使用 $\{settings.localRepository} Maven 对提供的值很好,但是在最终的选项文件中,实际 settings.localRepository 的值没有更新,而是提供的字符串本身,我最终得到类似 $/{settings.localRepository}/org/slf4j/... Javadoc 无法解析,因此仍然错过 jdrum-datastore-simple 依赖项的正确位置。

那么,如何将缺少的依赖项的路径添加到生成的选项文件中定义的 maven-javadoc-plugin 模块路径,以便 Maven 实际上能够生成整个报告?

似乎 java11 Update 9(也许还有更新 8;未测试)maven-javadoc-plugin 能够为多模块项目正确生成 Javadoc,而无需更改模块路径.

对于那些对实际 Maven POM 的样子感兴趣的人: