当前位置:Java -> 处理Javax迁移到Jakarta的最佳实践

处理Javax迁移到Jakarta的最佳实践

从旧版Jakarta EE或Java EE升级到Jakarta EE 9或更新版本可能会有些棘手,因为需要将javax更改为jakarta前缀。一些库可能仍在使用javax包,这可能会在尝试在诸如Eclipse GlassFish 7之类的Jakarta EE服务器上运行应用程序时引起冲突。当你尝试升级到Spring Framework 6或Spring Boot 3、Quarkus 3以及其他许多现在依赖于Jakarta EE 9 API的框架的新版本时,你可能会遇到相同的问题。

但不用担心,我会帮你解决!在本篇文章中,我将解释一切你需要了解的,以便成功且快速地升级到Jakarta EE 9+。所谓的Jakarta EE 9+是指Jakarta EE 9或10,目前是最新版本的Jakarta EE。

现有工具自动化升级步骤

幸运的是,许多挑战可以使用免费和开源工具如Openrewrite、WindUp和Eclipse Transformer来自动化。 Openrewrite 是一个强大的工具,可以自动更改应用程序源代码,如将所有对旧javax包的引用更新为新的jakarta前缀。

Eclipse Transformer 也可以执行相同的工作,但它还可以转换最终的JAR、WAR或EAR二进制文件,以防你的项目尚未准备好进行源代码转换。如果你只是想尝试在Jakarta EE 9+运行时上运行你的旧应用程序,这会很有用。

所有这些工具都可以节省你升级到Jakarta EE 9+的时间和精力,让你可以将精力集中在应用程序开发的其他重要方面。然而,仍然很重要的是要审查和测试这些工具所做的更改,以确保它们不会引入任何意外的后果。

使用Eclipse Transformer转换应用程序

我建议每次迁移都从Eclipse Transformer开始,这样你可以快速验证你的应用程序是否可以无需更改即可迁移到Jakarta EE 10运行时,或者识别迁移中可能出现的问题。尤其是如果你的应用程序依赖尚不兼容Jakarta EE 9+或者将它们升级到兼容版本存在风险,使用Eclipse Transformer可能在迁移的后期阶段至关重要。最终,使用Eclipse Transformer转换你的应用程序,然后再部署到Jakarta EE 9+运行时,可以作为一个安全网,检测并转换任何依赖于旧API包的剩余类和文件。你可以继续使用Eclipse Transformed,直到你确信应用程序的所有内容都已迁移完毕。

为了演示使用Eclipse Transformer的简便性,我们在OmniFish准备了一个示例应用程序项目 javax-jakarta-transform-whole-war。该项目展示了如何将Eclipse Transformer应用于Maven项目的构建。

应用转换为Maven项目的关键是Maven插件 transformer-maven-plugin。该插件可以安装为扩展,然后可以连接到标准Maven构建机制并修改最终构建成果。

Maven插件提供两个目标:

  1. jar – 该目标转换应用程序包,如JAR、WAR和EAR文件。它可以直接修改它们,也可以在单独的文件中创建它们的转换版本
  2. transform – 该目标转换目录(在它们被打包成JAR、WAR或其他应用程序包之前)。它可以在应用程序部署到应用服务器之前用于转换已解压的目录

示例应用程序同时使用了这两个插件目标。 jar 目标用于转换最终构建成果,这是将需要后续部署文件或将其部署到Maven存储库所需。 transform 目标是可选的,用于转换已解压的目录,这在开发过程中通常由各种IDE用于部署应用程序。使用transform目标是可选的,但它会使开发和轻松部署应用程序变得更容易,直到完全迁移到Jakarta EE 9,Eclipse Transformer就不再需要了。

除了作为Maven插件使用外,Eclipse Transformer还可以在命令行上使用,因此可以与任何项目或持续集成系统一起使用。

要在命令行上运行Eclipse Transformer,首先从Maven中央仓库下载 org.eclipse.transformer.cli分发 JAR文件。然后,解压此JAR,例如,解压到名为transformer的文件夹中。然后,你可以使用以下命令将你的应用程序文件,例如 jakarta-ee-8-app.war,转换为新的应用程序文件 jakarta-ee-10-app-transformed.war

java -jar transformer/org.eclipse.transformer.cli-0.5.0.jar jakarta-ee-8-app.war jakarta-ee-10-app-transformed.war


需要转换的文件不一定是WAR文件,可以是目录、WAR、JAR和Eclipse Transformer支持的许多其他包类型。

关于如何在命令行上使用Eclipse Transformer的更多信息,你可以在Github项目上找到。然而,在大多数情况下,你可能不需要其他任何东西;即使是在默认选项下,该工具也很好地完成了任务。

