Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/nebula-plugins/gradle-jakartaee-migration-plugin

Provides Gradle capabilities and transforms to ease the migration from Java EE to Jakarta EE
https://github.com/nebula-plugins/gradle-jakartaee-migration-plugin

Last synced: 2 months ago
JSON representation

Provides Gradle capabilities and transforms to ease the migration from Java EE to Jakarta EE

Awesome Lists containing this project

README

        

# Gradle Jakarta EE Migration Plugin

![Support Status](https://img.shields.io/badge/nebula-active-green.svg)
[![Gradle Plugin Portal](https://img.shields.io/maven-metadata/v/https/plugins.gradle.org/m2/com.netflix.nebula/gradle-jakartaee-migration-plugin/maven-metadata.xml.svg?label=gradlePluginPortal)](https://plugins.gradle.org/plugin/com.netflix.nebula.jakartaee-migration)
[![Maven Central](https://img.shields.io/maven-central/v/com.netflix.nebula/gradle-jakartaee-migration-plugin)](https://maven-badges.herokuapp.com/maven-central/com.netflix.nebula/gradle-jakartaee-migration-plugin)
![Build](https://github.com/nebula-plugins/gradle-jakartaee-migration-plugin/actions/workflows/nebula.yml/badge.svg)
[![Apache 2.0](https://img.shields.io/github/license/nebula-plugins/gradle-jakartaee-migration-plugin.svg)](http://www.apache.org/licenses/LICENSE-2.0)

Provides Gradle capabilities, transforms and dependency substitutions to ease the migration from Java EE to Jakarta EE.

## Features

- [Capabilities](https://docs.gradle.org/current/userguide/component_capabilities.html) to cause legacy and modern API artifacts of the EE specification to conflict
- [Capabilities Resolution](https://docs.gradle.org/current/userguide/dependency_capability_conflict.html) to resolve those capability conflicts by selecting the artifact providing the highest specification version:
- [Artifact Transforms](https://docs.gradle.org/current/userguide/artifact_transforms.html) to automate the migration of `javax` to `jakarta` 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](https://docs.gradle.org/current/userguide/resolution_rules.html#sec:dependency_substitution_rules) allow `javax` specifications to be automaticallly substituted for a JakartaEE version, avoiding having to configure replacements on the classpath

### Supported Artifacts

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` and `faces` implementations, because they are provided by the specification
- JAXB because of its extensive use as a library dependency

### Capabilities

Capabilities are configured for every [EE specification](src/main/kotlin/com/netflix/gradle/jakartaee/specifications). 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)]
```

### Capabilities Resolution

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

### Artifact Transforms

Transforms automatically migrate JavaEE `javax` package references to `jakarta`, and is implemented using the [tomcat-jakartaee-migration](https://github.com/apache/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
```

## Applying the Plugin

Refer to the [Gradle Plugin Portal](https://plugins.gradle.org/plugin/com.netflix.nebula.jakartaee-migration).

## Configuring the Plugin

### Migrate from EE 8 and earlier to EE 10

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()
}
```

### Substitute JakartaEE 10 Artifacts

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](https://github.com/spring-projects/spring-boot/issues/33661#issuecomment-1368218308).

### Configure Only Capabilities

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

Configure capabilities resolution for a given configuration. `configureCapabilities()` does not need to be called separately.
```
jakartaeeMigration {
resolveCapabilityConflicts('runtimeClasspath') // configuration name or configuration are supported
}
```

### Configure Only Transforms

Enable transforms for a given configuration:
```
jakartaeeMigration {
transform('runtimeClasspath') // configuration name or configuration are supported
}
```

### Default Excludes

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.

### Excluding Artifacts from Transformation

Artifacts can be excluded from transforms using `excludeTransform`:
```
jakartaeeMigration {
excludeTransform('org.apache.tomcat.embed:tomcat-embed-core')
}
```

### Excluding Specification Artifacts from Transformation

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()
}
```

### Transforming Only Specified Artifacts

Artifacts can be included explicitly to transforms using `includeTransform`:
```
jakartaeeMigration {
includeTransform('org.apache.tomcat.embed:tomcat-embed-core')
}
```

### Prevent Transformation of Production Configurations

Prevent accidental configuration of transforms on production configurations, for instance in library projects, by enabling:
```
jakartaeeMigration {
preventTransformsOfProductionConfigurations()
}
```

## Dependency Management

This plugin intentionally avoids managing constraints and other versioning concerns. Use Gradle standard dependency management features in your project configuration.

### Jakarta EE 8

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?](https://stackoverflow.com/questions/71095913/what-is-the-difference-between-jaxb-impl-and-jaxb-runtime/72151763#72151763) documents one specific option avoiding Jakarta EE 8 API artifacts for JAXB.

### Platforms

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'
```

### Rich Versions / Constraints

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'
}
}
```