Architecture Overview
The Blackjack API is built using a layered architecture that combines Hexagonal Architecture (Ports and Adapters), Domain-Driven Design (DDD), and Reactive Programming principles with Spring WebFlux.Architectural Layers
The application is organized into three primary layers:1. Domain Layer
The core of the application containing business logic and rules. Package:cat.itacademy.s05.t01.blackjack_api.domain
Domain Models
Core entities and value objects:
Game(Aggregate Root)Player(Aggregate Root)Card,Hand,Deck- Value Objects:
GameId,PlayerId,PlayerName
Ports
Interfaces defining dependencies:
GameRepositoryPortPlayerRepositoryPort
2. Application Layer
Orchestrates use cases and coordinates between domain and infrastructure. Package:cat.itacademy.s05.t01.blackjack_api.application
Use Cases
Business operations:
CreateNewGameUseCasePlayMoveUseCaseGetGameStateUseCaseChangePlayerNameUseCaseViewRankingUseCaseDeleteGameUseCase
DTOs & Mappers
Data transfer objects and mapping logic:
- Command objects (input)
- Result objects (output)
GameStateMapper
3. Infrastructure Layer
Provides concrete implementations for external concerns. Package:cat.itacademy.s05.t01.blackjack_api.infrastructure
Web Controllers
REST API endpoints:
GameControllerPlayerControllerRankingController
Persistence Adapters
Database implementations:
MongoGameRepositoryAdapterMySqlPlayerRepositoryAdapter
Component Interaction Flow
Here’s how components interact for a typical request:Example: Creating a New Game
- HTTP Request arrives at
GameController.create() - Controller invokes
CreateNewGameUseCase.execute() - Use case calls
PlayerRepositoryPort.findOrCreateByName() MySqlPlayerRepositoryAdapterqueries the MySQL database reactively- Use case creates domain
Gameobject with business logic - Use case calls
GameRepositoryPort.save() MongoGameRepositoryAdapterpersists to MongoDB- Result flows back through layers as
Mono<CreateGameResult>
Package Structure
Key Design Principles
Dependency Rule
Dependency Rule
Dependencies point inward. The domain layer has no dependencies on outer layers. Infrastructure depends on domain, not vice versa.
Separation of Concerns
Separation of Concerns
Each layer has a distinct responsibility:
- Domain: Business logic and rules
- Application: Use case orchestration
- Infrastructure: Technical implementation details
Immutability
Immutability
Domain models are immutable. Operations return new instances rather than modifying state.Example from
domain/model/Game.java:55-63:Reactive Streams
Reactive Streams
All repository operations return
Mono<T> or Flux<T> for non-blocking, asynchronous processing.Technology Stack
| Layer | Technologies |
|---|---|
| Web | Spring WebFlux, Spring MVC annotations |
| Application | Plain Java, Reactor Core |
| Domain | Pure Java (no framework dependencies) |
| Persistence | Spring Data MongoDB (Reactive), Spring Data R2DBC (MySQL) |
| API Documentation | SpringDoc OpenAPI |
Benefits of This Architecture
Testability
Domain logic can be tested in isolation without frameworks or databases.
Flexibility
Easy to swap implementations (e.g., switch from MongoDB to another NoSQL database).
Maintainability
Clear boundaries make code easier to understand and modify.
Scalability
Reactive programming enables efficient resource usage and high concurrency.
Next Steps
Hexagonal Architecture
Learn about ports and adapters pattern
Domain-Driven Design
Explore DDD concepts and implementations
Reactive Programming
Understand reactive patterns with Spring WebFlux
API Reference
View API endpoints and usage