使用 Java EE API 替换已弃用的 JPMS 模块

Posted

技术标签:

【中文标题】使用 Java EE API 替换已弃用的 JPMS 模块【英文标题】:Replacements for deprecated JPMS modules with Java EE APIs 【发布时间】:2018-06-20 14:38:47 【问题描述】:

Java 9 deprecated six modules that contain Java EE APIs 很快就会成为 going to be removed:

java.activation 带有javax.activationjava.corba 带有 javax.activityjavax.rmijavax.rmi.CORBAorg.omg.*java.transaction 带有javax.transactionjava.xml.bind 与所有 javax.xml.bind.*java.xml.wsjavax.jwsjavax.jws.soapjavax.xml.soap 和所有 javax.xml.ws.*java.xml.ws.annotation 带有javax.annotation

哪些维护的第三方工件提供了这些 API?它们提供这些 API 的能力如何或它们必须提供哪些其他功能并不重要——重要的是,它们是这些模块/包的直接替代品吗?

为了更容易收集知识,我用我目前所知道的内容进行了回答,并将答案制作为社区 wiki。我希望人们将其扩展而不是编写自己的答案。


在您投票结束之前:

是的,已经有一些关于各个模块的问题,并且对这个问题的回答当然会重复该信息。但是 AFAIK 没有任何一点可以了解所有这些,我认为这很有价值。 要求图书馆推荐的问题通常被认为是题外话,因为“它们往往会吸引固执己见的答案和垃圾邮件”,但我认为这不适用于这里。一组有效的库被清楚地描述:它们必须实现一个特定的标准。除此之外,其他一切都不重要,因此我认为意见和垃圾邮件的风险不大。

【问题讨论】:

您可以在github.com/javaee 下找到所有被移动的人,并在JEP 320: Remove the Java EE and CORBA Modules 上找到一些细节的链接 另请参阅 InfoWorld 中的这篇 2018-05-14 文章,Java roadmap: Eclipse’s Jakarta EE enterprise Java takes shape,作者是 Paul Krill。副标题:Eclipse 基金会概述了组成新的云原生、微服务友好型企业 Java 工作的 39 个项目,以及 GlassFish 将如何发展 从 JDK 11 中它已被删除。如果您使用的是 jdk 9 或更高版本,最好直接添加依赖项,而不是使用“--add-modules java.xml.bind”之类的东西 【参考方案1】:

不要使用已弃用的 Java EE 模块,而是使用以下工件。

JAF (java.activation)

JavaBeans Activation Framework(现为Jakarta Activation)是一项独立技术(可在 Maven Central 上获得):

<dependency>
    <groupId>com.sun.activation</groupId>
    <artifactId>jakarta.activation</artifactId>
    <version>1.2.2</version>
</dependency>

(Source)

CORBA (java.corba)

来自JEP 320:

除非第三方接管 CORBA API、ORB 实现、CosNaming 提供者等的维护,否则不会有独立版本的 CORBA。第三方维护是可能的,因为 Java SE 平台支持 CORBA 的独立实现。相比之下,RMI-IIOP 的 API 仅在 Java SE 中定义和实现。除非启动专门的 JSR 来维护 RMI-IIOP,否则不会有独立版本的 RMI-IIOP,或者 API 的管理权由 Eclipse 基金会接管(Java EE 的管理权从 JCP 到 Eclipse 基金会的过渡包括@ 987654323@及其CORBA和RMI-IIOP的实现)。

JTA (java.transaction)

单机版:

<dependency>
    <groupId>jakarta.transaction</groupId>
    <artifactId>jakarta.transaction-api</artifactId>
    <version>1.3.3</version>
</dependency>

(Source)

JAXB (java.xml.bind)

自从 Java EE更名为 Jakarta EE,JAXB 现在由新的工件提供:

<!-- API -->
<dependency>
    <groupId>jakarta.xml.bind</groupId>
    <artifactId>jakarta.xml.bind-api</artifactId>
    <version>2.3.3</version>
</dependency>

<!-- Runtime -->
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>2.3.3</version>
    <scope>runtime</scope>
</dependency>

<!-- Alternative runtime -->
<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <version>2.3.3</version>
    <scope>runtime</scope>
</dependency>

JAXB Reference Implementation page.

替代运行时是brought up by Abhijit Sarkar。

schemagenxjc 也可以作为独立 JAXB 发行版的一部分从那里下载。

另见linked answer。

JAX-WS (java.xml.ws)

参考实现:

