Message Intermediate Throw Event design

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?

Hi @IdemenB,

there is no endpoint available to get the message name of a message throw event.

You either can add it by yourself using the logic I posted here: Message Intermediate Throw Event design or get the complete bpmn model xml in the piece of code where you need the message name and extract the name from the xml there.

Hope this helps, Ingo

Thank you very much @Ingo_Richtsmeier. Unfortunately, because I am using external task pattern for everyting, your implementation I can’t use. Currently, my implementation has been defining a variable for message name on start of the event and retrieving that variable.

This use case which had been questioned by people is extremely helpful for me because my design is to have a single worker class in Python that cares of all intermediate throw message events in all processes. So, I need a way to dynamically feed the class with the message name to throw from it.

Hi @IdemenB,

I would suggest to get rid of the message name and use a input parameter in the modeler for this: https://docs.camunda.org/manual/7.13/user-guide/process-engine/variables/#input-output-variable-mapping

It will create a local variable that is available in the external task directly.

Hope this helps, Ingo

1 Like

Thanks @Niall for your useful comment!
I’m actually in this situation where I’m trying to make one generic method which sends different messages. Therefore, I made use of this useful property!

I enhanced the solution that was provided by @Ingo_Richtsmeier a little bit in order to be generic for my case.
Thanks to him, he guided me to implement a generic component for my intermediate throw events which I need them to be caught by IntermediateCatchEvent in the same process instance.
So, in order to catch IntermediateThrowEvent by the same process instance I only added extra property as below.

Hope is gonna help somebody who needs such a solution.

@Slf4j
@Component
public class IntermediateThrowEventAdapter implements JavaDelegate {

@Override
public void execute(final DelegateExecution execution) {

    log.info("Passing a new activity: {}", execution.getCurrentActivityName());

    final ThrowEvent messageEvent = (ThrowEvent) execution.getBpmnModelElementInstance();
    final MessageEventDefinition messageEventDefinition = (MessageEventDefinition) messageEvent.getEventDefinitions()
        .iterator()
        .next();

    final String receivingMessageName = messageEventDefinition.getMessage().getName();

    log.info("IntermediateThrowEvent's message name: {}", receivingMessageName);

    execution.getProcessEngineServices()
        .getRuntimeService()
        .createMessageCorrelation(receivingMessageName)
        .processInstanceBusinessKey(execution.getProcessBusinessKey())
        .correlate();
}

If you want to communicate within process instance, you’d better use link events, error events or escalation events (check what fits best in you rmodel). You don’t need to cope with correlations then.