转换与jakarta前缀不兼容的依赖项

现在,你需要升级或转换应用程序使用的各个库。这解决了两个问题。首先,它通过消除每次构建后都需要转换最终二进制文件的步骤,提高了应用程序在开发过程中的构建时间。其次,它解决了你在调整应用程序源代码以适应Jakarta EE 9后可能会遇到的一些库的编译问题。

已经兼容 Jakarta EE 9 版本的库可以简单地更新到该版本。大多数在企业项目中广泛使用的库已经支持 Jakarta EE 9。然而,一些库依然支持 Jakarta EE 9+ 和旧的 Jakarta EE 和 Java EE 版本。这些库有两个版本的变体。您需要选择支持 Jakarta EE 9+ 的变体。如果您使用 Maven,那么在大多数情况下,您需要使用 jakarta 分类器,就像这样:

<dependency>
  <groupId>org.primefaces</groupId>
  <artifactId>primefaces</artifactId>
  <version>13.0.0</version>
  <classifier>jakarta</classifier>
</dependency>


但并非所有库都是如此。一些库使用完全不同的坐标来提供 Jakarta EE 9 兼容的 Maven 构件,您需要进行一些研究来找到它们。

当无法升级库时,您可以使用 Eclipse Transformer来单独转换库,使用类似于我们在先前文章中解释的整个应用 WAR 转换的技术。您可以在个别库 JAR 上也使用 Eclipse Transformer,然后在构建过程中使用经过转换的 JAR。然而,在现代的基于 Maven 或 Gradle 的项目中,这并不容易,因为存在传递依赖。目前尚无工具能够自动正确转换所有传递依赖并正确地将它们安装到本地库中。但您可以使用一个技巧 - 您可以将所有需要转换的 JAR 合并成一个单独的 JAR(全能 JAR),其中包含所有传递依赖,然后对它进行转换,并将这个单一的 JAR 安装到 Maven 仓库中。然后,您只需要更改应用的 POM 文件,以依赖于这个单一的构件,而不是依赖于所有已转换的个别构件。

您需要创建一个新的 Maven 项目,比如,transform-depenendencies,在我们现有的项目旁边。然后将您需要转换的所有依赖项移动到这个新项目中。接着,从原始项目中删除所有这些依赖项,并用一个对新 transform-depenendencies 项目的单一依赖项来替代它们。

在最终的 WAR 文件中,不再像这样将每个 JAR 文件单独放在 WAR 中:

  • WEB-INF
    • classes
      • jasperreports.jar
      • quartz.jar

而是会得到一个像这样的单一转换的 JAR:

  • WEB-INF
    • classes
      • transform-dependencies.jar

这个transform-dependencies.jar文件将包含合并到其中的所有构件 - 它将包含来自所有构件的所有类和文件。

为了实现这一点,我们可以使用 Maven Shade 插件,它将多个 JAR 文件合并成项目所产生的单一构件:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-shade-plugin</artifactId>
  <version>3.5.0</version>
  <executions>
    <execution>
      <phase>package</phase>
      <goals>
        <goal>shade</goal>
      </goals>
      <configuration>
        <shadedClassifierName>jakarta</shadedClassifierName>
        <shadedArtifactAttached>true</shadedArtifactAttached>
        <transformers>
          <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
          <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"/>
        </transformers>
      </configuration>
    </execution>
  </executions>
</plugin>


该插件将定义项目中的所有依赖项并将它们合并为单一的全能 JAR,并将该 JAR 作为带有jakarta分类器的构件附加到项目中。

现在,我们需要向 Transformer 插件添加配置以将 Uber JAR 转换为与 Jakarta EE 9+ 兼容的版本。我们需要用以下内容配置 Transformer 插件:

  • 执行目标“jar”
  • 使用“jakartaDefaults”规则来应用 Jakarta EE 9 的转换
  • 定义由 shade maven 插件生成的分类器为“Jakarta”的构件。这将具有与当前项目相同的 groupId、artifactId 和 version

您只需要构建一次transform-dependencies项目并使用mvn install将依赖项转换成一个单一构件并安装到您的本地 Maven 仓库中。当构建原始应用程序项目时,它将使用转换后的 Uber JAR 并将它添加到最终的 WAR 中,而不是所有个别的(未转换的)JAR。当然,这可能会引入编译错误,因为您的源代码仍然使用 Javax 前缀。对此,有一个简单的解决方案,我将在下一节中描述。

转换应用程序源代码

