camunda_17_external_task

external task 是 Camunda 中Service task设计非常好的一种实现, 最大程度地做到了和流程引擎的解耦. 如果我们的流程是全自动的, 甚至可以完全使用 external task实现整个流程业务处理.

本文目的

  1. 学习 SpringBoot 版external-task-client 的使用
  2. 学习普通版 external-task-client 的使用

bpmn 流程

非常简单的流程图, 仅仅包含一个Service task, 实现类型选 External.
流程图

流程bpmn xml源码:

<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_0j7gdmg" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.3.0" modeler:executionPlatform="Camunda Platform" modeler:executionPlatformVersion="7.17.0">
  <bpmn:process id="loan_process" isExecutable="true">
    <bpmn:startEvent id="StartEvent_1">
      <bpmn:outgoing>Flow_011etxb</bpmn:outgoing>
    </bpmn:startEvent>
    <bpmn:sequenceFlow id="Flow_011etxb" sourceRef="StartEvent_1" targetRef="Activity_1dbhjra" />
    <bpmn:endEvent id="Event_1weohz6">
      <bpmn:incoming>Flow_0qtyon7</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:sequenceFlow id="Flow_0qtyon7" sourceRef="Activity_1dbhjra" targetRef="Event_1weohz6" />
    <bpmn:serviceTask id="Activity_1dbhjra" name="creditScoreChecker" camunda:type="external" camunda:topic="creditScoreChecker">
      <bpmn:incoming>Flow_011etxb</bpmn:incoming>
      <bpmn:outgoing>Flow_0qtyon7</bpmn:outgoing>
    </bpmn:serviceTask>
  </bpmn:process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="loan_process">
      <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
        <dc:Bounds x="179" y="99" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Event_1weohz6_di" bpmnElement="Event_1weohz6">
        <dc:Bounds x="432" y="99" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Activity_103uall_di" bpmnElement="Activity_1dbhjra">
        <dc:Bounds x="270" y="77" width="100" height="80" />
        <bpmndi:BPMNLabel />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="Flow_011etxb_di" bpmnElement="Flow_011etxb">
        <di:waypoint x="215" y="117" />
        <di:waypoint x="270" y="117" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_0qtyon7_di" bpmnElement="Flow_0qtyon7">
        <di:waypoint x="370" y="117" />
        <di:waypoint x="432" y="117" />
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn:definitions>

Post 请求测试脚本:

POST http://localhost:8080/engine-rest/process-definition/key/loan_process/start HTTP/1.1
Content-Type: application/json

{
    "variables": {
        "amount": {
            "value":555,
            "type":"long"
        },
        "item": {
            "value": "item-xyz"
        }
    }
}

SpringBoot 版 client 测试程序

官方项目主页
官方示例项目主页

pom.xml

项目只要是标准的SpringBoot Web 项目即可, 增加下面依赖:

    <dependency>
        <groupId>org.camunda.bpm.springboot</groupId>
        <artifactId>camunda-bpm-spring-boot-starter-external-task-client</artifactId>
        <version>7.17.0</version>
    </dependency>		

application.yaml

在application.yaml 文件中声明要监听的camunda Rest API 服务器, 并设定订阅的topic, 一个项目可以订阅多个topic.

camunda.bpm.client:
  base-url: http://localhost:8080/engine-rest
  async-response-timeout: 1000 # Defines the maximum duration of the long-polling request
  worker-id: spring-boot-client # Identifies the worker towards the Engine
  #basic-auth: # Configure if REST API is secured with basic authentication
  #  username: demo
  #  password: demo  

  subscriptions:
    creditScoreChecker:    # This topic name must match the respective `@ExternalTaskSubscription`
        process-definition-key: loan_process  # Filters for External Tasks of this key
        include-extension-properties: true
        variable-names: defaultScore
        lock-duration: 10000 # Defines for how long the External Tasks are locked until they can be fetched again

External task 监听类

@Configuration
@ExternalTaskSubscription("creditScoreChecker")
public class CreditScoreCheckerHandler implements ExternalTaskHandler {

	@Override
	public void execute(ExternalTask externalTask, ExternalTaskService externalTaskService) {
		// add your business logic here
		System.out.println("CreditScoreCheckerHandler done");
		Map<String, Object> variables = new HashMap<>();
		variables.put("approved", true);
		externalTaskService.complete(externalTask,variables);
	}
}

普通 Java jar 版client 测试程序

官方项目主页
我们的项目只要是标准的 Maven 项目即可, 简单使用 camunda-external-task-client 即可改造为 Listerner 后台程序.

pom.xml

增加下面依赖:

        <dependency>
            <groupId>org.camunda.bpm</groupId>
            <artifactId>camunda-external-task-client</artifactId>
            <version>7.17.0</version>
        </dependency>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.1</version>
        </dependency>   

External task 监听类

public class ExternalTaskTest {
	private final static Logger logger = Logger.getLogger(ExternalTaskTest.class.getName());

	public static void main(String[] args) {
		logger.info("ExternalTaskClient setup");

		// bootstrap the client
		ExternalTaskClient client = ExternalTaskClient.create()
				.baseUrl("http://localhost:8080/engine-rest")
				.workerId("java-client")
				.asyncResponseTimeout(1000).build();

		// subscribe to the topic
		client.subscribe("creditScoreChecker").lockDuration(10000).handler((externalTask, externalTaskService) -> {
			Map<String, Object> variables = new HashMap<>();
			variables.put("approved", true);

			// complete the external task
			externalTaskService.complete(externalTask, variables);
			System.out.println("The External Task " + externalTask.getId() + " has been completed!");
		}).open();

		logger.info("Listening topics...");
	}
}

posted @ 2022-10-09 21:04  harrychinese  阅读(577)  评论(0编辑  收藏  举报