Migrate to Java 17
Java 17 is the long-term support release that broadly replaced Java 8 and Java 11 in production environments. Upgrading to it lets your codebase adopt records, sealed classes, instanceof pattern matching, and text blocks – while clearing out APIs that have been deprecated since the early days of Java. Most of these transformations are simple individually, but applying them consistently across thousands of files turns a routine version bump into weeks of grinding work.
The UpgradeToJava17 recipe applies these changes automatically: it adopts the new language features, replaces deprecated APIs with their modern equivalents, and updates build files to target Java 17.
In this guide, we will show you how to run this recipe on the Moderne Platform or with the Moderne CLI.
Codebases on Java 8 or Java 11 are valid starting points. UpgradeToJava17 includes the Java 8 → 11 migration transitively, so you do not need to chain multiple migrations.
What this recipe does
UpgradeToJava17 is a composite recipe that bundles many smaller transformations. Some of the most visible changes this recipe makes to your code include:
- Adopt
instanceofpattern matching – removes redundant casts afterinstanceofchecks by binding the result directly to a typed variable (JEP 394). - Use text blocks – converts multi-line string concatenation into the
"""text-block syntax introduced in Java 15. - Prefer
String.formatted(...)– swapsString.format(template, args)calls for the more readabletemplate.formatted(args)form. - Add
@Serialannotation toserialVersionUID– marks serialization-related fields and methods so the compiler can validate them.
Beyond your code, the recipe also updates Maven and Gradle build files to target Java 17, bumps build plugins to Java 17-compatible versions, and (for codebases coming from Java 8) adds explicit dependencies for J2EE libraries like JAXB that are no longer bundled with the JDK. For the complete list of sub-recipes, see the recipe catalog page.
Example
Here is a small class before and after UpgradeToJava17 runs:
class Greeter {
String describe(Object obj) {
if (obj instanceof String) {
String s = (String) obj;
return String.format("string of length %d", s.length());
}
return "unknown";
}
}
class Greeter {
String describe(Object obj) {
if (obj instanceof String s) {
return "string of length %d".formatted(s.length());
}
return "unknown";
}
}
Running the recipe
- Moderne Platform
- Moderne CLI
- Sign in to your Moderne tenant or app.moderne.io.
- (Optionally) Use the Organization selector to scope the run to the repositories you want to upgrade.
- Search for the
Migrate to Java 17recipe (Moderne Platform link). - Click Dry run.
For a step-by-step walkthrough of the Moderne Platform UI, see Quickstart: Using the Moderne Platform.
Make sure you have built or downloaded Lossless Semantic Trees (LSTs) for the repositories you want to upgrade.
This recipe has no required configuration options. Users of Moderne can run it via the Moderne CLI.
You will need to have configured the Moderne CLI on your machine before you can run the following command.
mod run . --recipe UpgradeToJava17
If the recipe is not available locally, then you can install it using:
mod config recipes jar install org.openrewrite.recipe:rewrite-migrate-java:3.34.0
Reviewing and committing the changes
Running the recipe never modifies your source repositories directly. Instead, the changes are presented as a diff that you can inspect before deciding what to commit. Review them with whatever workflow fits your team, then use the Moderne Platform's commit options or the mod git CLI commands to push the changes across the affected repositories.
Additional reading
- Tracking migrations – use data tables and visualizations to track the rollout of a Java 17 upgrade across many repositories.