3

I own a DDD/CQRS application.

My question concerns the handling of an item creation through POST (Rest).

CQRS (based on CQS principle) promotes that commands should never return a value.
Queries are there for that.

So I wonder how to handle the use case of Item creation.

Here's my current command handler pattern (light for the sample (no interfaces etc.)):

@Service
@Transactional
public CreateItem {

    public void handle(CreateItemCommand command) {
       Customer customer = customerRepository.findById(command.customerId);
       ItemId generatedItemId = itemRepository.nextIdentity();  //generating the GUID 
       customer.createItem(generatedItemId, .....); 
    }

}

By reading this article, an easy method would be to declare an output property in the command, populated at the end of the handle method like this:

        public void handle(CreateItemCommand command) {
           Customer customer = customerRepository.findById(command.customerId);
           ItemId generatedItemId = itemRepository.nextIdentity();  //generating the GUID 
           customer.createItem(generatedItemId, .....);
           command.itemId = generatedItemId;  //populating the output property  
        }

However, I see one drawback with this approach: - A command, in theory, is meant to be immutable.

This itemId would then be sent thanks to the calling controller (webapp) through Location Header with the status 201 or 202 (depending if I expect async or not).

An other solution would be to let the controller initialize the GUID by accessing the repository itself, thus letting the command immutable:

//in my controller: 
ItemId generatedItemId = itemRepository.nextIdentity();  //controller generating the GUID 
createItem.handle(command);
// setting here the location header (201-202) containing the URL to the newly created item with the using the previous itemId.

Drawback: Controller (adapter layer) accessing directly the repository ..., that is too low-level IMO.

My extreme client being a Javascript application, I might have another solution to let the Javascript itself generate a GUID, and feed CreateItemCommand with it before sending the whole command to server.

Advantage: No more issues about potential violation of CQ(R)S guidelines.
Drawback: Should check the validity of the passed id at server side. Although there would have an index unique on this preventing an unexpected insertion in database.

What is the best (or just a good) strategy to handle this?

Steven
  • 166,672
  • 24
  • 332
  • 435
Mik378
  • 21,881
  • 15
  • 82
  • 180

1 Answers1

2

I am the developer of a CRM application based on the CQRS pattern. I tend to see commands as immutable. The team decided early on, that all IDs are generated on the client to have immutable commands. This is perfectly ok, as we are using UUIDs. So we are quite confident, that the IDs are valid and there are no ID collisions. We went well with that approach up to this point - I can definitely recommend this. In that scenario the client just knows the IDs.

Sometimes it happens though - especially in manual testing - that a create command is dispatched twice with the same ID. In that case the addition of events in the event store fails (we use event sourcing) with a duplicate key exception. The exception is passed to the controller. In fact we do return results from command executions with a call back, even though it's just "everything ok" most of the time - so no exception thrown. Also command validation is done this way. We do this using a command bus concept.

I would recommend taking a look at the Axon framework. We use it, it provides the common building blocks, and it just works. Maybe you can get some inspirations from that!

spa
  • 5,059
  • 1
  • 35
  • 59
  • Thanks a lot for this answer :) So if I well figure it out, my extreme client (Javascript application in my case), ("extreme" since controller (adapter layer) at server side being itself an intermediate client of my domain app) should create the GUID to be passed (http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript). Do you confirm? – Mik378 Jun 26 '14 at 16:16