Camunda ScriptTask SendTask ReceiveTask操作

news2024/12/23 6:28:56

文章目录

  • 开始
  • 脚本任务(ScriptTask)
  • 发送任务(SendTask)
  • 接收任务(ReceiveTask)
  • 流程图xml

开始

前面我们已经介绍了Camunda最基本的操作和常见的监听器,如果不熟悉Camunda,可以先看一下,方便搭建环境,亲手测试。

Camunda组件与服务与基本操作

Camunda中强大的监听服务

本篇将简单介绍Camunda的Script Task、Send Task、Receive Task。

熟悉这些Task,可以帮我们更好理解Camunda流程。

脚本任务(ScriptTask)

脚本任务

Format:JavaScript

Type:Inline script

execution.setVariable("pa", "javascript");

如果启动流程发现:Can’t find scripting engine for ‘javascript’: scriptEngine is null

可以加入下面的依赖:

<dependency>
    <groupId>org.graalvm.js</groupId>
    <artifactId>js</artifactId>
    <version>23.0.3</version>
</dependency>
<dependency>
    <groupId>org.graalvm.js</groupId>
    <artifactId>js-scriptengine</artifactId>
    <version>23.0.3</version>
</dependency>

除了JavaScript,还可以使用Python、Groovy、Ruby等,得添加相关的依赖。

尽量不要在脚本中实现复杂的逻辑,调试起来比较麻烦,排查问题也痛苦。

发送任务(SendTask)

发送任务

发送任务Send Task和我们之前介绍的Service Task差不多。

可以配置为Java Class然后实现JavaDelegate类。

在实现类中可以获取相关信息,例如:上一个脚本节点设置的参数。

import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.delegate.JavaDelegate;

public class SendTaskJavaDelegate implements JavaDelegate {

    @Override
    public void execute(DelegateExecution delegateExecution) {
        System.out.println(SendTaskJavaDelegate.class.getName() + "--start");

        System.out.println("获取参数:" + delegateExecution.getVariable("pa"));
        System.out.println("getId:" + delegateExecution.getId());
        System.out.println("getProcessInstanceId:" + delegateExecution.getProcessInstanceId());
        System.out.println("getActivityInstanceId:" + delegateExecution.getActivityInstanceId());
        System.out.println("getCurrentActivityId:" + delegateExecution.getCurrentActivityId());
        System.out.println("getCurrentActivityName:" + delegateExecution.getCurrentActivityName());
        System.out.println("getProcessBusinessKey:" + delegateExecution.getProcessBusinessKey());
        System.out.println("getProcessDefinitionId:" + delegateExecution.getProcessDefinitionId());
        System.out.println("getBusinessKey:" + delegateExecution.getBusinessKey());
        System.out.println("getEventName:" + delegateExecution.getEventName());
        System.out.println(SendTaskJavaDelegate.class.getName() + "--end");
    }
}
com.example.workflow.delegate.SendTaskJavaDelegate--start
获取参数:javascript
getId:1fbafcb1-c0ac-11ee-b7bf-00ffe7687986
getProcessInstanceId:1fbafcb1-c0ac-11ee-b7bf-00ffe7687986
getActivityInstanceId:Activity_0xcgnyl:2053ba46-c0ac-11ee-b7bf-00ffe7687986
getCurrentActivityId:Activity_0xcgnyl
getCurrentActivityName:发送任务
getProcessBusinessKey:task0002
getProcessDefinitionId:Process_0btcu4b:2:ca1b15a6-c0aa-11ee-8ced-00ffe7687986
getBusinessKey:task0002
getEventName:null
com.example.workflow.delegate.SendTaskJavaDelegate--end

接收任务(ReceiveTask)

接收任务节点可以用来阻塞节点往下执行,比如等一个外部任务完成。

有例如,一个节点必须依赖另一个节点完成,就可以在节点前添加一个接收任务节点,等其他节点完成之后,通过接收任务节点继续往下走。

接收任务

可以根据activityId来查询任务executionId

@Test
public void queryExecutionId() {
    String activityId = "Activity_1nu3d7a";
    Execution execution = runtimeService.createExecutionQuery()
            .activityId(activityId).singleResult();
    System.out.println(execution);
}
select * from act_hi_actinst where ACT_ID_ ='Activity_1nu3d7a';

然后通过executionId来通知接收消息的节点,不用等了,可以到下一个节点了。

@Test
public void signal() {
    String executionId = "2054cbb7-c0ac-11ee-b7bf-00ffe7687986";
    runtimeService.signal(executionId);
}

除了signal,还可以correlateMessage来通知Receive Task完成:

@Test
public void correlateMessage() {
    String messageName = "Message_0ud6hg1";
    runtimeService.correlateMessage(messageName);
}

