A Spring Boot starter for Domain-Driven Design (DDD) with CQRS, event-driven architecture, and enterprise best practices. This library helps you quickly build high-cohesion, easily extensible microservice systems.
- Layered DDD model: Clear separation of base, CQRS, and domain layers.
- CQRS support: Command/Query bus and handler interfaces for decoupled business logic.
- Domain events: Abstractions for domain events and aggregate roots, supporting event-driven design.
- Unified exception handling: Standard error codes and exception system.
- Parameter validation: Utilities for request and parameter checking.
- Configurable thread pool: For async CQRS operations, with support for custom configuration.
- Spring Boot auto-configuration: Beans and aspects are auto-registered, supporting override and extension.
- No business dependencies: Ready to use out of the box.
- Java 8 or higher
- Spring Boot 2.3.12.RELEASE or higher (Recommended: 2.7.18)
- Maven 3.6+ or Gradle 6+
<dependency>
<groupId>com.hibuka.soda</groupId>
<artifactId>soda-core</artifactId>
<version>2.0.0</version>
</dependency>implementation 'com.hibuka.soda:soda-core:2.0.0'src/main/java/com/hibuka/soda/ddd
├── component/ # Core beans, auto-configuration, CQRS facade, buses, aspects
├── model/
│ ├── base/ # Base capabilities: error, io, constants, validation
│ ├── cqrs/ # CQRS abstractions: Command, Query, handlers, buses
│ └── domain/ # Domain core: events, aggregate roots
├── utils/ # Utility classes (e.g., Snowflake ID generator)
Add the dependency to your pom.xml as shown in the Installation section above.
In your application.yaml:
soda:
ddd:
cqrs:
async:
core-pool-size: 8
max-pool-size: 16
queue-capacity: 100
thread-name-prefix: "cqrs-async-"If not configured, the starter will use default parameters.
@Autowired
private BusFacade busFacade;
// Synchronous command
busFacade.sendCommand(command);
// Asynchronous command
busFacade.sendAsyncCommand(command);
// Query
busFacade.sendQuery(query);public class CreateUserCommand extends BaseCommand {
private String username;
private String email;
// getters and setters
}
@Component
public class CreateUserCommandHandler implements CommandHandler<CreateUserCommand> {
@Override
public void handle(CreateUserCommand command) {
// Your business logic here
System.out.println("Creating user: " + command.getUsername());
}
}public class GetUserQuery extends BaseQuery<User> {
private String username;
// getters and setters
}
@Component
public class GetUserQueryHandler implements QueryHandler<GetUserQuery, User> {
@Override
public User handle(GetUserQuery query) {
// Your query logic here
return new User(query.getUsername());
}
}| Property | Default | Description |
|---|---|---|
soda.ddd.cqrs.async.core-pool-size |
8 | Core thread pool size |
soda.ddd.cqrs.async.max-pool-size |
16 | Maximum thread pool size |
soda.ddd.cqrs.async.queue-capacity |
100 | Queue capacity |
soda.ddd.cqrs.async.thread-name-prefix |
"cqrs-async-" | Thread name prefix |
| Property | Default | Description |
|---|---|---|
soda.event.serialization.circular-reference-handler |
IGNORE |
Circular reference handling strategy: IGNORE (ignore circular references), ERROR (throw error), RETAIN (retain circular references) |
soda.event.serialization.fail-on-self-references |
false |
Whether to fail on self references during serialization |
- Thread pool parameters: Override via
soda.ddd.cqrs.async.*configuration. - Custom thread pool: Define your own
@Bean("cqrsAsyncExecutor")to override the default. - Custom BusFacade: Define your own
@Beanto override the starter's BusFacade. - Command/Query/Event Handlers: Implement the corresponding interfaces; they will be auto-registered.
public class UserCreatedEvent extends AbstractDomainEvent {
private String username;
public UserCreatedEvent(String username) {
this.username = username;
}
// getters
}
@Component
public class UserCreatedEventHandler implements EventHandler<UserCreatedEvent> {
@Override
public void handle(UserCreatedEvent event) {
// Handle user created event
System.out.println("User created: " + event.getUsername());
}
}public class UserNotFoundException extends BaseException {
public UserNotFoundException(String username) {
super(BaseErrorCode.USER_NOT_FOUND, "User not found: " + username);
}
}BusFacade: Main facade for CQRS operationsBaseCommand: Base class for commandsBaseQuery: Base class for queriesBaseException: Base exception classAbstractAggregateRoot: Base class for aggregate rootsAbstractDomainEvent: Base class for domain events
CommandHandler<T>: Interface for command handlersQueryHandler<T, R>: Interface for query handlersEventHandler<T>: Interface for event handlers
If you're upgrading from scoda-ddd-starter:
- Update your dependency artifactId to
soda-core - Update your dependency version to
2.0.0 - No breaking changes are expected
- Review the changelog for any new features
This project uses Maven for building and supports multiple Spring Boot versions through different POM configurations.
The project provides separate POM files for different Spring Boot versions. To build for a specific version, copy the corresponding POM file to pom.xml:
# Spring Boot 2.3.12.RELEASE (Java 8)
cp pom-2.3.xml pom.xml
mvn clean package source:jar javadoc:jar
# Spring Boot 2.7.18 (Java 8)
cp pom-2.7.xml pom.xml
mvn clean package source:jar javadoc:jar
# Spring Boot 3.2.12 (Java 17) - Default
mvn clean package source:jar javadoc:jar# Skip tests during compilation and packaging
mvn clean package source:jar javadoc:jar -DskipTests
# Skip tests during installation
mvn clean install -DskipTests# Generate Javadoc documentation
mvn javadoc:javadoc
# Generate source and documentation JARs
mvn clean package source:jar javadoc:jarThe project includes the following POM files for different Spring Boot versions:
pom.xml- Default configuration for Spring Boot 3.2.12 (Java 17)pom-2.3.xml- Configuration for Spring Boot 2.3.12.RELEASE (Java 8)pom-2.7.xml- Configuration for Spring Boot 2.7.18 (Java 8)
# Deploy snapshot version to OSS Sonatype
mvn clean deploy
# Deploy release version (requires GPG signing)
mvn clean deploy -PreleaseWe welcome contributions! Please see our Contributing Guide for details.
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality
- Submit a pull request
- Spring Boot 3.2.12 support (Java 17)
- CQRS support with command/query buses
- Domain event abstractions
- Spring Boot auto-configuration
- Thread pool configuration support
- Multi-version POM configuration support
This project is licensed under the MIT License - see the LICENSE file for details.
- Documentation: GitHub Wiki
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Spring Boot team for the excellent framework
- Domain-Driven Design community for the architectural patterns
| soda-core Version | Supported Spring Boot Version | Java Version |
|---|---|---|
| 1.0.0 | 2.3.12.RELEASE | Java 8 |
| 1.1.0 | 2.7.18 | Java 8 |
| 2.0.0 | 3.2.12 | Java 17 |