Usage of camunda:expression or camunda:delegateExpression

Hi,

Is mandatory to that class I use as part of camunda:expression or camunda:delegateExpression is a spring bean?

Thanks,
Suhas Madap.

Hi @revsmadap,

In 1 you find the an explanation of the attributes in context of a service task. So, it depends on what you actually want to do. But did you already tried to use camunda:delegateExpression?

Cheers,
Roman

Hi @roman.smirnov

Yeah I tried using this attribute

 <bpmn:sendTask id="Task_0fyziz9" name="Task has expired" camunda:expression="${com.suhas.madap.camunda.loanapproval.delegate.BoundaryEventDelegate.taskExpired()}">
      <bpmn:incoming>SequenceFlow_0yq87zi</bpmn:incoming>
    </bpmn:sendTask>

Exception:

25-Jan-2017 18:42:25.915 WARNING [pool-2-thread-3] org.camunda.commons.logging.BaseLogger.logWarn ENGINE-14006 Exception while executing job ae17892a-e2fd-11e6-adc0-e4b318cb12e5:
org.camunda.bpm.engine.ProcessEngineException: Unknown property used in expression: ${com.suhas.madap.camunda.loanapproval.delegate.BoundaryEventDelegate.taskExpired()}. Cause: Cannot resolve identifier ‘com’
at org.camunda.bpm.engine.impl.el.JuelExpression.getValue(JuelExpression.java:60)
at org.camunda.bpm.engine.impl.el.JuelExpression.getValue(JuelExpression.java:48)
at org.camunda.bpm.engine.impl.bpmn.behavior.ServiceTaskDelegateExpressionActivityBehavior$3.call(ServiceTaskDelegateExpressionActivityBehavior.java:103)

Hi @revsmadap,

This will not work this way.

In your first comment your wrote that you have spring bean. Is that correct? What is the name of spring bean? When you use the expression attribute, then you cannot use the full qualified name of your class. You have to use the name of your spring bean, for example like this:

<bpmn:sendTask id="Task_0fyziz9" name="Task has expired" camunda:expression="${boundaryEventDelegate.taskExpired()}">

Anyway, maybe you should a have a look into the Spring getting started 1.

Cheers,
Roman

Hi @roman.smirnov,

sorry! may be my question is not vivid.

I’m not using any spring bean, it’s a simple POJO.

So my initial doubt is, to leverage camunda:expression or camunda:DelegateExpression attribute, do the expression class needs to be a Spring bean Or simple POJO will also works?

Thanks,
Suhas

Hi @revsmadap,

I am sorry, I misunderstood your question.

A simple POJO will work. In that case you have to use the camunda:class attribute, for example like this

<bpmn:sendTask id="Task_0fyziz9" name="Task has expired" camunda:class="com.suhas.madap.camunda.loanapproval.delegate.BoundaryEventDelegate">

But then the class BoundaryEventDelegate must implement the interface org.camunda.bpm.engine.delegate.JavaDelegate.

Cheers,
Roman

In addition in 1 you find some documentation about the JavaDelegate.

Cheers,
Roman

Hi @roman.smirnov,

With camunda:class camunda:class="com.suhas.madap.camunda.loanapproval.delegate.BoundaryEventDelegate"> this works.

But what I want to achieve is calling a specific method of a class. For ex. if my process has 3 boundary events viz. timer, follow up, expiry, then whenever event gets triggered, I want to call specific method.

for expiry boundary event I want to invoke BoundaryEventDelegate.expired(). Similary for follow up BoundaryEventDelegate.followUp() etc.

Thanks,
Suhas Madap.

Hi,

to get this, you either have to use a Spring Bean with camunda:expression or code it in the execute()-method.

Cheers, Ingo

Nobody mentioned CDI?

  • Context Dependency Injection.

Hi @garysamuelson, @Ingo_Richtsmeier ,

I tried using Spring bean

BoundaryEventDelegate.java

 @Service("boundaryEvent")
