Hexagonal Architecture In Context Of Spring Boot

Author: Zen and the Art of Computer Programming

1 Introduction

Hexagonal architecture is a design pattern designed to help applications maintain a good modular structure and isolate the impact of changes. It enables independent development, testing, deployment, and even deployment of modules into a production environment, thereby improving the maintainability and reusability of applications. In this article, we will discuss what it is, why it is so popular, and how to implement it in your Spring Boot project.

Why study Hexagonal Architecture?

First, let's take a look at the history and origin of the hexagonal architecture.

In the 1990s, and proposed a concept called "The onion" (Cold Noodles) architectural pattern. They believe that if a system is split into multiple layers, and each layer has its own area of ​​responsibility, the system will become easier to maintain, extend, and reuse.

This architectural pattern has gradually become a popular design pattern because it encourages the single responsibility principle while avoiding excessive coupling.

As time goes by, Hexagonal Architecture has become more and more popular due to the following reasons:

  1. Isolate the impact of changes: Hexagonal Architecture enables different parts of the system to be independent of each other and target each other without interfering with each other by modeling around business domain logic and bounded context. Therefore, it can help you reduce problems caused by modifying certain functions and facilitate maintenance, integration and delivery when adding new functions.
  2. Better testability: Since there are clear interface definitions between the various layers, you can easily unit test them, thereby enhancing the testability of your application.
  3. Improve code reuse: Hexagonal Architecture allows you to create reusable libraries or components that can be customized and extended according to different application scenarios. As a result, your engineers can reuse these components in other projects and save development time and costs.
  4. Supports multi-language programming: If you want your application to support multiple programming languages, Hexagonal Architecture can help as it provides a unified mechanism to call the underlying functionality.
  5. Implemented in a service-oriented architecture (SOA) pattern: Although Hexagonal Architecture was originally used only for monolithic architectures, it has recently been adopted by a variety of service-oriented architecture patterns.

Overall, Hexagonal Architecture has many advantages, and as the author says, they help you build applications that are robust, maintainable, scalable, testable, flexible, and easily extensible. However, if you don’t know Hexagonal Architecture very well, then I will explain its working principle and precautions through a practical example of how to implement Hexagonal Architecture in a Spring Boot project.

Implementing Hexagonal Architecture in Spring Boot project

Below we use an example to illustrate how to implement Hexagonal Architecture in a Spring Boot project.

Suppose we are developing an e-commerce website that contains many different subsystems, including product information, order management, payment processing, etc. There are complex dependencies between these subsystems, making the system difficult to maintain. To solve this problem, we can use the Hexagonal Architecture pattern to achieve this goal.

Here are the six key elements of the Hexagonal Architecture pattern:

  1. Inner circle (inner layer): inner circle. It is responsible for the implementation of business domain models, which represent the core business logic. In addition to being responsible for its own domain logic, it does not need to know the existence of other subsystems.
  2. Outer circle (outer layer): outer circle. It is responsible for providing necessary configuration and environmental support for the entire system. It can implement functions such as logging, configuration management, resource management, etc., which are shared by all other subsystems.
  3. Adapters: Adapters. It is responsible for connecting the boundary between the inner and outer rings. Adapters usually need to map the API of the external subsystem to the model of the internal subsystem.
  4. Ports: Port. It is the entry point of the application. It acts as a bridge between the client and the internal subsystem, enabling the client to access the functionality of the internal subsystem.
  5. Databases: databases. It is used to store data for internal subsystems. For some subsystems, the database may be the persistence tier.
  6. DDD - Domain-driven design: Domain-driven design. As a software design methodology, it aims to guide designers and developers to build understandable, complete and robust software.

In this example, we will take an e-commerce website based on the Spring Boot framework as an example to show how to implement the Hexagonal Architecture pattern.

Create the Inner Circle layer

In a Spring Boot project, we can implement the Inner Circle layer by creating different Maven modules. The following is a code example for the Inner Circle layer:

package com.example.demo.domain;

public class Product {
    private String name;
    private double price;

    public Product(String name, double price) {
        this.name = name;
        this.price = price;
    }

    // getters and setters...
}

This class is the core business logic of the e-commerce website, which contains the name and price of the product. It defines the product entity and contains two attributes: nameand price.

Create the Outer Circle layer

In addition to the Inner Circle layer, we also need to create a Maven module to implement the Outer Circle layer. The following is a code example for the Outer Circle layer:

@SpringBootApplication
@EnableAutoConfiguration
@Import({ DataSourceConfig.class })
public class DemoApplication extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

This class is the startup class of our SpringBoot project. It introduces one DataSourceConfig, which is used to configure data sources, such as setting username and password, URL, connection pool size, etc.

In addition, DemoApplicationuse automatic configuration to configure Spring Boot projects instead of manually writing configuration code.

Create Adapters

Adapters are the last part of the Hexagonal Architecture pattern and are used to connect the boundary between the Inner Circle and the Outer Circle. We need to create an Adapter for each subsystem and inject it into the Outer Circle layer.

For example, here is an Adapter for product information:

package com.example.demo.adapter.product;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.example.demo.domain.Product;
import com.example.demo.repository.ProductRepository;

@Component
public class ProductServiceAdapter implements ProductService {

    @Autowired
    private ProductRepository productRepository;

    // implementation of methods from interface...
}

This class implements ProductServicethe interface and @Autowiredinjects one using Spring Boot's annotations ProductRepository.

Similarly, we also need to create Adapters for other subsystems.

Create Ports

Ports is an important component, it is the entry point of the application. It acts as a bridge between the client and the internal subsystem, enabling the client to access the functionality of the internal subsystem.

For example, we can create a common interface in our project:

public interface CartService {
   Cart addItemToCart(Product product);

   List<CartLine> getCartLines();
}

This interface defines the interface of the shopping cart service, including a addItemToCart()method for adding items to the shopping cart, and getCartLines()a method for getting the list of items in the shopping cart.

We can use this interface by creating an CartServiceImplimplementation of this interface and injecting it into a controller:

@RestController
public class CheckoutController {

    @Autowired
    private CartService cartService;

    @PostMapping("/checkout")
    public ResponseEntity<Void> checkout() throws Exception {

        List<CartLine> lines = cartService.getCartLines();

        // processing the payment logic...

        return ResponseEntity.ok().build();
    }
}

This controller calls cartServicethe method and returns the list of items in the shopping cart to the user.

Similarly, we can also create other Ports, such as search ports, recommended ports, advertising ports, etc.

Configure data source

The final step is to configure the data source so that the data from the internal subsystem can be accessed.

In our example, we will use MySQL as the data source. To do this, we need to add the corresponding information to the configuration file:

spring:
  datasource:
    driverClassName: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/testdb?useSSL=false&serverTimezone=UTC
    username: root
    password: password

In this way, our project has completed the implementation of Hexagonal Architecture, and it has good modularity and scalability.

Future direction

The Hexagonal Architecture pattern is a classic design pattern that is still evolving. It has been widely used and has become an important architecture for large software systems. The Hexagonal Architecture pattern will continue to be improved and developed over time.

On the other hand, with the rise of cloud native, cloud computing is changing the concept of software architecture. Cloud native applications will be deployed on containers as services and scheduled to run in a distributed environment. As this trend develops, the Hexagonal Architecture pattern is being applied to cloud computing architecture.

Guess you like

Origin blog.csdn.net/universsky2015/article/details/133565940