How to setup conditionals for BPMN2 Exclusive Gateway

Jan Vladimir Mostert picture Jan Vladimir Mostert · Nov 20, 2014 · Viewed 10.5k times · Source

I'm using Camunda BPMN2 for the first time in my spring project and trying to get my head around a couple of things ...

In my applicationContext, I have the following block to setup Camunda:

    <!-- Setup BPMN Process Engine -->
    <bean id="processEngineConfiguration" class="org.camunda.bpm.engine.spring.SpringProcessEngineConfiguration">
        <property name="processEngineName" value="engine" />
        <property name="dataSource" ref="dataSource" />
        <property name="transactionManager" ref="transactionManager" />
        <property name="databaseSchemaUpdate" value="true" />
        <property name="jobExecutorActivate" value="false" />
        <property name="deploymentResources" value="classpath*:*.bpmn" />
    </bean>
    <bean id="processEngine" class="org.camunda.bpm.engine.spring.ProcessEngineFactoryBean">
        <property name="processEngineConfiguration" ref="processEngineConfiguration" />
    </bean>
    <bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService" />
    <bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService" />
    <bean id="taskService" factory-bean="processEngine" factory-method="getTaskService" />
    <bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService" />
    <bean id="managementService" factory-bean="processEngine" factory-method="getManagementService" />
    <context:annotation-config />

I've setup two services:

@Component(value="service1")
public class Service1 implements JavaDelegate {
    @Override
    public void execute(DelegateExecution execution) throws Exception {     
        System.out.println(">>>>>>>>>>>>>>>>>>>");
        System.out.println("SERVICE1");     
        System.out.println(">>>>>>>>>>>>>>>>>>>");      
    }
}

and

@Component(value="service2")
public class Service2 implements JavaDelegate {
    @Override
    public void execute(DelegateExecution execution) throws Exception {
        System.out.println(">>>>>>>>>>>>>>>>>>>");
        System.out.println("SERVICE2");     
        System.out.println(">>>>>>>>>>>>>>>>>>>");
    }
}

In scenario 1 I have a parallel gateway that calls both Service1 and Service2 (I've built these diagrams using BPMN2 editor in eclipse):

scenario 1

scenario 1 - service 1

scenario 1 - service 2

Running this line of code:

runtimeService.startProcessInstanceByKey("ConnectorSwitch");

Prints out

>>>>>>>>>>>>>>>>>>>
SERVICE1
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>
SERVICE2
>>>>>>>>>>>>>>>>>>>

as expected.

Now I'm trying to put in an Exclusive Gateway:

enter image description here

Running it gives me the following exception:

SEVERE: Error while closing command context                                                                                                                                                                                                 
org.camunda.bpm.engine.ProcessEngineException: Exclusive Gateway 'ExclusiveGateway_3' has outgoing sequence flow 'SequenceFlow_39' without condition which is not the default flow. | ..../ConnectorSwitch.bpmn | line 0 | column 0                                                                                                                                                                                                              
Exclusive Gateway 'ExclusiveGateway_3' has outgoing sequence flow 'SequenceFlow_40' without condition which is not the default flow. | ..../ConnectorSwitch.bpmn | line 0 | column 0                 

        at org.camunda.bpm.engine.impl.util.xml.Parse.throwExceptionForErrors(Parse.java:183)
        at org.camunda.bpm.engine.impl.bpmn.parser.BpmnParse.execute(BpmnParse.java:177)     
        at org.camunda.bpm.engine.impl.bpmn.deployer.BpmnDeployer.deploy(BpmnDeployer.java:106)
        at org.camunda.bpm.engine.impl.persistence.deploy.DeploymentCache.deploy(DeploymentCache.java:50)
        at org.camunda.bpm.engine.impl.persistence.entity.DeploymentManager.insertDeployment(DeploymentManager.java:42)
        at org.camunda.bpm.engine.impl.cmd.DeployCmd.execute(DeployCmd.java:81)                                        
        at org.camunda.bpm.engine.impl.cmd.DeployCmd.execute(DeployCmd.java:50)                                        
        at org.camunda.bpm.engine.impl.interceptor.CommandExecutorImpl.execute(CommandExecutorImpl.java:24)            
        at org.camunda.bpm.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:90)
        at org.camunda.bpm.engine.spring.SpringTransactionInterceptor$1.doInTransaction(SpringTransactionInterceptor.java:42)
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:130) 
    ......

The exception is pretty clear, I'm missing a condition on the Exclusive Gateway. So my question is, how do I assign a condition to the exclusive gateway, how do I call a method in a certain class and evaluate the true / false and if I want to call something else that is not a JavaDelegate for service1 / service2 (in other words, MyClass.doSomethingWithParams(someparam)), how would I go about that?

Answers in XML is fine as well, would prefer to learn how to use BPMN2 in XML instead of relying on the BPMN2 visuals.

Answer

Martin Schimak picture Martin Schimak · Nov 20, 2014

In Camunda Modeler, click on one of the sequence flows coming out of your exclusive gateway. Then select the Properties pane and the General subpane. You will see an attribute Condition. This attribute can be populated with a JUEL expression just like the one that you used for the delegates. You can use your Spring beans there and e.g. call a method on them. So if myClass is a Spring bean name, just write ${myClass.doSomethingWithParams(someparam)}. Or you can access process variables that are already attached to your process instance. someparam could be such a variable e.g. -> Just make sure that all the outgoing sequence flows have such a condition attached. Then your process will run again. Maybe start first with a simple condition like ${true} and ${false}. If this works, move on and do something more complex. And have fun! :-)