A comprehensive reference implementation of the Hexagonal Architecture (Ports and Adapters) pattern using the Spring ecosystem, demonstrating clean separation of concerns and domain-driven design principles.
This reference application demonstrates patterns and principles thoroughly explored in:
English Version
Decoupling by Design: A Pragmatic Approach to Hexagonal Architecture
VersiΓ³n en EspaΓ±ol
Desacoplamiento por DiseΓ±o: Una GuΓa PrΓ‘ctica para la Arquitectura Hexagonal
The book provides complete coverage of:
- End-to-end hexagonal architecture implementation
- Domain-driven design integration
- Spring Boot configuration for hexagonal systems
- Functional error handling patterns
- Adapter implementation strategies
- Testing approaches for each architectural layer
- Real-world case studies and evolution patterns
- Migration from traditional layered architectures
This project serves as a practical example of implementing the Hexagonal Architecture with Spring Boot. It showcases how to structure a Spring application with clear boundaries between the domain core and external dependencies, enabling better testability, maintainability, and flexibility.
- π· Pure Hexagonal Architecture: Complete implementation of ports and adapters pattern
- π§© Modular Structure: Clear separation between domain, application, and infrastructure layers
- π Functional Error Handling: Using Vavr's Either type for exception-free error management
- π§ͺ Comprehensive Testing: High test coverage across all architectural layers
- π Article Management: Full CRUD operations for article entities
- π€ Author Integration: External author service integration via adapters
- π Pluggable Repositories: Swappable data storage implementations
- π‘οΈ Validation: Robust input validation with clear error reporting
- π Spring Boot Integration: Seamless integration with Spring ecosystem
Add the project as a dependency to your pom.xml:
<dependency>
<groupId>io.github.emedina</groupId>
<artifactId>hexagonal-spring-ref-app</artifactId>
<version>0.0.1</version>
</dependency>Or clone the repository to explore and run locally:
git clone https://github.com/emedina/hexagonal-spring-ref-app.git
cd hexagonal-spring-ref-app
mvn clean installcd spring-boot-assembly
mvn spring-boot:run// Using the API adapter
HttpEntity<ApiRequest.Article> request = new HttpEntity<>(
new ApiRequest.Article("article-123", "author-456", "My Article Title", "Article content goes here")
);
ResponseEntity<Void> response = restTemplate.postForEntity("/api/articles", request, Void.class);// Using the application service directly
@Autowired
private FindArticleUseCase findArticleUseCase;
public void findArticle(String articleId) {
FindArticleQuery query = FindArticleQuery.validateThenCreate(articleId).get();
Either<Error, ArticleDTO> result = findArticleUseCase.handle(query);
result.fold(
error -> handleError(error),
article -> processArticle(article)
);
}// Using the command bus pattern
@Autowired
private CommandBus commandBus;
public void updateArticle(String id, String authorId, String title, String content) {
UpdateArticleCommand command = UpdateArticleCommand.validateThenCreate(id, authorId, title, content).get();
Either<Error, Void> result = commandBus.execute(command);
result.fold(
error -> handleError(error),
success -> System.out.println("Article updated successfully")
);
}The application is structured following the Hexagonal Architecture pattern:
- Contains the business entities, value objects, and domain services
- Implements core business rules and logic
- Has no dependencies on external frameworks or libraries
- Implements use cases as command and query handlers
- Orchestrates the flow of data between the domain and ports
- Contains application-specific business rules
- Defines interfaces for the primary/driving adapters to use
- Specifies commands and queries that the application can handle
- Provides clear entry points into the application
- Defines interfaces for the secondary/driven adapters to implement
- Specifies how the application interacts with external systems
- Enables pluggable implementations of infrastructure concerns
- Implements REST controllers as primary adapters
- Translates HTTP requests into application commands and queries
- Handles API-specific concerns like request validation and response formatting
- Implements repository interfaces as secondary adapters
- Provides in-memory storage for entities
- Demonstrates how to swap different persistence mechanisms
- Integrates with external author services
- Translates between external data formats and domain models
- Handles external service communication details
- Wires all components together using Spring Boot
- Configures dependency injection and application properties
- Provides the runnable application entry point
- π Request Handling: API requests are received by controllers in the API adapter
- π― Command/Query Creation: Controllers create commands or queries and pass them to the appropriate use case
- π§ Business Logic: Application services execute business logic using domain entities
- π External Integration: Output ports are used to interact with external systems when needed
- π Response Formation: Results are mapped back to API responses and returned to the client
The project includes comprehensive tests for all layers:
# Run all tests
mvn test
# Generate test coverage report
mvn clean test jacoco:report- β Domain Tests: Verify business rules and entity behavior
- β Application Tests: Ensure use cases work correctly with mocked dependencies
- β Adapter Tests: Validate correct interaction with external systems
- β Integration Tests: Verify components work together properly
- β 90%+ Coverage: Enforced by JaCoCo configuration
- Given/When/Then: Clear test structure for readability
- Isolated Components: Pure unit tests with mocking
- Hexagonal Testing: Each layer tested independently
- Behavior Verification: Focus on verifying correct behavior
The project includes ArchUnit-based architecture tests to enforce hexagonal architecture rules:
# Run architecture tests
mvn test -pl spring-boot-assembly -Dtest="*ArchitectureTest"Architecture tests validate:
- Shared Kernel: Only depends on allowed external libraries
- Domain Layer: No dependencies on infrastructure or frameworks
- Input Ports: Properly defined as interfaces with correct dependencies
- Output Ports: Properly defined as interfaces for secondary adapters
- Commands: Follow command pattern conventions
- Queries: Follow query pattern conventions
- Handlers: Implement use cases correctly
- Adapters: Only depend on allowed packages
Configuration is managed via application.yaml in test resources, allowing customization of allowed dependencies per layer.
| Dependency | Version | Purpose |
|---|---|---|
| Spring Boot | 4.0.1 | Core Spring Boot framework |
| Java | 25+ | Runtime platform |
| Vavr | 0.11.0 | Functional programming with Either |
| Lombok | 1.18.42 | Boilerplate code reduction |
| MapStruct | 1.6.3 | Object mapping |
| Shared Kernel | 1.0.0 | Common components |
| Dependency | Version | Purpose |
|---|---|---|
| JUnit Jupiter | 6.0.2 | Testing framework |
| Mockito | 5.21.0 | Mocking framework |
| AssertJ | 3.27.6 | Fluent assertions |
| SLF4J | 2.0.17 | Logging framework |
| ArchUnit Hexagonal | 1.0.0 | Architecture tests for hexagonal validation |
- Java 25+
- Maven 3.9+
- Spring Boot 4.0.1+
# Compile the project
mvn clean compile
# Run tests
mvn test
# Package the application
mvn clean package
# Run the application
java -jar spring-boot-assembly/target/spring-boot-assembly-0.0.1.jar- π΄ Fork the repository
- πΏ Create a feature branch (
git checkout -b feature/amazing-feature) - β Add tests for your changes
- π§ͺ Ensure all tests pass (
mvn test) - π Maintain 90%+ test coverage
- π Update documentation as needed
- π€ Submit a pull request
This project is licensed under the terms of the MIT license.
Enrique Medina Montenegro
hexagonal-architecture spring-boot ports-and-adapters ddd clean-architecture java vavr functional-programming reference-implementation testing spring-framework error-handling modular-design
π· This reference application demonstrates how to implement a clean, maintainable, and testable application using Hexagonal Architecture principles with the Spring ecosystem.