CDI injections into JavaDelegate on Wildfly


#1

Hi,

I currently failing in getting Camunda with CDI running on Wildfly.
My JavaDelegate looks like this:

import java.util.logging.Logger;
import javax.inject.Inject;
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.delegate.JavaDelegate;
public class ServiceTask1 implements JavaDelegate
{
    @Inject
    private Logger log;

    @Override
    public void execute( DelegateExecution aExecution ) throws Exception
    {
        log.info( "ServiceTask1 executed" );
    }
}

My process also calls this code but I always get an NPE, because this log variable is null. In other words, camunda did not inject the logger into this variable.

In my project I have the cdi dependency

    <dependency>
        <groupId>org.camunda.bpm</groupId>
        <artifactId>camunda-engine-cdi</artifactId>
    </dependency>

and I’m running Wildfly 10. In other classes the dependency injections work fine.

Any idea what I did wrong?

Regards
Johannes


#2

Hi @johannesschaefer,

Did you reference the javadelegate as an expression inside the bpmn process? Like this:

<serviceTask id="beanService"
     name="My Bean Service Task"
     camunda:delegateExpression="${myDelegateBean}" />

This part of the documentation should help you further, also this one.

Cheers,
Christian


#3

Hi Christan,

thanks for your reply. But I don’t get it.
I try so many ways. Maybe you can give me some more hints.
I absolutly missing in the documentation some java code.
So, for BPMN code like this:

<serviceTask id="javaService"
         name="My Java Service Task"
         camunda:class="abc.ServiceTask1" />

we need a java delegate like this:

package abc;
import java.util.logging.Logger;
import javax.inject.Inject;
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.delegate.JavaDelegate;
public class ServiceTask1 implements JavaDelegate
{
    @Inject
    private Logger log;

    @Override
    public void execute( DelegateExecution aExecution ) throws Exception
    {
        log.info( "ServiceTask1 executed" );
    }
}

Here everything is fine, but unfortunatelly CDI injections doesn’t work here.

So, what java code do I need for:

<serviceTask id="beanService"
         name="My Bean Service Task"
         camunda:delegateExpression="${performTask}" />

or for

<serviceTask id="expressionService"
         name="My Expression Service Task"
         camunda:expression="${GenericCDIService.performTask()}" />

For both I tried the following code:

package abc;
import java.util.logging.Logger;
import javax.inject.Inject;
import javax.inject.Named;
@Named
public class GenericCDIService
{
    @Inject
    private Logger log;

    @Named
    public void performTask()
    {
        log.info( "performTask" );
    }
}

But I always get an error like this:

org.camunda.bpm.engine.impl.javax.el.PropertyNotFoundException: Cannot resolve identifier 'GenericCDIService'

Thanks,
Johannes


#4

The solution should look like the following.

  1. Build
    Add the following to your Maven dependencies. Also add an empty beans.xml to enable CDI.
 <dependency>
      <groupId>org.camunda.bpm</groupId>
      <artifactId>camunda-engine-cdi</artifactId>
  </dependency>
  1. BPMN
<serviceTask id="javaService"
         name="My Java Service Task"
         camunda:delegateExpression="${serviceTask1}" />
  1. Java Delegate
//package and imports...

@Named
public class ServiceTask1 implements JavaDelegate
{
    @Inject
    private Logger log;

    @Override
    public void execute( DelegateExecution aExecution ) throws Exception
    {
        log.info( "ServiceTask1 executed" );
    }
}

Hint:

  • camunda:class=“abc.ServiceTask1” will create a new instance of the referenced java delegate by invoking class.newinstance
  • camunda:delegateExpression expects a CDI/Spring bean implementing the JavaDelegate interface
  • camunda:expression can be used to invoke any method inside a CDI/Spring

Does this help you?

Cheers,
Christian


#5

Hi,
Thanks for your hints, but it doesn’t work :frowning: :disappointed_relieved:

Maybe I describe my application structure here in some words.
Module server.connect with the Java code and the BPMN files
pom.xml:

...
<artifactId>server.connect</artifactId>
<packaging>ejb</packaging>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.camunda.bpm</groupId>
            <artifactId>camunda-bom</artifactId>
            <version>7.7.0</version>
            <scope>import</scope>
            <type>pom</type>
        </dependency>
    </dependencies>