是的,你可以手动或通过一些简单的查找替换机制来修复源代码中的编译错误。但我不推荐这样做。不是所有具有“javax.”前缀的包都应该被转换;还有像 XML 描述符之类的资源文件也需要被转换等。使用专为 Jakarta EE 9 设计的自动化工具来转换代码要容易得多且更可靠。

这里有两个免费工具可以帮助我们:

  1. Eclipse Transformer – 我们之前使用它来转换最终的应用程序,但它也能够转换 Java 源文件和资源文件
  2. Openrewrite – 一个可以根据指定规则自动更改应用程序源代码的工具。它包含适用于 Jakarta EE 9 的规则。

我建议在这一步中也使用 Eclipse Transformer,因为它具有更完整的适用于 Jakarta EE 9 的转换规则,而 Openrewrite 忽略了一些资源文件。然而,即使使用 Openrewrite,最终结果也是非常相似的。您只需要对源代码进行一些附加的手动更改。我将描述如何使用这两个工具,这样您就可以选择要使用哪一个。

对于单个应用程序,您只需要一次转换源代码。为了这一单一步骤,改变项目配置并不值得。因此,我们将描述如何在不向项目添加任何 Maven 插件或配置的情况下在命令行上使用Eclipse Transformer来执行这一步,这也意味着即使您使用除 Maven 之外的其他构建工具,比如 Gradle,您也可以应用此过程。

按照以下步骤来转换您的应用程序的源代码:

  1. Maven Central下载Eclipse Transformer CLI分发组件。下载最新版本的distribution.jar文件,而不是普通的jar文件。例如,对于版本0.5.0,这是直接下载链接:org.eclipse.transformer.cli-0.5.0-distribution.jar 
  2. 将JAR文件解压到某个目录,例如/path/to/transformer
  3. 进入应用程序的项目目录。
  4. 运行以下命令,将src目录(包含源代码、资源、测试代码和资源等)转换为output_src目录:java -jar /path/to/transformer/org.eclipse.transformer.cli-0.5.0.jar src
  5. output_src目录的内容移动到src目录(覆盖文件)。在Linux和Mac OS上,可以使用RSync命令行工具:rsync -a output_src/* src
  6. 手动编辑pom.xml,因为Eclipse Transformer不会执行该操作:
    • 将Jakarta EE版本升级到9.0.0或10.0.0,以使您的项目依赖于以下依赖项(或等效的Web Profile或Core Profile依赖项):
      • <dependency>
        <groupId>jakarta.platform</groupId>
        <artifactId>jakarta.jakartaee-api</artifactId>
        <version>10.0.0</version>
        <scope>provided</scope>
         </dependency>

作为Eclipse Transformer的替代方案,您可以使用Openrewrite来转换您的应用程序源代码,使其与Jakarta EE 9兼容。

应用OpenRewrite非常简单。如果您已经安装了Maven,您可以将其作为一个在命令行上配置的Maven插件来使用(请注意,您的项目不必是基于Maven的,只需要运行此转换时安装Maven):

  1. 转到应用程序的项目目录
  2. 执行以下命令:
    • mvn -U org.openrewrite.maven:rewrite-maven-plugin:run \
      -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-migrate-java:LATEST \
      -Drewrite.activeRecipes=org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta

这将直接修改您的应用程序。理论上,现在应该能够构建它,并且一切都应该按预期运行。但是,根据我的经验,在基于Maven的WAR项目中,我必须对pom.xml、web.xml和Java注解进行一些修复,而在使用Eclipse Transformer后却不需要这样做。

结论

完成这些步骤后,您的应用程序应该完全兼容Jakarta EE 9。如果所有未转换的依赖项都与Jakarta EE 9兼容,您可以删除对最终应用程序的转换,以节省构建时间。

我们需要执行以下三个步骤:

  1. (可选步骤) 使用Eclipse Transformer转换最终应用程序,并测试其是否与Jakarta EE 9+服务器或框架兼容。
  2. 升级依赖项的版本,使其与Jakarta EE 9兼容。
  3. 使用Eclipse Transformer转换无法升级到Jakarta EE 9的依赖项。
  4. 使用Eclipse Transformer或OpenRewrite转换应用程序源代码。
  5. (可选步骤) 移除最终应用程序的转换。

完成所有这些步骤后,您现在应该能够构建您的应用程序。如果将其部署在Jakarta EE 9+服务器上或在您选择的框架中运行,它应该能够成功编译并正常工作。您的项目已完全转换为Jakarta EE 9+,您可以像以前一样继续开发它,就好像它从一开始就是为Jakarta EE 9+设计的。

推荐阅读: 剑指offer 32-1.从上到下打印二叉树

本文链接: 处理Javax迁移到Jakarta的最佳实践