Understanding Hexagonal Architecture With a Spring Boot Implementation

An example using Spring Boot to detail the different layers of the application

Ramón Bailén
Better Programming

--

Photo by Donny Jiang on Unsplash

Hexagonal Architecture was proposed in 2005 by Alistair Cockburn.

The main idea behind this architecture is to isolate domain logic from external components when designing software applications.

Access to domain logic from the outside is available through ports and adapters.

A port is just an interface to be implemented by an adapter. There are two types of ports: input and output. We implement the first ones in the domain layer, while the infrastructure module will contain the implementation of the second ones.

With this approach, you will have well-defined interfaces to communicate in and out of the domain layer without depending on implementation details.

Example

Let’s consider a simple Product REST Service to understand this architecture. Resources of the product service are:

  • Create a Product
  • Get the Product by Id

We start creating the three layers: application, infrastructure, and domain.

Application

The application layer will contain the ports, which are interfaces that allow inbound or outbound flow.

We created use cases inside the input package, defining what the user would like to do in the application. In our example, create new products and get them by Id.

On the other hand, we use the output package to connect to some external components.

In our example, ProductOutputPort will get data from the database, while ProductEventPublisher will publish an event when a product has been created.

Infrastructure

The infrastructure layer represents the outer part of the hexagonal architecture through adapters.

Adapters interact with the core application only by using the inbound and outbound ports.

We divide the infrastructure.adapters package into three new ones:

  1. config: it contains the beans of the application
  2. input: it drives the application by invoking the corresponding use case (input port)
  3. output: it provides an implementation of the output ports like databases or messaging queues

Domain

The domain layer is the center of the system. It handles the business logic and represents the application core.

The domain layer is wholly decoupled from application and infrastructure layers, so changes in the other layers have no impact on the Product domain object unless there is a change in the business requirements.

The ProductService is a crucial component inside the domain, as it implements the input ports and uses the output interfaces implemented by the output adapters to return the result to the input adapters:

Domain exceptions are thrown in this layer and managed in the infrastructure one (CustomizedExceptionAdapter).

Conclusion

In this article, we saw through a practical example how to separate the logic related to our application into three specific layers: domain, application and infrastructure.

I recommend using a mapper library, like MapStruct, to convert objects between the different layers.

No two Hexagonal Architectures are the same, as you can find different proposed names for layers and ways to structure your application. All possible solutions should make the application easier to test, which is the real goal.

The code for this example is available on GitHub.

Want to Connect?Connect with me on LinkedIn or follow me on Twitter.

--

--