Simple command handling library!
This project composes of components for implementing the command handling parts of the CQRS pattern. This library was built with simplicity, modularity and pluggability in mind.
- Send commands to registered command handlers.
- Multiple ways of registering command handlers:
-
Simple registration (no IoC container).
-
IoC container registration
- achieved by creating implementations of CommandHandlerProvider: See sample CommandHandlerProvider implementations
-
Attribute registration (Soon!)
- achieved by marking methods with @CommandHandler annotations.
-
-
XerJ.CommandStack is also available in the Maven Central:
Maven:
<dependency> <groupId>io.github.xerprojects</groupId> <artifactId>xerj.commandstack</artifactId> <version>${xerj.commandstack.version}</version> </dependency>
Gradle:
implementation group: 'io.github.xerprojects', name: 'xerj.commandstack', version: $rootProject.commandStackVersion
Commands are just POJOs or if you are in a later java version, you can use records if you prefer.
// Example POJO command.
public class RegisterProductCommand {
private final int productId;
private final String productName;
public RegisterProductCommand(int productId, String productName) {
this.productId = productId;
this.productName = productName;
}
public int getProductId() {
return productId;
}
public String getProductName() {
return productName;
}
}
// Command handler.
public class RegisterProductCommandHandler implements CommandHandler<RegisterProductCommand> {
private final ProductRepository productRepository;
public RegisterProductCommandHandler(ProductRepository productRepository) {
this.productRepository = productRepository;
}
@Override
public void handle(RegisterProductCommand command) {
validate(command);
productRepository.save(new Product(command.getProductId(), command.getProductName()));
}
}
Before we can dispatch any commands, first we need to register our command handlers. There are several ways to do this:
public static void main(String[] args) {
RegistryCommandHandlerProvider provider = new RegistryCommandHandlerProvider(registry -> {
registry.registerCommandHandler(RegisterProductCommand.class, () ->
new RegisterProductCommandHandler(
new InMemoryProductRepository()
)
);
});
CommandDispatcher dispatcher = new CommandStackDispatcher(provider);
// Dispatch command.
dispatcher.send(new RegisterProductCommand(1, "My Product Name"));
}
-
Spring Context - See Sample Spring Context Command Handler Provider
-
Guice - See Sample Guice Command Handler Provider
-
Dagger - See Sample Dagger Command Handler Provider
Async dispatch is supported by decorating the CommandStackDispatcher
with AsyncCommandDispatcher
:
public static void main(String[] args) {
ExecutorService executor = Executors.newWorkStealingPool();
CommandHandlerProvider commandHandlerProvider = getCommandHandlerProvider();
CommandDispatcher dispatcher = new AsyncCommandDispatcher(
new CommandStackDispatcher(commandHandlerProvider),
executor);
dispatcher.send(new RegisterProductCommand(1, "My Product Name"));
}