public class BoundaryEventDelegate implements JavaDelegate {

    private static Logger LOGGER = Util.getLogger(BoundaryEventDelegate.class.getName());

    public void taskRejected(){
        LOGGER.info("Task Rejected");
    }

    public void taskExpired(){
        LOGGER.info("Task Expired");
    }

    public void taskErrored(){
        LOGGER.info("Task Error");
    }

    @Override
    public void execute(DelegateExecution delegateExecution) throws Exception {
        LOGGER.info("activity Name:"+delegateExecution.getCurrentActivityName());
        LOGGER.info("Even Name: "+delegateExecution.getEventName());
    }
}

Process.bpmn

 <bpmn:sendTask id="Task_0fyziz9" name="Task has expired" camunda:expression="${boundaryEvent.taskExpired()}">
      <bpmn:incoming>SequenceFlow_0yq87zi</bpmn:incoming>
    </bpmn:sendTask>

But I get following error:

27-Jan-2017 16:12:18.970 WARNING [pool-2-thread-1] org.camunda.commons.logging.BaseLogger.logWarn ENGINE-14006 Exception while executing job 9215f9da-e47c-11e6-adc0-e4b318cb12e5:
org.camunda.bpm.engine.ProcessEngineException: Unknown property used in expression: ${boundaryEvent.taskExpired()}. Cause: Cannot resolve identifier ‘boundaryEvent’
at org.camunda.bpm.engine.impl.el.JuelExpression.getValue(JuelExpression.java:60)
at org.camunda.bpm.engine.impl.el.JuelExpression.getValue(JuelExpression.java:48)
at org.camunda.bpm.engine.impl.bpmn.behavior.ServiceTaskExpressionActivityBehavior$1.call(ServiceTaskExpressionActivityBehavior.java:47)
at org.camunda.bpm.engine.impl.bpmn.behavior.ServiceTaskExpressionActivityBehavior$1.call(ServiceTaskExpressionActivityBehavior.java:43)
at org.camunda.bpm.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior.executeWithErrorPropagation(AbstractBpmnActivityBehavior.java:108)
at org.camunda.bpm.engine.impl.bpmn.behavior.ServiceTaskExpressionActivityBehavior.performExecution(ServiceTaskExpressionActivityBehavior.java:43)
at org.camunda.bpm.engine.impl.bpmn.behavior.TaskActivityBehavior.execute(TaskActivityBehavior.java:65)

Any assistance to resolve this will be a great help.

Thanks,
Suhas

I would guess that the component scan doesn’t work as expected.

Make sure the camunda-engine-spring module is a compile scope dependency of your application.

I switched over to CDI…

So, my Camunda task implementation classes would have the following annotations:

@Named("stpProcessDemo")
public class StpProcessDemo {


	@Inject @ProcessVariable("jMSReplyToName")
	private Object jMSReplyToName;
	
	@Inject @ProcessVariable("jMSCorrelationID")
	private Object jMSCorrelationID;

        public void camundaSaysHello(DelegateExecution execution) {
		
		LOGGER.info("*** camundaSaysHello: invoked");
		
		execution.setVariable("camundaGreeting", "Hello from Camunda");
		
	}

And then I provide direct, wrapper or facade, ReST Services:

@RequestScoped
@Path("bpm")
@Produces({ "application/xml", "application/json","application/text" })
@Consumes({ "application/xml", "application/json","application/text" })
public class BpmServices {
	
	/**
	 * Logging 
	 */
	private final Logger LOGGER = Logger.getLogger(BpmServices.class.getName());
	
	
	/**
	 * Access to the Camunda Process API
	 */
	@Inject
	private RuntimeService runtimeService;


[...]

