eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

Partner – LambdaTest – NPI EA (cat=Testing)
announcement - icon

Regression testing is an important step in the release process, to ensure that new code doesn't break the existing functionality. As the codebase evolves, we want to run these tests frequently to help catch any issues early on.

The best way to ensure these tests run frequently on an automated basis is, of course, to include them in the CI/CD pipeline. This way, the regression tests will execute automatically whenever we commit code to the repository.

In this tutorial, we'll see how to create regression tests using Selenium, and then include them in our pipeline using GitHub Actions:, to be run on the LambdaTest cloud grid:

>> How to Run Selenium Regression Tests With GitHub Actions

Course – LJB – NPI EA (cat = Core Java)
announcement - icon

Code your way through and build up a solid, practical foundation of Java:

>> Learn Java Basics

1. Introduction

In this tutorial, we’ll dive deep into the latest Java release, Java 22, which is now in General Availability.

2. Java Language Updates

Let’s talk about all the new changes to the Java language as part of this release.

2.1. Unnamed Variables and Patterns – JEP 456

We often define temporary variables or pattern variables that remain unused in code. More often than not, it is due to language constraints, and removing them is prohibited or introduces side effects. Exceptions, switch patterns, and Lambda expressions are examples where we define variables or patterns in a certain scope, but we never get to use them:

try {
    int number = someNumber / 0;
} catch (ArithmeticException exception) {
    System.err.println("Division by zero");
}

switch (obj) {
    case Integer i -> System.out.println("Is an integer");
    case Float f -> System.out.println("Is a float");
    case String s -> System.out.println("Is a String");
    default -> System.out.println("Default");
}

try (Connection connection = DriverManager.getConnection(url, user, pwd)) {
    LOGGER.info(STR."""
      DB Connection successful
      URL = \{url}
      usr = \{user}
      pwd = \{pwd}""");
} catch (SQLException e) {}

Unnamed variables(_) are perfect in such scenarios and make the variable’s intention unambiguous. They cannot be passed in code or used or assigned values. Let’s rewrite the previous examples:

try {
    int number = someNumber / 0;
} catch (ArithmeticException _) {
    System.err.println("Division by zero");
}

switch (obj) {
    case Integer _ -> System.out.println("Is an integer");
    case Float _ -> System.out.println("Is a float");
    case String _ -> System.out.println("Is a String");
    default -> System.out.println("Default");
}

try (Connection _ = DriverManager.getConnection(url, user, pwd)) {
    LOGGER.info(STR."""
      DB Connection successful
      URL = \{url}
      usr = \{user}
      pwd = \{pwd}""");
} catch (SQLException e) {
    LOGGER.warning("Exception");
}

2.2. Statements Before super() – JEP 447

Java, for a long time, didn’t allow us to put any statements before calling super() inside the constructor of a child class. Let’s say we have a class system of Shape and two classes, Square and Circle, extending from the Shape class. In the child class constructors, the first statement is a call to super():

public class Square extends Shape {
    int sides;
    int length;

    Square(int sides, int length) {
        super(sides, length);
        // some other code
    }
}

This was inconvenient when we would benefit from performing certain validations before even calling super(). With this release, this is addressed:

public class Square extends Shape {
    int sides;
    int length;

    Square(int sides, int length) {
        if (sides != 4 && length <= 0) {
            throw new IllegalArgumentException("Cannot form Square");
        }
        super(sides, length);
    }
}

We should note that statements we put before super() cannot access instance variables or execute methods. We can use this to perform validations. Additionally, we can use this to transform values received in the derived class before calling the base class constructor.

This is a preview Java feature.

3. String Templates – JEP 459

Java 22 introduces the second preview to Java’s popular String templates feature. String templates allow the embedding of literal texts along with expressions and template processors to produce specialized results. They are also a much safer and more efficient alternative to other String composition techniques.

With this release, String Templates continue to be in preview, with a minor update to the API since the first preview. A new change is introduced to the typing of template expressions to use the return type of the corresponding process() method in template processors.

