Hello everybody,
PS: Sorry about my english.
Im developing my first Axon application and I have two questions about design.
Lets suppose I have a domain model like this:
class ServiceType(val id: ServiceTypeId, val name String) - simple POJO
After publishing my ServiceTypeCreatedEvent views models will persist that event: 1) postgres, 2) Elasticsearch
- Talking about a POST API for that domain, most REST apps will call a @Service that will persist with a @Repository and return that @Entity in JSON Representation with the new ID generated by JPA sequence. Since everything is synchronous it works. I understand that CQRS/Axon its not synchronous. After publishing the event, I should forget about it, right? But I need to return at least the ID so my client can use a GET API later to retrieve that record.
So, to address that problem I decide to return at least one ID created on the Command and passed to the event:
public ServiceTypeId() {
this.id = IdentifierFactory.getInstance().generateIdentifier();
}
Does this seem appropriate in this scenario?
- look this:
@Aggregate
public class ServiceType {
@AggregateIdentifier
private ServiceTypeId id;
private String name;
@CommandHandler
public ServiceType(CreateServiceTypeCommand cmd) {
// business validation here or not?
apply(ServiceTypeCreatedEvent.of(cmd.getId(), cmd.getName()));
}
@EventSourcingHandler
private void on(ServiceTypeCreatedEvent event) {
this.id = event.getId();
this.name = event.getName();
}
}
I watched some videos that I should âvalidateâ my command before use the method apply. Those videos just validate if the attributes are null or something like that. But lets suppose I have a business rule that does not allow duplicated names.
Should I do this type of validation here on the @Aggregate before applying the event? for that, my @Aggregate will have to know the ServiceTypeJPARepository. Im not sure if Im breaking some cqrs/axon design here.
If I do that, I know I will not be storing a event that will be for sure rejected by all my Listeners. That looks good to me because when I replay the events I dont have a âinvalidâ event to process. Still looks weird to me have a specific view model implementation (in this case jpa/postgres) here in this aggregate. I guess I could call a regular @Service but itâs still the same, right?
so store/apply this âwrongâ event and keep my @Aggregate clean letting the Listeners deal with this validation or put that business validation on the Listeners side?