Skip to content

Spring Boot Job Worker / Zeebe Worker for Camunda 8

This document allows to leverage Zeebe (the orchestration engine that comes as part of Camunda Platform 8) Job Workers, within your Spring or Spring Boot environment easily.

Sample GitHub repo link: Optima Spring Job Workers - Repo Link


Get Started

Create a new Spring Boot project (e.g. using Spring initializr), or open a pre-existing one you already have, or simply fork our Optima Job Worker Template repo (reference provided above).

Add Spring Boot Starter to Your Project

Add the following Maven dependency to your Spring Boot Starter project:

<dependency>
    <groupId>io.camunda.spring</groupId>
    <artifactId>spring-boot-starter-camunda</artifactId>
    <version>8.4.0</version>
</dependency>

Note that if you are using @Variables, compiler flag -parameters is required for Spring-Zeebe versions higher than 8.3.1.

If using Maven:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <compilerArgs>
                    <arg>-parameters</arg>
                </compilerArgs>
            </configuration>
        </plugin>
    </plugins>
</build>

If using Gradle:

tasks.withType(JavaCompile) {
    options.compilerArgs << '-parameters'
}

If using Intellij:

Settings > Build, Execution, Deployment > Compiler > Java Compiler

Create a class with @Component annotation

Create a class with @Component annotation, so that the Job Workers methods can be defined in this class.

@Component
public class ExampleJobWorkers {
    // Job Worker methods will be defined here
}

Implement Job Worker

@Component
public class ExampleJobWorkers {

    @JobWorker(type = "foo")
    public void handleJobFoo(final ActivatedJob job) {
        // do whatever you need to do
    }

    @JobWorker(type = "bar")
    public void handleJobBar(final ActivatedJob job) {
        // do whatever you need to do
    }
}

NOTE: In the Camunda 8 BPMN Model, in order to use invoke Job Worker, provide the same labels which are provided in the annotation type property.

worker-type-foo worker-type-bar

More in-depth documentation on Job Worker with various configurations is given below.


Configure Zeebe Gateway

Configure Zeebe Gateway Cluster address in the application.properties or application.yml file:

zeebe:
    client:
        broker:
            gateway-address: ${OPTIMA_ZEEBE_GATEWAY_ADDRESS}
        security:
            certpath: ${CERTIFICATE_PATH} # certificates/rootchain.pem
        cloud:
            clientId: ${OPTIMA_ZEEBE_CLIENT_ID}
            clientSecret: ${OPTIMA_ZEEBE_CLIENT_SECRET}
            authUrl: ${OPTIMA_ZEEBE_CLIENT_AUTH_URL}
            credentialsCachePath: ${OPTIMA_ZEEBE_AUTH_CACHE_PATH} # Make sure this path is writable by the User.

The certificate will be present in the same GitHub repo in the certificates folder. Provide the path of that certificate for the CERTIFICATE_PATH property. (Note: Make sure to import the certificate in the truststore of the JVM running the application. Such as using keytool import command in the Dockerfile of the application, i.e. during the image build process.)

The other property values (OPTIMA_ZEEBE_GATEWAY_ADDRESS, OPTIMA_ZEEBE_CLIENT_ID, OPTIMA_ZEEBE_CLIENT_SECRET, OPTIMA_ZEEBE_CLIENT_AUTH_URL) will be provided by the Optima team.


Job Worker Configuration Options


Job Type

You can configure the job type via the JobWorker annotation:

@JobWorker(type = "foo")
public void handleJobFoo() {
    // handles jobs of type 'foo'
}

Define variables to fetch

You can specify that you only want to fetch some variables (instead of all) when executing a job, which can decrease load and improve performance:

@JobWorker(type = "foo", fetchVariables={"variable1", "variable2"})
public void handleJobFoo(final ActivatedJob job) {
    String variable1 = (String)job.getVariablesAsMap().get("variable1");
    System.out.println(variable1);
    // ...
}

Using @Variable

By using the @Variable annotation there is a shortcut to make variable retrieval simpler, including the type cast:

@JobWorker(type = "foo")
public void handleJobFoo(final ActivatedJob job, @Variable String variable1) {
    System.out.println(variable1);
    // ...
}

With @Variable or fetchVariables you limit which variables are loaded from the workflow engine. You can also override this and force that all variables are loaded anyway:

@JobWorker(type = "foo", fetchAllVariables = true)
public void handleJobFoo(final ActivatedJob job, @Variable String variable1) {
    // do whatever you need to do
}

Fetch variables via Job

You can access variables of a process via the ActivatedJob object, which is passed into the method if it is a parameter:

@JobWorker(type = "foo")
public void handleJobFoo(final ActivatedJob job) {
    String variable1 = (String)job.getVariablesAsMap().get("variable1");
    System.out.println(variable1);
    // ...
}

Disable worker

You can disable workers via the enabled parameter of the @JobWorker annotation :

@JobWorker(type = "foo", enabled = false)
public void handleJobFoo() {
    // worker's code - now disabled
}

This is especially useful, if you have a bigger code base including many workers, but want to start only some of them. Typical use cases are:

  • Testing: You only want one specific worker to run at a time
  • Load Balancing: You want to control which workers run on which instance of cluster nodes
  • Migration: There are two applications, and you want to migrate a worker from one to another. With this switch, you can simply disable workers via configuration in the old application once they are available within the new.