Provides Gradle capabilities, transforms and dependency substitutions to ease the migration from Java EE to Jakarta EE.
- Capabilities to cause legacy and modern API artifacts of the EE specification to conflict
- Capabilities Resolution to resolve those capability conflicts by selecting the artifact providing the highest specification version:
- Artifact Transforms to automate the migration of
javax
tojakarta
packages for legacy artifacts, avoiding needing to fork or manage multiple release lines for these libraries - Compatible with Gradle 4.0 and later
- Dependency Substitutions allow
javax
specifications to be automaticallly substituted for a JakartaEE version, avoiding having to configure replacements on the classpath
Only EE API artifacts are covered by this plugin, except for specific exceptions. The implementations are a concern of either the container or application, and any conflicts should be resolved manually.
The concrete implementations supported by the plugin features are:
- Embedded container artifacts such as
org.apache.tomcat.embed:tomcat-embed-core
that contain both API and implementation - The
json
andfaces
implementations, because they are provided by the specification - JAXB because of its extensive use as a library dependency
Capabilities are configured for every EE specification. They require that only one artifact provide a given EE specification API:
Cannot select module with conflict on capability 'com.netflix.gradle.jakartaee:servlet-api:3.0.1' also provided by [javax.servlet:servlet-api:2.2(runtime), javax.servlet:servlet-api:2.2(runtime), jakarta.servlet:jakarta.servlet-api:4.0.2(runtime)]
The default capability resolution strategy is to select the artifact that provides the highest version of the specification, with special handling for certain types of artifacts:
- Tomcat and GlassFish release versions, which use their own version scheme, are translated from release version to specification version
- Embedded container artifacts are selected regardless of the specification version they provide
Transforms automatically migrate JavaEE javax
package references to jakarta
, and is implemented using the tomcat-jakartaee-migration tool. The benefit of using transforms over packaging or deployment time conversion, is that dependencies are transformed and used at build, test, development and runtime, avoiding the potential for unexpected runtime side effects that weren't seen during development.
The transform eases migrations in ecosystems with legacy libraries that will not get jakarta
compatible releases, or internal libraries that need to retain javax
package references while applications roman-ride both package namespaces and multiple release lines would be prohibitive to maintain.
Transforms apply tranparently when files are resolved from a Gradle configuration, so your IDE, runtime, test runtime and distribution dependencies will have the transformation applied when configured:
Migration finished for archive [guava-31.1-jre.jar]
Migration completed successfully in [427] milliseconds
No JakartaEE transformation required for guava-31.1-jre.jar
Transforming reload4j-1.2.22.jar (ch.qos.reload4j:reload4j:1.2.22) with JakartaEeMigrationTransform
Caching disabled for JakartaEeMigrationTransform: .gradle/caches/modules-2/files-2.1/ch.qos.reload4j/reload4j/1.2.22/f9d9e55d1072d7a697d2bf06e1847e93635a7cf9/reload4j-1.2.22.jar because:
Build cache is disabled
JakartaEeMigrationTransform: .gradle/caches/modules-2/files-2.1/ch.qos.reload4j/reload4j/1.2.22/f9d9e55d1072d7a697d2bf06e1847e93635a7cf9/reload4j-1.2.22.jar is not up-to-date because:
No history is available.
Performing migration from source [.gradle/caches/modules-2/files-2.1/ch.qos.reload4j/reload4j/1.2.22/f9d9e55d1072d7a697d2bf06e1847e93635a7cf9/reload4j-1.2.22.jar] to destination [/var/folders/gl/9qw1jzv11r5_vxh0ngrk1hcw0000gn/T/jakartaee7252355990471961973transform] with Jakarta EE specification profile [EE]
Migration starting for archive [reload4j-1.2.22.jar] using streaming
Migration finished for archive [reload4j-1.2.22.jar]
Migration completed successfully in [46] milliseconds
Transformed reload4j-1.2.22.jar to JakartaEE reload4j-1.2.22-jakartaee.jar
Refer to the Gradle Plugin Portal.
To enable automatic migration from EE 8 (javax
) or earlier to EE 10 (jakarta
) or later, enable all features with migrate()
:
jakartaeeMigration {
migrate()
}
This configures migration for all Java sourceset classpath configurations, Spring Boot production, development-only and AOT processing configurations, and Protobuf plugin configurations. Capability conflicts are registered, so any configurations that are not included will need to have conflicts resolved manually with excludes, or using the additional methods below.
Calling migrate
on a java
project is equivalent to calling:
jakartaeeMigration {
configurations.all { config ->
resolveCapabilityConflicts(config)
substitute(config)
transform(config)
}
excludeSpecificationsTransform()
}
Call substitute
to automatically substitute EE10 APIs for every JavaEE API currently on the configuration. This avoids having to manually provide replacement artifacts:
jakartaeeMigration {
substitute()
}
This does not affect conflict resolution to higher versions or capabilities resolution between jakarta
artifacts, and can be combined with migrate
or any other option.
This is useful where upstream library projects are still targeting javax
and it's undesirable to add replacement artifacts everywhere those projects consumed. EE 10 is used as a baseline for Spring Boot 3 compatibility.
Configure only capabilities to cause EE API artifacts to conflict if more than one is present. Particularly useful for library authors that want to avoid accidentally exposing more than one implementation, or projects that want to migrate completely to the jakarta
package namespace.
jakartaeeMigration {
configureCapabilities()
}
Configure capabilities resolution for a given configuration. configureCapabilities()
does not need to be called separately.
jakartaeeMigration {
resolveCapabilityConflicts('runtimeClasspath') // configuration name or configuration are supported
}
Enable transforms for a given configuration:
jakartaeeMigration {
transform('runtimeClasspath') // configuration name or configuration are supported
}
Several artifacts are excluded by default because they are known to contain intentional references to javax
packages. See JakartaEeMigrationExtension.ARTIFACTS_WITH_INTENTIONAL_JAVAX
for details.
Artifacts can be excluded from transforms using excludeTransform
:
jakartaeeMigration {
excludeTransform('org.apache.tomcat.embed:tomcat-embed-core')
}
Exclude all EE API artifacts from transforms. Ensures that known artifacts providing javax
classes are not transformed, requiring that replacement jakarta
artifacts are explicitly added to the project.
jakartaeeMigration {
excludeSpecificationsTransform()
}
Artifacts can be included explicitly to transforms using includeTransform
:
jakartaeeMigration {
includeTransform('org.apache.tomcat.embed:tomcat-embed-core')
}
Prevent accidental configuration of transforms on production configurations, for instance in library projects, by enabling:
jakartaeeMigration {
preventTransformsOfProductionConfigurations()
}
This plugin intentionally avoids managing constraints and other versioning concerns. Use Gradle standard dependency management features in your project configuration.
If possible, completely avoid Jakarta EE 8 (i.e. jakarta
artifact coordinates with javax
packages). Our goal is this plugin makes the Jakarta EE 9 and later upgrade painless enough that you upgrade straight over that mess. What is the difference between jaxb-impl and jaxb-runtime? documents one specific option avoiding Jakarta EE 8 API artifacts for JAXB.
Use platform
to avoid needing to declare first order dependency versions or enforcedPlatform
ensure a minimum version of a specification is used:
implementation platform('jakarta.platform:jakarta.jakartaee-bom:10.0.0')
implementation 'jakarta.servlet:jakarta.servlet-api'
For stronger guarantees than platforms, use rich versions and constraints. Note that constraints are published in Gradle Module Metadata, so take care when using them in libraries to avoid unintended side effects. These constraints could be used to successfully use Jakarta EE 8 artifacts and prevent them from accidentally upgrading, but as mentioned above, it's probably more trouble than it's worth.
Use strictly
to force a version of an artifact:
constraints {
implementation('jakarta.servlet:jakarta.servlet-api') {
version {
strictly '[4.0.0, 5.0.0)'
}
because 'JakartaEE 8 required'
}
}
Or require
with reject
to cause dependency resolution to fail if an upgrade is attempted:
constraints {
implementation('jakarta.servlet:jakarta.servlet-api') {
version {
require '4.0.0'
reject '[5.0.0,)'
}
because 'JakartaEE 8 required'
}
}