Skip to main content

Migrate to Java 21

In this tutorial, we'll use OpenRewrite to perform an automated migration from Java 17 to Java 21. While this recipe will upgrade your Java 8 or Java 11 projects to Java 21, this guide won't cover the changes that occur from those versions to Java 21. For information on migrating to Java 17 from those versions, check out our migrate to Java 17 guide.

Example Configuration

The Java 21 migration recipe can be applied by including OpenRewrite's plugin to your project and including a dependency on rewrite-migrate-java:

build.gradle
  plugins {
id("java")
id("org.openrewrite.rewrite") version("7.1.5")
}

rewrite {
activeRecipe("org.openrewrite.java.migrate.UpgradeToJava21")
setExportDatatables(true)
}

repositories {
mavenCentral() // rewrite-spring is published to Maven Central
}

dependencies {
rewrite(platform("org.openrewrite.recipe:rewrite-recipe-bom:latest.release"))
rewrite("org.openrewrite.recipe:rewrite-migrate-java")

// Other project dependencies
}

At this point, you're ready to execute the migration by running mvn rewrite:run or gradlew rewriteRun. After running the migration you can inspect the results with git diff (or equivalent), manually fix anything that wasn't able to be migrated automatically, and commit the results.

Before and After

For the complete list of changes made by this recipe, please see the reference pages for Java 21.

Please note that this recipe will also migrate from Java 8 to Java 11 and migrate from Java 11 to Java 17 if you aren't already on Java 17. For details about migrating from Java 8 to 17, check out our migrate to Java 17 popular recipe guide.

If you have a specific use case that is not yet covered by this project, please reach out to our team!

Example Class

Before

package org.openrewrite.example;

import java.util.HashMap;;

public class Example {
JsonNode entity = entityList.get(0);
someObject.remove(0);
someOtherObject.add(0, token);

foo.get(foo.size() - 1);
bar.remove(bar.size() - 1);
bash.add(bash.size() - 1, token);

url = new URL(urlParam);
img = ImageIO.read(new URL(logo));

locale = new Locale(publishDateLocale);
}

After

package org.openrewrite.example;

// Illegal semi-colons removed
import java.util.HashMap;

public class Example {
// Better ways to access or change the first element of a collection
JsonNode entity = entityList.getFirst();
someObject.removeFirst();
someOtherObject.addFirst(token);

// Better ways to access or change the last element of a collection
foo.getLast();
bar.removeLast();
bash.addLast(token);

// Favor static methods over constructors
url = URI.create(urlParam).toURL();
img = ImageIO.read(URI.create(logo).toURL());

// Prefer Locale.of(..) over new Locale(..)
locale = Locale.of(publishDateLocale);
}
info

The above example class demonstrates a few of the most common changes when migrating from Java 17 to 21. That being said, there are many additional tasks covered by this recipe that are not represented in this example. Check out the migrate to Java 21 documentation for a full list of what the recipe does.

See how this recipe works across multiple open-source repositories

Run this recipe on OSS repos at scale with the Moderne SaaS.

The community edition of the Moderne platform enables you to easily run recipes across thousands of open-source repositories.

Please contact Moderne for more information about safely running the recipes on your own codebase in a private SaaS.