Hexagonal Architecture With Java and Spring
Hexagonal Architecture With Java and Spring
Table Of Contents
The term “Hexagonal Architecture” has been around for a long time.
Long enough that the primary source on this topic has been offline for a
while and has only recently been rescued from the archives.
I found, however, that there are very few resources about how to actually
implement an application in this architecture style. The goal of this
article is to provide an opinionated way of implementing a web
application in the hexagonal style with Java and Spring.
https://reflectoring.io/spring-hexagonal/ 1/26
11/30/22, 1:37 PM Hexagonal Architecture with Java and Spring
If you’d like to dive deeper into the topic, have a look at my book.
Example Code
This article is accompanied by a working code example on GitHub.
The hexagon is just a fancy way to describe the core of the application
that is made up of domain objects, use cases that operate on them, and
input and output ports that provide an interface to the outside world.
https://reflectoring.io/spring-hexagonal/ 2/26
11/30/22, 1:37 PM Hexagonal Architecture with Java and Spring
Domain Objects
In a domain rich with business rules, domain objects are the lifeblood of
an application. Domain objects can contain both state and behavior. The
closer the behavior is to the state, the easier the code will be to
understand, reason about, and maintain.
Domain objects don’t have any outward dependency. They’re pure Java
and provide an API for use cases to operate on them.
Use Cases
We know use cases as abstract descriptions of what users are doing
with our software. In the hexagonal architecture style, it makes sense to
promote use cases to first-class citizens of our codebase.
https://reflectoring.io/spring-hexagonal/ 3/26
11/30/22, 1:37 PM Hexagonal Architecture with Java and Spring
A use case in this sense is a class that handles everything around, well,
a certain use case. As an example let’s consider the use case “Send
money from one account to another” in a banking application. We’d
create a class SendMoneyUseCase with a distinct API that allows a user to
transfer money. The code contains all the business rule validations and
logic that are specific to the use case and thus cannot be implemented
within the domain objects. Everything else is delegated to the domain
objects (there might be a domain object Account, for instance).
An output port is again a simple interface that can be called by our use
cases if they need something from the outside (database access, for
instance). This interface is designed to fit the needs of the use cases, but
it’s implemented by an outside component called an output or “driven”
adapter. If you’re familiar with the SOLID principles, this is an
application of the Dependency Inversion Principle (the “D” in SOLID),
https://reflectoring.io/spring-hexagonal/ 4/26
11/30/22, 1:37 PM Hexagonal Architecture with Java and Spring
because we’re inverting the dependency from the use cases to the output
adapter using an interface.
With input and output ports in place, we have very distinct places where
data enters and leaves our system, making it easy to reason about the
architecture.
Adapters
The adapters form the outer layer of the hexagonal architecture. They
are not part of the core but interact with it.
Input adapters or “driving” adapters call the input ports to get something
done. An input adapter could be a web interface, for instance. When a
user clicks a button in a browser, the web adapter calls a certain input
port to call the corresponding use case.
Output adapters or “driven” adapters are called by our use cases and
might, for instance, provide data from a database. An output adapter
implements a set of output port interfaces. Note that the interfaces are
dictated by the use cases and not the other way around.
https://reflectoring.io/spring-hexagonal/ 5/26
11/30/22, 1:37 PM Hexagonal Architecture with Java and Spring
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class Account {
https://reflectoring.io/spring-hexagonal/ 6/26
11/30/22, 1:37 PM Hexagonal Architecture with Java and Spring
if (!mayWithdraw(money)) {
return false;
}
@Value
public static class AccountId {
private Long value;
}
As you can see in the code above, we build our domain objects
completely free of dependencies to the other layers of our architecture.
We’re free to model the code how we see fit, in this case creating a “rich”
behavior that is very close to the state of the model to make it easier to
understand.
We can use external libraries in our domain model if we choose to, but
those dependencies should be relatively stable to prevent forced changes
https://reflectoring.io/spring-hexagonal/ 8/26
11/30/22, 1:37 PM Hexagonal Architecture with Java and Spring
@Value
@EqualsAndHashCode(callSuper = false)
class SendMoneyCommand extends SelfValidating<SendMoneyCommand> {
@NotNull
private final AccountId sourceAccountId;
@NotNull
private final AccountId targetAccountId;
@NotNull
private final Money money;
public SendMoneyCommand(
AccountId sourceAccountId,
https://reflectoring.io/spring-hexagonal/ 9/26
11/30/22, 1:37 PM Hexagonal Architecture with Java and Spring
AccountId targetAccountId,
Money money) {
this.sourceAccountId = sourceAccountId;
this.targetAccountId = targetAccountId;
this.money = money;
this.validateSelf();
}
}
@RequiredArgsConstructor
@Component
@Transactional
public class SendMoneyService implements SendMoneyUseCase {
https://reflectoring.io/spring-hexagonal/ 10/26
11/30/22, 1:37 PM Hexagonal Architecture with Java and Spring
@Override
public boolean sendMoney(SendMoneyCommand command) {
accountLock.lockAccount(sourceAccountId);
if (!sourceAccount.withdraw(command.getMoney(), targetAccountId)) {
accountLock.releaseAccount(sourceAccountId);
return false;
}
accountLock.lockAccount(targetAccountId);
if (!targetAccount.deposit(command.getMoney(), sourceAccountId)) {
accountLock.releaseAccount(sourceAccountId);
accountLock.releaseAccount(targetAccountId);
return false;
}
updateAccountStatePort.updateActivities(sourceAccount);
updateAccountStatePort.updateActivities(targetAccount);
https://reflectoring.io/spring-hexagonal/ 11/26
11/30/22, 1:37 PM Hexagonal Architecture with Java and Spring
accountLock.releaseAccount(sourceAccountId);
accountLock.releaseAccount(targetAccountId);
return true;
}
Basically, the use case implementation loads the source and target
account from the database, locks the accounts so that no other
transactions can take place at the same time, makes the withdrawal and
deposit, and finally writes the new state of the accounts back to the
database.
For loading and storing the accounts from and to the database, the
implementation depends on the output ports LoadAccountPort and
UpdateAccountStatePort, which are interfaces that we will later
The shape of the output port interfaces is dictated by the use case. While
writing the use case we may find that we need to load certain data from
the database, so we create an output port interface for it. Those ports
may be re-used in other use cases, of course. In our case, the output ports
look like this:
https://reflectoring.io/spring-hexagonal/ 12/26
11/30/22, 1:37 PM Hexagonal Architecture with Java and Spring
@RestController
@RequiredArgsConstructor
public class SendMoneyController {
@PostMapping(path = "/accounts/send/{sourceAccountId}/{targetAccountI
void sendMoney(
@PathVariable("sourceAccountId") Long sourceAccountId,
@PathVariable("targetAccountId") Long targetAccountId,
@PathVariable("amount") Long amount) {
new AccountId(targetAccountId),
Money.of(amount));
sendMoneyUseCase.sendMoney(command);
}
If you’re familiar with Spring MVC, you’ll find that this is a pretty boring
web controller. It simply reads the needed parameters from the request
path, puts them into a SendMoneyCommand and invokes the use case. In a
more complex scenario, the web controller may also check
authentication and authorization and do more sophisticated mapping of
JSON input, for example.
The above controller exposes our use case to the world by mapping
HTTP requests to the use case’s input port. Let’s now see how we can
connect our application to a database by connecting the output ports.
@RequiredArgsConstructor
@Component
class AccountPersistenceAdapter implements
LoadAccountPort,
https://reflectoring.io/spring-hexagonal/ 14/26
11/30/22, 1:37 PM Hexagonal Architecture with Java and Spring
UpdateAccountStatePort {
@Override
public Account loadAccount(
AccountId accountId,
LocalDateTime baselineDate) {
AccountJpaEntity account =
accountRepository.findById(accountId.getValue())
.orElseThrow(EntityNotFoundException::new);
List<ActivityJpaEntity> activities =
activityRepository.findByOwnerSince(
accountId.getValue(),
baselineDate);
return accountMapper.mapToDomainEntity(
account,
activities,
withdrawalBalance,
https://reflectoring.io/spring-hexagonal/ 15/26
11/30/22, 1:37 PM Hexagonal Architecture with Java and Spring
depositBalance);
@Override
public void updateActivities(Account account) {
for (Activity activity : account.getActivityWindow().getActivities(
if (activity.getId() == null) {
activityRepository.save(accountMapper.mapToJpaEntity(activity))
}
}
}
Again, we use @Component to make this a Spring bean that can be injected
into the use case service above.
https://reflectoring.io/spring-hexagonal/ 16/26
11/30/22, 1:37 PM Hexagonal Architecture with Java and Spring
If we’re building a CRUD application that simply stores and saves data,
an architecture like this is probably overhead. If we’re building an
application with rich business rules that can be expressed in a rich
domain model that combines state with behavior, then this architecture
really shines because it puts the domain model in the center of things.
Dive Deeper
The above only gives an idea of what a hexagonal architecture might
look like in real code. There are other ways of doing it, so feel free to
experiment and find the way that best fits your needs. Also, the web and
persistence adapters are just examples of adapters to the outside. There
may be adapters to other third party systems or other user-facing
frontends.
If you want to dive deeper into this topic, have a look at my book which
goes into much more detail and also discusses things like testing,
mapping strategies, and shortcuts.
Written By:
https://reflectoring.io/spring-hexagonal/ 17/26
11/30/22, 1:37 PM Hexagonal Architecture with Java and Spring
Tom Hombergs
As a professional software engineer, consultant, architect, general problem solver, I've been
practicing the software craft for more fifteen years and I'm still learning something new
every day. I love sharing the things I learned, so you (and future me) can get a head start.
That's why I founded reflectoring.io.
https://reflectoring.io/spring-hexagonal/ 18/26
11/30/22, 1:37 PM Hexagonal Architecture with Java and Spring
Simplify! Newsletter
"You can't just keep it simple. Make it simple, then it's easy."
Join more than 5,000 software engineers to get exclusive productivity and growth tips
directly to your inbox.
https://reflectoring.io/spring-hexagonal/
Check out the Wall of Love! 19/26
11/30/22, 1:37 PM Hexagonal Architecture with Java and Spring
Check out the Wall of Love!
Subscribe
No spam. Your email address is safe with us. Your data will be used according to the privacy policy.
https://reflectoring.io/spring-hexagonal/ 20/26
11/30/22, 1:37 PM Hexagonal Architecture with Java and Spring
https://reflectoring.io/spring-hexagonal/ 21/26
11/30/22, 1:37 PM Hexagonal Architecture with Java and Spring
https://reflectoring.io/spring-hexagonal/ 22/26
11/30/22, 1:37 PM Hexagonal Architecture with Java and Spring
Recent Posts
Software Craft
Teams looking to control and reduce their cloud costs can choose from multiple cloud cost
management approaches. All of them require at least a basic understanding of what’s
going on in your cloud infrastructure - this part relies on monitoring and reporting.
Read More
Node
https://reflectoring.io/spring-hexagonal/ 23/26
11/30/22, 1:37 PM Hexagonal Architecture with Java and Spring
How to design a URL shortening service like tinyurl.com is a frequently asked question in
system design interviews. URL shortener services convert long URLs into significantly
shorter URL links.
Read More
Spring
Cross-site Request Forgery (CSRF, sometimes also called XSRF) is an attack that can trick
an end-user using a web application to unknowingly execute actions that can compromise
security.
R dM
https://reflectoring.io/spring-hexagonal/ 24/26
11/30/22, 1:37 PM Hexagonal Architecture with Java and Spring
Read More
Content
Spring Boot
Java
Node
AWS
Software Craft
Simplify!
Meta
Book Reviews
Products
Simplify! Newsletter
Stratospheric
https://reflectoring.io/spring-hexagonal/ 25/26
11/30/22, 1:37 PM Hexagonal Architecture with Java and Spring
Contribute
Become an Author
Writing Guide
Author Workflow
Author Payment
Reflectoring
About
Atom Feed
Advertise
Book me
Privacy
https://reflectoring.io/spring-hexagonal/ 26/26