<!-- API -->
<dependency>
    <groupId>jakarta.xml.ws</groupId>
    <artifactId>jakarta.xml.ws-api</artifactId>
    <version>2.3.3</version>
</dependency>

<!-- Runtime -->
<dependency>
    <groupId>com.sun.xml.ws</groupId>
    <artifactId>jaxws-rt</artifactId>
    <version>2.3.3</version>
</dependency>

Standalone distribution download(包含wsgenwsimport)。

常用注解(java.xml.ws.annotation

Java Commons Annotations(在 Maven 中心可用):

<dependency>
    <groupId>jakarta.annotation</groupId>
    <artifactId>jakarta.annotation-api</artifactId>
    <version>1.3.5</version>
</dependency>

(Source)

【讨论】:

如果模块从 jdk 和 com.sun.xml.ws 依赖中读取 jax-ws 怎么办? 我不确定你到底在问什么。哪个模块读取 jax-ws?如果您在模块图中有 java.xml.ws 并且在类路径中有 com.sun.xml.ws:jaxws-ri,则后者将被忽略(因为split packages)。 好吧,我想在我的模块中使用com.sun.xml.ws:jaxws-ri 而不是java.xml.ws,因为后者已被弃用并将被删除。我将依赖项添加到我的 pom 文件中,出现错误“模块 xyz 从 'java.xml.ws' 和 'java.xml.ws' 读取包 'javax.xml.ws'”。 看起来模块 java.xml.ws 终于被解析了,可能是因为--add-modules 或者因为其他一些模块需要它。你能打开一个新问题,让我们看看吗? 确实如此。两个细节:(1)如果没有显式模块(即具有模块声明的模块)依赖于 JAXB,您仍然可以将它们放在类路径上,其中拆分包无关紧要。 (2) 命令行选项--patch-module可以补分割。【参考方案2】:

JDK9 的 JAXB (java.xml.bind)

在 jdk9/10 EA 上的桌面应用程序中完美运行

<properties>
    <jaxb-api.version>2.3.0</jaxb-api.version>
</properties>

<!-- JAXB 2.3.0 for jdk9+ -->
<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>$jaxb-api.version</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <version>$jaxb-api.version</version>
</dependency>
<!-- JAXB needs javax.activation module (jdk9) -->
<dependency>
    <groupId>javax.activation</groupId>
    <artifactId>javax.activation-api</artifactId>
    <version>1.2.0</version>
</dependency>

【讨论】:

谢谢,这在 Java 10 上对我有用。但是,对于 jaxb-apijaxb-runtime 使用版本号 2.3.0 的单个属性并不是一个好主意。 Glassfish runtime is currently at 2.3.0.1,而 API 保持在 2.3.0。我建议在答案中完全删除 properties 元素,并分别在每个 dependency 中硬编码每个版本号。 我的建议:在&lt;dependencyManagement&gt;中,导入某个版本的org.glassfish.jaxb:jaxb-bom BOM(现在最新的是2.3.0.1),然后在实际的&lt;dependencies&gt;部分中,不要指定版本jaxb-apijaxb-runtime。版本号将从 BOM 中获取,这将确保它们始终保持同步并一起升级。 JAXB 2.3.[0|1] 将不再适用于 Java 11!见github.com/eclipse-ee4j/jaxb-api/issues/78【参考方案3】:

似乎 jaxws-ri 可传递地依赖于 commonj.sdo:commonj.sdo:jar:2.1.1.v201112051852,这显然可以从存储库 http://download.eclipse.org/rt/eclipselink/maven.repo 中找到

【讨论】:

可能是因为它更适合评论而不是答案。无论如何,你能解决问题吗?我似乎无法检索依赖项。 mvn -U clean install 一直说Could not find artifact commonj.sdo:commonj.sdo:jar:2.1.1.v201112051852 我不是 Maven 专家,但是当 pom.xml 中没有声明存储库时,它似乎正在寻找 commonj.sdo:commonj.sdo:jar:2.1.1.v201112051852。如果 pom.xml 中有存储库(如 spring-snapshot),还必须添加 download.eclipse.org/rt/eclipselink/maven.repository,例如 my-ideclipse-repodownload.eclipse.org/rt/eclipselink/maven.repo</url> ps。如果我的声誉足够大,我会添加评论而不是回答:) 我可以让它工作,但我还必须从我的 settings.xml 中删除一个镜像。然而,经过进一步检查,我无法重现这是如何替代已弃用的软件包。相反,我发现这个依赖关系很好:&lt;dependency&gt; &lt;groupId&gt;javax.jws&lt;/groupId&gt; &lt;artifactId&gt;jsr181-api&lt;/artifactId&gt; &lt;version&gt;1.0-MR1&lt;/version&gt; &lt;/dependency&gt; 我只能排除包sdo-eclipselink-plugin【参考方案4】:

我需要为基于 Spring Boot 2 的应用程序替换 JAX-WS (java.xml.ws) 和 JAXB (java.xml.bind),最终得到了这些 JAR(Gradle 构建):

// replacements for deprecated JDK module java.xml.ws
runtimeOnly 'javax.xml.ws:jaxws-api:2.3.0' // javax.xml.ws.* classes
runtimeOnly 'javax.jws:jsr181-api:1.0-MR1' // for javax.jws.* classes

// replacement for deprecated JDK module java.xml.bind
runtimeOnly 'javax.xml.bind:jaxb-api'
runtimeOnly 'org.glassfish.jaxb:jaxb-runtime:2.3.0.1'
runtimeOnly 'org.glassfish:javax.json:1.1.2'
runtimeOnly 'org.eclipse:yasson:1.0.1'

(您可能需要compile 或其他范围,runtimeOnly 对我们来说已经足够了。)

我注意到https://mvnrepository.com/artifact/com.sun.xml.bind/jaxb-core 被描述为“旧”,并且使用this answer 用于基于org.glassfish 的东西也带来了org.eclipse.yasson

现在情况真的很混乱,它可以工作,但任何人都应该如何确定它是最好的替代品,对吧?

【讨论】:

我们也在使用 gradle,但我一无所获。试图将 maven 解决方案翻译成 gradle 但没有成功。您的示例对我有用(虽然使用了编译,但未提供,我尝试迁移的项目正在使用 vertx)。感谢分享,事实上,我也希望很快会有关于 gradle 的一些澄清:) 请注意,情况发展得很快——就在最近我将另一个项目转移到 Spring Boot 2.2,Jakarta API 更加突出,但我们仍然需要实现。为此,我仍然使用 org.glassfish.* 的东西。每当我使用 Spring Boot 项目时,我倾向于检查它们的依赖版本附录并尽可能地遵守(将当前更改为您需要的版本):docs.spring.io/spring-boot/docs/current/reference/html/…【参考方案5】:

我发现解决这些问题的 JAXB 部分的最简单方法是在我的根 pom 或我的 bom 中使用依赖管理:

    <project ...>
      <dependencyManagement>
        <dependencies>
          <!-- ... -->
          <!-- Gone from jvm in java11 -->
          <dependency>
          <groupId>com.sun.xml.bind</groupId>
          <artifactId>jaxb-ri</artifactId>
          <version>2.4.0-b180830.0438</version>
          <scope>import</scope>
          <type>pom</type>
        </dependency>
        <!-- ... -->
      </dependencies>
    </dependencyManagement>
    </project>

在 jdk11 上编译失败的模块中:

    <!-- ... -->
    <dependencies>
      <!-- Gone from jvm in java11 -->
      <dependency>
         <groupId>javax.xml.bind</groupId>
         <artifactId>jaxb-api</artifactId>
      </dependency>
      <dependency>
         <groupId>com.sun.xml.bind</groupId>
         <artifactId>jaxb-impl</artifactId>
         <scope>runtime</scope>
      </dependency>
      <dependency>
         <groupId>org.glassfish.jaxb</groupId>
         <artifactId>jaxb-runtime</artifactId>
         <scope>runtime</scope>
      </dependency>
      <!-- ... -->
    </dependencies>  
    <!-- ... -->

另外,将org.jvnet.jaxb2.maven2:maven-jaxb2-plugin 的版本更新为 0.14.0 为我解决了所有 jaxb 生成问题。

【讨论】:

【参考方案6】:

上述答案只是一个微小的变化(改进)——此处仅针对 JAXB 举例说明。可以使用 runtime 范围添加依赖项,并且仅在有效需要的情况下(即,在构建以在版本 >= 9 的 JRE 中运行时 --- 这里以 v11 为例):

<profile>
        <id>when-on-jdk-11</id>
        <activation>
            <jdk>11</jdk>
        </activation>

        <properties>
            <!-- missing artefacts version properties -->
            <jaxb-api.version>2.3.1</jaxb-api.version>
            <jaxb-impl.version>2.3.2</jaxb-impl.version> <!-- one might let it the same with the jaxb-api.version -->
        </properties>

        <dependencies>
            <!-- runtime dependencies to avoid JAXB related CNF exceptions when running on Java 11 (e.g.: ClassNotFoundException: javax.xml.bind.annotation.XmlType) -->
            <dependency>
                <groupId>javax.xml.bind</groupId>
                <artifactId>jaxb-api</artifactId>
                <version>$jaxb-api.version</version>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>org.glassfish.jaxb</groupId>
                <artifactId>jaxb-runtime</artifactId>
                <version>$jaxb-impl.version</version>
                <scope>runtime</scope>
            </dependency>
        </dependencies>
    </profile>

