跳到主要内容

JEP 320:移除 Java EE 和 CORBA 模块

QWen Max 中英对照 JEP 320 Remove the Java EE and CORBA Modules

概述

从 Java SE 平台和 JDK 中移除 Java EE 和 CORBA 模块。这些模块在 Java SE 9 中已被标记为过时,并声明将在未来的版本中移除。

动机

Java SE 6 包含了一个完整的 Web 服务栈,为 Java 开发者提供了便利。该栈由四项技术组成,这些技术最初是为 Java EE 平台开发的:JAX-WS(基于 XML 的 Java API Web 服务)、JAXB(XML 绑定的 Java 架构)、JAF(JavaBeans 激活框架)以及通用注解。在被引入时,Java SE 中的版本与 Java EE 中的版本完全相同,只是 Java SE 删除了 Common Annotations 中与 Java EE 安全模型相关的包。然而,随着时间推移,Java EE 中的版本不断演进,这导致了 Java SE 中的版本面临以下困难:

  • 这些技术获得了与 Java SE 无关的功能。例如,Common Annotations 在 Java EE 6 中添加了一个与 Java EE 容器中的数据源有关的包。这就使得有必要定期对 Java EE 版本进行快照并创建子集,这对 JDK 工程师来说非常耗时,也让开发人员感到困惑。

  • 这些技术由 java.net 上游项目维护,后来又在 GitHub 上进行维护。由于必须将 OpenJDK 代码库中的 Java SE 版本与上游代码库中的 Java EE 版本同步,因此维护起来存在问题。

  • 开发人员可以从上游项目获取这些技术的独立版本,并通过认可标准覆盖机制进行部署。这种长期存在的机制允许独立版本安全地覆盖 Java SE 版本。但不幸的是,该机制在实践中并未得到广泛使用,开发人员反而使用特设机制来部署独立版本,例如将它们预先添加到 JDK 的引导类路径中,或者简单地将它们放在类路径上,寄希望于生成的拆分包不会引发问题。

由于 Java EE 技术的独立版本可以从第三方站点(如 Maven Central)轻松获取,因此 Java SE 平台或 JDK 无需包含它们。

另一个 Java SE 包含为开发者提供便利的技术的案例可以追溯到 1998 年。在 Ken Cavanaugh 的杰出领导下,Java SE 通过提供 OMG CORBA API、一个 ORB 实现、一个 CosNaming 实现、idlj 编译器以及对 rmic 编译器中 IDL 和 IIOP 的支持,接纳CORBA 技术。然而,随着时间推移,对 CORBA 的支持变得问题重重:

  • 由于 CORBA 是一个在 Java 社区流程之外演进的“认可标准”,因此与 Web 服务类似的评论也适用于 JDK 中 CORBA 的维护,以及安全覆盖 JDK 的 CORBA 实现的能力。在 JDK 中的 ORB 与 Java EE 应用服务器中的 ORB 同步没有任何现实的前景。

  • 在 Java 中使用 CORBA 开发现代应用程序没有显著的兴趣。此外,Java EE 8 将 CORBA、RMI-IIOP 和 JavaIDL 列为“建议可选项”,这表明对这些技术的必要支持可能会在未来被取消。

由于维护 CORBA 支持的成本超过了收益,因此 Java SE 平台或 JDK 没有理由包含它。

最后,自 Java SE 1.3 以来,Java SE 包含了 JTA(Java 事务 API)的一个子集,而自 Java SE 5.0 以来,包含了 J2EE Activity Service for Extended Transactions(J2EE 活动服务)的一个子集。

JTA 包含两个扮演不同角色且需要不同处理的包:

  • javax.transaction.xa 包支持 JDBC 中的 XA 事务。这个 “XA 包” 在 Java SE 9 中与 JDBC 一起位于 java.sql 模块中。由于 java.sql 模块不可升级,因此独立版本的 JTA 无法覆盖 Java SE 版本的 XA 包,但这通常对应用程序是可以接受的,因为 XA 包多年来一直保持稳定,并且 Java SE 版本与 Java EE 版本相同。为了便于维护,Java SE 中的 XA 包将来可能会移动到另一个不可升级的模块中,但从架构的角度来看,它将长期与 JDBC 一起保留在 Java SE 中,对于此 JEP 来说不再具有进一步的关注价值。

  • javax.transaction 包定义了一个通用的事务管理 API。该包的 Java EE 版本始终超出 Java SE 的范围,并以与 Java SE 无关的方式进行了演变。例如,JTA 在 Java EE 7 中添加了与 CDI 相关的类型。由 Java SE 定义的 javax.transaction 子集支持与 CORBA 事务服务的互操作。这个 “CORBA 互操作包” 在 Java SE 9 中存在于其自己的 java.transaction 模块中。然而,Java SE 版本通常不被使用 CORBA 事务服务的应用程序所接受,因此它们通常会用 Java EE 版本来覆盖它。