消息也可以是中文:

@Test
public void correlate() {
    String messageName = "消息2";
    MessageCorrelationBuilder messageCorrelation =
            runtimeService.createMessageCorrelation(messageName);
    messageCorrelation.correlate();
}

完整的测试用例:

import jakarta.annotation.Resource;
import org.camunda.bpm.engine.RuntimeService;
import org.camunda.bpm.engine.runtime.Execution;
import org.camunda.bpm.engine.runtime.MessageCorrelationBuilder;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;


@SpringBootTest
class ApplicationTest {

    @Resource
    private RuntimeService runtimeService;

    @Test
    public void queryExecutionId() {
        String activityId = "Activity_1nu3d7a";
        Execution execution = runtimeService.createExecutionQuery()
                .activityId(activityId).singleResult();
        System.out.println(execution);
    }

    @Test
    public void signal() {
        String executionId = "2054cbb7-c0ac-11ee-b7bf-00ffe7687986";
        runtimeService.signal(executionId);
    }

    @Test
    public void correlateMessage() {
        String messageName = "Message_0ud6hg1";
        runtimeService.correlateMessage(messageName);
    }

    @Test
    public void correlate() {
        String messageName = "消息2";
        MessageCorrelationBuilder messageCorrelation =
                runtimeService.createMessageCorrelation(messageName);
        messageCorrelation.correlate();
    }
}

记得添加依赖,不要加错了,不然执行不了。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
</dependency>

流程图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_18zyppt" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.19.0" modeler:executionPlatform="Camunda Platform" modeler:executionPlatformVersion="7.20.0">
  <bpmn:process id="Process_0btcu4b" name="任务测试" isExecutable="true" camunda:historyTimeToLive="180">
    <bpmn:startEvent id="StartEvent_1">
      <bpmn:outgoing>Flow_0x6f2m3</bpmn:outgoing>
    </bpmn:startEvent>
    <bpmn:sequenceFlow id="Flow_0x6f2m3" sourceRef="StartEvent_1" targetRef="Activity_08nl9jt" />
    <bpmn:scriptTask id="Activity_08nl9jt" name="脚本任务" scriptFormat="JavaScript">
      <bpmn:incoming>Flow_0x6f2m3</bpmn:incoming>
      <bpmn:outgoing>Flow_1kkp455</bpmn:outgoing>
      <bpmn:script>execution.setVariable("pa", "javascript");</bpmn:script>
    </bpmn:scriptTask>
    <bpmn:sequenceFlow id="Flow_1kkp455" sourceRef="Activity_08nl9jt" targetRef="Activity_0xcgnyl" />
    <bpmn:sendTask id="Activity_0xcgnyl" name="发送任务" camunda:class="com.example.workflow.delegate.SendTaskJavaDelegate">
      <bpmn:incoming>Flow_1kkp455</bpmn:incoming>
      <bpmn:outgoing>Flow_0gw8gq5</bpmn:outgoing>
    </bpmn:sendTask>
    <bpmn:sequenceFlow id="Flow_0gw8gq5" sourceRef="Activity_0xcgnyl" targetRef="Activity_1nu3d7a" />
    <bpmn:receiveTask id="Activity_1nu3d7a" name="接收任务" messageRef="Message_13j3si4">
      <bpmn:incoming>Flow_0gw8gq5</bpmn:incoming>
      <bpmn:outgoing>Flow_09l62nk</bpmn:outgoing>
    </bpmn:receiveTask>
    <bpmn:sequenceFlow id="Flow_09l62nk" sourceRef="Activity_1nu3d7a" targetRef="Activity_1oedt3n" />
    <bpmn:userTask id="Activity_1oedt3n" name="用户任务">
      <bpmn:incoming>Flow_09l62nk</bpmn:incoming>
      <bpmn:outgoing>Flow_1yorrvs</bpmn:outgoing>
    </bpmn:userTask>
    <bpmn:endEvent id="Event_1o1zu4l">
      <bpmn:incoming>Flow_1yorrvs</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:sequenceFlow id="Flow_1yorrvs" sourceRef="Activity_1oedt3n" targetRef="Event_1o1zu4l" />
  </bpmn:process>
  <bpmn:message id="Message_3n3k1s8" name="消息1" />
  <bpmn:message id="Message_13j3si4" name="消息2" />
  <bpmn:message id="Message_0ud6hg1" name="Message_0ud6hg1" />
  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_0btcu4b">
      <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
        <dc:Bounds x="149" y="99" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Activity_0slvat5_di" bpmnElement="Activity_08nl9jt">
        <dc:Bounds x="220" y="77" width="100" height="80" />
        <bpmndi:BPMNLabel />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Activity_1obj6uy_di" bpmnElement="Activity_0xcgnyl">
        <dc:Bounds x="360" y="77" width="100" height="80" />
        <bpmndi:BPMNLabel />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Activity_1gz5v9p_di" bpmnElement="Activity_1nu3d7a">
        <dc:Bounds x="250" y="210" width="100" height="80" />
        <bpmndi:BPMNLabel />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Activity_0k177dl_di" bpmnElement="Activity_1oedt3n">
        <dc:Bounds x="410" y="210" width="100" height="80" />
        <bpmndi:BPMNLabel />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Event_1o1zu4l_di" bpmnElement="Event_1o1zu4l">
        <dc:Bounds x="572" y="232" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="Flow_0x6f2m3_di" bpmnElement="Flow_0x6f2m3">
        <di:waypoint x="185" y="117" />
        <di:waypoint x="220" y="117" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_1kkp455_di" bpmnElement="Flow_1kkp455">
        <di:waypoint x="320" y="117" />
        <di:waypoint x="360" y="117" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_0gw8gq5_di" bpmnElement="Flow_0gw8gq5">
        <di:waypoint x="410" y="157" />
        <di:waypoint x="410" y="184" />
        <di:waypoint x="300" y="184" />
        <di:waypoint x="300" y="210" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_09l62nk_di" bpmnElement="Flow_09l62nk">
        <di:waypoint x="350" y="250" />
        <di:waypoint x="410" y="250" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_1yorrvs_di" bpmnElement="Flow_1yorrvs">
        <di:waypoint x="510" y="250" />
        <di:waypoint x="572" y="250" />
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn:definitions>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1425137.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

