Dependency injection not working with CDI

Dependency Injection is not working for my JavaDelegates and TaskListeners. It works for neither Flowable beans (e.g., RuntimeService) nor application EJB beans. In the other parts of the application, dependency injection works for both of them.

I use Flowable 6.4.2 with the CdiStandaloneProcessEngineConfiguration on TomEE 7.1.1, and I use the flowable:class attribute in the BPMN 2.0 XML file.

I followed the documentation on setting up Flowable with CDI.

My flowable.cfg.xml looks as follows:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

  <bean id="processEngineConfiguration" class="org.flowable.cdi.CdiStandaloneProcessEngineConfiguration">
    <property name="dataSourceJndiName" value="openejb:Resource/ProcessEngine" />
    <property name="databaseSchemaUpdate" value="true" />

    <property name="asyncExecutorActivate" value="true" />
  </bean>

</beans>

What am I missing?

I’ve never used Flowable with CDI, but in general flowable:class uses the new operator to instantiate your delegates. Your best bet is to use flowable:expression or flowable:delegateExpression so the beans can be injected/autowired.

OK, thank you.

That’ s too bad because it keeps me from migrating to Flowable. For Camunda, injection works with camunda:class too. My JavaDelegates and TaskListeners are not stateless, so I cannot easily switch to flowable:expression and flowable:delegateExpression.

Do you have an example xml of where the class injection is working? I’m trying to see if this was old behavior that was working differently in the past.

A delegateExpression should give you the same behavior (as no new instance is created). However, do note that in multi-threaded usages this can lead to unforseen behavior.

Sorry, maybe I misled you.

I need separate instances for each invocation. Otherwise, I will get unforeseen behavior when multiple activity instances execute concurrently as my delegate is not stateless.

In Camunda injection works, in Flowable it does not.

In Camunda my XML looks like

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" id="definitions-external" name="definitions-external" targetNamespace="de.montigem.wf.external">
    <bpmn:process isExecutable="true" name="External" id="external">
        <bpmn:laneSet>
            <bpmn:lane name="Secretariat" id="lane-secretariat">
                <bpmn:flowNodeRef>foo</bpmn:flowNodeRef>
                <bpmn:flowNodeRef>anonymous_1</bpmn:flowNodeRef>
                <bpmn:flowNodeRef>anonymous_2</bpmn:flowNodeRef>
            </bpmn:lane>
        </bpmn:laneSet>
        <bpmn:serviceTask name="Foo" id="foo" camunda:class="de.montigem.be.wf.external.service.Foo" camunda:asyncBefore="true">
            <bpmn:incoming xmlns="">from-anonymous_1-to-foo</bpmn:incoming>
            <bpmn:outgoing xmlns="">from-foo-to-anonymous_2</bpmn:outgoing>
        </bpmn:serviceTask>
        <bpmn:startEvent parallelMultiple="false" name="Anonymous_1" id="anonymous_1">
            <bpmn:outgoing xmlns="">from-anonymous_1-to-foo</bpmn:outgoing>
        </bpmn:startEvent>
        <bpmn:endEvent name="Anonymous_2" id="anonymous_2">
            <bpmn:incoming xmlns="">from-foo-to-anonymous_2</bpmn:incoming>
        </bpmn:endEvent>
        <bpmn:sequenceFlow sourceRef="anonymous_1" targetRef="foo" isImmediate="true" id="from-anonymous_1-to-foo"/>
        <bpmn:sequenceFlow sourceRef="foo" targetRef="anonymous_2" isImmediate="true" id="from-foo-to-anonymous_2"/>
    </bpmn:process>
</bpmn:definitions>

In Flowable:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:flowable="http://flowable.org/bpmn" id="definitions-external" name="definitions-external" targetNamespace="de.montigem.wf.external">
    <bpmn:process isExecutable="true" name="External" id="external">
        <bpmn:laneSet>
            <bpmn:lane name="Secretariat" id="lane-secretariat">
                <bpmn:flowNodeRef>foo</bpmn:flowNodeRef>
                <bpmn:flowNodeRef>anonymous_1</bpmn:flowNodeRef>
                <bpmn:flowNodeRef>anonymous_2</bpmn:flowNodeRef>
            </bpmn:lane>
        </bpmn:laneSet>
        <bpmn:serviceTask name="Foo" id="foo" flowable:class="de.montigem.be.wf.external.service.Foo" flowable:asyncBefore="true">
            <bpmn:incoming xmlns="">from-anonymous_1-to-foo</bpmn:incoming>
            <bpmn:outgoing xmlns="">from-foo-to-anonymous_2</bpmn:outgoing>
        </bpmn:serviceTask>
        <bpmn:startEvent parallelMultiple="false" name="Anonymous_1" id="anonymous_1">
            <bpmn:outgoing xmlns="">from-anonymous_1-to-foo</bpmn:outgoing>
        </bpmn:startEvent>
        <bpmn:endEvent name="Anonymous_2" id="anonymous_2">
            <bpmn:incoming xmlns="">from-foo-to-anonymous_2</bpmn:incoming>
        </bpmn:endEvent>
        <bpmn:sequenceFlow sourceRef="anonymous_1" targetRef="foo" isImmediate="true" id="from-anonymous_1-to-foo"/>
        <bpmn:sequenceFlow sourceRef="foo" targetRef="anonymous_2" isImmediate="true" id="from-foo-to-anonymous_2"/>
    </bpmn:process>
</bpmn:definitions>

Ok, i think we were indeed talking about different things. I thought you mean class injection, but you mean injection of other services/beans into your service task class Foo in this example?

My CDI is quite rusty. Can you give an example how that Foo service task looks like (doesn’t need the logic, just the injection part).

Exactly. I would like to inject other service beans into the service task delegate classes.

Like MyService below.

package demo;

import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.JavaDelegate;

import demo.MyService;

import javax.inject.Inject;

public class Foo implements JavaDelegate {

    @Inject
    protected MyService service;

    @Override
    public void execute(DelegateExecution delegateExecution) {
      service.doStuff();
    }
}
package demo;

import javax.ejb.Stateless;

@Stateless
public class MyService {

  public void doStuff() {
    // ...
  }

}