Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 6e7e76a

Browse files
committedJan 7, 2025·
Refactor Zeebe workflow start endpoint to accept JSON request body and enhance error handling; update README with usage examples and add unit tests for controller
1 parent 9c0e861 commit 6e7e76a

File tree

4 files changed

+119
-22
lines changed

4 files changed

+119
-22
lines changed
 

‎README.md

+11-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,17 @@ The Zeebe client automatically deploys the BPMN files to the Zeebe broker. It is
6666

6767
You can start the process using the controller (see the example in ZeebeController.java). The controller will start the process with the given variables.
6868

69-
The JobWorkers will automatically pick up the tasks and execute them. The JobWorkers for the example BPMN file are configured in ZeebeWorker.java.
69+
The Controller for starting the process is configured in ZeebeController.java. The controller will start the given process with the given variables. They will be passed to the process as JSON. For example, the ticket-process.bpmn file has the processID "ticket-process" and a variable "approve". The JSON should look like this:
70+
71+
{
72+
"processId": "ticket-process",
73+
"variables": {
74+
"approve": true
75+
}
76+
}
77+
78+
The JobWorkers will automatically pick up the tasks and execute them.
79+
The JobWorkers are configured in ZeebeWorker.java. The worker will pick up the tasks with the given task type and execute them. They are annotated with @ZeebeWorker. The task type must match the task type in the BPMN file. When the worker picks up the task, it will execute the given function. After the function is executed, the worker will complete the task and pass the result back to the Zeebe broker. Then the next task will be picked up by the worker.
7080

7181
This setup provides a foundational integration of Zeebe into your project.
7282

‎remsfal-service/src/main/java/de/remsfal/service/control/ZeebeController.java

+45-14
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,59 @@
33
import io.camunda.zeebe.client.ZeebeClient;
44
import jakarta.inject.Inject;
55
import jakarta.ws.rs.Path;
6-
import jakarta.ws.rs.QueryParam;
6+
import jakarta.ws.rs.core.Response;
7+
8+
import java.util.HashMap;
79
import java.util.Map;
10+
import org.jboss.logging.Logger;
11+
812

913
@Path("/zeebe")
1014
public class ZeebeController {
1115

1216
@Inject
1317
ZeebeClient zeebeClient;
1418

15-
@Path("/start")
16-
public String startWorkflow(@QueryParam("approve") Boolean approve) {
17-
18-
Map<String, Object> variables = Map.of("approve", approve);
19-
20-
var workflowInstance = zeebeClient.newCreateInstanceCommand()
21-
.bpmnProcessId("ticket-process")
22-
.latestVersion()
23-
.variables(variables)
24-
.send()
25-
.join();
19+
@Inject
20+
Logger logger;
2621

27-
return "Ticket Process instance started with key: " + workflowInstance.getProcessInstanceKey();
28-
}
22+
@Path("/start")
23+
public Response startWorkflow(Map<String, Object> requestBody) {
24+
try {
25+
if (!requestBody.containsKey("processId")) {
26+
throw new IllegalArgumentException("Missing 'processId' in request body.");
27+
}
28+
29+
String processId = (String) requestBody.get("processId");
30+
Map<String, Object> variables = new HashMap<>();
31+
32+
Object rawVars = requestBody.get("variables");
33+
if (rawVars instanceof Map<?, ?> rawMap) {
34+
for (Map.Entry<?, ?> entry : rawMap.entrySet()) {
35+
if (entry.getKey() instanceof String key) {
36+
variables.put(key, entry.getValue());
37+
}
38+
}
39+
}
40+
41+
var workflowInstance = zeebeClient
42+
.newCreateInstanceCommand()
43+
.bpmnProcessId(processId)
44+
.latestVersion()
45+
.variables(variables)
46+
.send()
47+
.join();
48+
49+
return Response.ok("Workflow '" + processId + "' started with key: "
50+
+ workflowInstance.getProcessInstanceKey())
51+
.build();
52+
53+
} catch (IllegalArgumentException e) {
54+
logger.error("Bad request: " + e.getMessage(), e);
55+
return Response.status(Response.Status.BAD_REQUEST)
56+
.entity("Error: " + e.getMessage())
57+
.build();
58+
}
59+
}
2960

3061
}

‎remsfal-service/src/main/resources/application.properties

+11-7
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,20 @@ de.remsfal.auth.oidc.client-id=821093255871-8pnrdogfojdc36mqooovf951ao9r4o8i.app
4141
de.remsfal.auth.oidc.client-secret=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
4242
de.remsfal.auth.session.secret=removeMe
4343

44+
# Zeebe Production Configuration
45+
quarkus.zeebe.client.broker.gateway-address=zeebe.remsfal.de:26500
46+
quarkus.zeebe.client.security.plaintext=false
47+
quarkus.zeebe.client.worker-name=remsfal-worker
48+
quarkus.zeebe.client.request-timeout=20s
4449
# quarkus.zeebe configuration
4550
quarkus.zeebe.resources.enabled=true
4651
quarkus.zeebe.resources.location=processes
47-
quarkus.zeebe.devservices.enabled=true
48-
quarkus.zeebe.devservices.shared=true
49-
quarkus.zeebe.devservices.service-name=zeebe_broker
50-
quarkus.zeebe.devservices.reuse=false
51-
quarkus.zeebe.dev-mode.watch-bpmn-dir=true
52-
quarkus.zeebe.dev-mode.watch-bpmn-files=true
53-
quarkus.zeebe.dev-mode.watch-job-worker=true
52+
quarkus.zeebe.client.request-timeout=20s
53+
# Disable Development Features
54+
quarkus.zeebe.devservices.enabled=false
55+
quarkus.zeebe.dev-mode.watch-bpmn-dir=false
56+
quarkus.zeebe.dev-mode.watch-bpmn-files=false
57+
quarkus.zeebe.dev-mode.watch-job-worker=false
5458

5559
# MinIO configuration for Dev Profile
5660
%dev.quarkus.minio.devservices.enabled=false
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package de.remsfal.service.control;
2+
3+
import io.quarkus.test.junit.QuarkusTest;
4+
import io.restassured.http.ContentType;
5+
import jakarta.ws.rs.core.Response;
6+
import org.junit.jupiter.api.Test;
7+
8+
import static io.restassured.RestAssured.given;
9+
import static org.hamcrest.Matchers.containsString;
10+
import static org.hamcrest.Matchers.equalTo;
11+
12+
@QuarkusTest
13+
class ZeebeControllerTest {
14+
15+
@Test
16+
void testStartWorkflowSuccess() {
17+
given()
18+
.contentType(ContentType.JSON)
19+
.body("""
20+
{
21+
"processId": "ticket-process",
22+
"variables": {
23+
"approved": "true"
24+
}
25+
}
26+
""")
27+
.when()
28+
.post("/zeebe/start")
29+
.then()
30+
.statusCode(Response.Status.OK.getStatusCode())
31+
.body(containsString("Workflow 'test-process' started with key:"));
32+
}
33+
34+
@Test
35+
void testStartWorkflowMissingProcessId() {
36+
given()
37+
.contentType(ContentType.JSON)
38+
.body("""
39+
{
40+
"variables": {
41+
"approved": "true"
42+
}
43+
}
44+
""")
45+
.when()
46+
.post("/zeebe/start")
47+
.then()
48+
.statusCode(Response.Status.BAD_REQUEST.getStatusCode())
49+
.body(equalTo("Error: Missing 'processId' in request body."));
50+
}
51+
52+
}

0 commit comments

Comments
 (0)
Please sign in to comment.