Dynamic selection of a delegate

Hi,

I am wondering whether it is possible to dynamically select a delegate to run.

I have created sample process:

Delegate at Choose Delegate, depending on passed parameter, sets value of chosenDelegate to one of two delegates: lowercaseDelegate or uppercaseDelegate.

BPMN:

<bpmn:serviceTask id="chooseDelegate" name="Choose Delegate" camunda:expression="${selectionDelegate.select(request)}" camunda:resultVariable="chosenDelegate">
      <bpmn:incoming>SequenceFlow_0seflsk</bpmn:incoming>
      <bpmn:outgoing>SequenceFlow_1kyw1dl</bpmn:outgoing>
</bpmn:serviceTask>

SelectionDelegate (it does not implement JavaDelegate):

public class SelectionDelegate {
  public String select(final String request) {
    if ("lowercase".equals(request)) {
      return "lowercaseDelegate";
    } else {
      return "uppercaseDelegate";
    }
  }
}

Value of chosenDelegate is set correctly to either lowercaseDelegate or uppercaseDelegate, as I print it out in Print Chosen Delegate.

However, when trying to actually run chosen delegate, I get error:
org.camunda.bpm.engine.ProcessEngineException: ENGINE-02033 Delegate Expression '${chosenDelegate}' did neither resolve to an implementation of 'interface org.camunda.bpm.engine.impl.pvm.delegate.ActivityBehavior' nor 'interface org.camunda.bpm.engine.delegate.JavaDelegate'.

My BPMN in Run Delegate:

<bpmn:serviceTask id="runDelegate" name="Run Delegate" camunda:delegateExpression="${chosenDelegate}">
      <bpmn:incoming>SequenceFlow_0ifau4e</bpmn:incoming>
      <bpmn:outgoing>SequenceFlow_0jwh9an</bpmn:outgoing>
</bpmn:serviceTask>

LowercaseDelegate (UpperCase is analogical, it just prints out “HELLO WORLD”):

public class LowercaseDelegate implements JavaDelegate {
  @Override
  public void execute(DelegateExecution execution) throws Exception {
    System.out.println("hello world");
  }
}

If I refer to ${lowercaseDelegate} instead of ${chosenDelegate}, it works correctly, but can I make it dynamic - and if so, how?

My test case:

  @Test
  @Deployment(resources = "dynamicDelegate.bpmn")
  public void testLowercase() {
    // Instantiate delegates used during test case execution
    Mocks.register("selectionDelegate", new SelectionDelegate());
    Mocks.register("lowercaseDelegate", new LowercaseDelegate());
    Mocks.register("uppercaseDelegate", new UppercaseDelegate());

    // Process variables
    final VariableMap variables = Variables.createVariables();
    variables.put("request", "lowercase");

    // Requester submits form
    final ProcessInstance processInstance = ProcessEngineAssertions.processEngine().getRuntimeService()
      .startProcessInstanceByKey("dynamicDelegate", variables);

    ProcessEngineAssertions.assertThat(processInstance).isEnded();
  }

Any help would be appreciated!

camunda:delegateExpression must return an instance of JavaDelegate. You could achieve this by implementing an additional delegate that resolves your delegate identifier chosenDelegate to such an instance.

2 Likes