4. Implicitly Declared Classes and Instance Main Methods – JEP 463

Java finally supports writing a program without defining an explicit class or a main method with its standard template. This is how we generally define a class:

class MyClass {
    public static void main(String[] args) {
    }
}

Developers can now simply create a new file with a main() method definition as follows and start coding:

void main() {
    System.out.println("This is an implicitly declared class without any constructs");

    int x = 165;
    int y = 100;

    System.out.println(y + x);
}

We can compile this using its file name. The unnamed classes reside in an unnamed package, which resides in an unnamed module.

5. Libraries

Java 22 also brings new libraries and updates some existing ones.

5.1. Foreign Function and Memory API – JEP 454

Java 22 finalized the Foreign Function and Memory API after a few incubator iterations as part of Project Loom. This API allows developers to invoke foreign functions, i.e., functions outside the JVM ecosystem, and access memory that is foreign to the JVM.

It allows us to access libraries of other runtimes and languages, something which JNI (Java Native Interface) did but with more efficiency, performance boost, and security. This JEP brings broader support for invoking native libraries on all platforms where the JVM runs. Additionally, the API is extensive and more readable and provides ways to operate on structured and unstructured data of unlimited size across multiple memory types, such as heap and transient memory.

We’ll make a native call to C’s strlen() function to compute the length of a string using the new Foreign Function and Memory API:

public long getLengthUsingNativeMethid(String string) throws Throwable {
    SymbolLookup stdlib = Linker.nativeLinker().defaultLookup();
    MethodHandle strlen =
      Linker.nativeLinker()
        .downcallHandle(
          stdlib.find("strlen").orElseThrow(),
          of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS));

    try (Arena offHeap = Arena.ofConfined()) {
        MemorySegment str = offHeap.allocateFrom(string);

        long len = (long) strlen.invoke(str);
        System.out.println("Finding String length using strlen function: " + len);
        return len;
    }
}

5.2. Class File API – JEP 457

The Class File API standardizes the process of reading, parsing, and transforming Java .class files. Additionally, it aims to eventually deprecate the JDK’s internal copy of the third-party ASM library.

The Class File API provides several powerful APIs to transform and modify elements and methods inside a class selectively. As an example, let’s see how we can leverage the API to remove the methods in a class file that starts with test_:

ClassFile cf = ClassFile.of();
ClassModel classModel = cf.parse(PATH);
byte[] newBytes = cf.build(classModel.thisClass()
  .asSymbol(), classBuilder -> {
    for (ClassElement ce : classModel) {
        if (!(ce instanceof MethodModel mm && mm.methodName()
          .stringValue()
          .startsWith(PREFIX))) {
            classBuilder.with(ce);
        }
    }
});

This code parses the bytes of the source class file and transforms them by only taking the methods (represented by the MethodModel type) that satisfy our given condition. The resulting class file, which omits the test_something() method of the original class, can be verified.

5.3. Stream Gatherers – JEP 461

JEP 461 brings support for custom intermediate operations in the Streams API with Stream::gather(Gatherer). Developers have long wanted support for additional operations because of limited built-in stream intermediate operations. With this enhancement, Java allows us to create a custom intermediate operation.

We can achieve this by chaining the gather() method on a stream and supplying it with a Gatherer, which is an instance of the java.util.stream.Gatherer interface.

Let’s use Stream gatherers to group a list of elements in groups of 3 with a sliding window approach:

public List<List<String>> gatherIntoWindows(List<String> countries) {
    List<List<String>> windows = countries
      .stream()
      .gather(Gatherers.windowSliding(3))
      .toList();
    return windows;
}

// Input List: List.of("India", "Poland", "UK", "Australia", "USA", "Netherlands")
// Output: [[India, Poland, UK], [Poland, UK, Australia], [UK, Australia, USA], [Australia, USA, Netherlands]]

There are five built-in gatherers as part of this preview feature:

  • fold
  • mapConcurrent
  • scan
  • windowFixed
  • windowSliding