J2EE 活动服务定义了一个通用的中间件 API。自 2006 年以来,它一直没有更新,并且不是 Java EE 平台的一部分。它与本 JEP 的相关性仅在于 Java SE 包含了其一个包 javax.activity 的子集,用于与 CORBA 事务服务进行互操作。这个“活动包”存在于 Java SE 9 的 java.corba 模块中。

在 Java SE 平台或 JDK 中没有 CORBA 支持的情况下,没有理由包含来自 JTA 的 CORBA 互操作包或来自 J2EE Activity Service 的 activity 包。

描述

在 Java SE 9 中,包含 Java EE 和 CORBA 技术的 Java SE 模块被标注为计划移除的已弃用功能,这表明了在未来的版本中将移除这些模块的意图:

  • java.xml.ws(JAX-WS,以及相关的技术 SAAJWeb 服务元数据
  • java.xml.bind(JAXB)
  • java.activation(JAF)
  • java.xml.ws.annotation(通用注解)
  • java.corba(CORBA)
  • java.transaction(JTA)

Java SE 9 中的相关模块也已被弃用以便删除:

  • java.se.ee(上述六个模块的聚合器模块)
  • jdk.xml.ws(JAX-WS 的工具)
  • jdk.xml.bind(JAXB 的工具)

由于弃用模块以进行移除仅仅会导致编译时警告,JDK 9 采取了更为强有力的步骤,以让开发者为这些模块在将来版本中的实际移除做好准备:在类路径上编译或运行代码时,JDK 运行时镜像中的模块未被解析。这使得使用 JDK 9 的开发者能够在类路径上部署 Java EE 和 CORBA 技术的独立版本,就像在 JDK 8 上一样。或者,使用 JDK 9 的开发者可以在命令行中使用 --add-modules 来解析 JDK 运行时镜像中的模块。

在 Java SE 11 中,上文列出的九个模块将被移除:

  • 它们的源代码将从 OpenJDK 仓库中删除。
  • 它们的类将不存在于 JDK 运行时镜像中。
  • 它们的工具将不再可用:
    • wsgenwsimport(来自 jdk.xml.ws
    • schemagenxjc(来自 jdk.xml.bind
    • idljorbdservertooltnamesrv(来自 java.corba
  • JNDI CosNaming 提供程序(来自 java.corba)将不再可用。
  • 没有任何命令行标志能够启用它们,就像 JDK 9 中的 --add-modules 那样。

rmic 编译器将被更新以移除 -idl-iiop 选项。因此,rmic 将不再能够生成 IDL 或 IIOP 存根和绑定类。

JDK 文档 和手册页将更新,以删除对这些模块和工具的引用,并指明 rmic 的变化。

测试

所有运行 Java EE 或 CORBA API 的 JDK、JCK 和 SQE 测试都将被移除。

风险与假设

Java EE 模块

移除 Java EE 模块的风险在于,如果应用程序依赖 JDK 中“开箱即用”的 Java EE API 和工具支持,它们将无法编译或运行。当这些应用程序从 JDK 6、7 或 8 迁移到 JDK 9 或更高版本时,将会遇到二进制和源码不兼容的问题。一般来说,这些应用程序可以分为以下两类:

  1. 独立的程序,位于 Java EE 应用服务器之外,用于操作 Web 服务和 XML。

  2. 与 Web 服务或 XML 无关,但依赖于 Java EE API 中的个别类来实现通用功能的应用程序。例如,某些应用程序依赖 JAXB 并非为了 XML 绑定,而是为了 javax.xml.bind.DatatypeConverter 类提供的 Base64 支持。(从历史上看,这个类比 sun.misc.Base64{Encoder,Decoder} 是更好的选择,不过在 Java SE 8 中引入的 java.util.Base64 类则是更好的选择。)再比如,有些应用程序依赖 @Generated 注解,其类型 javax.annotation.Generated 在 JDK 9 中与 JAX-WS 共存。(应用程序也可以选择依赖在 Java SE 9 中引入的 javax.annotation.processing.Generated 类型。)

移除 Java EE 模块的另一个风险是,那些已经从 JDK 6、7 或 8 迁移到 JDK 9 的应用程序如果使用了命令行标志 --add-modules java.se.ee--add-modules java.xml.bind 等,将无法启动。

该提案假定希望在最新的 JDK 上编译或运行应用程序的开发人员可以找到并部署 Java EE 技术的替代版本。JAX-WS 和 JAXB 的参考实现 (RIs) 是一个好的起点,因为它们是 JDK 9 中 java.xml.wsjava.xml.bind 模块的完整替代品。这些 RIs 可作为 Maven 构件获取:(注意,它们必须部署在类路径上)。

JAX-WS 和 JAXB 的工具也可以作为 Maven 工件使用:

还有一些 Maven 工件,其中仅包含 Java EE 技术的 API:

在此 JEP 实施后,这些 API 的 JAR 文件可以部署在类路径上,就像在 JDK 8 和 JDK 9 上一样。它们也可以部署在模块路径上,以便模块化应用程序可以通过 requires 指令依赖它们:

  • JAX-WS、JAXB 和 SAAJ 的 API JAR 文件是名为 java.xml.wsjava.xml.bindjava.xml.soap 的显式模块。

  • Web Services Metadata 的 API JAR 文件是一个名为 webservices.api 的自动模块。(此名称是从 JAR 文件名派生的,因为 JAR 清单尚未使用 Automatic-Module-Name 属性进行更新。)

  • JAF 和 Common Annotations 的 API JAR 文件是名为 java.activationjava.annotation 的自动模块。(这些名称由 JAR 清单中的 Automatic-Module-Name 属性指定。)

在 JDK 9 中,描述中提到的所有模块(java.se.ee 聚合器除外)都是可升级的。这意味着使用 --add-modules java.xml.bind 等选项的 JDK 9 开发人员可以选择依赖 JDK 运行时镜像中的 Java EE 模块,或者通过在升级模块路径上部署 API JAR 文件来覆盖它们。请注意,这里涉及的是升级模块路径,而不是模块路径;在 JDK 9 的模块路径上部署 API JAR 文件不会产生任何效果,即使使用了 --add-modules java.xml.bind 等选项,因为 JDK 运行时镜像中的 Java EE 模块优先于模块路径上同名的模块。在此 JEP 实施后,Java EE 模块将不再存在于 JDK 运行时镜像中,因此开发人员可以在模块路径上部署 API JAR 文件。

CORBA 和 JTA 模块

移除 java.corba 模块的风险包括:

  1. 如果 CORBA 实现仅包含部分 "认可的" CORBA API,并期望 JDK 提供其余部分,则这些实现将无法编译或运行。

  2. 使用 RMI-IIOP 的应用程序和 CORBA 实现将无法编译或运行。RMI-IIOP 包(javax.rmijavax.rmi.CORBA)位于 java.corba 模块中,并与其中的 CORBA 实现绑定,因此一旦移除 java.corba,Java SE 中将不再支持 RMI-IIOP。

  3. 使用 javax.activity 包的应用程序和 CORBA 实现将无法编译或运行。该包位于 java.corba 模块中,并与其中的 CORBA 实现绑定,因此一旦移除 java.corba,Java SE 中将不再提供支持。

除非第三方接手 CORBA API、ORB 实现、CosNaming 提供者等的维护工作,否则将不会有单独版本的 CORBA。第三方维护是可能的,因为 Java SE 平台支持 CORBA 的独立实现。相比之下,RMI-IIOP 的 API 仅在 Java SE 内定义和实现。除非启动专门的 JSR 来维护它,或者 API 的管理权被 Eclipse 基金会接管,否则将不会有单独版本的 RMI-IIOP。Java EE 从 JCP 到 Eclipse 基金会的管理权过渡包括 CORBA 和 RMI-IIOP 的 GlassFish 实现。最后,J2EE Activity Service 没有单独版本。

JTA 的独立版本作为 Maven 工件 javax.transaction : javax.transaction-api 提供。截至 2017 年 11 月,此 JAR 文件代表 JTA 1.2,包含 XA 包和 CORBA 互操作包。在 2018 年初,JTA 1.3 将被定义为仅包含 CORBA 互操作包;JAR 文件将相应更新。JTA 1.2 和 JTA 1.3 的 JAR 文件可以如下部署:

  • JTA 1.2 的 JAR 文件可以部署在类路径上。(JAR 文件中的 XA 包会被忽略,而优先使用 java.sql 模块中的 XA 包。JAR 文件中的 CORBA 互操作包会优先于 java.transaction 模块中的包,后者在 JDK 9 中默认未解析。需要注意的是,如果在 JDK 9 中使用了 --add-modules java.se.ee--add-modules java.transaction,那么 JAR 文件中的 CORBA 互操作包将被忽略,而优先使用 java.transaction 模块中的包。)

  • JTA 1.2 的 JAR 文件可能无法部署在模块路径上。(它会被视为一个包含 XA 包的自动模块,但这个包会与 java.sql 模块中的 XA 包发生冲突。)

  • JTA 1.3 的 JAR 文件可以部署在类路径上。(JAR 文件中的 CORBA 互操作包会优先于 java.transaction 模块中的包,后者在 JDK 9 中默认未解析。)

  • JTA 1.3 的 JAR 文件可以部署在模块路径上,并用作名为 java.transaction 的自动模块。