Message Intermediate Throw Event design

Greets, I am trying to incorporate message ikntermediate throw event in my schema, and I’m kinda confused. At first I thought that the whole purpose of the thing is to throw a message, so I expected this element to only have Message attribute at the properties panel (like in message receive intermediate event), but turns out it asks for some implementation as well as for message name. I don’t quite get it. Is it the same as send task? And if yes, what is this message property it’s asking for, if I need to code the way I throw message anyways?

@ilyabr Implementation must be provided for both activity types(intermediate message throw event & send task).

When it comes to configuring message, intermediate throw event allows to configure the message name (can be called as named message) while modeling the bpmn, but in the send task, one must need to explicitly correlate the message name.

A Send Task is used to send a message. In Camunda this is done by calling Java code.

<sendTask id="sendTask" camunda:class="org.camunda.bpm.MySendTaskDelegate" />

Message Intermediate Throwing event sends a message to an external service. This event has the same behavior as a Send Task.

<intermediateThrowEvent id="message">
  <messageEventDefinition camunda:class="org.camunda.bpm.MyMessageServiceDelegate" />
</intermediateThrowEvent>

To correlate the message to the specific process instance waiting for it by matching some properties of the incoming message to some properties of your process instance:

runtimeService
  .createMessageCorrelation("myMessage") 
  .processInstanceBusinessKey(myMessage.getOrderId().toString()) 
  .processInstanceVariableEquals("customerId", myMessage.getCustomerId()) 
  .correlate();
  • A process instance matches if it is waiting for a message named myMessage, …​
  • if it carries the orderId of the message as its business key , …​
  • and if a process variable “customerId” also matches the expectations.

There are other differences can be read from,

3 Likes

@aravindhrs, I see, man. But can you give an example of Message Intermediate Throwing event implementation? You said that “intermediate throw event allows to configure the message name”, but what does implementation look like then? Do I somehow skip the createMessageCorrelation in your example:

runtimeService
  .createMessageCorrelation("myMessage") 
  .processInstanceBusinessKey(myMessage.getOrderId().toString()) 
  .processInstanceVariableEquals("customerId", myMessage.getCustomerId()) 
  .correlate();

since I’ve configured message name using properties already or something else?

@ilyabr there’s no much difference, from the properties panel, you can access the message name to correlate in the code.

@aravindhrs, I feel like I’m still missing something here :frowning: What is the point of specifying message name in the properties panel, if it is going to be coded anyways ( like myMessage in .createMessageCorrelation(“myMessage”) )? To me it seems like an unnecessary duplicate.

1 Like

Yes, that’s a very good question! I can only assume that you specify the message name for documentation purposes. Please, experts, correct me!

The message name isn’t required - but it can be quite useful if you have a generic messages sending method that can query the symbol for the message name before doing the send.

So in some cases it’s not needed.

1 Like

But the question still remains: why do we need a message name on the send event element?

1 Like

It’s not really needed, but can be useful in cases - like you said - documentation but has no affect on execution.

@Niall, can you please give an example where it can be useful? I mean, other than just documentation purpose.

If you want to reuse the same method that sends a message - each message would require it’s own message name. If this send message gets the message name from the element itself it can be reused more easily.
Thanks a pretty good use case.

2 Likes

@Niall, do you mean I can somehow use message name property in the class that will correlate the message? Taking an example from aravindhrs, for instance:

runtimeService
  .createMessageCorrelation("myMessage") 
  .processInstanceBusinessKey(myMessage.getOrderId().toString()) 
  .processInstanceVariableEquals("customerId", myMessage.getCustomerId()) 
  .correlate();

Can I fetch “myMessage” from message name property I specified in modeler instead of hardcoding it?

Yes, you can. Via the execution object you can access the model element (activity) and its properties. But it’s a rather theoretical use. Because all the messages must correlate the same way. This will hardly occur in real life projects.

@fml2, indeed, this is rather theoretical use. I’m wondering if there is any convenient way to get message name from this property. Otherwise I don’t see why would I specify message name on the scheme at all (apart from documentation purposes)

Hey @ilyabr and @fml2,

I followed your interesting discussion and thought about an implementation.

This is a generic JavaDelegate implementation which combines the message property with a correlation to a receiving process instance:

  public void execute(DelegateExecution execution) throws Exception {
    LOG.info("Passing: {}", execution.getCurrentActivityName());
    
    ThrowEvent messageEvent = (ThrowEvent) execution.getBpmnModelElementInstance();
    MessageEventDefinition messageEventDefinition = (MessageEventDefinition) messageEvent
        .getEventDefinitions().iterator().next();
    String receivingMessageName = messageEventDefinition.getMessage().getName();
    LOG.info("Message: {}", receivingMessageName);
    
    execution.getProcessEngineServices()
      .getRuntimeService()
      .createMessageCorrelation(receivingMessageName)
      .correlate();
  }

I would say, it makes sense to use both for a thowing message event: The messageRef and the delegate implementation.

This the process model I used to test it: process.bpmn (3.3 KB)

Cheers, Ingo

1 Like

But how would you define what instance is to receive the message? You have to specify more criteria prior to calling correlate() (business key or a variable value or …). But those criteria are highly individual for a process model. Hence I still fail to see a real use case for this generic implementation.

1 Like

Hey, @Ingo_Richtsmeier, thanks for the implementation! This is somewhat I thought when I first read aravindhrs’s answer. But it really feels like a crutch, since this generic approach requires some coding. Seems like specifying a message name is mainly for documentation purposes then.

Just to clarify my statement: I understood your proposal in the way that we should have a standard generic component that would be attached as the implementation to every element of type “message throw event”. Such a component would make no sence IMO because you have to specify the correlation criteria which are highly individual.

If your proposal is to copy the code at every place (then you can specify different criteria at every place), then what is the benefit of it? The only one I can see is that you don’t have to repeat the message name in the java code (but rather take it from the process model). But then we could do it the other way around: do not specify any message name in the model and only specify it in the code.

Pros: No duplication, no complex code to extract the message name from the execution
Cons: No documentation at the process model level

Hey everybody,

I don’t want to convice anybody to use it, for me it is just a proof of concept.

If you want to use a generic, reusable send event implementation, first you should consider, how generic you could be in your project.

When it is possible to establish a convention to implement all send message events with the receiving message name and use only the business key for correlation, then it’s fine. If you need more, try a different approach.

P.S. I don’t like intermediate throwing message events, I prefer message send task. And they don’t offer to add messages in the Camunda modeler.

2 Likes

Hi @Ingo_Richtsmeier, can I ask through which REST API endpoint I can get the defined “message name” attribute of an intermediate message throw event in a process instance?