Java
QuantumBPM/quantum-java-sdk — split into a plain Java client and a Spring Boot starter. Requires Java 21+ (the worker runtime uses virtual threads).
Installation
<!-- Plain Java client -->
<dependency>
<groupId>com.quantumbpm</groupId>
<artifactId>quantum-client</artifactId>
<version>1.0.0</version>
</dependency>
<!-- Spring Boot starter — autoconfigured client + @JobWorker registration -->
<dependency>
<groupId>com.quantumbpm</groupId>
<artifactId>quantum-spring</artifactId>
<version>1.0.0</version>
</dependency>
Quick start (plain Java)
import com.quantumbpm.client.QuantumBPM;
import com.quantumbpm.client.auth.ZitadelTokenProvider;
import com.quantumbpm.client.variables.Vars;
import java.util.UUID;
ZitadelTokenProvider provider = new ZitadelTokenProvider(
"./service-account.json",
"https://auth.quantumbpm.com",
"your-zitadel-project-id");
QuantumBPM client = QuantumBPM.builder()
.baseUrl("https://api.quantumbpm.com")
.projectId(UUID.fromString("YOUR_PROJECT_ID"))
.tokenProvider(provider)
.build();
var result = client.dmn().evaluate(
"loan-eligibility",
new Vars().set("requestedAmt", 1000).set("creditScore", 720));
Quick start (Spring Boot)
application.yml:
quantumbpm:
base-url: https://api.quantumbpm.com
project-id: YOUR_PROJECT_ID
auth:
zitadel:
key-file: /path/to/service-account.json
issuer: https://auth.quantumbpm.com
project-id: YOUR_ZITADEL_PROJECT_ID
worker:
enabled: true # default; scans @JobWorker beans
client-id: billing-svc
Then inject QuantumBPM anywhere and annotate handler methods with @JobWorker:
import com.quantumbpm.client.variables.Vars;
import com.quantumbpm.client.workers.Job;
import com.quantumbpm.spring.JobWorker;
import org.springframework.stereotype.Component;
@Component
public class EmailHandler {
@JobWorker(type = "send-email", maxJobs = 5, lockDuration = "1m")
public Vars handle(Job<EmailJob> job) {
emailService.send(job.typed().recipient(), job.typed().subject());
return new Vars().set("messageID", "msg-123");
}
public record EmailJob(String recipient, String subject) {}
}
The autoconfig scans every Spring bean for @JobWorker methods, infers the typed payload from Job<T>, and starts/stops a managed worker via SmartLifecycle.
Correlation keys (businessId)
Stamp a caller-supplied correlation key (order number, ticket ID, etc.) on a new instance by passing it as the third argument to startInstance. The key is inherited by every child instance, external job, user task, and DMN execution emitted by the process — workers read it as job.businessId().
client.bpmn().startInstance(processDefId, vars, "ORDER-42");
// Filter listings by the same key.
var page = client.bpmn().listInstances(null, null, null, null, null, "ORDER-42", null, null);
var tasks = client.bpmn().listUserTasks(null, null, null, null, null, "ORDER-42", null, null);
// DMN evaluations stamp it on the resulting execution row.
client.dmn().evaluate("loan-eligibility", vars, DmnClient.withBusinessId("ORDER-42"));
External job workers (without Spring)
import com.quantumbpm.client.workers.BpmnError;
import com.quantumbpm.client.workers.Worker;
Worker worker = client.newWorker("billing-svc");
worker.handle("send-email", job -> {
String recipient = job.vars().get("recipient", String.class);
emailer.send(recipient);
return new Vars().set("messageID", "msg-123"); // → Complete
}, Worker.withMaxJobs(10), Worker.withLockDuration("1m"));
worker.start(); // returns immediately; loops on virtual threads
Runtime.getRuntime().addShutdownHook(new Thread(() -> worker.stop(15_000)));
Throw a BpmnError to fail with a code boundary error events can catch:
throw new BpmnError("INSUFFICIENT_FUNDS", new Vars().set("balance", 12.0));
Any other thrown exception is reported with the code WORKER_ERROR and the message attached as the error variable (truncated to 2048 bytes by default, raise via the maxErrorMessageBytes parameter on the Worker constructor). A boundary error event with errorRef="WORKER_ERROR" will catch it once the retry budget is exhausted — see Failure handling.
For typed dispatch outside Spring, pass the type as the second argument:
record EmailJob(String recipient, String subject) {}
worker.handle("send-email", EmailJob.class, job -> {
emailer.send(job.typed().recipient());
return new Vars();
});
Full reference
See the SDK README for the complete API surface, the Vars typed-access helpers, and the Spring Boot configuration reference.