Reputation: 47
I'm just wondering why Axon implicitly instantiate another aggregate. This behavior causes multiple event handling and I don't think this overhead is expected. Having this endpoint:
@PostMapping("ship")
public void shipOrder(@RequestBody Product product) {
String orderId = UUID.randomUUID().toString();
commandGateway.sendAndWait(new PlaceOrderCommand(orderId, product.getName()));
commandGateway.sendAndWait(new ConfirmOrderCommand(orderId));
}
and following aggregate:
@Aggregate
public class Order {
@AggregateIdentifier
private String orderId;
private boolean orderConfirmed;
@CommandHandler
public Order(PlaceOrderCommand command) {
System.out.println("Calling COMMAND constructor");
apply(new OrderPlacedEvent(command.getOrderId(), command.getProduct()));
}
protected Order() {
System.out.println("Calling PARAMLESS constructor");
}
@CommandHandler
public void handle(ConfirmOrderCommand command) {
apply(new OrderConfirmedEvent(command.getOrderId()));
}
@EventSourcingHandler
public void on(OrderPlacedEvent event) {
System.out.println(">>>>>> Handling OrderPlacedEvent: " + this);
this.orderId = event.getOrderId();
orderConfirmed = false;
}
@EventSourcingHandler
public void on(OrderConfirmedEvent event) {
System.out.println(">>>>>> Handling OrderConfirmedEvent: " + this);
orderConfirmed = true;
}
}
After calling endpoint once I'm getting this log:
Calling COMMAND constructor
>>>>>> Handling OrderPlacedEvent: Order@3eecb9e2
Calling PARAMLESS constructor
>>>>>> Handling OrderPlacedEvent: Order@cd10277
>>>>>> Handling OrderConfirmedEvent: Order@cd10277
As you can see OrderPlacedEvent is called twice, along with constructor without parameters. Anyone know why I'm experiencing following behavior?
Upvotes: 0
Views: 331
Reputation: 141
That behaviour is correct and expected when you use Event Sourcing. In Event Sourcing, whenever you send a command to an aggregate, it will first load all previous events to hydrate the aggregate and determine it's current state. These event are your source of thruth. The current state of the aggregate is, aside from some exceptions, not stored.
As such, in general you should make sure you only use your EventSourcingHandler
in your aggregate to populate its state.
Note that once a system grows a lot, an aggregate could potentially have a large number of events that will need to be read. Should this occurs, there is some optimization you can do, by storing a snapshot of your aggregate (it's current state) after every n
events. This way you won't have to load more than n
events.
Upvotes: 1