Axon framework support for synchronous callback

I’m bit new to CQRS pattern and fed up with traditional CRUD approach. Need to know if whatever I’m trying fits into CQRS pattern and secondly, the implementation of the same using Axon framework.

Below is the scenario,
I’m trying to implement shopping cart model where multiple users can in parallel query their items present in cart and checkout whereas the update/add would be less accounted. Need to know if this component would really fit into CQRS terminology.

As per the docs for getting started, This was the flow that I came up with,

Client --> initiate AddItemtoCart command --> command bus --> command handler (Validate structure/business) --> Event trigger --> Event bus --> Event handler --> Write database

It did work well with standalone but mixing the same with REST API led me to confused state.
Client POST request --> API --> Initate command --> Command bus --> command handler --> Event trigger --> Event bus --> Event handler

By this way, the command handler can respond in ‘fire and forget style’ but I require the added item as response to the client with synchronous event handling to ensure consistency.(Since CRUD works so with REST). I need to know how to do this either synchronous/asynchronous using Axon ?

Exploring on forums, got some working mechanisms. Command handler can respond back with exception/response using callbacks and even Spring async context within command handler scope. But what I’m looking is the response back to client after event being handled. Correct me if am wrong in expecting this with CQRS approach.

Whatever i understood till now is that, I need to have separate Commands and query handling mechanism. Below are approaches that i found while exploring in terms of REST response,

approach#1: If the command does the event sourcing asynchronously, respond back to the client with HTTP 202 Accepted response including url to check the status of asynchronous handled event.
Poll the URL to know if the status has updated and once it is green, query the items in the cart and show it in UI. (multiple http calls as a whole, traditionally one would suffice)

approach#2: Use websocket or such to push the response from the server to client async but need to know how to the implement it with axon framework ?
approach#3: After the event has been handled, publish the message to MQ and client should pick that. Got it logically but need to know if it will create a listener inside the command handler side and wait for event response MQ ?

May be u guys can help me out in understanding Axon better.

Thanks,
Sivarajan R P

Hi,

in CQRS, you never want to wait for an event being handled when sending a command. Why would you? The responsibility of the command should stop at publishing the results of that command (i.e. events). You never know howmany handlers are listening to that event, and how long they take to process it.
Instead, use the callback to report results of command processing.

I don’t like the approach#1 you mention. I have heard of it being used, but in my opinion, the overhead is unnecessary. Usually, the overhead in open connections is not in the connections themselves, but in the fact that there is a thread for each one of them. Using callbacks and asynchronous processing resolves that issue.

Approach#2 is more complex, but works magnificently. In one of my own projects, we “subscribe” to queries. When a component subscribes, it is first given the “current state” of the query, after which deltas are pushed automatically. We’re using a combination of WebSockets and Stomp for transport and JSON and JsonPatch to send the initial state and deltas. Spring Websockets can help you here as well.

Approach#3 is possible, but ties your UI with the Events you generate. Not bad per-se, but have you a risk of duplicating logic.

Cheers,

Allard

Hi Allard,

Thanks for your time. As you have mentioned, I just need to acknowledge the client that the command has been processed (say,event triggered).
If that is the case and event results in exception, then Callbacks should be used in command handler (synchronous, if am right) to respond back to client.

As per approach#2, would the command part be responsible for responding back the deltas to the client and result in mixing of command+query concerns ?

Just want to know, what will be the correct way of handling this flow in axon/CQRS in async way,
Say, If i post REST request for addItemCommand, then the result should be “item has been added” and UI should add it to cart (Though event handled asynchronously)
If something goes wrong and say, event fails. Then. how should this be updated to UI ? (Should there be another endpoint to say the event failed or anything else)

Pls help me in understanding this better.

Hi,

once an event is published, you should forget about it. Event Handler cannot respond to an event with an Exception, so errors in this case are always bugs or infrasrtucture issues. You shouldn’t report those to the end-user, but to support personnel. In some cases, we do send a message to clients that an error has occurred. We assign an id to each client, and that ID is passed along with every command and attached to each event generated by that command. When an error occurs, we can asynchronously send a “sorry” message to that specific client.

What I meant for approach #2 was that the Event Handler build up a model on the server side, and push changes to this model to all clients subscribed to the query that responds with that model. The essence of CQRS is that commands and queries are separated. Therefore, Command will only reply with “OK” or perhaps a little information about the result of the command.

Hope this helps.
Cheers,

Allard

Thanks a lot and now I understand better :slight_smile:

Hi Allard,

I am still curious what’s the best way of handling this with a query model that takes multiple events from multiple aggregates.
I have an example - we have Order, Checkout and Bill aggregates. Checkout is created from the Order and can reference 1 to N bills (for example when splitting an order).
Bill is designed as a separate aggregate for various reasons (must be referenced somewhere else etc etc) and the checkout object references the bill identifiers.

When a checkout is created a CheckoutManagementSaga does the following

  1. associates the order with the checkout
  2. dispatches commands to create the needed bills.

So the query model is in a logically “consistent” state after applying multiple events and the client should be able to process the resource only afterwards.
Still trying to figure out what route to take with this …

What comes to my mind is some sort of the event aggregator pattern that would fire a notification event after it has aggregated all the required events.

Dňa streda, 27. mája 2015 14:07:41 UTC+2 Allard Buijze napísal(-a):

Hi David,

how long do you expect the query model to be in an inconsistent state? And if it “inconsistent”, is that really a bad thing? After all, it does represent the actual state of things.

Example, if I transfer money from account A to account B, I will see the amount deducted from account A, but not added to account B for a while. You might argue that this is inconsistent, but it’s just the state of things as they are. When the money arrives at account B, the transfer is completed and all is “consistent”.

So before solving all kinds of things by adding complexity, evaluate the approach where you “embrace” eventual consistency…

Cheers,

Allard

In this special case I would consider it as a bad thing :frowning:

Dňa pondelok, 15. februára 2016 9:27:49 UTC+1 Allard Buijze napísal(-a):

Then you’ll have to aggregate a few events until the information you have gathered is “consistent” enough to be published as a query result. This could be something you need to design into your view model. An external component gathering these events and publishing another aggregation event is also a possibility. The latter, depending on your usecase, may however introduce unwanted complexity. Only do this if such an event logically occurs within the domain (i.e. if you have to come up with a name for it, it probably doesn’t exist in the domain).

Cheers,

Allard

Thanks Allard,

just one last question - my idea was to implement the aggregation using the message aggregator in spring integration.
The idea would be to set up an EventListeningMessageChannelAdapter that would forward the filtered messages to a spring integration channel.
Here I would utilize the aggregator to aggregate the messages and once released they would be applied to the query model at once and a STOMP message would be released to the client.
My only concern is event replay - is it possible to set up the replaying cluster so it would still utilize the channel adapter and forward the events into the aggregator during replay ?

david

Dňa utorok, 16. februára 2016 9:42:26 UTC+1 Allard Buijze napísal(-a):

Yes, you can replay to your message aggregator. The EventListeningMessageChannelAdapter is an Event Listener. The Cluster is a “wrapper” of event listeners, which may (or may not) support replays. So when you replay all events, these are then sent to all of the listeners registered in that cluster.

Cheers,

Allard