	@GET
    @Path("echoBpm/{processID}/{hello}")
	@Produces(MediaType.APPLICATION_JSON)
    public String echoBpm(@PathParam("processID") String processID, 
    				    @PathParam("hello") String hello ){
		
		LOGGER.info("*** echoBpm - processID: " + processID);
		LOGGER.info("*** echoBpm - hello: " + hello);
		
		ProcessInstanceWithVariables pVariablesInReturn = runtimeService.createProcessInstanceByKey(processID)
												.setVariable("hello", hello)
												.executeWithVariablesInReturn();
		
		String piid = pVariablesInReturn.getProcessInstanceId();
		
		return "{\"processInstanceID\": \"" + piid + "\"}";	
		// String returnVal = producerTemplate.requestBodyAndHeader("direct:startIbmBpmProcess", "msg_body_in_value", "case_id",case_id).toString();
		

	}

Hi @garysamuelson ,

I tried using CDI.

@javax.inject.Named("boundaryEvent")
public class BoundaryEventDelegate implements JavaDelegate {

    private static Logger LOGGER = Util.getLogger(BoundaryEventDelegate.class.getName());

    public void taskRejected(){
        LOGGER.info("Task Rejected");
    }

    public void taskExpired(){
        LOGGER.info("Task Expired");
    }

    public void taskErrored(){
        LOGGER.info("Task Error");
    }

    @Override
    public void execute(DelegateExecution delegateExecution) throws Exception {
        LOGGER.info("activity Name:"+delegateExecution.getCurrentActivityName());
        LOGGER.info("Even Name: "+delegateExecution.getEventName());
    }
}

process:

 <bpmn:sendTask id="Task_0fyziz9" name="Task has expired" camunda:delegateExpression="#{boundaryEvent}">
      <bpmn:incoming>SequenceFlow_0yq87zi</bpmn:incoming>
    </bpmn:sendTask>

pom.xml:

  <dependency>
            <groupId>org.camunda.bpm</groupId>
            <artifactId>camunda-engine-cdi</artifactId>
            <version>7.6.0</version>
            <scope>compile</scope>
        </dependency>

web.xml:

 <listener>
    <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
  </listener>

  <!-- for CDI support -->
  <resource-env-ref>
    <resource-env-ref-name>BeanManager</resource-env-ref-name>
    <resource-env-ref-type>javax.enterprise.inject.spi.BeanManager</resource-env-ref-type>
  </resource-env-ref>

But I see following Exception:

28-Jan-2017 13:14:54.495 WARNING [pool-2-thread-1] org.camunda.commons.logging.BaseLogger.logWarn ENGINE-14006 Exception while executing job eba32d25-e52c-11e6-adc0-e4b318cb12e5:
 org.camunda.bpm.engine.ProcessEngineException: Error while evaluating expression: #{boundaryEvent}. Cause: Could not lookup beanmanager in jndi. If no jndi is available, set the beanmanger to the 'localInstance' property of this class.
        at org.camunda.bpm.engine.impl.el.JuelExpression.getValue(JuelExpression.java:66)
        at org.camunda.bpm.engine.impl.el.JuelExpression.getValue(JuelExpression.java:48)
        at org.camunda.bpm.engine.impl.bpmn.behavior.ServiceTaskDelegateExpressionActivityBehavior$3.call(ServiceTaskDelegateExpressionActivityBehavior.java:103)
        at org.camunda.bpm.engine.impl.bpmn.behavior.ServiceTaskDelegateExpressionActivityBehavior$3.call(ServiceTaskDelegateExpressionActivityBehavior.java:98)
        at org.camunda.bpm.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior.executeWithErrorPropagation(AbstractBpmnActivityBehavior.java:108)
        at org.camunda.bpm.engine.impl.bpmn.behavior.ServiceTaskDelegateExpressionActivityBehavior.performExecution(ServiceTaskDelegateExpressionActivityBehavior.java:123)
        at org.camunda.bpm.engine.impl.bpmn.behavior.TaskActivityBehavior.execute(TaskActivityBehavior.java:65)
        at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationActivityExecute$2.callback(PvmAtomicOperationActivityExecute.java:57)
        at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationActivityExecute$2.callback(PvmAtomicOperationActivityExecute.java:46)
        at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.continueIfExecutionDoesNotAffectNextOperation(PvmExecutionImpl.java:1936)
        at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationActivityExecute.execute(PvmAtomicOperationActivityExecute.java:38)
        at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationActivityExecute.execute(PvmAtomicOperationActivityExecute.java:27)
        at org.camunda.bpm.engine.impl.interceptor.AtomicOperationInvocation.execute(AtomicOperationInvocation.java:89)
        at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.invokeNext(CommandInvocationContext.java:125)
        at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performNext(CommandInvocationContext.java:104)
        at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performOperation(CommandInvocationContext.java:79)
        at org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:611)
        at org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:587)
        at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl$5.callback(PvmExecutionImpl.java:1875)
        at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl$5.callback(PvmExecutionImpl.java:1872)
        at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.continueExecutionIfNotCanceled(PvmExecutionImpl.java:1942)
        at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.dispatchDelayedEventsAndPerformOperation(PvmExecutionImpl.java:1891)
        at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.dispatchDelayedEventsAndPerformOperation(PvmExecutionImpl.java:1872)
        at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationTransitionNotifyListenerStart.eventNotificationsCompleted(PvmAtomicOperationTransitionNotifyListenerStart.java:57)

