javacompatibilityjakarta-migration

How to avoid compatibility issues between Java EE and Jakarta EE?


After Oracle donated Java EE to the Eclipse Foundation, it was renamed to Jakarta EE.

With that, the javax namespace was changed to jakarta.

What does one need to take care about in order to avoid compatibility issues due to the change from Java EE to Jakarta EE?


Solution

  • Don't mix Java EE and Jakarta EE dependencies

    You cannot use Java EE and Jakarta EE together. You have to use one or the other.
    If a project is using Java EE, there should not be any Jakarta EE dependencies in the project.

    Here are a few examples of Java EE/Jakarta dependencies (in group.id:artifact-id notation):

    Java EE dependency Jakarta EE dependency
    javax.servlet:javax.servlet-api jakarta.servlet:jakarta.servlet-api
    javax.persistence:javax.persistence-api jakarta.persistence:jakarta.persistence-api
    javax.xml.bind:jaxb-api jakarta.xml.bind:jakarta.xml.bind-api
    javax.validation:validation-api jakarta.validation:jakarta.validation-api
    javax.mail:javax.mail-api jakarta.mail:jakarta.mail-api

    You should not have both javax and jakarta dependencies in the same project.

    You can use mvn dependency:list (with Maven) or gradlew dependencies (with Gradle) for checking your dependencies.

    Other/transitive dependencies

    Your project might use dependencies that are written for Java EE or Jakarta EE.
    You need to make sure that you are using a version of these dependencies that matches the specification you are using.

    This table provides examples of dependencies that use Java EE in some versions and Jakarta EE in other versions:

    Dependency versions supporting Java EE versions supporting Jakarta EE
    Spring Boot <= 2.x >= 3.x
    Spring <= 5.x >= 6.x
    Hibernate <= 5.x >= 6.x (or 5.x with hibernate-core-jakarta)

    The package name

    With the change of the name Java EE to Jakarta EE, all Java EE types were moved from the javax package to jakarta (e.g. javax.servlet was changed to jakarta.servlet).

    If the project is using Java EE, it should not contain any jakarta.* imports and if it is using Jakarta EE, it should not use any Java EE classes from javax.*.

    There are tools for changing all imports and other type references in a project.

    configuration files

    Some configuration files (e.g. persistence.xml) might be different depending on whether Java EE or Jakarta is used.

    If configuration file references something starting with javax, this typically belongs to Java EE while references starting with jakarta typically belong in Jakarta EE projects.

    Here is an example persistence.xml file for both Java EE and Jakarta EE:

    <!-- This is for Java EE -->
    <persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
        version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
    
        <persistence-unit name="MyPersistenceUnit" transaction-type="JTA">
            <properties>
                <property name="javax.persistence.jdbc.url" value="jdbc:my-database-url" />
            </properties>
        </persistence-unit>
    </persistence>
    
    <!-- This is for Jakarta EE -->
    <persistence xmlns="https://jakarta.ee/xml/ns/persistence"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd"
                 version="3.0">
        <persistence-unit name="MyPersistenceUnit" transaction-type="JTA">
            <properties>
                <property name="jakarta.persistence.jdbc.url" value="jdbc:my-database-url" />
            </properties>
        </persistence-unit>
    </persistence>
    

    Other configuration files might require similar changes.

    Application servers/Containers

    Java EE projects should be deployed to an application server/web container supporting Java EE and Jakarta EE projects should be deployed to an application server/web container supporting Jakarta EE.

    For example:

    Possible issues caused by incompatibilities

    If a project references classes that are not available, ClassNotFoundExceptions/NoClassDefFoundErrors can occur.

    It is possible that some elements like servlets are not found by the container due to e.g. the container scanning for javax.servlet.annotation.WebServlet but the servlet being annotated with jakarta.servlet.annotation.WebServlet.

    The application might not correctly pick up some configurations.

    Of course, there can be many other issues depending on what exactly is done wrong.

    Migration tooling

    There are tools that help migrate from Java EE to Jakarta EE.

    For example, Eclipse Transformer can do most of the migration steps and can perform the namespace change in both source code and existing JAR/WAR files (e.g. libraries). It is also available as a Maven plugin.

    Alternatively, IntelliJ Ultimate allows migrating the source code of existing projects from Java EE to Jakarta EE. Similarly, Spring Tools allows to do the same for Spring projects.