Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
199 changes: 58 additions & 141 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,49 +21,62 @@
[![Contributing Guide](https://img.shields.io/badge/Contributing-Guide-informational)](https://github.com/openrewrite/.github/blob/main/CONTRIBUTING.md)
</div>

### What is this?
## What is this?

This project implements a [Rewrite module](https://github.com/openrewrite/rewrite) that performs common tasks when
migrating to a new version of either Java and/or J2EE.
This project implements an [OpenRewrite](https://github.com/openrewrite/rewrite) module with recipes for migrating to newer versions of Java and Jakarta EE. It supports both Maven and Gradle projects.

Browse [a selection of recipes available through this module in the recipe catalog](https://docs.openrewrite.org/recipes/java/migrate).
Browse [all available recipes in the recipe catalog](https://docs.openrewrite.org/recipes/java/migrate).

# Java
## Java version migration

In releases of Java prior to Java 11, it was not uncommon for there to be more than three years between major releases
of the platform. This changed in June 2018 when a new, six-month release cadence was adopted by the OpenJDK community.
The new model allows features to be released within any six-month window allowing features to be incrementally
introduced when they are ready. Additionally, there are Java LTS (Long term support) releases on which there exists
enterprise support offered through several vendors that provide builds of the JVM, compiler, and standard libraries. The
current LTS versions of the Java platform (Java 8, 11, 17, and 21) are the most common versions in use within the Java
ecosystem.
Java adopted a six-month release cadence in 2018, with Long-Term Support (LTS) releases every two years. The current LTS versions are **Java 8, 11, 17, 21, and 25**.

# Java EE/Jakarta EE
This module provides composite migration recipes for each LTS version:

The Java Platform, Enterprise Edition (Java EE) consists of a set of specifications that extend Java Standard Edition to
enable the development of distributed applications and web services. Examples of the most commonly used parts of Java EE
include JAXB, JAX-WS, and the activation framework. These APIs and their associated reference implementations were
bundled with the Java standard library in JDK 6 through JDK 8 and deprecated in JDK 9. Starting with JDK 11, the
libraries were removed from the standard library to reduce the footprint of the Java standard
library ([See JEP 320 for details](https://openjdk.org/jeps/320)).
| Recipe | Description |
|--------|-------------|
| `org.openrewrite.java.migrate.Java8toJava11` | Migrate from Java 8 to 11 |
| `org.openrewrite.java.migrate.UpgradeToJava17` | Migrate from Java 11+ to 17 |
| `org.openrewrite.java.migrate.UpgradeToJava21` | Migrate from Java 17+ to 21 |
| `org.openrewrite.java.migrate.UpgradeToJava25` | Migrate from Java 21+ to 25 |

**Any projects that continue to use the JAXB framework (on JDK 11+) must now explicitly add the JAXB API and a runtime
implementation to their builds.**
Each composite recipe builds on the previous one, so `UpgradeToJava25` includes all changes from `UpgradeToJava21`, which includes those from `UpgradeToJava17`, and so on. These recipes handle:

To muddy the waters further, the governance of the Java Platform, Enterprise Edition, was transferred to the Eclipse
Foundation and was renamed to Jakarta EE. The Jakarta EE 8 release (the first under the Jakarta name) maintains
the `javax.xml.bind` package namespace, whereas Jakarta EE 9 is the first release where the package namespace was changed
to `jakarta.xml.bind`:
- Replacing deprecated APIs with their modern equivalents
- Updating build files to target the new Java version
- Upgrading build plugins to versions compatible with the target Java version
- Upgrading third-party libraries to versions compatible with the Java module system
- Adopting new language features (e.g., text blocks, pattern matching, sequenced collections, switch expressions)

## Java Architecture for XML Binding (JAXB)
## Jakarta EE migration

Java Architecture for XML Binding (JAXB) provides a framework for mapping XML documents to/from a Java representation of
those documents. The specification/implementation of this library that is bundled with older versions of the JDK was
part of the Java EE specification before it was moved to the Jakarta project. It can be confusing because Java EE 8
and Jakarta EE 8 provides exactly the same specification (they use the same `javax.xml.bind` namespace), and there are
two different reference implementations for the specification.
When Java EE governance transferred to the Eclipse Foundation, it was renamed Jakarta EE. The key migration milestones are:

| Jakarta EE Version | XML Binding Artifact | Package Namespace | Description |
| Version | Key change |
|---------|-----------|
| **Jakarta EE 8** | Same APIs as Java EE 8, under the `javax` namespace |
| **Jakarta EE 9** | Package namespace changed from `javax.*` to `jakarta.*` |
| **Jakarta EE 10** | Updated API versions on the `jakarta` namespace |
| **Jakarta EE 11** | Latest API versions |

This module provides comprehensive migration recipes for each version:

| Recipe | Description |
|--------|-------------|
| `org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta` | Migrate to Jakarta EE 9 |
| `org.openrewrite.java.migrate.jakarta.JakartaEE10` | Migrate to Jakarta EE 10 |
| `org.openrewrite.java.migrate.jakarta.JakartaEE11` | Migrate to Jakarta EE 11 |

These recipes cover the full breadth of Jakarta EE specifications, including Servlet, JPA, EJB, CDI, Bean Validation, JSON-B, JAX-RS, WebSocket, Mail, JMS, and more. They also update related third-party libraries (Jackson, Jetty, EhCache, EclipseLink, etc.) to Jakarta-compatible versions.

### JAXB and JAX-WS reference

Two of the most commonly encountered Jakarta EE migration challenges are JAXB (XML binding) and JAX-WS (web services), because these APIs were bundled with the JDK through Java 8, deprecated in Java 9, and removed in Java 11 ([JEP 320](https://openjdk.org/jeps/320)). Projects using these APIs on Java 11+ must add explicit dependencies.

<details>
<summary>JAXB artifact mapping</summary>

| Jakarta EE Version | Artifact | Package Namespace | Description |
|--------------------|---------------------------------------------|-------------------|-------------------------------|
| Java EE 8 | javax.xml.bind:jaxb-api:2.3.x | javax.xml.bind | JAXB API |
| Jakarta EE 8 | com.sun.xml.bind:jaxb-impl:2.3.x | javax.xml.bind | JAXB Reference Implementation |
Expand All @@ -72,130 +85,34 @@ two different reference implementations for the specification.
| Jakarta EE 9 | jakarta.xml.bind:jakarta.xml.bind-api:3.x | jakarta.xml.bind | JAXB API |
| Jakarta EE 9 | org.glassfish.jaxb:jaxb-runtime:3.x | jakarta.xml.bind | JAXB Reference Implementation |

## Java API for XML Web Services (JAX-WS)
</details>

Java API for XML Web Services (JAX-WS) provides a framework for building SOAP-based XML web services in Java. This
framework was originally part of the Java Platform, Enterprise Edition (J2EE), and both the API and the reference
implementation was governed as part of the J2EE specification.
<details>
<summary>JAX-WS artifact mapping</summary>

| Jakarta EE Version | XML Web Services Artifact | Package Namespace | Description |
|--------------------|-----------------------------------------|-------------------|---------------------------------|
| Jakarta EE Version | Artifact | Package Namespace | Description |
|--------------------|------------------------------------------|-------------------|---------------------------------|
| Java EE 8 | javax.xml.ws:jaxws-api:2.3.1 | javax.jws | JAX-WS API |
| Jakarta EE 8 | jakarta.xml.ws:jakarta.xml.ws-api:2.3.x | javax.jws | JAX-WS API |
| Jakarta EE 8 | com.sun.xml.ws:jaxws-rt:2.3.x | javax.jws | JAX-WS Reference Implementation |
| Jakarta EE 9 | jakarta.xml.ws:jakarta.xml.ws-api:2.3.x | jakarta.jws | JAX-WS API |
| Jakarta EE 9 | com.sun.xml.ws:jaxws-rt:2.3.x | jakarta.jws | JAX-WS Reference Implementation |

# Java Migration Recipes

OpenRewrite provides a set of recipes that will help developers migrate to either Java 11, Java 17, or Java 21. These LTS
releases are the most common targets for organizations that are looking to modernize their applications.

## Java 11 Migrations

OpenRewrite provides a set of recipes that will help developers migrate to Java 11 when their existing application
workloads are on Java 8 through 10. The biggest obstacles for the move to Java 11 are the introduction of the module
system (in Java 9) and the removal of J2EE libraries that were previously packaged with the core JDK.

The composite recipe for migrating to Java 11 `org.openrewrite.java.migrate.Java8toJava11` will allow developers to
migrate applications that were previously running on Java 8 through 10. This recipe covers the following themes:

- Applications that use any of the Java EE specifications will have those dependencies migrated to Jakarta EE 8.
Additionally, the migration to Jakarta EE 8 will also add explicit runtime dependencies on those projects that have
transitive dependencies on the Jakarta EE APIs. **Currently, only Maven-based build files are supported.**
- Applications that use maven plugins for generating source code from XSDs and WSDLs will have their plugins
updated to use a version of the plugin that is compatible with Java 11.
- Any deprecated APIs in the earlier versions of Java that have a well-defined migration path will be automatically
applied to an application's sources. The remediations included with this recipe were originally identified using
a build plugin called [`Jdeprscan`](https://docs.oracle.com/javase/9/tools/jdeprscan.htm).
- Illegal Reflective Access warnings will be logged when an application attempts to use an API that has not been
publicly exported via the module system. This recipe will upgrade well-known, third-party libraries if they provide
a version that is compliant with the Java module system. See [Illegal Reflective Access](#IllegalReflectiveAccess) for
more information.

## Java 17 Migrations

OpenRewrite provides a set of recipes that will help developers migrate to Java 17 when their existing application
workloads are on Java 11 through 16. The composite recipe `org.openrewrite.java.migrate.UpgradeToJava17` will cover the
following themes:

- Any deprecated APIs in the earlier versions of Java that have a well-defined migration path will be automatically
applied to an application's sources. The remediations included with this recipe were originally identified using
a build plugin called [`Jdeprscan`](https://docs.oracle.com/javase/9/tools/jdeprscan.htm).
- Illegal Reflective Access errors are fatal in Java 17 and will result in the application terminating when an
application or a third-party library attempts to access an API that has not been publicly exported via the module
system. This recipe will upgrade well-known, third-party libraries if they provide a version that is compliant with
the Java module system.

## Java 21 Migrations

OpenRewrite provides a set of recipes that will help developers migrate to Java 21 when their existing application
workloads are on Java 11 through 20. The composite recipe `org.openrewrite.java.migrate.UpgradeToJava21` will cover the
following themes:

- everything covered by the Java 17 Migration
- initial support for the migration to Sequenced collections

## Illegal Reflective Access<a name="IllegalReflectiveAccess"></a>

The Java module system was introduced in Java 9 and provides a higher-level abstraction for grouping a set of Java
packages and resources along with additional metadata. The metadata is used to identify what services the module
offers, what dependencies the module requires, and provides a mechanism for explicitly defining which module classes are
“visible” to Java classes that are external to the module.

The module system provides strong encapsulation and the core Java libraries, starting with Java 9, have been designed
to use the module specification. The rules of the module system, if strictly enforced, introduce breaking changes to
downstream projects that have not yet adopted the module system. In fact, it is very common for a typical Java
application to have a mix of module-compliant code along with code that is not aware of modules.

Even as Java has reached Java 15, there are a large number of applications and libraries that are not compliant with
the rules defined by the Java module system. Rather than breaking those libraries, the Java runtime has been configured
to allow mixed-use applications. If an application makes an illegal, reflective call to a module’s unpublished resource,
a warning will be logged.

The default behavior, starting with Java 11, is to log a warning the first time an illegal access call is made. All
subsequent calls will not be logged, and the warning looks similar to the following:

```log
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.thoughtworks.xstream.core.util.Fields (file.....)
WARNING: Please consider reporting this to the maintainers of com.thoughtworks.xstream.core.util.Fields
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
```

This warning, while valid, produces noise in an organization's logging infrastructure. In Java 17, these types of issues
are now fatal and the application will terminate if such illegal access occurs.

### Suppressing Illegal Reflective Access Exceptions.

In situations where a third-party library does not provide a version that is compliant with the Java module
system, it is possible to suppress these warnings/errors. An application may add `Add-Opens` declarations to its
top-level JAR's manifest:

```xml

<Add-Opens>
java.base/java.lang java.base/java.util java.base/java.lang.reflect java.base/java.text java.desktop/java.awt.font
</Add-Opens>
```

This solution will suppress the warnings and errors in the deployed artifacts while still surfacing the warning when
developers run the application from their development environments.

**NOTE: You cannot add these directives to a library that is transitively included by an application. The only place the
Java runtime will enforce the suppressions when they are applied to the top-level, executable Jar.**
</details>

There are currently no recipes that will automatically apply "<Add-Opens>" directives to Jar manifests.
## Other recipes

## Helpful tools
Beyond Java and Jakarta EE version migrations, this module also includes recipes for:

- http://ibm.biz/WAMT4AppBinaries
- **Guava** — Replace Guava utilities with Java standard library equivalents
- **Lombok** — Best practices and modernization
- **JSpecify** — Adopt JSpecify nullability annotations
- **DataNucleus** — Upgrade DataNucleus versions

## Contributing

We appreciate all types of contributions. See the [contributing guide](https://github.com/openrewrite/.github/blob/main/CONTRIBUTING.md) for detailed instructions on how to get started.

### Licensing
## Licensing

For more information about licensing, please visit our [licensing page](https://docs.openrewrite.org/licensing/openrewrite-licensing).
Loading