Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ before writing code. The hard rules:
root package, so `io.miragon.blueprint.config` would fail. Cross-cutting `@Configuration` (CORS,
OpenAPI, error handling) goes in `adapter.inbound.rest` — the `Configuration` suffix is whitelisted
there.
- **`adapter/process` is generated.** Never hand-edit `*ProcessApi.java`; edit the `.bpmn` and re-run
- **`adapter/process` is generated.** Never hand-edit `*ProcessApi.java` or the shared
`ServiceTasks`/`Messages`/`ProcessVariables`/`Errors`/`Escalations` files; edit the `.bpmn` and re-run
`./mvnw -pl service/app generate-sources`.
- **Service tasks are external topics.** A custom model rule (`ServiceTaskExternalTopicRule`) requires
every service task to be an external task with a topic — no embedded delegates. The trade-offs
Expand All @@ -81,6 +82,8 @@ before writing code. The hard rules:

- `bpmn-to-code` generates typed process constants from the models at build time; a custom model
test requires every service task to be an external task with a topic.
- Since bpmn-to-code 6 the API is node-centric: `<Process>ProcessApi.FlowNodes.<Node>` carries the
element (`ELEMENT_ID`, `INSTANCE`), its `Variables` and its successors (`Next`).
- `bpmnlint` tooling lives at the **repo root** (`package.json`, `.bpmnlintrc`): `npm ci && npm run
lint:bpmn`. It also runs on staged `.bpmn` via `.githooks/pre-commit` (install: `npm run hooks:install`).

