什么是Kogito
Kogito是一个云原生的业务自动化工具包,旨在让你的生活更轻松。可以把它看作是业务流程管理(BPM)和决策管理的结合体,由它的云端父母Quarkus精心培育。
但为什么你,作为一名经验丰富的开发者,应该关注Kogito呢?这里是简要概述:
- 它是云原生的,并且开箱即用地支持Kubernetes
- 它与Quarkus完美结合,赋予你超音速、亚原子的Java能力
- 它将你的业务流程和决策变成代码库中的一等公民
- 它是开源的,并由Apache软件基金会支持(目前在孵化中)
深入Kogito示例库
现在我们已经引起了你的兴趣,让我们来参观一下apache/incubator-kie-kogito-examples库。这些丰富的示例是你掌握Kogito的通行证。
设置你的Kogito游乐场
在我们深入之前,确保你拥有运行这些示例所需的一切:
- Java 11+(因为我们不是野蛮人)
- Maven 3.8.1+
- Docker(满足容器化的需求)
- Quarkus CLI(可选,但强烈推荐以提高生产力)
都准备好了吗?太好了!现在让我们动手实践。
Quarkus:Kogito的犯罪搭档
你可能会问,“Quarkus与这有什么关系?”其实,关系重大。Quarkus是超音速、亚原子的Java框架,赋予Kogito云原生的超能力。它就像是Java应用程序的红牛,但没有咖啡因的副作用。
Kogito利用Quarkus来:
- 实现闪电般的启动时间
- 减少内存占用(你的钱包会感谢你)
- 提供热重载功能(因为谁有时间重启呢?)
- 提供与云原生技术的无缝集成
探索Kogito示例:旋风之旅
让我们来看看库中一些最精彩的示例:
1. 流程 + 规则:动态二人组
导航到kogito-quarkus-examples/process-business-rules-quarkus
目录。这个示例展示了Kogito如何结合流程和规则来创建一个强大的决策引擎。
关键要点:
- 将BPMN2流程与DMN决策表集成
- 为你的流程自动生成REST端点
- 在流程上下文中无缝执行规则
2. 无服务器工作流:因为服务器已经过时了
查看serverless-workflow-examples/serverless-workflow-greeting-quarkus
示例。这是为所有无服务器爱好者准备的。
亮点:
- YAML定义的工作流(谁不喜欢YAML呢?)
- 轻松实现事件驱动架构
- 与AWS Lambda和Knative的集成
3. DMN:让决策再次伟大
前往kogito-quarkus-examples/dmn-quarkus-example
深入了解Kogito中的决策模型和标记(DMN)。
你将学到:
- 直观地建模复杂的决策逻辑
- 为你的决策服务自动生成REST API
- 像专业人士一样测试和调试DMN模型
运行你的第一个Kogito示例:逐步指南
理论够多了,让我们动手实践!我们将使用process-business-rules-quarkus示例来开始。
一旦它运行起来,测试API:
curl -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -d '{"person": {"name":"John Doe", "age": 25}}' http://localhost:8080/persons
构建并运行示例:
./mvnw clean compile quarkus:dev
克隆仓库:
git clone https://github.com/apache/incubator-kie-kogito-examples.git
cd incubator-kie-kogito-examples/kogito-quarkus-examples/process-business-rules-quarkus
瞧!你刚刚使用Kogito执行了一个嵌入规则的业务流程。感受到力量了吗?
实现业务流程:BPMN和DMN,哦我的天!
Kogito将BPMN(业务流程模型和标记)和DMN(决策模型和标记)带入了21世纪。笨重的BPM引擎的日子已经过去了。使用Kogito,你的流程和决策在代码库中是头等公民。
BPMN:增强版流程图
让我们看看一个简单的BPMN流程:
<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" id="_6063f3a1-5ba3-4f0e-b1f2-ad49e8e6f2a7" targetNamespace="http://www.omg.org/bpmn20">
<bpmn2:process id="greeting" name="Greeting Process" isExecutable="true">
<bpmn2:startEvent id="_1" name="StartProcess">
<bpmn2:outgoing>_1-_2</bpmn2:outgoing>
</bpmn2:startEvent>
<bpmn2:scriptTask id="_2" name="Hello" scriptFormat="http://www.java.com/java">
<bpmn2:incoming>_1-_2</bpmn2:incoming>
<bpmn2:outgoing>_2-_3</bpmn2:outgoing>
<bpmn2:script>System.out.println("Hello World");</bpmn2:script>
</bpmn2:scriptTask>
<bpmn2:endEvent id="_3" name="EndProcess">
<bpmn2:incoming>_2-_3</bpmn2:incoming>
</bpmn2:endEvent>
<bpmn2:sequenceFlow id="_1-_2" sourceRef="_1" targetRef="_2"/>
<bpmn2:sequenceFlow id="_2-_3" sourceRef="_2" targetRef="_3"/>
</bpmn2:process>
</bpmn2:definitions>
这个简单的流程只是打印“Hello World”,但想象一下,当你开始与业务逻辑和外部系统集成时的可能性!
DMN:决策,决策
现在,让我们看看一个DMN模型:
<?xml version="1.0" encoding="UTF-8"?>
<dmn:definitions xmlns:dmn="http://www.omg.org/spec/DMN/20180521/MODEL/" xmlns="https://kiegroup.org/dmn/_52CEF9FD-9943-4A89-96D5-6F66810CA4C1" xmlns:di="http://www.omg.org/spec/DMN/20180521/DI/" xmlns:kie="http://www.drools.org/kie/dmn/1.2" xmlns:dmndi="http://www.omg.org/spec/DMN/20180521/DMNDI/" xmlns:dc="http://www.omg.org/spec/DMN/20180521/DC/" id="_4F7C97F9-EA35-4CB5-8E4C-C40C91B5F729" name="Greeting" typeLanguage="http://www.omg.org/spec/DMN/20180521/FEEL/" namespace="https://kiegroup.org/dmn/_52CEF9FD-9943-4A89-96D5-6F66810CA4C1">
<dmn:decision id="_23B84E59-33C6-4D3A-9314-CF0724714606" name="Greeting Message">
<dmn:extensionElements/>
<dmn:variable id="_078A6F79-1861-47A1-8921-C9E7F2B728D1" name="Greeting Message" typeRef="string"/>
<dmn:informationRequirement id="_2066A270-2A88-4B77-9F90-1F683FDF852C">
<dmn:requiredInput href="#_C7ED7EFC-9F7F-4FBE-81DB-57A32A56502C"/>
</dmn:informationRequirement>
<dmn:decisionTable id="_5A25D948-34E0-4527-9EE2-7A9C0DC663A5" hitPolicy="UNIQUE" preferredOrientation="Rule-as-Row">
<dmn:input id="_79ECD1F2-E11E-4F6D-9038-C47AE6EC1C9C">
<dmn:inputExpression id="_E17A0C1D-A0F0-4C5F-8A0E-8B5F9A1BAB08" typeRef="number">
<dmn:text>Age</dmn:text>
</dmn:inputExpression>
</dmn:input>
<dmn:output id="_EC6A4902-BD03-4D48-AA45-9AD2AEB83E8B"/>
<dmn:annotation name="annotation-1"/>
<dmn:rule id="_C3F28427-2608-4ACE-98EE-C5C2F0AEF7A7">
<dmn:inputEntry id="_0FBE3F3C-5F3A-4A21-A4A5-D207B2BA7808">
<dmn:text>< 18</dmn:text>
</dmn:inputEntry>
<dmn:outputEntry id="_C05BE7BB-BDA0-4C45-9ED1-4F5B17B2A3E6">
<dmn:text>"Hello young person!"</dmn:text>
</dmn:outputEntry>
<dmn:annotationEntry>
<dmn:text/>
</dmn:annotationEntry>
</dmn:rule>
<dmn:rule id="_C3B07D74-0354-4C44-9587-9B44C67F5AE0">
<dmn:inputEntry id="_8A9B0EEC-5CB9-4D31-BB56-0A723CEABFBC">
<dmn:text>>= 18</dmn:text>
</dmn:inputEntry>
<dmn:outputEntry id="_42C4EB7F-3F00-4A19-9F43-D2E246F378F9">
<dmn:text>"Hello adult!"</dmn:text>
</dmn:outputEntry>
<dmn:annotationEntry>
<dmn:text/>
</dmn:annotationEntry>
</dmn:rule>
</dmn:decisionTable>
</dmn:decision>
<dmn:inputData id="_C7ED7EFC-9F7F-4FBE-81DB-57A32A56502C" name="Age">
<dmn:extensionElements/>
<dmn:variable id="_F0B70F13-94CB-4FB9-BD89-4AB84F8BDB07" name="Age" typeRef="number"/>
</dmn:inputData>
<dmndi:DMNDI>
<dmndi:DMNDiagram>
<di:extension>
<kie:ComponentsWidthsExtension>
<kie:ComponentWidths dmnElementRef="_5A25D948-34E0-4527-9EE2-7A9C0DC663A5">
<kie:width>50</kie:width>
<kie:width>100</kie:width>
<kie:width>100</kie:width>
<kie:width>100</kie:width>
</kie:ComponentWidths>
</kie:ComponentsWidthsExtension>
</di:extension>
<dmndi:DMNShape id="dmnshape-_23B84E59-33C6-4D3A-9314-CF0724714606" dmnElementRef="_23B84E59-33C6-4D3A-9314-CF0724714606" isCollapsed="false">
<dmndi:DMNStyle>
<dmndi:FillColor red="255" green="255" blue="255"/>
<dmndi:StrokeColor red="0" green="0" blue="0"/>
<dmndi:FontColor red="0" green="0" blue="0"/>
</dmndi:DMNStyle>
<dc:Bounds x="364" y="227" width="100" height="50"/>
<dmndi:DMNLabel/>
</dmndi:DMNShape>
<dmndi:DMNShape id="dmnshape-_C7ED7EFC-9F7F-4FBE-81DB-57A32A56502C" dmnElementRef="_C7ED7EFC-9F7F-4FBE-81DB-57A32A56502C" isCollapsed="false">
<dmndi:DMNStyle>
<dmndi:FillColor red="255" green="255" blue="255"/>
<dmndi:StrokeColor red="0" green="0" blue="0"/>
<dmndi:FontColor red="0" green="0" blue="0"/>
</dmndi:DMNStyle>
<dc:Bounds x="365" y="94" width="100" height="50"/>
<dmndi:DMNLabel/>
</dmndi:DMNShape>
<dmndi:DMNEdge id="dmnedge-_2066A270-2A88-4B77-9F90-1F683FDF852C" dmnElementRef="_2066A270-2A88-4B77-9F90-1F683FDF852C">
<di:waypoint x="415" y="119"/>
<di:waypoint x="414" y="252"/>
</dmndi:DMNEdge>
</dmndi:DMNDiagram>
</dmndi:DMNDI>
</dmn:definitions>
这个DMN模型根据一个人的年龄决定问候语。这是一个简单的例子,但想象一下将其扩展到复杂的业务规则和决策过程!
自定义规则和决策:按你的方式或高效方式
Kogito不仅提供开箱即用的规则和决策。它还允许你根据独特的业务需求进行定制。以下是一些定制方法:
1. Drools规则语言(DRL)
当视觉模型无法满足需求时,你可以使用传统的DRL:
package org.acme.rules
import org.acme.model.Person
rule "Greet adults"
when
$person: Person(age >= 18)
then
System.out.println("Hello, responsible adult!");
end
rule "Greet children"
when
$person: Person(age < 18)
then
System.out.println("Hi, youngster! Where are your parents?");
end
2. 决策表
对于那些看到代码就过敏的业务用户,决策表是福音:
RuleSet,org.acme.rules
RuleSetName,Greeting Rules
RuleTable Greeting
CONDITION,ACTION
Person.age,System.out.println
>=18,"Hello, responsible adult!"
<18,"Hi, youngster! Where are your parents?"
3. 使用自定义函数扩展DMN
需要在DMN模型中增加一些额外的功能?用自定义Java函数扩展它们:
@DMNFunction(name = "toUpperCase")
public static String toUpperCase(String input) {
return input.toUpperCase();
}
现在你可以在DMN表达式中使用toUpperCase()
。很酷吧?
将Kogito与外部世界集成
Kogito与其他系统配合得很好。让我们看看如何将它与一些流行的外部系统集成:
REST API:因为SOAP是用来洗的
Kogito自动为你的流程和决策生成REST端点。但如果你需要调用外部REST API呢?轻而易举:
@Inject
RestClient myExternalService;
@POST
@Path("/process")
public Response startProcess(ProcessPayload payload) {
// 启动你的Kogito流程
ProcessInstance<?> processInstance = processService.createProcessInstance(...);
// 调用外部REST API
ExternalData data = myExternalService.getData(payload.getId());
// 更新流程变量
processInstance.updateVariables(Collections.singletonMap("externalData", data));
return Response.ok(processInstance).build();
}
Kafka:为那些事件驱动的时刻
Kogito和Kafka就像花生酱和果冻一样搭配。这里是一个例子:
@Inject
Emitter<PersonEvent> personEventEmitter;
@POST
@Path("/persons")
public Response createPerson(Person person) {
// 你的Kogito流程逻辑在这里
// 向Kafka发送事件
personEventEmitter.send(new PersonEvent(person));
return Response.ok(person).build();
}
别忘了在application.properties
中配置你的Kafka连接:
mp.messaging.outgoing.person-events.connector=smallrye-kafka
mp.messaging.outgoing.person-events.topic=person-events
mp.messaging.outgoing.person-events.value.serializer=io.quarkus.kafka.client.serialization.JsonbSerializer
调试Kogito:当事情出错时
即使是最好的开发者有时也会陷入调试困境。这里有一些保持理智的技巧:
1. 启用调试日志
首先,增加日志记录:
quarkus.log.category."org.kie".level=DEBUG
quarkus.log.category."org.drools".level=DEBUG
quarkus.log.category."org.jbpm".level=DEBUG
2. 使用Kogito开发UI
Kogito带有一个时尚的开发UI。只需添加这个依赖项:
<dependency>
<groupId>org.kie.kogito</groupId>
<artifactId>kogito-addons-quarkus-process-management</artifactId>
</dependency>
现在你可以访问http://localhost:8080/q/dev
来查看你的流程和决策的运行情况。
3. 测试,测试,测试
单元测试是你的朋友。这里是一个快速示例:
@QuarkusTest
public class GreetingProcessTest {
@Inject
ProcessService processService;
@Test
public void testGreetingProcess() {
ProcessInstance<?> processInstance = processService.createProcessInstance(
"greeting",
Collections.singletonMap("name", "John")
);
assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_COMPLETED);
assertThat(processInstance.variables()).containsEntry("greeting", "Hello, John!");
}
}
性能调优:让它飞速运行
Kogito已经很快了,但通过这些技巧,你可以让它突破音障:
1. 原生编译
Quarkus提供原生编译,可以显著减少启动时间和内存使用:
./mvnw package -Pnative
2. 响应式编程
采用响应式范式以获得更好的可扩展性:
@Inject
ReactiveProcessService processService;
@POST
@Path("/process")
public Uni<ProcessInstance<?>> startProcess(ProcessPayload payload) {
return processService.createProcessInstance("myProcess", payload.toMap());
}
3. 缓存
使用Quarkus的内置缓存功能来加速频繁操作:
@CacheResult(cacheName = "greeting-cache")
public String getGreeting(String name) {
// 耗时操作在这里
return "Hello, " + name + "!";
}
最佳实践:该做和不该做的事
让我们以一些Kogito开发的黄金法则来结束:
该做:
- 保持你的流程和决策简单且模块化
- 为你的BPMN和DMN元素使用有意义的名称
- 利用Quarkus的热重载进行快速开发
- 记录你的流程和决策(你的未来自我会感谢你)
- 为你的BPMN和DMN文件使用版本控制
不该做:
- 不要在你的流程图中放置业务逻辑(使用服务任务代替)
- 不要忽视流程中的错误处理
- 不要忘记监控和可观察性
- 不要忽视安全最佳实践(Kogito不是神奇的安全粉尘)
真实世界的Kogito:不仅仅是个漂亮的面孔
Kogito不仅仅用于玩具示例。它在野外被用于一些严肃的业务自动化。以下是一些真实世界的应用:
- 金融服务:自动化贷款审批流程和欺诈检测
- 医疗保健:管理患者工作流和保险索赔处理
- 电子商务:协调订单履行和退货流程
- 制造业:优化供应链决策和质量控制流程
为Kogito做贡献:加入酷小孩俱乐部
感到灵感了吗?想要回馈社区?以下是你可以为Kogito做贡献的方法:
记住,没有贡献是太小的。即使是修正文档中的一个错字也会受到赞赏!
最后倒计时:总结
这就是全部,朋友们!Kogito及其超能力的旋风之旅。我们涵盖了从设置你的第一个Kogito项目到为开源社区做贡献的一切。
Kogito,由Quarkus驱动,正在改变业务自动化的游戏规则。它将云原生技术的力量带入业务流程和决策的世界。无论你是在构建一个简单的工作流还是一个复杂的决策系统,Kogito都能满足你的需求。
那么,你还在等什么?深入研究,开始实验,加入Kogito革命。你的未来自我(以及你的运维团队)会感谢你。
记住:能力越大,责任越大。明智地使用Kogito,愿你的业务流程永远对你有利!