Hi,
I am relatively new to Axon so please forgive any basic errors!
When trying to construct a complex aggregate, I am first creating the aggregate root which extends AbstractAnnotatedAggregateRoot like so:
MyComplexAggregateRoot(AggregateIdentifier identifier) {
super(identifier);
}
public MyComplexAggregateRoot(AggregateRootDto aggregateRootDto) {
super(new UUIDAggregateIdentifier());
apply(new MyComplexAggregateRootCreatedEvent(aggregateRootDto));
}
@EventHandler
private void onCreate(MyComplexAggregateRootCreatedEvent event) {
// business logic to create aggregate structure (uses builder pattern)
}
I am also catching the ‘MyComplexAggregateRootCreatedEvent’ event in an event handler in the query side so that I can persist a representation of the ‘MyComplexAggregateRoot’ object in the query database.
This is all ok and working as expected.
The aggregate itself contains many objects that are constructed in the ‘onCreate’ event handler, I also need information from these objects in my query database and this information is not available when the MyComplexAggregateRootCreatedEvent event is constructed. I am therefore registering/applying further events when these objects are created. This works as expected and the object structure and query database representation are generated as expected. However, when the aggregate root is loaded from the repository (i.e. reconstructed from the events in the repository), this causes and IllegalStateException:
14:14:51.108 [main] WARN o.a.repository.LockingRepository - Exception occurred while trying to load an aggregate. Releasing lock.
java.lang.IllegalStateException: Cannot set first sequence number if events have already been added
at org.axonframework.util.Assert.state(Assert.java:40) ~[axon-core-1.0.jar:na]
at org.axonframework.domain.EventContainer.initializeSequenceNumber(EventContainer.java:109) ~[axon-core-1.0.jar:na]
at org.axonframework.domain.AbstractAggregateRoot.initializeEventStream(AbstractAggregateRoot.java:128) ~[axon-core-1.0.jar:na]
at org.axonframework.eventsourcing.AbstractEventSourcedAggregateRoot.initializeState(AbstractEventSourcedAggregateRoot.java:94) ~[axon-core-1.0.jar:na]
at org.axonframework.eventsourcing.EventSourcingRepository.doLoad(EventSourcingRepository.java:118) ~[axon-core-1.0.jar:na]
at org.axonframework.eventsourcing.EventSourcingRepository.doLoad(EventSourcingRepository.java:54) ~[axon-core-1.0.jar:na]
at org.axonframework.repository.AbstractRepository.load(AbstractRepository.java:70) [axon-core-1.0.jar:na]
at org.axonframework.repository.LockingRepository.load(LockingRepository.java:119) ~[axon-core-1.0.jar:na]
at org.axonframework.repository.AbstractRepository.load(AbstractRepository.java:80) [axon-core-1.0.jar:na]
This seems to be because of the events generated in the onCreate() handler.
I have also tried adding a separate command and corresponding event to build the ‘MyComplexAggregateRoot’ object after it has been created but this suffers from exactly the same problem. So it seems that you cannot register/apply new DomainEvents in the call hierarchy when handling an event - is this the case?
Is it possible to mark such events so that they are ignored when the object is reconstructed from the event repository?
I think I am probably using events incorrectly here. I guess the event is not really a ‘DomainEvent’ as such as it is used to indicate to the query repository (or whoever is listening) that an object has been created (so that any info needed by the query layer can be created). However, it is not really an Application or System event either (as far as I can tell!).
Is there a standard way to generate complex aggregates and have information about these aggregates persisted for use by the query layer?
Thanks in advance for any help/hints provided.
Regards,
John