A practical demonstration of hexagonal architecture using Kotlin, MongoDB and Kafka. This project shows how to structure microservices properly with domains, adapters and controllers in a real-world CRUD application.
Perfect for developers looking to level up, prepare for interviews, or learn better architecture practices.
This repository implements a complete microservice following hexagonal architecture (ports and adapters) principles, showcasing:
- Clean separation between business logic and external concerns
- Domain-driven design principles in practice
- Integration with external systems via adapters
- Asynchronous communication using Kafka
- Persistence with MongoDB
- RESTful API controllers
- Language: Kotlin
- Framework: Spring Boot
- Build Tool: Gradle
- Database: MongoDB
- Messaging: Apache Kafka
- Containerization: Docker
- Docker and Docker Compose
- JDK 17 or higher
- Gradle 8.x or higher
- Start the required infrastructure (MongoDB, Kafka):
docker-compose up -d
- Wait for all containers to be healthy (usually takes about 30 seconds)
- Option 1: Using Gradle
./gradlew bootRun
- Option 2: Build and Run JAR
./gradlew build
java -jar build/libs/hexagonal-demo-0.1.0.jar
The application will be available at http://localhost:8080
CRUD implemented: http://localhost:8080/api/v1/customers
src/
├── main/
│ ├── kotlin/
│ │ └── br/com/hexagonal/api
│ │ ├── adapters/ # Implementation of ports (infrastructure layer)
│ │ │ ├── in/ # Inbound adapters handling incoming requests
│ │ │ │ ├── consumer/ # Kafka message consumers
│ │ │ │ ├── controller/ # REST API controllers
│ │ │ ├── out/ # Outbound adapters handling external systems
│ │ │ │ ├── client/ # HTTP clients for external services
│ │ │ │ ├── repository/ # Data persistence implementations
│ │ │ ├── AllAdapter.kt # Implementation adapter interfaces
│ │ ├── application/ # Application layer
│ │ │ ├── core/ # Core application components
│ │ │ │ ├── domain/ # Business entities and value objects
│ │ │ │ ├── exceptions/ # Custom exception classes
│ │ │ │ ├── useCase/ # Business logic implementations
│ │ │ ├── ports/ # Interface definitions (ports)
│ │ │ │ ├── in/ # Input ports for receiving commands/queries
│ │ │ │ ├── out/ # Output ports for external system operations
│ │ ├── config/ # Spring configuration and dependency injection
│ │ └── HexagonalApplication.kt # Main application entry point
│ └── resources/
│ └── application.yml # Application configuration
- Domain (core): Pure business logic and entities, with no external dependencies
- Ports: Interfaces defining the boundaries of the application
- Output Ports: Interfaces for the application to interact with external systems
- Input Ports: Interfaces for operations triggered from outside
- Adapters: Implementations connecting the application to the outside world
- Inbound Adapters: Handle requests coming into the application (controllers, consumers)
- Outbound Adapters: Handle interactions with external systems (repositories, clients)
- Use Cases: Application-specific business rules implementing input ports
- External requests enter through inbound adapters (controllers, consumers)
- Adapters convert requests to application-specific format and invoke use cases
- Use cases implement business logic using the domain model
- When external resources are needed, use cases call output ports
- Outbound adapters implement these ports to interact with external systems
- Responses flow back through the same layers in reverse
- Study the domain models in the core package to understand business concepts
- Examine the port interfaces that define application boundaries
- See how use cases implement business logic using these ports
- Look at how adapters connect the application to the outside world
- Observe the clear separation between business logic and infrastructure concerns
Feel free to submit issues, fork the repository and send pull requests!
This project is licensed under the MIT License - see the LICENSE file for details.