轻量式RPC调用日志链路设计方案

导语: 调用链跟踪系统,又称为tracing&#xff0c;是微服务设计架构中&#xff0c;从系统层面对整体的monitoring和profiling的一种技术手 背景说明 由于我们的项目是微服务方向&#xff0c;中后台服务调用链路过深&#xff0c;追踪路径过长&#xff0c;其中某个服务报错或者异…

YOLOv5改进芒果首发:24年最新论文Shift-ConvNets:稀疏/移位操作让小卷积核也能达到大卷积核效果,来打造新颖YOLOv5检测器

💡本篇内容:YOLOv5改进芒果首发:24年最新论文Shift-ConvNets:稀疏/移位操作让小卷积核也能达到大卷积核效果,来打造新颖YOLOv5检测器 💡附改进源代码及教程,用来改进作为 🚀改进Shift-ConvNets 深圳大学出品!!24年最新论文 Shift-ConvNets地址:https://arxiv.o…

c/c++串的链式操作

文章目录 1.链式串的定义2.初始化3.赋值为04.赋值操作5.打印操作6.源码 本篇博客中都是带头结点的串。 1.链式串的定义 这里的数据域是4个字节&#xff0c;是为了节省空间。 typedef struct StringNode{char ch[4]; //按串长分配存储区&#xff0c;ch指向串的基地址struct S…

史诗级详细离线更新centos系统的openssh,升级到9.3p1!!

离线更新openssh步骤 文章目录 前言一、openssh是什么?二、更新步骤 1.查看相关组件版本是否存在(代码包已全部打包)2.进行openssh离线更新总结(安装时可能出现的问题等)前言 对于可能很多人在离线更新openssh时都没找到一篇能解决实际问题的文章,那么今天它来了,请往下看…

安卓相对布局RelativeLayout

<?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"150dp"><TextViewandroid…

PostgreSql和Oracle的事务机制区别以及对程序的影响

前言 几年前IT信息产业的一些核心技术包括架构、产品以及生态都是国外制定&#xff0c;然而自从“遥遥领先”公司被制裁后&#xff0c;国家开始大力支持信息产业“新基建”&#xff0c;自2020年开始市场上涌现出了大量的国产化软件&#xff0c;就国产化数据库而言我所在的公司…

vue2+html2pdf下载PDF,PDF分页切割

问题: PDF下载下来后,文档内容被暴力分割。 解决方案: HTML <!-- 打印按钮 --> <el-button type="primary" size="small" class="el-icon-download right_btn" @click="downloadPDF">PDF</el-button><!-- …

Windows存储空间不足局域网文件共享 Dism备份系统空间不足

问题情景 在日常使用中难免遇到Windows的空间不足的情况&#xff0c;常用办法是清理垃圾释放空间&#xff0c;部分场景例如我们需要使用Dism备份完整系统&#xff0c;所以需要非常大的存储空间不够&#xff0c;如果空间不够什么才是最有效的方案呢&#xff1f; 我们假设身边没有…

字符串转换const char* , char*,QByteArray,QString,string相互转换,支持中文

