(Re-)using messages in element templates

Hi Folks,

is it possible to create a Modeller element template which is able to select a Message (or even define a Message) as it done for example by a Message throwing event?

I would like to build a “Send” task, with a Message attribute, defined in the model. By parsing a model, I created some code that extracts this attributes and is able to use it during the execution of the delegate.

Kind regards,

Simon

How are you sending/generating your message? script, expression or delegate?

I would go for a delegate and read the message name from the element definition.

For a throwing event I’m doing it like this (here in Kotlin, as an extension function to delegate execution):

fun DelegateExecution.messageName(): String {
  // rebind to allow smart cast
  val modelInstance = bpmnModelElementInstance

  // try the message throw event
  if (modelInstance is ThrowEvent) {
    val eventDefinition = modelInstance.eventDefinitions.iterator().next()
    if (eventDefinition is MessageEventDefinition) {
      return eventDefinition.message.name.trim()
    }
  }
  throw IllegalArgumentException("Message must be set.")
}

Can you use local variable inputs or field injection ? And have this populated with your element template?

Hm… I know how to build a work-around for this, but this is actually not the question.

Creating a Message Template you cannot currently do as per: https://github.com/camunda/camunda-modeler/issues/861.

@zambrovski as a interim, have you considered editing the BPMN post deployment as a parse listener and/or editing it as a fluent API? Where you could add the required data / flags as extension key/values (or wherever you see as best) and then you further configure the BPMN/add the missing config using a parse listener

@zambrovski here is a simple solution that adds the custom message based on a Extension property on the task:

 BpmnModelInstance addMessages(BpmnModelInstance modelInstance){
        modelInstance.getModelElementsByType(ReceiveTask.class).each { receiveTask ->
            CamundaProperties properties = receiveTask.getExtensionElements().getElementsQuery().filterByType(CamundaProperties.class).singleResult()
            Collection<CamundaProperty> messageDetails = properties.getCamundaProperties().findAll { property ->
                property.getCamundaName() == 'MessageName'
            }
            if (!messageDetails.first().getCamundaValue().isEmpty()){
                receiveTask.builder().message(messageDetails.first().getCamundaValue()).done()
            } else {
                throw new Exception("Cannot add message to element: ${it.getId()} because MessageName extension property value is not set")
            }
        }
        return modelInstance
    }

and then setting up the builder with something like:

...
BpmnModelInstance instance = Bpmn.readModelFromStream(resourceStream('bpmn/addMessage.bpmn'))
builder.addModelInstance('addMessage.bpmn', addMessages(instance))
...

its just setup for Receive Task, but you can easily extend / apply the same logic in kotlin and for Throw Events.

inside of the BPMN:

before deployment:

and the result after running the above code:

1 Like

Excellent idea to use the deployment to modify the BPMN. In fact, I created the extension element and just work with the message name from there…

@zambrovski take a look at: Ability to edit BpmnModelInstance before bpmn parse listener? If you want to build a deployment modifier. It will implement your transformations during deployment