DDD/CQRS : where to persist - domain-driven-design

We recently started developing apps using concepts from both DDD and CQRS (no Event Sourcing). I am still somewhat confused as where exactly to call the repository to persist my Aggregate Roots.
Do I do it inside Command Handlers or do I do it in the Event Handlers?

You do this inside your command handler. You save your domain objects as normal. Even if you are not using event sourcing as a means of persisting your domain entities, you will still need to fire events that your query service will subscribe to. The event handlers on the read side will then update de-normalised tables tailor made for the UI screens. So basically you have two sets of data access code: one for the domain, one for the query service (read side). Its less work if you make use of event sourcing to persist your domain entities...

Related

Why do we need command model in CQRS

So I was watching this video Event Sourcing You are doing it wrong by David Schmitz at the 15:17 he was talking about eventual consistency in event-sourcing. At first, I was like oh I got it so this is why CQRS is helpful with Event-sourcing because we can validate this things through command model before publishing an event right? but after I did a few research I was wrong. So I wonder why command model even exists since we can just retrieve the request body (suppose it's http request) put some business logic and then publish event.
With Event Sourcing we store events. A model exists in your application to support applying your business logic before deciding to save new event(s). To be able to make that decision, it must be possible to consistently read/write events to materialize your model before applying your business logic on it when a command is processed.
You need to store the events consistently to be able to make decisions further on. If you only publish your events to other parts of the system your model cannot use them in a consistent way.
The publishing of events to other systems is something that potentially can happen as a side-effect to use these events to also create read-models/projections or to react to them in other ways.
It does not have to be a push/publish though. It is perfectly valid to have a pull-based solution where downstream systems poll for events.
For example, in Serialized we store events in Aggregates. Feeds are used to provide a poll-based (eventually-consistent) downstream view of these events, but there is no publishing at all.

Considering Axon in greenfield project

I'll be starting on a greenfield project in a few months.
The project will contain lot's of business logic, spread over several subdomains. Yes, we'll be using principles of Domain Driven Design.
Tech will consist of Spring, Spring Boot & Hibernate stack.
I was looking after some Java libs to cover infrastructural things like:
domain event publication
event store
event deduplication
resequencers on consumer side
projections
reliable publishing
reliable delivery & redelivery
...
I came across the Axon Framework. I already heard about it, didn't know it in details. So I read some blogposts, little bit of documentation and watched some broadcasts on Youtube.
It seems very promising, I'm considering to use it because I don't want to reinvent to wheel over and over again on the infrastructural side.
So I'm looking for someone to answer and clarify my questions:
Command handling
Axon use CommandHandlers with void methods. Is it possible to make them return a value (for instance a generated business id) or objects for notification purposes concerning the business operation? It's not a issue to me that the method will be I/O blocking by this.
Local vs remote domain events publication
I want to have a clear separation of local vs remote domain events.
Local domain events should only be visible and consumed to the local subdomain. Is it possible to configure event consumption sync and/or async?
My Local domain events can be 'fat'. They are allowed to carry more data because it won't cross the domain boundaries.
Remote domain events will be 'thin', so only the minimum data necessary for remote domains. This type op events need always to be handles async.
Is it possible to convert a local (fat) domain event to a remote (thin) domain event at the edge of a domain? By 'edge', I mean the infrastructural side.
By this, the domain model doesn't need to know distinction between local & remote domain events.
CQRS synchronously
My application will consist of 1 (maybe 2) core domains and several subdomains. Some domains contain lot's of business logic and will require CQRS.
Other domain will be more 'crudy' style.
Is it possible to do CQRS synchronously? I want to start this way before adding technical complexities like async handling. It this plossible with Axon?
This also means that domain events will be stored in a events store without using event sourcing. Can Axon's event store be used without event sourcing?
Same for projection stuff, I just want to projection domain events to build my read model.
Modular monolith
We'll use a modular monolith.
Not very trendy these days with all the microservices stuff. Although, I'm convinced of having a monolith where each domain is completely separated (application code & DB-schema), where operations will be handled with eventual consistency and domain events contain the necessary data.
Later on, and if necessary, it will be easier to migrate to a microservices architecture.
Is Axon a framework that fits in a modular monolith kind of architecture? Is there anything to take into account?
Fully separated domain model (persistence agnostic)
The domain model will be completely separated from the data model.
We need to have a repository that reads a data model (using Hibernate) and uses a data mapper to create an aggregate when it needs to be loaded.
The other way is also needed, an aggregate needs to be converted and saved into the data model (using data mapper).
Additionally, the aggregates's domain events need to be stored into an event store and published to local or remote event handlers.
This has some consequences:
we need to have full control of repository implementation that communicates with one or more DAO's (Spring data repositories) to take the necessary data out of Hibernate entities and construct an aggregate with it. An aggregate might be modeled in 2 or even 3 relational tables after all.
we don't need any Hibernate annotation in the domain model
Is this approach possible with Axon? I only see examples using direct JPA (domain model maps 1 to 1 to entities) or event sourcing.
This approach is really a deal breaker for us, a separated domain model gives so much more possibilities than mapping it directly to data entities.
Below an example of what I want to achieve:
Aggregate (without JPA) in some domain model package:
public class ScoringResultAggregate {
// members, constructor, operation omitted for brevity
}
Hibernate Entity in some infrastructure package:
#Entity
#Table(name ="SOME_TABLE_NAME)
public class ScoringResultEntity {
// member and getters & setters; no domain logic
}
Repository interface that belongs to the domain model:
public interface ScoringResultRepository {
void save(ScoringResultAggregate scoringResultAggregate);
ScoringResultAggregate findByApplicationNumber(ApplicationNumber applicationNumber);
}
Adapter that implements repository interface; responsible for mapping aggregate from/to data (JPA) model:
class ScoringResultAdapterRepository implements ScoringResultRepository {
private ScoringResultJpaRepository scoringResultJpaRepository;
ScoringResultJPARepository(ScoringResultJpaRepository scoringResultJpaRepository) {
this.scoringResultJpaRepository= scoringResultJpaRepository;
public void save(ScoringResultAggregate scoringResultAggregate) {
// converts aggregate to ScoringResultEntity and saves the state into DB
}
public ScoringResultAggregate findByApplicationNumber(ApplicationNumber applicationNumber) {
// loads an ScoringResultEntity from DB and converts it into an aggregate
}
}
Axon Server
Axon server looks very promising. Although, is it only useful for event sourcing?
Can it be used together with a Sql DB where aggregates are stored (state persistence) and domain events get persisted in Axon Server?
Lot of questions. Hopefully, someone with Axon experience can help me out :-)
I feel Jasper is saying the right things, but I also think I can emphasize them a little more:
Command handling - Yes you can have return values on command handlers. Just be mindful that you do no abuse this to return state of the to the user, as that would be mixing the Command Model (your Aggregate handling the command) with your Query Model.
Local vs remote domain events publication - Jasper states this clearly and he's right. Your hitting the desire to form bounded context's, for which Axon Server (Enterprise) has support. If you'd not use Axon, you'll have to build this infrastructure yourself.
CQRS synchronously - Axon provides handles for asynchronous and synchronous messaging just fine. The main difference is that you'll block on the result of sending your messages. The CommandGateway for example has a send and sendAndWait method, thus providing you with sync and async command dispatching. Lastly, it's perfectly fine to use Axon Server as the event store without doing Event Sourcing. Event Sourcing is an choice when using Axon, not a requirement.
Modular monolith - AxonIQ as a company actively encourages this approach to building software. So yes, you can do this, and no, I cannot think of anything you should think of prior to doing this.
Fully separated domain model (persistence agnostic) - From your Query Model you have full control over how you'd want to map your data model to and from the actual model you'd use. The Aggregate in Axon terms should be regarded as your Command Model, for which you can choose the Event Sourced storage approach or the State Stored storage approach. The state-stored implementation given by Axon Framework works based on JPA, which would thus require you to set some annotations along side the axon annotations in your Command Model. If you need to segregate this, I could imagine you'd create your own variant of the Repository and AggregateFactory. Then again, the Event Sourcing approach would make your domain model clear of persistence annotations altogether, so I'd go for that route to be honest.
Axon Server - Yes you can use Axon Server even if you go the state-stored approach for Aggregates. Know that Axon Server next to being an event store is a unified routing solution for commands, events and queries. If you would move from a modular monolith to a (micro) services set up, having Axon Server in place to perform all the message routing will make your life very, very easy.
I hope I can answer some of them, but I'm also not really experienced in using Axon:
Return values from command handler - Yes, thats possible. We had an example where we return the generated aggregate id (I'm not 100% sure about this answer)
Local vs remote domain events publication - Yes, Axon Server ENTERPRISE (!) supports multi-context thats build for this purpose. https://axoniq.io/product-overview/axon-server-enterprise
CQRS synchronously - The question is not totally clear but it's not necessary to model your complete system with CQRS. You can use CQRS for some domains and other architecture for subdomains.
Use Saga's for any kind of "transaction" like stuff. Rollbacks should be written by the developer. The system can't do this for you.
Modular monolith - Shouldn't be a technical problem.
Fully separated domain model (persistence agnostic) - The question is not totally clear but store only events in Axon Server. Aggregates are build up by a sequence of aggregates. Don't use any other data for it. The aggregate are used to do the command handling with state checks and apply new events.
I a system gets a command message, Axon Framework will look at the aggregate id and re-creates the aggregate by replay all the existing events for that aggregate. Then the method for #CommandHandler and command message type is called on the aggregate with the state of the system. Don't do this by yourself.
On the other hand. Create own custom projections (view models) by listening to the events (#EventHandler) and store the data in your own format to any kind of data models/repository. You can for example build a REST api on top of this to use the data.
Axon Server - Use it where it's built for. Use it as event store and not for other purposes.
See for more info and why: https://www.youtube.com/watch?v=zUSWsJteRfw

#Service injection into aggregates?

I have an Order aggregate with the following commands:
CreateOrderCommand
PlaceOrderCommand
... (rest redacted as they are not pertinent to the question) ...
The PlaceOrderCommand refers to placing the Order onto an external execution venue. I have captured the behaviour for placing an order onto an external execution venue within a separate (non CQRS) #Service. However, I am struggling (due to lack of experience with Axon) with how best to connect my #Service with the aggregate.
My normal way of thinking would have me:
Inject the #Service into the aggregate's #Autowired constructor.
When the PlaceOrderCommand is issued, use the service to place the order onto the relevant execution venue and once done emit an event (either OrderPlacedSuccessfullyEvent or ErrorInOrderPlacementEvent).
Change the aggregate's state within the relevant #EventSourcingHandler.
My question is:
does my description above of how to handle this particular use case with Axon make sense (in particular injecting a #Service into an aggregate feels a bit off to me)?
Or is there a different best practice of how to model my scenario when using CQRS/event sourcing with Axon?
Axon requires an empty constructor in the aggregate. How does this reconcile with having the #Autowired constructor?
The other thing I was potentially considering was:
having a PlaceOrderInstructionCommand (instead of the simple PlaceOrderCommand) which emits a ReceivedPlaceOrderInstructionEvent that a separate event listener is listening for.
that event listener would have the relevant #Service injected into it and would do the placement of the Order.
then after placing the Order it would send a command (or should it emit an event?) to the aggregate informing it to update its state.
Could you please advise on what is best practice for modelling this scenario?
The PlaceOrderCommand refers to placing the Order onto an external execution venue.
I'm assuming that placing the Order to an external execution venue means interacting with an external system. If yes, then it is should not be part of your domain. In that case, you would need to raise an Integration Event.
As you mentioned, you could raise a Command like ProcessOrder from your Domain. Within that Command, you can update your Domain (eg, set the OrderStatus to Processing) and raise an integration event like OrderArrived which is then handled by a separate process.
From Microsoft Docs:
The purpose of integration events is to propagate committed transactions and updates to additional subsystems, whether they are other microservices, Bounded Contexts or even external applications.
Integration events must be based on asynchronous communication between multiple microservices (other Bounded Contexts) or even external systems/applications.
You would handle that integration event as a separate process (or worker) outside of your Domain. This is where your#Service would be injected. Once, the order is processed successfully you can then broadcast integration event called OrderPlaced.
Now, any subscriber which has anything to do with placing the order would subscribe to the event. In your case, your Domain is interested in updating the state once the order is placed. Hence, you would would Subscribe to OrderPlaced event within your Domain to update the status of the Order.
Hope it helps.

Should I put command bus between controller and domain service?

I am working on a backend and try to implement CQRS patterns.
I'm pretty clear about events, but sometimes struggle with commands.
I've seen that commands are requested by users, or example ChangePasswordCommand. However in implementation level user is just calling an endpoint, handled by some controller.
I can inject an UserService to my controller, which will handle domain logic and this is how basic tutorials do (I use Nest.js). However I feel that maybe this is where I should use command - so should I execute command ChangePasswordCommand in my controller and then domain module will handle it?
Important thing is that I need return value from the command, which is not a problem from implementation perspective, but it doesn't look good in terms of CQRS - I should ADD and GET at the same time.
Or maybe the last option is to execute the command in controller and then emit an event (PasswordChangedEvent) in command handler. Next, wait till event comes back and return the value in controller.
This last option seems quite good to me, but I have problems with clear implementation inside request lifecycle.
I base on
https://docs.nestjs.com/recipes/cqrs
While the answer by #cperson is technically correct, I would like to add a few nuances to it.
First something that may not be clear from the answer description where it advises to "emit an event (PasswordChangedEvent) in command handler". This is what I would prefer as well, but watch out:
The Command is part of the infrastructure layer, and the Event is part of the domain.
So from the command you should trigger code on the AggregateRoot that emits the event.
This can be done with mergeObjectContext or eventBus.publish (see the NestJS docs).
Events can be applied from other domain objects, but the aggregate usually is the emitter (upon commit).
The other point I wanted to address is that an event-sourced architecture is assumed, i.e. applying CQRS/ES. While CQRS is often used in combination with Event Sourcing there is nothing that prescribes doing so. Event Sourcing can give additional advantages, but also comes with significant added complexity. You should carefully weigh the pros and cons of having ES.
In many cases you do not need Event Sourcing. Having just CQRS already gives you a lot of benefits, such as having your domain / bounded contexts well-contained. Separation between reads and writes, single-responsibility commands + queries (more SOLID in general), cleaner architecture, etc. On a higher level it is easier to shift focus from 'how do I implement this (CRUD-wise)?', to 'how do these user requirements fit in the domain model?'.
Without ES you can have a single relational database and e.g. persist using TypeORM. You can persist events, but it is not needed. In many scenario's you can avoid the eventual consistency where clients need to subscribe to events (maybe you just use them to drive saga's and update read-side views/projections).
You can always start with just CQRS and add Event Sourcing later, when the need arises.
As your architecture evolves, you may find that you require a command bus if you are using Processes/Sagas to manage workflows and inter-aggregate communication. If and when that is the case, it will naturally make sense to use that bus for all commands.
The following is the method I would prefer:
execute the command in controller and then emit an event (PasswordChangedEvent) in command handler. Next, wait till event comes back and return the value in controller.
As for implementation details, in .NET, we use a SignalR websockets service that will read the event bus (where all events are published) and will forward events to clients that have subscribed to them.
In this case, the workflow would be:
The user posts to the controller.
The controller appends the command to the command bus.
The controller returns an ID identifying the command.
The client (browser client) subscribes to events relating to this command.
The command is received by the domain service and handled. An event is emitted to the event store.
The event is published to the event bus.
The event listener subscription service receives the event, finds the subscription, and sends the event to the client.
The client receives the event and notifies the user.

How to reliably store event to Azure CosmosDB and dispatch to Event Grid exactly once

I'm experimenting with event sourcing / cqrs pattern using serverless architecture in Azure.
I've chosen Cosmos DB document database for Event Store and Azure Event Grid for dispachting events to denormalizers.
How do I achieve that events are reliably delivered to Event Grid exactly once, when the event is stored in Cosmos DB? I mean, if delivery to Event Grid fails, it shouldn't be stored in the Event Store, should it?
Look into Cosmos Db Change Feed. Built in event raiser/queue for each change in db. You can register one or many listeners/handlers. I.e. Azure functions.
This might be exactly what you are asking for.
Some suggest you can go directly to cosmos db and attach eventgrid at the backside of changefeed.
You cannot but you shouldn't do it anyway. Maybe there are some very complicated methods using distributed transactions but they are not scalable. You cannot atomically store and publish events because you are writing to two different persistences, with different transactional boundaries. You can have a synchronous CQRS monolith, but only if you are using the same technology for the events persistence and readmodels persistence.
In CQRS the application is split in Write/Command and Read/Query sides (this long video may help). You are trying to unify the two parts into a single one, a downgrade if you will. Instead you should treat them separately, with different models (see Domain driven design).
The Write side should not depend on the outcome from the Read side. This means, that after the Event store persist the events, the Write side is done. Also, the Write side should contain all the data it needs to do its job, the emitting of events based on the business rules.
If you have different technologies in the Write and Read part then your Read side should be decoupled from the Write side, that is, it should run in a separate thread/process.
One way to do this is to have a thread/process that listens to appends to the Event store, fetch new events then publish them to the Event Grid. If this process fails or is restarted, it should resume from where it left off. I don't know if CosmosDB supports this but MongoDB (also a document database) has the rslog that you can tail to get the new events, in a few milliseconds.

Resources