Making the command identifier available

Hi,

So I have a ReST api that has a service injected which then submits a command. Currently, I’m using the callback version of sending commands with the ReST api being asynchronous. This works well.

I’m exploring the scenario where the ReST API can be truly fire and forget - so here’s the flow I’m trying to model the flow:

  1. User submits POST to /api/greetings
  2. Controller calls service api which submits a command using the .send(Object) variant
  3. Return the command id to the client with a 202 Accepted status
  4. Once command is processed and events raised, event has the command Id as metadata. Event and metadata are pushed over a websocket channel.

For (4), I have hooked up the CommandHandlerInterceptor to copy over the command identifier to the event metadata.

I’m hitting an issue with 3 - basically getting access to the command id after sending the command. I can solve it with introducing a separate commandId property in my commands and having custom interceptor/provider to copy that custom property into the metadata.
Just that it seems like taking a shotgun to kill an ant :). Secondly, the command id etc are not really properties of the domain - it’s infrastructure - so I’d rather not mess my domain for that.

I’ve looked at commandDispatchInterceptors - which will let me modify the command before it gets sent out (and gets a CommandMessage object) but there doesn’t seem a way out other than introducing a commandId attribute in my command object. This gets me almost what I want but I still need to introduce a base class for commands with a commandId attribute.

Is there a way to do this without introducing the base and an extra property in the commands?

I’ve been staring at it for a few hours and not seeing a solution - and so I’m here :slight_smile:

Thanks for reading.
Raghu

Hi Raghu,

each Message contains an identifier. You could use that identifier in your callback. You can use a CommandHandlerInterceptor to attach the command id as correlationID in the meta data of generated events.

You seem to be looking for “fire and forget”. What’s the goal you’re trying to achieve? What’s wrong with sending a 200OK based on the outcome of command handling?

Cheers,

Allard

Hi Allard,

each Message contains an identifier. You could use that identifier in your callback. You can use a CommandHandlerInterceptor to attach the command id as correlationID in the meta data of generated events.

I have this working without issue. I’m having trouble on the command side of things basically getting access to the command id after the command is dispatched:

ReST Controller -> create a command object -> send a command -> return the command id to the client.

I missed answering the second question:

At the moment, this is mostly academic - I have the scenario where the ReST API is async and returns a response once command handling is complete working. I’m trying out a scenario where the client gets an OpID once a command is dispatched and then waits for events with the same OpId.
-Raghu

Did you try this?

CommandMessage<> message = GenericCommandMessage.asCommandMessage(new Payload());commandBus.dispatch(message, callback);
return message.getIdentifier();

Super - thanks! hadn’t looked hard enough. It would help to document this in the reference guide as this is a (I feel) pretty common use case?

Rahgu,

Can you share the stub of your code as I am trying to understand how is this connecting to CommandHandler logic and the controller call. I am doing something like this. But messageIdentifier is not stored with the event so whats the benefit of sending commandId to the client?

@ResponseStatus(HttpStatus.OK)
@RequestMapping(value = "/{id}/deactivate", method = RequestMethod.GET)
public void deactivate(@PathVariable("id")  String id) {
    FutureCallback callback = new FutureCallback();
    DeactivateGroupCommand deactivateGroupCommand = new DeactivateGroupCommand(id);
    CommandMessage<DeactivateGroupCommand> message = GenericCommandMessage.asCommandMessage(deactivateGroupCommand);
    this.commandGateway.send(message, callback);
    System.out.println(message.getIdentifier());
}

But messageIdentifier is not stored with the event so whats the benefit of sending commandId to the client?

Yes - but it’s available as metadata when the event is raised (it’s also stored in the eventstore as well).

  1. Configure a CommandHandlerInterceptor to copy the command id as the Event metadata

`
@Bean
public CommandHandlerInterceptor commandHandlerInterceptor() {
AuditingInterceptor auditingInterceptor = new AuditingInterceptor();
auditingInterceptor.setAuditDataProvider(new CorrelationAuditDataProvider());
// elided…
return auditingInterceptor;
}

`

  1. In my case, for events I send a websocket push - you can declare a parameter of type MetaData and you will get the associated metadata in the event handler. Here’s what my code for the push looks like:

`
@EventHandler
public void handleEvent(GreetingUpdated ev, MetaData m) {
Message payload = new Message(ev, m);
log.info(“Publishing websocket message: {}”, payload);
this.messagingTemplate.convertAndSend("/topic/greeting", payload);
}

`