Expand Down
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,11 @@ docs/{README.md, adr/, assets/} ADR index + records + the process diagram
- **Stack:** Java 21 · Spring Boot 4 · Operaton 2.1 (embedded) · process-engine-api (bpm-crafters) · PostgreSQL · Maven
multi-module (`./mvnw`), versions centralized in the root `pom.xml`.
- **Generated process API:** the [`bpmn-to-code`](https://github.com/emaarco/bpmn-to-code) Maven
plugin turns each `.bpmn` into a typed `*ProcessApi` class, so element ids, messages, timers and
variables are compile-checked constants used by both delegates and tests.
plugin turns each `.bpmn` into a typed `*ProcessApi` class plus shared `ServiceTasks`, `Messages`,
`ProcessVariables`, `Errors` and `Escalations` files. Since 6.x the API is node-centric:
`<Process>ProcessApi.FlowNodes.<Node>` carries the element id (`ELEMENT_ID`), its `Variables` and its
successors (`Next`), so element ids, messages, timers and variables are compile-checked constants used
by both workers and tests.
- **Forms:** Camunda Forms (`.form`) are deployed with the process and render in the Operaton
Tasklist/Cockpit for the user tasks.
- **BPMN linting:** [`bpmnlint`](https://github.com/bpmn-io/bpmnlint) (`bpmnlint:recommended` plus
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
<!-- 3.x is the Spring Boot 4 line; 3.1.0 is built against Spring Boot 4.1.0. -->
<springdoc.version>3.1.1</springdoc.version>
<!-- Maven plugin, runtime and testing library deliberately aligned on one release. -->
<bpmn-to-code.version>5.2.0</bpmn-to-code.version>
<bpmn-to-code.version>6.6.1</bpmn-to-code.version>
<archunit.version>1.5.1</archunit.version>
<!-- pitest-maven version == PIT engine version; pinned so the mutation baseline stays comparable. -->
<pitest.version>1.30.0</pitest.version>
Expand Down
5 changes: 5 additions & 0 deletions service/app/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,11 @@
<failWhenNoMutations>false</failWhenNoMutations>
<excludedClasses>
<param>io.miragon.blueprint.adapter.process.*ProcessApi*</param>
<param>io.miragon.blueprint.adapter.process.ServiceTasks*</param>
<param>io.miragon.blueprint.adapter.process.Messages*</param>
<param>io.miragon.blueprint.adapter.process.ProcessVariables*</param>
<param>io.miragon.blueprint.adapter.process.Errors*</param>
<param>io.miragon.blueprint.adapter.process.Escalations*</param>
<param>io.miragon.blueprint.adapter.process.HistoryCleanupConfiguration*</param>
<param>io.miragon.blueprint.adapter.process.EngineApiConfiguration*</param>
<param>io.miragon.blueprint.OperatonBikeLeasingApplication*</param>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import dev.bpmcrafters.processengine.worker.ProcessEngineWorker;
import dev.bpmcrafters.processengine.worker.Variable;
import io.miragon.blueprint.adapter.process.BikeLeasingProcessProcessApi.ServiceTasks;
import io.miragon.blueprint.adapter.process.ServiceTasks;
import io.miragon.blueprint.application.port.inbound.ActivateLeasingUseCase;
import io.miragon.blueprint.domain.leasing.ApplicationId;
import org.springframework.stereotype.Component;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import dev.bpmcrafters.processengine.worker.ProcessEngineWorker;
import dev.bpmcrafters.processengine.worker.Variable;
import io.miragon.blueprint.adapter.process.CancelBikeOrderProcessApi.ServiceTasks;
import io.miragon.blueprint.adapter.process.ServiceTasks;
import io.miragon.blueprint.application.port.inbound.BookCancellationCostsUseCase;
import io.miragon.blueprint.domain.bike.OrderId;
import org.springframework.stereotype.Component;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import dev.bpmcrafters.processengine.worker.ProcessEngineWorker;
import dev.bpmcrafters.processengine.worker.Variable;
import io.miragon.blueprint.adapter.process.BikeLeasingProcessProcessApi.ServiceTasks;
import io.miragon.blueprint.adapter.process.ServiceTasks;
import io.miragon.blueprint.application.port.inbound.CancelContractUseCase;
import io.miragon.blueprint.domain.leasing.ApplicationId;
import org.springframework.stereotype.Component;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import dev.bpmcrafters.processengine.worker.ProcessEngineWorker;
import dev.bpmcrafters.processengine.worker.Variable;
import io.miragon.blueprint.adapter.process.BikeLeasingProcessProcessApi.ServiceTasks;
import io.miragon.blueprint.adapter.process.ServiceTasks;
import io.miragon.blueprint.application.port.inbound.CancelInsurancePolicyUseCase;
import io.miragon.blueprint.domain.leasing.ApplicationId;
import org.springframework.stereotype.Component;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import dev.bpmcrafters.processengine.worker.ProcessEngineWorker;
import dev.bpmcrafters.processengine.worker.Variable;
import io.miragon.blueprint.adapter.process.BikeLeasingProcessProcessApi.ServiceTasks;
import io.miragon.blueprint.adapter.process.ServiceTasks;
import io.miragon.blueprint.application.port.inbound.IssueInsurancePolicyUseCase;
import io.miragon.blueprint.domain.leasing.ApplicationId;
import org.springframework.stereotype.Component;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
import dev.bpmcrafters.processengine.worker.BpmnErrorOccurred;
import dev.bpmcrafters.processengine.worker.ProcessEngineWorker;
import dev.bpmcrafters.processengine.worker.Variable;
import io.miragon.blueprint.adapter.process.BikeLeasingProcessProcessApi.Errors;
import io.miragon.blueprint.adapter.process.BikeLeasingProcessProcessApi.ServiceTasks;
import io.miragon.blueprint.adapter.process.BikeLeasingProcessProcessApi.Variables;
import io.miragon.blueprint.adapter.process.Errors;
import io.miragon.blueprint.adapter.process.ServiceTasks;
import io.miragon.blueprint.adapter.process.BikeLeasingProcessProcessApi.FlowNodes;
import io.miragon.blueprint.application.port.inbound.OrderBikeUseCase;
import io.miragon.blueprint.domain.bike.BikeId;
import io.miragon.blueprint.domain.bike.BikeUnavailableException;
Expand Down Expand Up @@ -34,7 +34,7 @@ public Map<String, Object> orderBike(@Variable String applicationId, @Variable S
throws BpmnErrorOccurred {
try {
OrderId orderId = useCase.orderBike(ApplicationId.of(applicationId), new BikeId(bikeId));
return Map.of(Variables.ServiceTaskOrderBike.ORDER_ID.getValue(), orderId.value());
return Map.of(FlowNodes.ServiceTaskOrderBike.Variables.ORDER_ID.getValue(), orderId.value());
} catch (BikeUnavailableException e) {
throw new BpmnErrorOccurred(e.getMessage(), Errors.BIKE_UNAVAILABLE.getCode(), Map.of());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import dev.bpmcrafters.processengine.worker.ProcessEngineWorker;
import dev.bpmcrafters.processengine.worker.Variable;
import io.miragon.blueprint.adapter.process.CancelBikeOrderProcessApi.ServiceTasks;
import io.miragon.blueprint.adapter.process.CancelBikeOrderProcessApi.Variables;
import io.miragon.blueprint.adapter.process.ServiceTasks;
import io.miragon.blueprint.adapter.process.CancelBikeOrderProcessApi.FlowNodes;
import io.miragon.blueprint.application.port.inbound.RequestOrderCancellationUseCase;
import io.miragon.blueprint.domain.bike.OrderId;
import java.util.Map;
Expand All @@ -25,6 +25,6 @@ public RequestCancellationWorker(RequestOrderCancellationUseCase useCase) {
@ProcessEngineWorker(topic = ServiceTasks.REQUEST_CANCELLATION)
public Map<String, Object> requestCancellation(@Variable String orderId) {
boolean cancellationPossible = useCase.requestCancellation(new OrderId(orderId));
return Map.of(Variables.ServiceTaskRequestCancellation.CANCELLATION_POSSIBLE.getValue(), cancellationPossible);
return Map.of(FlowNodes.ServiceTaskRequestCancellation.Variables.CANCELLATION_POSSIBLE.getValue(), cancellationPossible);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import dev.bpmcrafters.processengine.worker.ProcessEngineWorker;
import dev.bpmcrafters.processengine.worker.Variable;
import io.miragon.blueprint.adapter.process.BikeLeasingProcessProcessApi.ServiceTasks;
import io.miragon.blueprint.adapter.process.ServiceTasks;
import io.miragon.blueprint.application.port.inbound.SendCancellationConfirmationUseCase;
import io.miragon.blueprint.domain.leasing.ApplicationId;
import org.springframework.stereotype.Component;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import dev.bpmcrafters.processengine.worker.ProcessEngineWorker;
import dev.bpmcrafters.processengine.worker.Variable;
import io.miragon.blueprint.adapter.process.BikeLeasingProcessProcessApi.ServiceTasks;
import io.miragon.blueprint.adapter.process.ServiceTasks;
import io.miragon.blueprint.application.port.inbound.SendContractUseCase;
import io.miragon.blueprint.domain.leasing.ApplicationId;
import org.springframework.stereotype.Component;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import dev.bpmcrafters.processengine.worker.ProcessEngineWorker;
import dev.bpmcrafters.processengine.worker.Variable;
import io.miragon.blueprint.adapter.process.BikeLeasingProcessProcessApi.ServiceTasks;
import io.miragon.blueprint.adapter.process.ServiceTasks;
import io.miragon.blueprint.application.port.inbound.RejectApplicationUseCase;
import io.miragon.blueprint.domain.leasing.ApplicationId;
import org.springframework.stereotype.Component;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import dev.bpmcrafters.processengine.worker.ProcessEngineWorker;
import dev.bpmcrafters.processengine.worker.Variable;
import io.miragon.blueprint.adapter.process.BikeLeasingProcessProcessApi.ServiceTasks;
import io.miragon.blueprint.adapter.process.ServiceTasks;
import io.miragon.blueprint.application.port.inbound.SendSignatureReminderUseCase;
import io.miragon.blueprint.domain.leasing.ApplicationId;
import org.springframework.stereotype.Component;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@
import dev.bpmcrafters.processengineapi.task.TaskInformation;
import dev.bpmcrafters.processengineapi.task.UserTaskCompletionApi;
import dev.bpmcrafters.processengineapi.task.support.UserTaskSupport;
import io.miragon.blueprint.adapter.process.BikeLeasingProcessProcessApi.Elements;
import io.miragon.blueprint.adapter.process.BikeLeasingProcessProcessApi.Messages;
import io.miragon.blueprint.adapter.process.BikeLeasingProcessProcessApi.Variables;
import io.miragon.blueprint.adapter.process.BikeLeasingProcessProcessApi.FlowNodes;
import io.miragon.blueprint.adapter.process.Messages;
import io.miragon.blueprint.application.port.outbound.LeasingProcess;
import io.miragon.blueprint.domain.bike.BikeId;
import io.miragon.blueprint.domain.leasing.ApplicationId;
Expand Down Expand Up @@ -60,11 +59,11 @@ public LeasingProcessAdapter(
public void submitRequest(LeasingApplication application) {
var key = application.id().value().toString();
var payload = new HashMap<String, Object>();
payload.put(Variables.StartEventLeasingRequestReceived.APPLICATION_ID.getValue(), key);
payload.put(Variables.StartEventLeasingRequestReceived.BIKE_ID.getValue(), application.bikeId().value());
payload.put(Variables.StartEventLeasingRequestReceived.MONTHLY_NET_INCOME.getValue(),
payload.put(FlowNodes.StartEventLeasingRequestReceived.Variables.APPLICATION_ID.getValue(), key);
payload.put(FlowNodes.StartEventLeasingRequestReceived.Variables.BIKE_ID.getValue(), application.bikeId().value());
payload.put(FlowNodes.StartEventLeasingRequestReceived.Variables.MONTHLY_NET_INCOME.getValue(),
application.monthlyNetIncome());
payload.put(Variables.StartEventLeasingRequestReceived.AGE.getValue(), application.age());
payload.put(FlowNodes.StartEventLeasingRequestReceived.Variables.AGE.getValue(), application.age());
// Preserve the engine business key and seed the global correlation variable.
payload.put(CommonRestrictions.BUSINESS_KEY, key);
payload.put(CommonRestrictions.CORRELATION_KEY, key);
Expand Down Expand Up @@ -125,9 +124,9 @@ private void correlate(String messageName, ApplicationId id) {
public void completeAlternativeClarification(ApplicationId id, boolean alternativeFound, @Nullable BikeId bikeId) {
var taskId = awaitClarifyAlternativeTaskId(id);
var variables = new HashMap<String, Object>();
variables.put(Variables.UserTaskClarifyAlternative.ALTERNATIVE_FOUND.getValue(), alternativeFound);
variables.put(FlowNodes.UserTaskClarifyAlternative.Variables.ALTERNATIVE_FOUND.getValue(), alternativeFound);
if (bikeId != null) {
variables.put(Variables.UserTaskClarifyAlternative.BIKE_ID.getValue(), bikeId.value());
variables.put(FlowNodes.UserTaskClarifyAlternative.Variables.BIKE_ID.getValue(), bikeId.value());
}
userTaskCompletionApi.completeTask(new CompleteTaskCmd(taskId, variables)).join();
}
Expand All @@ -138,10 +137,10 @@ public void completeAlternativeClarification(ApplicationId id, boolean alternati
*/
private String awaitClarifyAlternativeTaskId(ApplicationId id) {
var applicationId = id.value().toString();
var applicationIdKey = Variables.StartEventLeasingRequestReceived.APPLICATION_ID.getValue();
var applicationIdKey = FlowNodes.StartEventLeasingRequestReceived.Variables.APPLICATION_ID.getValue();
for (int attempt = 0; attempt < TASK_LOOKUP_ATTEMPTS; attempt++) {
var task = userTaskSupport.getAllTasks().stream()
.filter(it -> Elements.USER_TASK_CLARIFY_ALTERNATIVE.getValue()
.filter(it -> FlowNodes.UserTaskClarifyAlternative.ELEMENT_ID
.equals(it.getMeta().get(CommonRestrictions.ACTIVITY_ID)))
.filter(it -> belongsToApplication(it, applicationIdKey, applicationId))
.findFirst()
Expand All @@ -152,7 +151,7 @@ private String awaitClarifyAlternativeTaskId(ApplicationId id) {
sleep(TASK_LOOKUP_INTERVAL_MS);
}
throw new IllegalStateException(
"No open '" + Elements.USER_TASK_CLARIFY_ALTERNATIVE.getValue() + "' task for application "
"No open '" + FlowNodes.UserTaskClarifyAlternative.ELEMENT_ID + "' task for application "
+ applicationId);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.miragon.blueprint.adapter.outbound.operaton;

import io.miragon.blueprint.adapter.process.BikeLeasingProcessProcessApi.Elements;
import io.miragon.blueprint.adapter.process.BikeLeasingProcessProcessApi.FlowNodes;
import io.miragon.blueprint.application.port.outbound.TaskInboxPort;
import io.miragon.blueprint.domain.leasing.ApplicationId;
import java.time.ZoneId;
Expand Down Expand Up @@ -38,7 +38,7 @@ public TaskInboxAdapter(TaskService taskService, RuntimeService runtimeService)

@Override
public List<TaskInboxPort.OpenClarification> findOpenClarifications() {
var tasks = findOpenTasks(Elements.USER_TASK_CLARIFY_ALTERNATIVE.getValue());
var tasks = findOpenTasks(FlowNodes.UserTaskClarifyAlternative.ELEMENT_ID);
var businessKeys = businessKeysById(tasks.stream().map(Task::getProcessInstanceId).toList());
var clarifications = new ArrayList<TaskInboxPort.OpenClarification>();
for (var task : tasks) {
Expand Down
Loading
Loading