Hi again.
Finally it’s official, we do are going to use Axon in our project and my PoC is now being “migrated” to a full production-level service. For that I did some work in:
Serialization:
We have to support Postgres with XML data types. That means serialize Metadata, Events and Sagas to XML (or a string representation of) and store then as XML. For that I had to implement a Axon Serializer, extend GenericEventSqlSchema, PostgresSagaSqlSchema and JdbcSagaRepository. Not a big problem here but the code could be more clean with some small changes in Axon itself, if you want to discuss that I’ll be happy to do it.
Security:
I’m going to implement a CommandDispatchInterceptor for Identity and a CommandHandlerInterceptor for Access Control. For the first I don’t see any problems, however for the second I did got into trouble. The intention here was to access the Aggregate itself from the CommandHandlerInterceptor to check some constraints in the aggregate entity itself. I do have access to the unitOfWork there and I was hoping to access the aggregate from there, but I couldn’t find a way. Did I forgot something?
A few more doubts I’m having. I tend to have a command raising a event only. However in some cases it may make sense to raise more than one event, or raising different events depending on some conditions. Is this OK or is considered a bad practice?
Some times it make sense to me to do the “work” in the commands and pass the results to the event, while other times I tend to do that “work” in the events themselves. But I think this second option can be dangerous because of the replays. Should the “work” always be done in the command handler? A example:
- “work” done on the event
@CommandHandler
public TaskAggregate(CreateTaskCommand command) throws Exception {
apply(new TaskCreatedEvent(command.getId()) );
}
@EventSourcingHandler
public void on(TaskCreatedEvent event) throws Exception {
this.id = event.getId();
Task task = new Task();
task.creationDate = DateTime.now();
task.setState(TaskState.CREATED);
}
- “work” done on the command
@CommandHandler
public TaskAggregate(CreateTaskCommand command) throws Exception {
Task task = new Task();
task.creationDate = DateTime.now();
apply(new TaskCreatedEvent(task) );
}
@EventSourcingHandler
public void on(TaskCreatedEvent event) throws Exception {
this.id = event.getId();
Task task = event.getTask();
task.setState(TaskState.CREATED);
}
3) hybrid "work"
@CommandHandler
public TaskAggregate(CreateTaskCommand command) throws Exception {
apply(new TaskCreatedEvent(command.getId(), DateTime.now());
}
@EventSourcingHandler
public void on(TaskCreatedEvent event) throws Exception {
this.id = event.getId();
Task task = new Task();
task.creationDate = event.getDate()
task.setState(TaskState.CREATED);
}
This is a simple example, but taking into account that for the creation of a entity it will take more than just creating a object (call injected services, access repositories, etc.) what is the “correct” way of do it? Assuming there is such a thing…
Thanks again for your precious support.
Cheers.