In order to implement conflict resolution in our project i have done the following
added @TargetAggregateVersion to all the commands
modified all the @CommandHandler methods to return getVersion() , i am still using 2.4
invoke the command gateway using sendAndWait and send the return value back to the client
This seems to work and is fairly intuitive. I am wondering though if returning the AR version is really a concern of the commandhandler. While changing all the command handler methods i felt like i was adding “infrastructure” code to my AR, nothing related to the business invariants it is supposed to enforce. Just a thought …
depending on what you’re trying to achieve, but returning the version of the aggregate may not be necessary for conflict resolution. It should be enough to return this version from the query along with the query results. When a command is sent based on the information shown in this query, the version can be sent along with it.
It may feel a bit infrastructurish, but see it as a token that you get as a result and need to send with future requests, until you get a new ‘token’. You clients shouldn’t care about the actual contents of the token.
Also, i found that having to use @TargetAggregateVersion on the command handler side and @SequenceNumber on the event handler side was a bit confusing. IIUC the latter could also be called @AggregateVersion no ?
In our case the client side model is not refreshed after each command sent(we might need to revise this). So for each command sent we should return the AR version in response, so that when the next command is sent we can pass it along again.
However, my previous observation about getVersion() is incorrect. It does not return the latest sequence number, presumably because the UOW was not committed yet. Is there another way, can i assume getLastCommittedEventSequenceNumber() + getUncommittedEventCount() ?
sorry for the late reply. Yes, you can use getLastCommitted…() + getUncommittedEventCount().
Alternatively, you can grab the sequence number from each event by adding a long parameter abd annotating it with @SequenceNumber. You can then make the seq# part of the aggregate state. Whichever tou prefer.
In the end i went with a solution where the rest service dispatching the commands and the eventhandler on the read side share a request scoped bean. From the eventhandler i then set the value of @SequenceNumber in this bean. This does assume sendAndWait() type dispatching though, but that’s something we can live with.