Sample event sourced application
In my last post I wrote about domain events publishing. Events were published at the end of aggregate public methods as a natural consequence of internal state modification. Let's look again at this code sample:
class User {
//...
@Transactional
public void register(LocalDateTime at, RegisteredBy by) {
markRegistered();
markSuspiciousIfAtNight(at);
DomainEventsPublisher.publish(new UserRegistered(this.id(), at));
}
}
The problem that we might face is different source of truth between created UserRegistered and internal changes done by markRegistered and markSuspiciousIfAtNight(at) method invocations. The path to mistake is fairly simple, we could throw this domain event with Instant.now() instead of at parameter. Thus, misleading listeners of domain events, because internal state was modified differently.
If we were storing our aggregate state with the help of event sourcing, so by serializing domain events, this mistake cannot be done. I've created a sample application that might show how to deal with such an approach. Those serialized events can be published to external listeners. The same events from which we rebuild our domain object</a>
Take a look how ease it is to test such an aggregate. By invocking public method, we expect that proper domain events were raised. Simple as that. It is also tested in integration test, together with storage. Please note, that with this approach it is simple to create Shop Item as truly immutable aggregate and favour functional programming.
***Event Store***Event store was implemented very simply - as database table EventStream that represents all events comming from one aggregate instance, which holds collection of all events (EventDescriptors).
***CQRS***Read model in CQRS applcations is build when changes to write model are performed. That is why event sourcing can naturally lead to CQRS usage - is there any better way for listening for write model changes than subscribing to events raised from write model? The same events, from which write model is built? Take a look how simply it is to update read model in event sourced application. Read model there is implemented by directly using JDBC queries with denormalized table, beacuse why not? </p>