Thanks,
Suhas

This looks like you may want to start with a fresh download of Camunda’s WildFly platform - though not sure which is you targeted application container:

Here’s a reference to a slightly aged example from the v7.6 BETA. Not sure if this still builds - but, the code reference should be good. But, this was intended mostly to reference syntax/usage.

https://github.com/g4code8/gs_codesamples/tree/master/bpmcamundacamel2 

https://camunda.org/download/
-> I prefer the WildFly version. This should be setup to handle CDI (as configured).

Looks like you have the correct version in your pom.xml

Though - I’ve not spent much time in the “web.xml”. But, weld looks good.

I’m setting up a new, GA Camunda v7.6 soon and I’ll verify.

Key bit (from a beta example):

NOTE:
This is an old POM I was using for the v7.6 beta

camunda-archetype-ejb-war [version]
This is pointing at a BETA release - so, disregard groupId and ArtifcatId

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>camunda76a3</groupId>
  <artifactId>camunda76a3</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <packaging>war</packaging>

  <name>Camunda BPM Process Application</name>
  <description>A Process Application for [Camunda BPM](http://docs.camunda.org). [The project has been generated by the Maven archetype 'camunda-archetype-ejb-war-7.5.0']</description>

  <properties>
    <!-- <camunda.version>7.5.0</camunda.version>  -->
    <!-- NOTE that I've switched to the new alpha4 release -->
    <camunda.version>7.6.0-alpha4</camunda.version>
    <arquillian.version>1.1.2.Final</arquillian.version>
    <jboss.version>7.2.1.Final</jboss.version>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <failOnMissingWebXml>false</failOnMissingWebXml>

Make sure your deployment unit contains a beans.xml file to enable CDI.
In case of a war-file it must reside in WEB-INF folder and contains:

<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
       version="1.1"
       bean-discovery-mode="annotated">
</beans>

The stuff in your web.xml should not be needed. I never saw this.

Hi @garysamuelson,

Thanks a lot for the references. I’ll try them.

I’m using tomcat distribution of camunda v7.6.

Thanks,
Suhas.

Hi @langfr,

Yeah. I’ve beans.xml in WEB-INF.

Regarding web.xml, I referred this blog https://antoniogoncalves.org/2011/01/12/bootstrapping-cdi-in-several-environments/

Thanks,
Suhas.

I’d recommend starting with the JBoss/WildFly (WildFly is the new name for the JBoss distro).

TomEE (sp?) might work. But, you’d really need a robust CDI platform. Not sure if Tomcat is there yet.

You can also start with the full build from Camunda (github), which includes the platform. But, that tends to get a little more complicated unless you’re interested in all the parts/assembly