有选择地对已弃用的 JavaEE 模块使用第三方实现
Selectively using third-party implementation for deprecated JavaEE modules
我目前正在移植一个开源库以符合 JDK9+,它依赖于 Java 9 中已弃用的一些 Java EE 模块和在 Java 11 中删除:具体来说,JAXB、JAX-WS 和 javax.annotation。
我按照建议向第三方实现添加了显式依赖项:
<dependency>
<groupId>com.sun.xml.ws</groupId>
<artifactId>jaxws-ri</artifactId>
<version>2.3.0.1</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-ri</artifactId>
<version>2.3.0.1</version>
</dependency>
<dependency>
<groupId>com.sun.activation</groupId>
<artifactId>javax.activation</artifactId>
<version>1.2.0</version>
</dependency>
但是,我希望我的库仅在必要时(即在 JDK9+ 上)使用它们,并继续在 JDK8.
上使用认可的实现
我可以通过在 Maven 配置文件中添加依赖项来做到这一点,以便仅在 JDK 9 及更高版本上激活,但是如果我想在 Maven Central 上发布我的库的 jar 文件怎么办?我是否应该发布两种不同的 jar,一种包含 Java EE 第三方实现,用于 JDK9+,另一种不用于 JDK8?
有没有办法生成一个 jar 文件,该文件将在 JDK9+ 上使用第三方实现并在 JDK8 上使用认可的实现?
我查看了 multi-release jars,但看起来它们是为项目 类 中的 jdk 版本相关实现而设计的,而不是依赖项中的。
此外,如果无法在 JDK 8 上使用认可的实现,是否有可靠的方法来测试使用第三方实现不会引入任何回归?
Is there a way to produce a jar file that will use the third party
implementations on JDK9+ and the endorsed ones on JDK8?
不幸的是,没有。通过 jar 文件分发库时,您无法控制其他 jar 和库在 class 路径中的列出方式。这使得 class 加载对你来说是不确定的。对于您的情况,这意味着如果上述库包含在 JDK8 环境中的 class 路径中,则无法确定或控制加载哪个版本的 classes。
Also, in case it's not possible to use the endorsed implementations on
JDK 8, is there a way to reliably test that using the third party
implementations does not introduce any regressions?
作为作者,您可以在不同的运行时环境中执行测试以检查回归。
Should I publish two different jars, one with the Java EE third party
implementations included, for JDK9+ and one without for JDK8?
这是一个非常合理的解决方案,其他人以前也使用过。以 sqlserver jdbc jar 为例,它们具有基于 jre 的不同版本:https://docs.microsoft.com/en-us/sql/connect/jdbc/using-the-jdbc-driver?view=sql-server-2017
对于此处描述的情况,JDK9+ 版本的 jar 可以声明您在问题中提到的附加依赖项,而 JDK8 版本则不会。
另一种选择是使用一个 jar 并声明您提到的依赖项。这将向消费者发出信号,表明运行时环境必须在声明的依赖项中包含 classes。需要一些文档来指导库的使用者何时必须明确地将声明为提供的 jar 添加到他们的 class 路径。
恕我直言,最清晰的解决方案是两个 jar,在 jar 名称中引用 JRE 版本并具有不同的依赖项。它只需要很少的文档(大多数人根本不会看)。并且它允许您更自由地在您的库中进行更改。
我目前正在移植一个开源库以符合 JDK9+,它依赖于 Java 9 中已弃用的一些 Java EE 模块和在 Java 11 中删除:具体来说,JAXB、JAX-WS 和 javax.annotation。
我按照建议向第三方实现添加了显式依赖项
<dependency>
<groupId>com.sun.xml.ws</groupId>
<artifactId>jaxws-ri</artifactId>
<version>2.3.0.1</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-ri</artifactId>
<version>2.3.0.1</version>
</dependency>
<dependency>
<groupId>com.sun.activation</groupId>
<artifactId>javax.activation</artifactId>
<version>1.2.0</version>
</dependency>
但是,我希望我的库仅在必要时(即在 JDK9+ 上)使用它们,并继续在 JDK8.
上使用认可的实现我可以通过在 Maven 配置文件中添加依赖项来做到这一点,以便仅在 JDK 9 及更高版本上激活,但是如果我想在 Maven Central 上发布我的库的 jar 文件怎么办?我是否应该发布两种不同的 jar,一种包含 Java EE 第三方实现,用于 JDK9+,另一种不用于 JDK8?
有没有办法生成一个 jar 文件,该文件将在 JDK9+ 上使用第三方实现并在 JDK8 上使用认可的实现?
我查看了 multi-release jars,但看起来它们是为项目 类 中的 jdk 版本相关实现而设计的,而不是依赖项中的。
此外,如果无法在 JDK 8 上使用认可的实现,是否有可靠的方法来测试使用第三方实现不会引入任何回归?
Is there a way to produce a jar file that will use the third party implementations on JDK9+ and the endorsed ones on JDK8?
不幸的是,没有。通过 jar 文件分发库时,您无法控制其他 jar 和库在 class 路径中的列出方式。这使得 class 加载对你来说是不确定的。对于您的情况,这意味着如果上述库包含在 JDK8 环境中的 class 路径中,则无法确定或控制加载哪个版本的 classes。
Also, in case it's not possible to use the endorsed implementations on JDK 8, is there a way to reliably test that using the third party implementations does not introduce any regressions?
作为作者,您可以在不同的运行时环境中执行测试以检查回归。
Should I publish two different jars, one with the Java EE third party implementations included, for JDK9+ and one without for JDK8?
这是一个非常合理的解决方案,其他人以前也使用过。以 sqlserver jdbc jar 为例,它们具有基于 jre 的不同版本:https://docs.microsoft.com/en-us/sql/connect/jdbc/using-the-jdbc-driver?view=sql-server-2017 对于此处描述的情况,JDK9+ 版本的 jar 可以声明您在问题中提到的附加依赖项,而 JDK8 版本则不会。
另一种选择是使用一个 jar 并声明您提到的依赖项。这将向消费者发出信号,表明运行时环境必须在声明的依赖项中包含 classes。需要一些文档来指导库的使用者何时必须明确地将声明为提供的 jar 添加到他们的 class 路径。
恕我直言,最清晰的解决方案是两个 jar,在 jar 名称中引用 JRE 版本并具有不同的依赖项。它只需要很少的文档(大多数人根本不会看)。并且它允许您更自由地在您的库中进行更改。