This API also empowers developers to define a custom Gatherer.

5.4. Structured Concurrency – JEP 462

Structured Concurrency API, an incubator feature in Java 19, was introduced as a preview feature in Java 21 and returns in Java 22 without any new changes.

The goal of this API is to introduce structure and coordination in Java concurrent tasks. Structured Concurrency API aims to improve the development of concurrent programs by introducing a pattern of coding style that aims to reduce the common pitfalls and drawbacks of concurrent programming.

This API streamlines error propagation, reduces cancellation delays, and improves reliability and observability.

5.5. Scoped Values – JEP 464

Java 21 introduced the Scoped Values API as a preview feature along with Structured Concurrency. This API moves into the second preview in Java 22 without any changes.

Scoped values enable storing and sharing immutable data within and across threads. Scoped values introduce a new type, ScopedValue<>. We write the values once, and they remain immutable throughout their lifecycle.

Web requests and server code typically use ScopedValues. They are defined as public static fields and allow data objects to be passed across methods without being defined as explicit parameters.

In the following example, let’s see how we can authenticate a user and store its context as a ScopedValue across multiple instances:

private void serve(Request request) {
    User loggedInUser = authenticateUser(request);
    if (loggedInUser) {
        ScopedValue.where(LOGGED_IN_USER, loggedInUser)
          .run(() -> processRequest(request));
    }
}

// In a separate class

private void processRequest(Request request) {
    System.out.println("Processing request" + ScopedValueExample.LOGGED_IN_USER.get());
}

Multiple login attempts from unique users scope the user information to its unique thread:

Processing request :: User :: 46
Processing request :: User :: 23

5.6. Vector API (Seventh Incubator) – JEP 460

Java 16 introduced the Vector API, and Java 22 brought its seventh incubator. This update provides performance improvements and minor updates. Previously, vector access was limited to heap MemorySegments, which were backed by a byte array. They are now updated to be backed by an array of primitive element types.

This update is low-level and does not impact the API usage in any way.

6. Tooling Updates

Java 22 brings an update on the tooling of Java build files.

6.1. Multi-File Source Programs – JEP 458

Java 11 introduced executing a single Java file without explicitly compiling it using the javac command. This was very efficient and quick. The downside is that when there are dependent Java source files, we cannot its advantage.

Starting with Java 22, we can finally run multi-file Java programs:

public class MainApp {
    public static void main(String[] args) {
        System.out.println("Hello");
        MultiFileExample mm = new MultiFileExample();
        mm.ping(args[0]);
    }
}

public class MultiFileExample {
    public void ping(String s) {
        System.out.println("Ping from Second File " + s);
    }
}

We can run the MainApp directly without explicitly running javac:

$ java --source 22 --enable-preview MainApp.java "Test"

Hello
Ping from Second File Test

Here are a few things to keep in mind:

  • the compilation order is not guaranteed when classes are scattered across multiple source files
  • the .java files whose classes are referenced by the main program are compiled
  • duplicate classes in source files are not allowed and will error out
  • we can pass –class-path option to use pre-compiled programs or libraries

7. Performance

The performance update this iteration of Java brings is an enhancement to the G1 Garbage Collector mechanism.

7.1. Region Pinning for G1 Garbage Collector – JEP 423

Pinning is the process of informing the JVM’s underlying garbage collector not to remove specific objects from memory. Garbage collectors that do not support this feature generally pause garbage collection until the JVM is instructed that the critical object is released.

This was a problem primarily seen in JNI critical section regions. The absence of the pinning functionality in a Garbage collector impacts its latency, performance, and overall memory consumption in the JVM.

With Java 22, the G1 Garbage Collector finally supports region pinning. This removes the need for Java threads to pause the G1 GC while using JNI.

8. Conclusion

Java 22 brings a plethora of updates, enhancements, and new preview features to Java.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

Course – LS – NPI (cat=Java)
announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

eBook Jackson – NPI EA – 3 (cat = Jackson)