A modern banking client management REST API built with a hybrid approach combining Domain-Driven Design principles and hexagonal architecture (ports and adapters).
The application implements a hybrid approach that combines the benefits of Domain-Driven Design's strategic patterns with hexagonal architecture's technical organization:
-
Domain Layer (Core Hexagon)
- Organized by subdomains and bounded contexts
- Contains business logic and rules
- Pure Java, no frameworks or external dependencies
- Uses DDD tactical patterns within each subdomain
-
Application Layer (Use Cases)
- Organized by subdomains matching the domain layer
- Orchestrates the flow of data and domain objects
- Implements use cases using domain objects
- Defines ports (interfaces) for external adapters
-
Infrastructure Layer (Adapters)
- Implements the interfaces defined by ports
- Contains framework-specific code
- Handles external concerns (persistence, API, etc.)
- Adapters can be shared across subdomains when appropriate
The project is organized into distinct subdomains, each representing a specific area of the business:
-
Client Management (Core Subdomain)
- Handles client onboarding and profile management
- Manages client verification and status
- Core business differentiator
-
Account Management (Supporting Subdomain)
- Manages account operations and status
- Handles balance tracking
- Essential but not unique to the business
-
Transaction Processing (Generic Subdomain)
- Handles financial transactions
- Follows standard banking practices
- Could potentially be replaced by a third-party solution
The project implements DDD tactical patterns within each subdomain:
-
Aggregates
- Strong consistency boundaries
- Accessed only through aggregate root
- Example:
Client
aggregate includesClientStatus
-
Entities
- Have identity and lifecycle
- Mutable objects
- Example:
Transaction
in the Account context
-
Value Objects
- Immutable
- No identity
- Example:
Address
,Balance
-
Domain Events
- Represent significant domain occurrences
- Enable loose coupling between aggregates
- Used for cross-subdomain communication
This is the core domain that handles all client-related operations and management.
-
Client Aggregate
- Client (Root Entity)
- PersonalInformation (Value Object)
- Address (Value Object)
- ContactDetails (Value Object)
-
Account Aggregate
- Account (Root Entity)
- Balance (Value Object)
- TransactionHistory (Entity)
- AccountStatus (Value Object)
-
Client
- Manages client's core information
- Handles client status and verification
- Links to accounts and products
-
Account
- Manages account operations
- Tracks balance and status
- Handles transaction history
-
Transaction
- Records financial movements
- Maintains transaction details
- Links to accounts involved
- Language: Java 17
- Framework: Spring Boot 3.x
- Database: PostgreSQL
- Cache: Redis
- ORM: Hibernate
- API Style: REST
- Build Tool: Maven
- Monitoring: Prometheus & Grafana
- Unit Testing: JUnit 5
- Integration Testing: TestContainers
- API Testing: REST Assured
src/
├── main/
│ └── java/org/kolmanfreecss/
│ ├── domain/ # Domain Layer (Core Hexagon)
│ │ ├── clientmanagement/ # Client Management Subdomain
│ │ │ ├── model/ # Domain Models
│ │ │ │ ├── Client.java # Aggregate Root
│ │ │ │ ├── ClientStatus.java
│ │ │ │ └── vo/
│ │ │ └── repository/ # Repository Interfaces
│ │ ├── accountmanagement/ # Account Management Subdomain
│ │ │ ├── model/
│ │ │ │ ├── Account.java # Aggregate Root
│ │ │ │ └── vo/
│ │ │ └── repository/
│ │ ├── transactionprocessing/ # Transaction Processing Subdomain
│ │ │ ├── model/
│ │ │ │ ├── Transaction.java
│ │ │ │ └── vo/
│ │ │ └── repository/
│ │ └── common/ # Shared Kernel
│ │ └── vo/
│ │
│ ├── application/ # Application Layer
│ │ ├── clientmanagement/ # Client Management Use Cases
│ │ │ ├── ports/
│ │ │ │ ├── input/
│ │ │ │ └── output/
│ │ │ └── services/
│ │ ├── accountmanagement/ # Account Management Use Cases
│ │ │ ├── ports/
│ │ │ └── services/
│ │ └── transactionprocessing/ # Transaction Processing Use Cases
│ │ ├── ports/
│ │ └── services/
│ │
│ ├── infrastructure/ # Infrastructure Layer (Pure Hexagonal)
│ │ ├── adapters/
│ │ │ ├── in/ # Input/Driving Adapters
│ │ │ │ ├── rest/ # REST Controllers
│ │ │ │ └── messaging/ # Message Consumers
│ │ │ └── out/ # Output/Driven Adapters
│ │ │ ├── persistence/ # Database Repositories
│ │ │ └── messaging/ # Message Publishers
│ │ └── config/ # Infrastructure Configuration
│ │
│ └── shared/ # Shared/Common Components
│ ├── config/ # Global Configuration
│ └── exceptions/ # Global Exception Handling
-
Prerequisites
- Java 17
- Maven
- PostgreSQL
- Docker and Docker Compose (for Redis)
-
Clone the repository
git clone https://github.com/yourusername/kf-bank.git
- Start Redis using Docker Compose
docker-compose up -d
This will start Redis on port 6379. You can verify Redis is running with:
docker-compose ps
- Configure database
# Create database
createdb kfbank
- Configure application.yml
cp src/main/resources/application.yml.example src/main/resources/application.yml
- Run the application
mvn spring-boot:run
Once the application is running, you can access the API documentation at:
- Swagger UI: http://localhost:8080/swagger-ui.html
- OpenAPI JSON: http://localhost:8080/v3/api-docs
-
GraphQL API:
http://localhost:8080/graphql
- Supports both GET and POST methods
- Available operations:
# Queries query { hello # Test query that returns a greeting getClientRights(clientId: ID!) { clientId rights } } # Mutations mutation { updateClientRights(clientId: ID!, rights: [String!]!) { clientId rights } invalidateClientRightsCache(clientId: ID!) # Returns Boolean invalidateAllClientRightsCache # Returns Boolean }
-
GraphiQL Interface:
http://localhost:8080/graphiql
- Interactive GraphQL IDE for testing queries
- Available in development mode
-
Swagger UI:
http://localhost:8080/swagger-ui.html
- Interactive API documentation
- Try-out functionality enabled
-
OpenAPI Specification:
http://localhost:8080/api-docs
- Raw OpenAPI/Swagger specification
- Actuator Endpoints:
http://localhost:8080/actuator
/health
- Application health information/info
- Application information/metrics
- Application metrics/prometheus
- Prometheus format metrics
- H2 Console:
http://localhost:8080/h2-console
- Database:
jdbc:h2:mem:testdb
- Username:
sa
- Password:
password
- Database:
Redis is available on:
- Host:
localhost
(in Docker:redis
) - Port:
6379
The following origins are allowed:
http://localhost:8080
http://localhost:3000
Allowed methods:
- For GraphQL: GET, POST, PUT, DELETE, OPTIONS
- For GraphiQL: GET, POST, OPTIONS
Key application properties:
- Server port: 8080
- Spring profiles: Default profile active
- Database: H2 in-memory database
- Cache: Redis
- GraphQL: Enabled with GraphiQL interface
- Health Check:
GET /actuator/health
- Overall application health
- Individual component status
- Custom health indicators
- Application Info:
GET /actuator/info
- Environment information
- Git details
- Java runtime
- OS information
- General Metrics:
GET /actuator/metrics
- List of available metrics
- Specific Metric:
GET /actuator/metrics/{metric.name}
- Detailed metric information
- Method Performance:
GET /actuator/metrics/method.execution.time
GET /actuator/metrics/method.execution.time.histogram
GET /actuator/metrics/method.execution.time.percentiles
- Prometheus Format:
GET /actuator/prometheus
- Metrics in Prometheus format
- HTTP Traces:
GET /actuator/httptrace
- Recent HTTP request-response exchanges
- Request Mappings:
GET /actuator/mappings
- All @RequestMapping paths
- Handler methods information
- Environment:
GET /actuator/env
- Environment properties
- Property sources
- Configuration Properties:
GET /actuator/configprops
- @ConfigurationProperties
- Beans:
GET /actuator/beans
- Spring bean list
- Dependencies
- Auto-configuration:
GET /actuator/conditions
- Auto-configuration report
- Scheduled Tasks:
GET /actuator/scheduledtasks
- Scheduled task details
- Caches Overview:
GET /actuator/caches
- Cache names
- Cache managers
- Specific Cache:
GET /actuator/caches/{cache.name}
- Individual cache details
- Thread Dump:
GET /actuator/threaddump
- JVM thread dump
- Heap Dump:
GET /actuator/heapdump
- JVM heap dump (downloadable)
- Loggers:
GET /actuator/loggers
- Logger configurations
- Specific Logger:
GET /actuator/loggers/{logger.name}
- Individual logger settings
- Runtime log level management
In production environments:
- Restrict access to sensitive endpoints
- Enable authentication
- Consider using a separate management port
- Disable unnecessary endpoints
- Check application health:
curl http://localhost:8080/actuator/health
- View method performance metrics:
curl http://localhost:8080/actuator/metrics/method.execution.time
- Get Prometheus metrics:
curl http://localhost:8080/actuator/prometheus
- Change logger level:
curl -X POST http://localhost:8080/actuator/loggers/org.springframework \
-H "Content-Type: application/json" \
-d '{"configuredLevel": "DEBUG"}'
The application includes comprehensive monitoring using Prometheus and Grafana. Key features include:
-
Custom Business Metrics
- Client operations tracking
- Active clients count
- Operation timing measurements
- Success/failure rates
-
Available Metrics
bank.clients.created
: Counter for client creationsbank.clients.deleted
: Counter for client deletionsbank.clients.active
: Gauge showing current active clientsbank.clients.operation.time
: Timer for operation durations- Tagged by operation type: create_client, update_client, delete_client, etc.
-
JVM Metrics
- Memory usage
- Garbage collection
- Thread states
- CPU usage
-
HTTP Metrics
- Request latencies
- Response codes
- Request counts
- Start the monitoring stack:
docker-compose up -d
-
Access monitoring interfaces:
- Prometheus: http://localhost:9090
- Grafana: http://localhost:3000 (admin/admin)
-
Recommended Grafana Dashboards:
- JVM Micrometer (ID: 4701)
- Spring Boot Statistics (ID: 6756)
- Custom Business Metrics Dashboard (included)
Metrics are collected through several mechanisms:
-
Spring Boot Actuator
- Endpoint:
/actuator/prometheus
- Scrape interval: 5s
- Includes: health, info, metrics, etc.
- Endpoint:
-
Micrometer Integration
- Auto-configuration enabled
- Custom metrics via
MeterRegistry
- Common tags: application name, environment
-
Custom Business Metrics
- Centralized in
ClientMetrics
service - Automatic timing of operations
- Counter-based operation tracking
- Real-time client count monitoring
- Centralized in
Prometheus alerting rules are configured for:
- High error rates
- Slow response times
- Resource constraints
- Business metric thresholds
- ANSI Colors:
- ANSI colors must be explicitly enabled in the Log4j2 configuration.
- Logging Conflicts:
- Logback and the default Spring Boot logger need to be disabled to fully enable Log4j2.
- Spring Boot DevTools:
- DevTools may produce silent warnings or issues, which can generally be ignored.
- Banner and Spring Properties:
- Banner configuration can conflict between Java-based and
.txt
file-based setups. Using.txt
files is preferable for simplicity, as Java-based configuration can hinder the proper loading of Spring properties.
- Banner configuration can conflict between Java-based and
- ANSI color configuration can vary depending on the execution environment and the terminal used.
- It is important to verify that the code correctly uses the Log4j2 logger to generate logs.