How does JavaDelegate via JavaClass Implementation work?

If I have following bpmn:

Prozess1908.bpmn (2.9 KB)

And connect those Service Tasks to my Java Classes via JavaDelegate it will always instantiate those Class ?

I get following Error, if I dont add default constructor to Class Presse.java:

ENGINE-09008 Exception while instantiating class ‘com.example.workflow.Presse’: couldn’t instantiate class com.example.workflow.Presse

My Code for Presse.java is:

package com.example.workflow;

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

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class Presse implements JavaDelegate {

    String param = "5";
    private HexToByteConverter hexToByteConverter = new HexToByteConverter();
    Socket socket;
    InputStream in;
    OutputStream out;


    byte[]Pressen1hexdump110 = hexToByteConverter.hexStringToByteArray("33333333003d0064000600000004004001c9c78900010000006e0000000000000000000000000001000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"+param);
    byte[]Pressen2hexdump = hexToByteConverter.hexStringToByteArray("3333333300400065000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
    byte[]Pressen3hexdump = hexToByteConverter.hexStringToByteArray("3333333300400065001400000000004001c9c6e900010000006e000000000000000000000000000100000000001e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");

    /*public Presse(){

    }*/

    public Presse(Socket clientSocket) throws IOException {
        this.socket = clientSocket;
        //Inputstream
        in = socket.getInputStream();
        //Outputstream
        out = socket.getOutputStream();
    }

    public void sendMessage() throws IOException {
        byte[] buf = new byte[1];
        in.read(buf);
        while (buf[0] != -1) {
            out.write(Pressen1hexdump110);
            out.write(Pressen2hexdump);
            out.write(Pressen3hexdump);
            //in.read(buf);
        }
    }

    @Override
    public void execute(DelegateExecution delegateExecution) throws Exception {
        param = (String) delegateExecution.getVariable("durationglobal");
        System.out.println("durationglobal:    "+ param);
        //sendMessage();
    }
}

Now I want to use not my default constructor, I want to instantiate in another Class with
Presse p = new Presse(clientSocket);
And want to pass this Object to my Presse.java class so that I can use this Object in execute method from Presse.java class. For example:
p.sendMessage(); How can I achieve this ?

@andii04 Are you using Spring framework or java only?

@aravindhrs Im using Spring Boot Application

Then you have to make your class a spring bean (e.g. by adding the @Component annotation) and refer to it in the process model: Delegate Expression, the expression would be ${Presse}. Spring is then responsible for instantiating the class. It will be only instantiated once (if it’s a singleton bean).

@fml2 Sorry for my miss understanding. So you mean I should add in above Class in the line over

@Component
public class Presse implements JavaDelegate {

In Modeler I should change from a Java Class Implementation to Delegate Expression like in this image ?:

The BPMN:Prozess1908.bpmn (2.9 KB)

And then I think I need to add something like @Bean or @Autowired, but I don’t know where. I think in my ServerAzyklisch Class ?

package com.example.workflow;

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

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ServerAzyklisch implements Runnable, JavaDelegate {
    //maybe here ? @Autowired
    Socket finalSocket;
    //new
    int maxClients = 4;
    ExecutorService threadPool = Executors.newFixedThreadPool(maxClients);
    //
    int count = 0;
    private final ServerSocket ssocket;
    static String param;
    HexToByteConverter hexToByteConverter = new HexToByteConverter();
    // 2 TCP Server starten Port 2000, Port 2001
    public ServerAzyklisch(String Pparam) throws IOException {
        ssocket = new ServerSocket(2000);
        param = Pparam;
    }

    public ServerAzyklisch() throws IOException {
        ssocket = new ServerSocket(2000);
    }

    public void run() {
        byte[] buf = new byte[1];
        System.out.println(param+"Paraaam");
        InputStream in;
        OutputStream out = null;
        Socket socket;
        //Thread immer aktiv
        while(true){
            try {
                // Wartet auf Socket Verbindung
                System.out.println("Server is listening on port "+ ssocket.getLocalPort());
                socket = ssocket.accept();
                finalSocket = socket;
                threadPool.submit(() -> {
                    // Communicate with clientSocket, for example:
                    try {
                        Presse p = new Presse(finalSocket);
                        Bohrer b = new Bohrer(finalSocket);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                });
                count++;
                System.out.println("Countet clients: "+count);
                socket.setSoLinger(true, 1000);
            } catch (IOException e) {
                e.printStackTrace();
            }catch (Exception e) {
                e.printStackTrace();
            }

        }
    }

    @Override
    public void execute(DelegateExecution delegateExecution) throws IOException {
        
    }
}

I hope you can help me, where I have to add which Annotations, …

@andii04 refer the below project:

1 Like

I added a no args default constructor, but whats about my other questions above ? did I the right way ?

This is not correct. If you use Spring you can and should only define constructors that make sense in your application. And use Spring to wire the constructor parameters. See the many spring tutorials on the internet on how to use spring.

@andii04: Your assumptions were correct. The only error was that the expression should be ${presse} (lower case “p”) because the default name of s spring bean is the simple class name with the lowercase first letter.

2 Likes

Adding ${presse} will solve the issue

1 Like

I changed my Bohrer and Presse Class, like this (both are similiar)

package com.example.workflow;

import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.delegate.JavaDelegate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

@Component
public class Bohrer implements JavaDelegate {
    private HexToByteConverter hexToByteConverter = new HexToByteConverter();
    byte[]Pressen2hexdump = hexToByteConverter.hexStringToByteArray("3333333300400065000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
    byte[]Pressen3hexdump = hexToByteConverter.hexStringToByteArray("3333333300400065001400000000004001c9c6e900010000006e000000000000000000000000000100000000001e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");

    byte[]Bohrer1hexdump120 = hexToByteConverter.hexStringToByteArray("33333333003d0064000600000004004001c9c78900010000007800000000000000000000000000010000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002");
    byte[]Bohrer2hexdump121 = hexToByteConverter.hexStringToByteArray("33333333003d0064000600000004004001c9c78900010000007800000000000000000000000000010000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001");
    byte[]Bohrer3hexdump122 = hexToByteConverter.hexStringToByteArray("33333333003d0064000600000004004001c9c78900010000007800000000000000000000000000010000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003");
    @Autowired
    Socket socket;
    InputStream in;
    OutputStream out;
    @Override
    public void execute(DelegateExecution delegateExecution) throws Exception {
        System.out.println("In Execute von Bohrer");
        PostRequestDelegate postRequestDelegate = new PostRequestDelegate();
        postRequestDelegate.postBohrer();
        sendMessage();
    }

    @PostConstruct
    public void init() throws IOException {
        in = socket.getInputStream();
        out = socket.getOutputStream();
    }

    public Bohrer() {

    }

    public Bohrer(Socket clientsocket) throws IOException {
        /*ssocket = new ServerSocket();
        ssocket.setReuseAddress(true);
        ssocket.bind(new InetSocketAddress(2000));
        socket = ssocket.accept();*/
        this.socket = clientsocket;
        //Inputstream
        in = socket.getInputStream();
        //Outputstream
        out = socket.getOutputStream();
    }

    public void sendMessage() throws IOException {
        byte[] buf = new byte[1];
        in.read(buf);
        while (buf[0] != -1) {
            out.write(Bohrer1hexdump120);
            out.write(Pressen2hexdump);
            out.write(Pressen3hexdump);
            //in.read(buf);
        }
    }
}

And added this AppConfig.class:

package com.example.workflow;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

@Configuration
public class AppConfig {

    private ServerSocket ssocket = new ServerSocket(2000);

    public AppConfig() throws IOException {
    }

    @Bean
    public Socket socket() throws IOException {
        Socket clientSocket = ssocket.accept();
        return clientSocket;
    }
}

I thought this could be a way that it works, but now the Webapp of Camunda isnt starting anymore. I just get this:

Do you have any suggestions why this happend ? I cant go to localhost:8080 to Webapp anymore for using Cockpit/Tasklist,…

In the class Bohrer, you don’t need the no-arg constructor. Just move the @Autowired from the declaration of the instance variable to the constructor parameter. There is also no neen in no-arg constructor in AppConfig.

As to why the app is not starting: I think it has to do with opening the socket. Put in some log messages or debug the application. Then you’ll see where the problem lies.

1 Like

Now I fixxed it a bit and the connection is up. I can handle Webapp again. Now if I start the Process above, I get following Error:

2020-08-20 10:08:25.322  WARN 10956 --- [aTaskExecutor-3] org.camunda.bpm.engine.jobexecutor       : ENGINE-14006 Exception while executing job 524b5868-e2bc-11ea-8ac8-34f39aa06df0: 

org.camunda.bpm.engine.ProcessEngineException: Unknown property used in expression: ${presse}. Cause: Cannot resolve identifier 'presse'

Did you include camunda-spring integration library into your project? This is the library that makes spring beans accessible in the expressions.

You mean in my pom.xml ?

This is my pom.xml:

<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>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.5.RELEASE</version>
    <relativePath/>
  </parent>

  <properties>
    <java.version>8</java.version>
  </properties>

  <groupId>com.example.workflow</groupId>
  <artifactId>arbeit</artifactId>
  <version>1.0.0-SNAPSHOT</version>

  <dependencies>
    <dependency>
      <groupId>com.googlecode.json-simple</groupId>
      <artifactId>json-simple</artifactId>
      <version>1.1</version>
    </dependency>

    <dependency>
      <groupId>org.camunda.bpm.springboot</groupId>
      <artifactId>camunda-bpm-spring-boot-starter-rest</artifactId>
      <version>7.13.0</version>
    </dependency>

    <dependency>
      <groupId>org.camunda.bpm.springboot</groupId>
      <artifactId>camunda-bpm-spring-boot-starter-webapp</artifactId>
      <version>7.13.0</version>
    </dependency>

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
      <groupId>com.h2database</groupId>
      <artifactId>h2</artifactId>
    </dependency>

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-beans</artifactId>
          <version>5.2.7.RELEASE</version>
      </dependency>
    <dependency>
      <groupId>com.googlecode.json-simple</groupId>
      <artifactId>json-simple</artifactId>
      <version>1.1</version>
    </dependency>

  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>9</source>
                <target>9</target>
            </configuration>
        </plugin>
    </plugins>
  </build>

</project>

Tje property issue is solved. But now I get this Error:

ENGINE-02033 Delegate Expression '{bohrer} did neither resolve to an implementation of …interface …ActivityBehaviour nor interface org.camunda.bpm.engine.delegate.JavaDelegate

In modeller I clicked the implementation -> delegate Expression and in delegate expression I wrote the class names in lowercase, like this {bohrer}

I missed the ‘$’ im the expression. Now I ll get error: pvmException:couldnt execute activity servicetask bohren software caused connection abort: recv failed

How?

I think this is a problem with the socket, is not related to camunda.

1 Like

I don’t know why. After a restart it was solved and found the property