Upgrading from Java 11 to Java 21: A Guide for AEM Developers
by @daniel-strmecki
Overview
As an AEM developer, staying current with Java versions ensures we can leverage the latest features, security patches, and performance improvements. With Java 21 being the latest Long-Term Support (LTS) release, it's a critical upgrade for enterprises and developers working on Adobe Experience Manager (AEM) projects. Java LTS versions are supported for a longer period than non-LTS releases, making them ideal for production environments where stability and security are paramount. For example, Java 21 was released in September 2023 and will receive Premier Support until September 2028 and Extended Support until September 2031.
In the latest release of Cloud Manager 2025.1.0, Adobe announced that they now support Java 21 in AEMaaCS. Java 21 will be enabled for all customers in February 2025, along with the rollout of a new SonarQube version. This article focuses on API features and enhancements introduced between Java 11 and Java 21 that are most relevant for developers. We'll briefly touch on the upgrade progress and then dive into new APIs and syntax improvements with practical examples. The main goal of the article is to inform developers of the latest API improvements, so we can start using them immediately after the upgrade.
Key Points
Learn how to upgrade your AEMaaCS from Java 11 to 21 and then be able to leverage the
new API features and syntax improvements:
Pattern Matching
if (obj instanceof String str) {
System.out.println(str.toUpperCase());
}
Switch Expressions
String result = switch (day) {
case MONDAY, FRIDAY -> "Workday";
default -> "Weekend";
};
Text Blocks
String html = """
<html>
<head>
<title>Welcome Page</title>
</head>
<body>
<h1>Hello, World!</h1>
<p>This is an example of HTML in Java.</p>
</body>
</html>
""";
Records
public record User(String name, int age) {}
Sealed Classes
public sealed class Shape permits Circle, Rectangle, CustomShape {}
public final class Circle extends Shape {}
public sealed class Rectangle extends Shape permits Square {}
public non-sealed class CustomShape extends Shape {}
Virtual Threads
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
IntStream.range(0, 10).forEach(i ->
executor.submit(() -> System.out.println(Thread.currentThread()))
);
}
Scoped Values
private static final ScopedValue<String> USERNAME = ScopedValue.newInstance();
public static void main(String[] args) {
try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) {
executor.submit(() -> ScopedValue.runWhere(USERNAME, "Daniel", () -> {
processRequest();
}));
executor.submit(() -> ScopedValue.runWhere(USERNAME, "Ema", () -> {
processRequest();
}));
}
}
private static void processRequest() {
System.out.println("Processing request for user: " + USERNAME.get());
}
Structured Concurrency
public static void main(String[] args) throws Exception {
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
var task1 = scope.fork(() -> fetchData("Task 1", 2));
var task2 = scope.fork(() -> fetchData("Task 2", 3));
scope.join();
scope.throwIfFailed();
System.out.println(task1.resultNow());
System.out.println(task2.resultNow());
}
}
Collections and Steams
public static void main(String[] args) {
SequencedCollection<String> list = List.of("A", "B", "C");
System.out.println(list.getFirst());
System.out.println(list.getLast());
System.out.println(list.reversed());
}
Full Article
Read the full article on https://meticulous.digital/blog/f/upgrading-from-java-11-to-java-21-a-guide-for-aem-developers to find out more.
Q&A
Please use this thread to ask questions relating to this article