A Quick and Practical Example of Hexagonal Architecture in Java
1. Overview
In this tutorial, we’ll implement a Spring Boot application using Hexagonal architecture along with DDD in Java.
Let’s explore Hexagonal Architecture along with a demonstration. We’ll see by adopting this pattern how it benefits the overall health of an application.
2. Principle
The hexagonal architecture is based on three principles and techniques:
- Explicitly separate Application, Domain, and Infrastructure
- Dependencies are going from Application and Infrastructure to the Domain
- We isolate the boundaries by using Ports and Adapters
The following diagram depicts the idea behind the hexagonal architecture and its associated layers:
3. Demonstration: a small example of an application
Let’s design an Application that manages change requests of software releases. The user can query the application with a change request id. The app returns application metadata for the given change request id.
Let’s divide the application into three parts:
- Application — This is the side through which the user or external programs will interact with the application. It contains the code that allows these interactions. Typically, your user interface code, your HTTP routes for an API, your JSON serializations to programs that consume your application are here.
- Domain — This is the part that we want to isolate from both application and infrastructure. It contains all the code that concerns and implements business logic. The business vocabulary and the pure business logic, which relates to the concrete problem that solves your application, everything that makes it rich and specific is at the center.
- Infrastructure — This is where we’ll find what your application needs, what it drives to work. It contains essential infrastructure details such as the code that interacts with your database, makes calls to the file system, or code that handles HTTP calls to other applications on which you depend for example.
3.1 Domain
Let’s begin with Domain Layer which is the centerpiece of the architecture:
Firstly, we write a ChgRequest class:
The class is responsible for the state transitions of our domain object. Next, we will write a port(repository) which will help us interact with infrastructure:
Additionally, we will write a Domain Service which will interact with infrastructure:
We can test the domain layer since it is decoupled from infrastructure and application:
3.2 Infrastructure
In this section, we’ll implement the infrastructure layer. We’ll use our CassandraDbChgRequestRepository in our implementation
Therefore, let’s write the CassandraDbChgRequestRepository:
We can even write a test for this:
3.3 Application
Lastly, we’ll allow the user to communicate with our application via a RESTful API.
Hence, we’ll implement the ChgRequestController from the domain layer:
4. Benefits
We have learned the following benefits of adopting hexagonal architecture:-
- Maintainability — We build layers that are independent and loosely coupled. It becomes easy to add new features in one layer without affecting other layers.
- Testability — We can write tests for each layer. Unit tests are cheap to write and fast to run. We can mock the dependencies while testing. For example:- We can mock a database dependency by adding an in-memory datastore.
- Adaptability — Our core domain becomes independent of changes in external entities. For eg:- If we plan to use a different database, we don’t need to change the domain. We can introduce the appropriate database adapter. e.g DynamoDb.
5. Conclusion
In this article, we have learned how to decouple layers intelligently of our application. And then we came up with the implementation of each layer and build the application around our domain object.
As always, the code for these examples is available over on GitHub.