</dependencyManagement>
<dependencies>
    <dependency>
      <groupId>org.camunda.bpm</groupId>
      <artifactId>camunda-engine</artifactId>
      <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.camunda.bpm</groupId>
        <artifactId>camunda-engine-cdi</artifactId>
    </dependency>
    <dependency>
      <groupId>org.camunda.bpm.javaee</groupId>
      <artifactId>camunda-ejb-client</artifactId>
      <scope>provided</scope>
    </dependency> 
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.camunda.bpm</groupId>
            <artifactId>camunda-bom</artifactId>
            <version>7.7.0</version>
            <scope>import</scope>
            <type>pom</type>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
      <groupId>org.camunda.bpm</groupId>
      <artifactId>camunda-engine</artifactId>
      <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.camunda.bpm</groupId>
        <artifactId>camunda-engine-cdi</artifactId>
    </dependency>
    <dependency>
      <groupId>org.camunda.bpm.javaee</groupId>
      <artifactId>camunda-ejb-client</artifactId>
      <scope>provided</scope>
    </dependency> 
...

<build>
    <finalName>${project.artifactId}</finalName>
    <plugins>
        <plugin>
            <artifactId>maven-ejb-plugin</artifactId>
            <version>2.5.1</version>
            <configuration>
                <!-- Tell Maven we are using EJB 3.1 -->
                <ejbVersion>3.1</ejbVersion>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <configuration>
                <skipTests>true</skipTests>
            </configuration>
        </plugin>
    </plugins>
</build>
...

Java code in src/main/java…/GenericCDIService.java

import java.util.logging.Logger;

import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.inject.Named;

import org.camunda.bpm.engine.delegate.DelegateExecution;

@Stateless
@Named( "genericCDIService" )
public class GenericCDIService
{
    @Inject
    private Logger log;

    @Named
    public void performTask( DelegateExecution delegateExecution )
    {
        log.info( "performTask" );
    }
}

I have a src/main/resouces/META-INF/beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>

Also an empty src/main/resouces/META-INF/processes.xml

My flow.bpmn contains the following snippet:

<bpmn:serviceTask id="serviceTask1" name="serviceTask1" camunda:expression="${genericCDIService.performTask(execution)}">
  <bpmn:incoming>SequenceFlow_158gl99</bpmn:incoming>
  <bpmn:outgoing>SequenceFlow_00yppcv</bpmn:outgoing>
</bpmn:serviceTask>

But I also tried a Java Delegate with an delegateExpression.
I always get an

Cannot resolve identifier 'genericCDIService'

The module is included by an server.deployable artifact.
pom.xml:

...
<artifactId>server.deployable</artifactId>
<packaging>ear</packaging>
...
    <dependency>
        <groupId>${project.groupId}</groupId>
        <artifactId>server.connect</artifactId>
        <version>${project.version}</version>
        <type>ejb</type>
    </dependency>
...

<build>
    <finalName>${project.artifactId}</finalName>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-ear-plugin</artifactId>
            <version>2.10.1</version>
            <configuration>
                <!-- Tell Maven we are using Java EE 7 -->
                <version>7</version>
                <!-- Use Java EE ear libraries as needed. Java EE ear libraries
                    are in easy way to package any libraries needed in the ear, and automatically
                    have any modules (EJB-JARs and WARs) use them -->
                <defaultLibBundleDir>lib</defaultLibBundleDir>
                <modules />
                <fileNameMapping>no-version</fileNameMapping>
                
                <archive>
                    <manifestEntries>
                        <Dependencies>org.camunda.bpm.camunda-engine</Dependencies>
                    </manifestEntries>
                </archive>
            </configuration>
        </plugin>
 ...

In the deployable module I have an
jboss-app.xml

<?xml version="1.0" encoding="UTF-8"?>
<jboss-app xmlns="http://www.jboss.com/xml/ns/javaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.com/xml/ns/javaee/jboss-app_7_0.xsd" version="7.0">
    
</jboss-app>

and a
jboss-deployment-structure.xml

<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
    <!-- Make sub deployments isolated by default, so they cannot see each others classes without a Class-Path entry -->
    <ear-subdeployments-isolated>false</ear-subdeployments-isolated>

    <deployment>
        <dependencies>
            <module name="javax.api"/>
            <module name="javax.annotation.api"/>
            <module name="javax.resource.api" export="true"/>
            <module name="javax.transaction.api"/>
            <module name="org.slf4j"/>
            <module name="org.jboss.logging"/>

            <!-- TODO OPT1: global modules loaded from ${WILDFLY_HOME}/modules directory -->
            <!--module name="javax.cache.api" export="true"/-->
            <!--module name="com.hazelcast.cache" export="true"/-->
            <!-- TODO OPT2: deployment modules that are just defined below -->
            <module name="deployment.jcache" export="true"/>
            <module name="deployment.hazelcast" export="true"/>
        </dependencies>
    </deployment>
</jboss-deployment-structure>

The deployable module produces the final ear file that I deploy.
Do you see there any issues or configurations problems?

Thanks for your help.
Regards
Johannes.