Hexagonal Architecture on Spring Boot
In this article, I’ll show how to implement a Spring Boot application using Hexagonal Architecture.
We’ll build a Bank Account simulation with deposit and withdraw operations exposed through REST endpoints.
Hexagonal Architecture
Hexagonal architecture is an architectural style that focuses on keeping the business logic decoupled from external concerns.
The business core interacts with other components through ports and adapters. This way, we can change the underlying technologies without having to modify the application core.
Application Core
Domain Model
Let’s start with the domain model. Its main responsibility is to model the business rules. It also verifies that the objects are always in a valid state:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
The domain model should have no dependency on any specific technology. That’s the reason why you’ll find no Spring annotations here.
Ports
Now it’s time to have our business logic interact with the outside world. To achieve this, we’ll introduce some ports.
First, let’s define 2 incoming ports. These are used by external components to call our application. In this case, we’ll have one per use case. One for Deposit:
1 2 3 |
|
And one for Withdraw:
1 2 3 |
|
Similarly, we’ll also have 2 outgoing ports. These are for our application to interact with the database. Once again, we’ll have one per use case. One for Loading the Account:
1 2 3 |
|
And one for Saving it:
1 2 3 |
|
Service
Next, we’ll create a service to tie all the pieces together and drive the execution:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
|
Note how the service implements the incoming ports. On each method, it uses the Load port to fetch the account from the database. Then, it performs the changes on the domain model. And finally, it saves those changes through the Save port.
Adapters
Web
To complete our application, we need to provide implementations for the defined ports. We call these adapters.
For the incoming interactions, we’ll create a REST controller:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
The controller uses the defined ports to make calls to the application core.
Persistence
For the persistence layer, we’ll use Mongo DB through Spring Data:
1
|
|
Also, we’ll create a BankAccountRepository class that connects the outgoing ports with the SpringDataBankAccountRepository:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
Infrastructure
Finally, we need to tell Spring to expose the BankAccountService as a bean, so it can be injected in the controller:
1 2 3 4 5 6 7 8 9 |
|
Defining the beans in the Adapters layer helps us maintain the infrastructure code decoupled from the business logic.
Conclusion
In this article, we’ve seen how to implement an application using Hexagonal Architecture and Spring Boot. This is what the system ends up looking like:
The code for this example is available on Github.
This article is based on the highly recommendable “Get Your Hands Dirty on Clean Architecture by Tom Hombergs, and this Baeldung article by Łukasz Ryś.