文章目录 1.char * 与 const char * 的转换2.QByteArray 与 char* 的转换3.QString 与 QByteArray 的转换4.QString 与 string 的转换5.QString与const string 的转换6.QString 与 char* 的转换 在开发中&#xff0c;经常会遇到需要将数据类型进行转换的情况&#xff0c;下面依…

伪原创生成器手机版,移动端上写文章更方便!

伪原创生成器虽然不少&#xff0c;但我们大家见到最多的还是电脑使用版&#xff0c;然而提及到伪原创生成器手机版的资源却不是那么多&#xff0c;特别是对于现在手机端也成为了大家办公的一大途径&#xff0c;这主要也是因为手机的便携性&#xff0c;它可以做到让大家随时随地…

【图例】直观的感受MySQL事务的隔离级别分别解决了什么问题?以及如何查看和设置事务隔离级别!

目录 前言一、读未提交&#xff08;Read Uncommitted&#xff09;二、读已提交&#xff08;Read Committed&#xff09;三、可重复读&#xff08;Repeatable Read&#xff09;四、串行化&#xff08;Serializable&#xff09; 前言 在MySQL中&#xff0c;事务的隔离级别决定了…

如何本地搭建Emby影音管理服务并结合内网穿透实现远程访问本地影音库

文章目录 1.前言2. Emby网站搭建2.1. Emby下载和安装2.2 Emby网页测试 3. 本地网页发布3.1 注册并安装cpolar内网穿透3.2 Cpolar云端设置3.3 Cpolar内网穿透本地设置 4.公网访问测试5.结语 1.前言 在现代五花八门的网络应用场景中&#xff0c;观看视频绝对是主力应用场景之一&…

UE4 C++ 结构体

先在UCLASS()前写入&#xff1a; USTRUCT(BlueprintType) struct FMyStruct //必须以"F"开头 {GENERATED_BODY() //必须添加“GENERATED_BODY()”UPROPERTY(EditAnywhere, BlueprintReadWrite, Category "MyStruct1")int32 Health;UPROPERTY(EditAnywher…

【算法】拦截导弹(线性DP)

题目 某国为了防御敌国的导弹袭击&#xff0c;发展出一种导弹拦截系统。 但是这种导弹拦截系统有一个缺陷&#xff1a;虽然它的第一发炮弹能够到达任意的高度&#xff0c;但是以后每一发炮弹都不能高于前一发的高度。 某天&#xff0c;雷达捕捉到敌国的导弹来袭。 由于该系…

04. 【Linux教程】安装 Linux 操作系统

通过前面的小节学习&#xff0c;我们已经对 Linux 操作系统有了简单的了解&#xff0c;同时也在 Windows 下安装了虚拟机软件 VMware &#xff0c;那么本节课我们就介绍下如何使用虚拟机软件安装 Linux 操作系统。 通过第一小节的学习我们知道 Linux 有很多的发行版本&#xf…

Unity 访问者模式(实例详解)

文章目录 实例1&#xff1a;简单的形状与统计访客实例2&#xff1a;游戏对象组件访问者实例4&#xff1a;Unity场景对象遍历与清理访客实例5&#xff1a;角色行为树访问者 访问者模式&#xff08;Visitor Pattern&#xff09;在Unity中主要用于封装对一个对象结构中各个元素的操…

用Audio2Face导出Unity面部动画

开始之前说句话&#xff0c;新年前最后一篇文章了 一定别轻易保存任何内容&#xff0c;尤其是程序员不要轻易Ctrl S 在A2F去往Unity的路上&#xff0c;还要经历特殊Blender&#xff0c;自己电脑中已下载好的可能不是很好使。 如果想查看UE相关的可以跳转到下边这两篇链接 1. …

Qt QWidget Loading界面并覆盖在其他控件上面

目录 一、效果图二、Loading三、使用 一、效果图 界面中有一个Label&#xff0c;一个Button 点击Buttion&#xff0c;显示Loading的界面&#xff0c;并覆盖到Label和Button上面 二、Loading loadingwidget.h #ifndef LOADINGWIDGET_H #define LOADINGWIDGET_H#include <…

曲线拟合、多项式拟合、最小二乘法

最近在做自车轨迹预测的工作&#xff0c;遇到 曲线拟合、多项式拟合、最小二乘法这些概念有点不清晰&#xff0c; 做一些概念区别的总结&#xff1a; 曲线拟合用于查找一系列数据点的“最佳拟合”线或曲线。 大多数情况下&#xff0c;曲线拟合将产生一个函数&#xff0c;可用于…

1.26模拟退火

模拟退火是爬山算法的一种&#xff0c;是搜索算法 初始阶段 即只有在每次更新方案时&#xff0c;才会使循环次数增加