Simplifying migration to Jakarta EE with tools

In this article we will learn some of the available tools or plugins you can use to migrate your legacy Java EE/Jakarta EE 8 applications to the newer Jakarta EE environment. We will also discuss the common challenges that you can solve by using tools rather than performing a manual migration of your projects.

Challenges in Jakarta EE 10 migration

Although the main change to your project is the migration of the javax namespace to jakarta you cannot simply apply a “replace all” on your entire project. Here is why:

Firstly, there are some packages in the javax namespace which do not belong to Jakarta EE. Therefore, they still exist even when running Jakarta EE 10 projects. The most common case is the javax.naming package but there are a few more. Let’s take a look inside a Jakarta EE 10 application server:

grep -r "javax/"
javax/xml/stream/api/main/module.xml:                    <path name="javax/xml/stream"/>
javax/xml/stream/api/main/module.xml:                    <path name="javax/xml/stream/events"/>
javax/xml/stream/api/main/module.xml:                    <path name="javax/xml/stream/util"/>
javax/rmi/api/main/module.xml:                    <path name="javax/rmi"/>
javax/rmi/api/main/module.xml:                    <path name="javax/rmi/CORBA"/>
javax/rmi/api/main/module.xml:                    <path name="org/jboss/javax/rmi"/>
jakarta/resource/api/main/module.xml:                <include path="javax/naming"/>

Besides, there are some migration steps that you should take into account besides the simple javax to jakarta migration. For example:

The following CDI Methods have been removed:

  • The javax.enterprise.inject.spi.Bean.isNullable()
  • The javax.enterprise.inject.spi.BeanManager.createInjectionTarget(AnnotatedType)

Besides, there’s a behavior change to bean discovery in modules with beans.xml file with no version specified. See this article to learn more: How to configure beans.xml in CDI applications

With regards to EJB, the following EJB methods have been removed:

  • javax.ejb.EJBContext.getCallerIdentity(). Use EJBContext.getCallerPrincipal() instead, which returns a
  • javax.ejb.EJBContext.isCallerInRole(Identity role). Use EJBContext.isCallerInRole(String roleName) instead.

With regards to Jakarta Server Faces, the concept of managed beans has been removed in Faces 4.0 in favor of Jakarta Contexts and Dependency Injection (CDI) beans.

Then, Jakarta Servlet 6.0 removes a number API classes and methods such as:

  • javax.servlet.SingleThreadModel
  • javax.servlet.http.HttpSessionContext
  • javax.servlet.http.HttpUtils

With regards to Jakarta SOAP:

The javax.xml.soap.SOAPElementFactory class has been removed. Use jakarta.xml.soap.SOAPFactory for creating SOAPElements.

Finally, with regards to Jakarta XML Binding:

The XML namespace that you should use in xml binding files has changed. Replace the namespace with

Although this was not an exaustive list of all changes, it is clear that a bare replacement of javax is not sufficient to complete a real-world migration to Jakarta EE 10. Let’s see some tools which are freely available to migrate to Jakarta EE 10 safely

Openrewrite to migrate to Jakarta EE 10

OpenRewrite, now part of the Commonhaus Foundation, provides several plugins to perform most common migration scenarios. Jakarta EE 10 makes no exception.

As a matter of fact, you can perform a one-liner migration with no need to install anything on your machine. Just invoke the org.openrewrite.maven:rewrite-maven-plugin from the top of your project as follows:

mvn -U org.openrewrite.maven:rewrite-maven-plugin:run -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-migrate-java:RELEASE

As you can see from the output, the OpenRewrite plugin will apply the changes directly to your project. It will also raise a warning upon changes in the XML descriptors:

Besides, you can also include the Maven plugin directly in your project as follows:


When using the recipe in your Maven project, you can activate it with:

mvn rewrite:run

Using Eclipse Transformer to migrate to jakarta EE 10

This handy tool is available as a Maven plugin or for command-line use, making it a versatile option for any project or continuous integration system.

Here’s how to use the command line tool:

  1. Download the JAR: Head over to Maven Central and grab the org.eclipse.transformer.cli distribution JAR file.
  2. Unpack the JAR: Extract the downloaded JAR into a folder, let’s call it “transformer”.
  3. Transform your application: Use the following command to transform your application file (e.g., java-ee-8-app.war) into a Jakarta EE 10 compatible version (jakarta-ee-10-app-transformed.war):
java -jar transformer/org.eclipse.transformer.cli-0.5.0.jar java-ee-8-app.war jakarta-ee-10-app-transformed.war

Using Windup Migration Tool

Windup is a tool that can help you in automating the modernization of Java applications using a large number of transformations and use cases. You can both perform the code migration and approach it first with code analysis and effort estimation.

You can download it either as Web application or as CLI. When using the CLI, it will use behind the hoods the OpenRewrite recipes to perform the migration of your applications to Jakarta EE.

Once you unzip the Windup CLI in a folder, you can optionally set a WINDUP_HOME:

export WINDUP_HOME=/path/towindupcli

Then, you can invoke the JavaxToJakarta Recipe pointing to the location where the Rule is available and to the Source code of your application:

windup-cli --openrewrite "-DactiveRecipes=org.jboss.windup.JavaxToJakarta" "-Drewrite.configLocation=$WINDUP_HOME/rules/openrewrite/jakarta/javax/imports/rewrite.yml" --input /path/source  --goal run

You should be able to see in the output, the outcome of the OpenRewrite recipe:

[WARNING] Changes have been made to javaee/javaee7example/src/main/java/com/mastertheboss/repository/ by:
[WARNING]     org.jboss.windup.JavaxToJakarta
[WARNING]         org.jboss.windup.JavaxAnnotationToJakartaAnnotation
[WARNING]    {oldFullyQualifiedTypeName=javax.annotation.PostConstruct, newFullyQualifiedTypeName=jakarta.annotation.PostConstruct}
[WARNING]         org.jboss.windup.JavaxInjectToJakartaInject
[WARNING]    {oldPackageName=javax.inject, newPackageName=jakarta.inject, recursive=true}
[WARNING]         org.jboss.windup.JavaxPersistenceToJakartaPersistence
[WARNING]    {oldPackageName=javax.persistence, newPackageName=jakarta.persistence, recursive=true}
[WARNING] Please review and commit the results.
[INFO] ------------------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  9.069 s
[INFO] Finished at: 2024-04-11T10:13:11+02:00
[INFO] ------------------------------------------------------------------------

Alternatively, you can use the Windup Web application which lets you upload the artifact and produce a set of reports, with all the migration steps you need to perform:

migrate to jakarta ee 10 tutorial

Tomcat Migration Tool for Jakarta EE

Finally, I’d like to mention another tool which is available from Apache Tomcat:

The documentation of this tool is pretty much a readme file, which shows how to launch the script which will perform the actual migration of an older Java EE application to Jakarta EE.

In any case, I was able to complete the migration of a sample application just by providing the input and the output to the script

./ hello.war helloJEE10.war
Performing migration from source [/home/francesco/jboss/jakartaee-migration-1.0.8/bin/hello.war] to destination [/home/francesco/jboss/jakartaee-migration-1.0.8/bin/helloJEE10.war] with Jakarta EE specification profile [TOMCAT]
Migration starting for archive [hello.war] using streaming
Migration finished for archive [hello.war]
Migration completed successfully in [90] milliseconds


In this article we have explored several tools to perform a successful migration of a Java EE application ( or Jakarta EE 8) to Jakarta EE 10. Also, we have covered the challenges which you can face during this migration which does not just require renaming the import packages