【讨论】:

【参考方案7】:

我已经使用 JDK 11.0.3 对上述大多数建议进行了试验,但都没有成功。我最终发现唯一可行的解​​决方案如下。也许还有其他选项也有效,但似乎版本的选择至关重要。例如,将 com.sun.xml.ws:rt 更改为 2.3.2 会导致模块 javax.jws 不再可用。

    <dependency>
        <groupId>org.glassfish.jaxb</groupId>
        <artifactId>jaxb-runtime</artifactId>
        <version>2.4.0-b180830.0438</version>
    </dependency>
    <dependency>
        <groupId>com.sun.xml.ws</groupId>
        <artifactId>rt</artifactId>
        <version>2.3.1</version>
    </dependency> 

【讨论】:

【参考方案8】:

我在我的 spring mvc 项目中使用 jdk 11 + ant + ivy。 我收到错误“package javax.jws 不存在”所以我将 javax.jws-api-1.1.jar 添加到 classpath 并且它工作! 只需从https://repo1.maven.org/maven2/javax/jws/javax.jws-api/1.1/javax.jws-api-1.1.jar下载jar 并将其添加到 build.xml 中的类路径中

或者将其添加到您的pom.xml

<dependency>
  <groupId>javax.jws</groupId>
  <artifactId>javax.jws-api</artifactId>
  <version>1.1</version>
</dependency>

【讨论】:

您可以通过 Maven 的依赖解析系统正确包含它:&lt;dependency&gt; &lt;groupId&gt;javax.jws&lt;/groupId&gt; &lt;artifactId&gt;javax.jws-api&lt;/artifactId&gt;&lt;version&gt;1.1&lt;/version&gt; &lt;/dependency&gt;,它实际上正确解析了“javax.jws”类。【参考方案9】:

如果您在 Talend(例如 7.x)中遇到此问题,您可以在项目的 Default POM.xml 中添加:

<dependencies>
    <dependency>
        <groupId>javax.xml.soap</groupId>
        <artifactId>javax.xml.soap-api</artifactId>
        <version>1.4.0</version>
    </dependency>
</dependencies>

经过测试:

采用JDK 8.0.275.1-hotspot:好的 采用JDK 11.0.9.101-hotspot:好的 AdoptJDK 15.0.1.9-hotspot : KO(但这是另一个问题:不兼容的条件操作数类型 Exception 和 TDieException) Zulu-8.50.0.1017:好的 Zulu-11.43.1015:好的

【讨论】:

【参考方案10】:

如果您有同样的问题,请将以下依赖项添加到 pom.xml &lt;dependency&gt; &lt;groupId&gt;com.sun.xml.ws&lt;/groupId&gt; &lt;artifactId&gt;jaxws-rt&lt;/artifactId&gt; &lt;version&gt;2.3.3&lt;/version&gt; &lt;/dependency&gt;

然后使用 JAVA 8 作为替代 JRE。有关更多详细信息,请关注https://www.youtube.com/watch?v=pgSJda16N54 视频,它对我有用。

【讨论】:

【参考方案11】:

截至 2022 年,这确实是一种真正的痛苦! 我尝试了许多上述建议,但只能让它与以下依赖项一起使用。

<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-core</artifactId>
    <version>2.3.0.1</version>
</dependency>
 
<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.1</version>
</dependency>
 
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>2.3.1</version>
</dependency>
  
<dependency>
    <groupId>org.javassist</groupId>
    <artifactId>javassist</artifactId>
    <version>3.25.0-GA</version>
</dependency>

注意:不要试图更新依赖项,就这样吧,它对我有用。

【讨论】:

以上是关于使用 Java EE API 替换已弃用的 JPMS 模块的主要内容,如果未能解决你的问题,请参考以下文章

如何用新的 Blob 构造函数替换已弃用的 BlobBuilder?

如何在 Java GUI 游戏中使用已弃用的音频 API 来解决问题

用 .on 替换已弃用的 .live [重复]

替换已弃用的 `keypress` DOM 事件

jQuery:替换已弃用的“.load()”? [复制]

尝试替换已弃用的 loadnibnamed:owner