Course – Black Friday 2025 – NPI EA (cat= Baeldung)
announcement - icon

Yes, we're now running our Black Friday Sale. All Access and Pro are 33% off until 2nd December, 2025:

>> EXPLORE ACCESS NOW

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

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag=Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

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 – 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

Partner – Orkes – NPI EA (cat=Java)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

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 – Black Friday 2025 – NPI (cat=Baeldung)
announcement - icon

Yes, we're now running our Black Friday Sale. All Access and Pro are 33% off until 2nd December, 2025:

>> EXPLORE ACCESS NOW

1. Introduction

Recently we looked at Creational Design Patterns and where to find them within the JVM and other core libraries. Now we’re going to look at Behavioral Design Patterns. These focus on how our objects interact with each other or how we interact with them.

2. Chain of Responsibility

The Chain of Responsibility pattern allows for objects to implement a common interface and for each implementation to delegate on to the next one if appropriate. This then allows us to build a chain of implementations, where each one performs some actions before or after the call to the next element in the chain:

interface ChainOfResponsibility {
    void perform();
}
class LoggingChain {
    private ChainOfResponsibility delegate;

    public void perform() {
        System.out.println("Starting chain");
        delegate.perform();
        System.out.println("Ending chain");
    }
}

Here we can see an example where our implementation prints out before and after the delegate call.

We aren’t required to call on to the delegate. We could decide that we shouldn’t do so and instead terminate the chain early. For example, if there were some input parameters, we could have validated them and terminated early if they were invalid.

2.1. Examples in the JVM

Servlet Filters are an example from the JEE ecosystem that works in this way. A single instance receives the servlet request and response, and a FilterChain instance represents the entire chain of filters. Each one should then perform its work and then either terminate the chain or else call chain.doFilter() to pass control on to the next filter:

public class AuthenticatingFilter implements Filter {
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
      throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        if (!"MyAuthToken".equals(httpRequest.getHeader("X-Auth-Token")) {
             return;
        }
        chain.doFilter(request, response);
    }
}

3. Command

The Command pattern allows us to encapsulate some concrete behaviors – or commands – behind a common interface, such that they can be correctly triggered at runtime.

Typically we’ll have a Command interface, a Receiver instance that receives the command instance, and an Invoker that is responsible for calling the correct command instance. We can then define different instances of our Command interface to perform different actions on the receiver:

interface DoorCommand {
    perform(Door door);
}
class OpenDoorCommand implements DoorCommand {
    public void perform(Door door) {
        door.setState("open");
    }
}

Here, we have a command implementation that will take a Door as the receiver and will cause the door to become “open”. Our invoker can then call this command when it wishes to open a given door, and the command encapsulates how to do this.

In the future, we might need to change our OpenDoorCommand to check that the door isn’t locked first. This change will be entirely within the command, and the receiver and invoker classes don’t need to have any changes.

3.1. Examples in the JVM

A very common example of this pattern is the Action class within Swing:

Action saveAction = new SaveAction();
button = new JButton(saveAction)

Here, SaveAction is the command, the Swing JButton component that uses this class is the invoker, and the Action implementation is called with an ActionEvent as the receiver.

4. Iterator

The Iterator pattern allows us to work across the elements in a collection and interact with each in turn. We use this to write functions taking an arbitrary iterator over some elements without regard to where they are coming from. The source could be an ordered list, an unordered set, or an infinite stream:

void printAll<T>(Iterator<T> iter) {
    while (iter.hasNext()) {
        System.out.println(iter.next());
    }
}

4.1. Examples in the JVM

All of the JVM standard collections implement the Iterator pattern by exposing an iterator() method that returns an Iterator<T> over the elements in the collection. Streams also implement the same method, except in this case, it might be an infinite stream, so the iterator might never terminate.

5. Memento

The Memento pattern allows us to write objects that are able to change state, and then revert back to their previous state. Essentially an “undo” function for object state.

This can be implemented relatively easily by storing the previous state any time a setter is called:

class Undoable {
    private String value;
    private String previous;

    public void setValue(String newValue) {
        this.previous = this.value;
        this.value = newValue;
    }

    public void restoreState() {
        if (this.previous != null) {
            this.value = this.previous;
            this.previous = null;
        }
    }
}

This gives the ability to undo the last change that was made to the object.

This is often implemented by wrapping the entire object state in a single object, known as the Memento. This allows the entire state to be saved and restored in a single action, instead of having to save every field individually.

5.1. Examples in the JVM

JavaServer Faces provides an interface called StateHolder that allows implementers to save and restore their state. There are several standard components that implement this, consisting of individual components – for example, HtmlInputFile, HtmlInputText, or HtmlSelectManyCheckbox – as well as composite components such as HtmlForm.

6. Observer

The Observer pattern allows for an object to indicate to others that changes have happened. Typically we’ll have a Subject – the object emitting events, and a series of Observers – the objects receiving these events. The observers will register with the subject that they want to be informed about changes. Once this has happened, any changes that happen in the subject will cause the observers to be informed:

class Observable {
    private String state;
    private Set<Consumer<String>> listeners = new HashSet<>;

    public void addListener(Consumer<String> listener) {
        this.listeners.add(listener);
    }

    public void setState(String newState) {
        this.state = state;
        for (Consumer<String> listener : listeners) {
            listener.accept(newState);
        }
    }
}

This takes a set of event listeners and calls each one every time the state changes with the new state value.

6.1. Examples in the JVM

Java has a standard pair of classes that allow us to do exactly this – java.beans.PropertyChangeSupport and java.beans.PropertyChangeListener.

PropertyChangeSupport acts as a class that can have observers added and removed from it and can notify them all of any state changes. PropertyChangeListener is then an interface that our code can implement to receive any changes that have happened:

PropertyChangeSupport observable = new PropertyChangeSupport();

// Add some observers to be notified when the value changes
observable.addPropertyChangeListener(evt -> System.out.println("Value changed: " + evt));

// Indicate that the value has changed and notify observers of the new value
observable.firePropertyChange("field", "old value", "new value");

Note that there are another pair of classes that seem a better fit – java.util.Observer and java.util.Observable. These are deprecated in Java 9 though, due to being inflexible and unreliable.

7. Strategy

The Strategy pattern allows us to write generic code and then plug specific strategies into it to give us the specific behavior needed for our exact cases.

This will typically be implemented by having an interface representing the strategy. The client code is then able to write concrete classes implementing this interface as needed for the exact cases. For example, we might have a system where we need to notify end-users and implement the notification mechanisms as pluggable strategies:

interface NotificationStrategy {
    void notify(User user, Message message);
}
class EmailNotificationStrategy implements NotificationStrategy {
    ....
}
class SMSNotificationStrategy implements NotificationStrategy {
    ....
}

We can then decide at runtime exactly which of these strategies to actually use to send this message to this user. We can also write new strategies to use with minimal impact on the rest of the system.

7.1. Examples in the JVM

The standard Java libraries use this pattern extensively, often in ways that may not seem obvious at first. For example, the Streams API introduced in Java 8 makes extensive use of this pattern. The lambdas provided to map(), filter(), and other methods are all pluggable strategies that are provided to the generic method.

Examples go back even further, though. The Comparator interface introduced in Java 1.2 is a strategy that can be provided to sort elements within a collection as required. We can provide different instances of the Comparator to sort the same list in different ways as desired:

// Sort by name
Collections.sort(users, new UsersNameComparator());

// Sort by ID
Collections.sort(users, new UsersIdComparator());

8. Template Method

The Template Method pattern is used when we want to orchestrate several different methods working together. We’ll define a base class with the template method and a set of one or more abstract methods – either unimplemented or else implemented with some default behavior. The template method then calls these abstract methods in a fixed pattern. Our code then implements a subclass of this class and implements these abstract methods as needed:

class Component {
    public void render() {
        doRender();
        addEventListeners();
        syncData();
    }

    protected abstract void doRender();

    protected void addEventListeners() {}

    protected void syncData() {}
}

Here, we have some arbitrary UI components. Our subclasses will implement the doRender() method to actually render the component. We can also optionally implement the addEventListeners() and syncData() methods. When our UI framework renders this component it will guarantee that all three get called in the correct order.

8.1. Examples in the JVM

The AbstractList, AbstractSet, and AbstractMap used by Java Collections have many examples of this pattern. For example, the indexOf() and lastIndexOf() methods both work in terms of the listIterator() method, which has a default implementation but which gets overridden in some subclasses. Equally, the add(T) and addAll(int, T) methods both work in terms of the add(int, T) method which doesn’t have a default implementation and needs to be implemented by the subclass.

Java IO also makes use of this pattern within InputStream, OutputStream, Reader, and Writer. For example, the InputStream class has several methods that work in terms of read(byte[], int, int), which needs the subclass to implement.

9. Visitor

The Visitor pattern allows our code to handle various subclasses in a typesafe way, without needing to resort to instanceof checks. We’ll have a visitor interface with one method for each concrete subclass that we need to support. Our base class will then have an accept(Visitor) method. The subclasses will each call the appropriate method on this visitor, passing itself in. This then allows us to implement concrete behavior in each of these methods, each knowing that it will be working with the concrete type:

interface UserVisitor<T> {
    T visitStandardUser(StandardUser user);
    T visitAdminUser(AdminUser user);
    T visitSuperuser(Superuser user);
}
class StandardUser {
    public <T> T accept(UserVisitor<T> visitor) {
        return visitor.visitStandardUser(this);
    }
}

Here we have our UserVisitor interface with three different visitor methods on it. Our example StandardUser calls the appropriate method, and the same will be done in AdminUser and Superuser. We can then write our visitors to work with these as needed:

class AuthenticatingVisitor {
    public Boolean visitStandardUser(StandardUser user) {
        return false;
    }
    public Boolean visitAdminUser(AdminUser user) {
        return user.hasPermission("write");
    }
    public Boolean visitSuperuser(Superuser user) {
        return true;
    }
}

Our StandardUser never has permission, our Superuser always has permission, and our AdminUser might have permission but this needs to be looked up in the user itself.

9.1. Examples in the JVM

The Java NIO2 framework uses this pattern with Files.walkFileTree(). This takes an implementation of FileVisitor that has methods to handle various different aspects of walking the file tree. Our code can then use this for searching files, printing out matching files, processing many files in a directory, or lots of other things that need to work within a directory:

Files.walkFileTree(startingDir, new SimpleFileVisitor() {
    public FileVisitResult visitFile(Path file, BasicFileAttributes attr) {
        System.out.println("Found file: " + file);
    }

    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
        System.out.println("Found directory: " + dir);
    }
});

10. Conclusion

In this article, we’ve had a look at various design patterns used for the behavior of objects. We’ve also looked at examples of these patterns as used within the core JVM as well, so we can see them in use in a way that many applications already benefit from.

Course – Black Friday 2025 – NPI EA (cat= Baeldung)
announcement - icon

Yes, we're now running our Black Friday Sale. All Access and Pro are 33% off until 2nd December, 2025:

>> EXPLORE ACCESS NOW

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

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag = Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

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 – Black Friday 2025 – NPI (All)
announcement - icon

Yes, we're now running our Black Friday Sale. All Access and Pro are 33% off until 2nd December, 2025:

>> EXPLORE ACCESS NOW

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