You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何追踪Camunda流程执行?从Java API获取执行路径对接bpmn.io展示

Hey there! I’ve tackled similar integration challenges with Camunda embedded in Java apps and bpmn.io for visualization, so let’s break down how to solve this step by step.

1. Fetching Execution Path Data via Camunda Java API

The core challenge here is pulling the right data from Camunda’s runtime and history services to map out completed, active, and failed process elements. Here’s how to approach each piece:

Get Completed Activities & Tasks

Camunda’s HistoryService lets you query finished activities (including user tasks and automated steps like service tasks):

// Fetch completed user tasks
List<HistoricTaskInstance> completedTasks = historyService.createHistoricTaskInstanceQuery()
    .processInstanceId(processInstanceId)
    .finished()
    .list();

// Fetch completed automated activities (service tasks, gateways, etc.)
List<HistoricActivityInstance> completedActivities = historyService.createHistoricActivityInstanceQuery()
    .processInstanceId(processInstanceId)
    .finished()
    .excludeTaskInstances() // Exclude tasks we already fetched above
    .list();

Get Current Active Tasks/Activities

Use RuntimeService to find active execution nodes in the process:

List<Execution> currentExecutions = runtimeService.createExecutionQuery()
    .processInstanceId(processInstanceId)
    .active()
    .list();

// For user tasks specifically, you can also use TaskService
List<Task> currentTasks = taskService.createTaskQuery()
    .processInstanceId(processInstanceId)
    .active()
    .list();

Get Failed Tasks/Activities

Identify failed elements using incident and failure status filters:

// Failed user tasks
List<HistoricTaskInstance> failedTasks = historyService.createHistoricTaskInstanceQuery()
    .processInstanceId(processInstanceId)
    .failed()
    .list();

// Automated activities with incidents (e.g., failed service tasks)
List<HistoricActivityInstance> failedActivities = historyService.createHistoricActivityInstanceQuery()
    .processInstanceId(processInstanceId)
    .withIncidents()
    .list();

Derive Completed Sequence Flows (Connectors)

Camunda doesn’t directly log sequence flow execution, but you can infer it using the process model and activity order:

  1. Fetch the BPMN model instance for the process definition
  2. Sort completed activities by end time to get execution order
  3. For each consecutive pair of activities, find the sequence flow that connects them in the model
BpmnModelInstance modelInstance = repositoryService.getBpmnModelInstance(processDefinitionId);

// Sort completed activities by end time to maintain execution order
completedActivities.sort(Comparator.comparing(HistoricActivityInstance::getEndTime));

List<String> completedSequenceFlowIds = new ArrayList<>();
for (int i = 0; i < completedActivities.size() - 1; i++) {
    HistoricActivityInstance current = completedActivities.get(i);
    HistoricActivityInstance next = completedActivities.get(i + 1);

    // Find the outgoing sequence flows from the current activity
    BaseElement currentElement = modelInstance.getModelElementById(current.getActivityId());
    if (currentElement instanceof FlowNode) {
        Collection<SequenceFlow> outgoingFlows = ((FlowNode) currentElement).getOutgoing();
        // Check which flow points to the next activity
        for (SequenceFlow flow : outgoingFlows) {
            if (flow.getTargetRef().getId().equals(next.getActivityId())) {
                completedSequenceFlowIds.add(flow.getId());
                break;
            }
        }
    }
}

2. Expose Data via a Custom API

Wrap the fetched data into a clean DTO and expose it via a REST endpoint (using Spring Boot as an example):

Define a Response DTO

public class ProcessVisualizationData {
    private List<String> completedElementIds;
    private List<String> currentElementIds;
    private List<String> failedElementIds;
    private List<String> completedSequenceFlowIds;

    // Getters and setters
}

Create a REST Controller

@RestController
@RequestMapping("/api/process")
public class ProcessVisualizationController {

    @Autowired
    private HistoryService historyService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private RepositoryService repositoryService;

    @GetMapping("/{processInstanceId}/visualization")
    public ResponseEntity<ProcessVisualizationData> getProcessVisualizationData(
            @PathVariable String processInstanceId) {

        ProcessVisualizationData data = new ProcessVisualizationData();
        // Populate data using the queries and sequence flow logic from section 1
        // ...

        return ResponseEntity.ok(data);
    }
}

3. Frontend Highlighting with bpmn.io

Once you fetch the data from your API, use bpmn.io’s API to apply color coding to elements:

// Initialize bpmn.io viewer
const viewer = new BpmnJS({ container: '#process-canvas' });

// Fetch your BPMN XML and visualization data from the API
fetch('/api/process/{processInstanceId}/visualization')
    .then(res => res.json())
    .then(visualizationData => {
        fetch('/api/process/{processDefinitionId}/bpmn') // Fetch your BPMN XML
            .then(res => res.text())
            .then(bpmnXml => {
                viewer.importXML(bpmnXml, (err) => {
                    if (!err) {
                        const canvas = viewer.get('canvas');
                        const elementRegistry = viewer.get('elementRegistry');

                        // Highlight completed elements and flows
                        visualizationData.completedElementIds.forEach(id => {
                            const element = elementRegistry.get(id);
                            if (element) {
                                canvas.setColor(element, { fill: '#b8e986', stroke: '#86b94b' });
                            }
                        });
                        visualizationData.completedSequenceFlowIds.forEach(id => {
                            const flow = elementRegistry.get(id);
                            if (flow) {
                                canvas.setColor(flow, { stroke: '#86b94b', strokeWidth: 2 });
                            }
                        });

                        // Highlight current active elements
                        visualizationData.currentElementIds.forEach(id => {
                            const element = elementRegistry.get(id);
                            if (element) {
                                canvas.setColor(element, { fill: '#4a90e2', stroke: '#2563eb' });
                                canvas.addMarker(element, 'current'); // Add a pulse animation via CSS
                            }
                        });

                        // Highlight failed elements
                        visualizationData.failedElementIds.forEach(id => {
                            const element = elementRegistry.get(id);
                            if (element) {
                                canvas.setColor(element, { fill: '#f5a623', stroke: '#d39200' });
                            }
                        });
                    }
                });
            });
    });

Add CSS for extra visual cues:

.bpmn-element.current {
    animation: pulse 2s infinite;
}

@keyframes pulse {
    0% { box-shadow: 0 0 0 0 rgba(37, 99, 235, 0.4); }
    70% { box-shadow: 0 0 0 10px rgba(37, 99, 235, 0); }
    100% { box-shadow: 0 0 0 0 rgba(37, 99, 235, 0); }
}

Key Notes to Keep in Mind

  • Sequence Flow Inference: Since Camunda doesn’t log sequence flows directly, make sure to handle gateways carefully—you may need to check execution variables to determine which path was taken for exclusive/inclusive gateways.
  • Element Types: Remember that user tasks and automated activities are stored in different Camunda entities (HistoricTaskInstance vs HistoricActivityInstance), so your queries need to cover both.
  • Incident Handling: For failed automated activities, use withIncidents() to catch elements that threw errors but weren’t marked as "failed" in the task query.

内容的提问来源于stack exchange,提问作者BudJB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:46:00