หลังจาก Blog ตอนก่อน ผมได้ลอง Service Task เชื่อมกับ Web Service ผ่านวิธีการ GET เพื่อที่ดึงข้อมูลมาแสดงผลครับ คราวนี้หลังจาก GET ข้อมูลไปแล้วคราวนี้ เราลองมาทำการแก้ไขข้อมูลครับ ซึ่งการแก้ไขข้อมูลบางส่วน อันนี้ทาง Web Service (REST API) เค้ามีวิธีการที่เรียกว่า PATCH ครับ ส่วนจะทำอย่างไรนั้นมาลุยกันเลยครับ
เตรียมตัวครับ
- Camunda BPMN Engine - Blog ผมมีเขียนนะ อิอิ
- JSON-Server - ตัว Mock API ครับ ถ้าสนใจ ผมก็มีเขียน Blog ไว้ครับ ^__^
กระบวนการที่สร้างกันก่อนครับ
- สำหรับกระบวนการที่สร้างคราวนี้ผมทั้ง JSON Server ขึ้นมาเองครับ โดยใช้ข้อมูล Request ซึ่งผู้ใช้ต้องใส่ ID เพื่อให้ระบบดึงข้อมูล Request ขึ่นมาครับ หลังจากดูเสร็จ แล้วกด Complete ข้อมูลของ Request ในช่อง "requeststatus" ถูกแก้ไขค่าจาก "wait-for-review" เป็น "completed" ครับ
ลองมือทำ โดยมี Task ที่เกี่ยวข้อง ดังนี้
- Task "Enter Request Id" เป็น User Task เอาไว้สำหรับกรอก Id ของ Request ครับ
- Task "Test REST-API (GET)" เป็น Service Task ที่ติดต่อกับ Web Service โดยมี Config ดังนี้
- Connector Id = "http-connector"
- Input มีค่าตามตารางด้านล่างครับ
์Name Type Script Format Data url script groovy "http://localhost:3000/requests/${RequestId}".toString() method text - GET header map - Key = "Accept"
Value = "application/json" - Output เนื่องจากข้อมูลที่ได้เป็นอยู่ในรูปแบบ JSON จึงต้องมีการแปลงค่า และยัดลง Process ของ BPMN ได้แก่ id, projectid, requestid, requestby และ requeststatus ครับ โดยมี Code ดังนี้
import groovy.json.JsonSlurper; jsonResponse= connector.getVariable("response"); out:println "jsonResponse :" + jsonResponse.getClass(); JsonSlurper jsonSlurper = new JsonSlurper(); Object result = jsonSlurper.parseText(jsonResponse); //Convert to MAP Map jsonResponseMap = (Map)result ; //Step Value to Process Engine connector.setVariable('id', jsonResponseMap.get("id")); connector.setVariable('projectId', jsonResponseMap.get("projectId")); connector.setVariable('requestId', jsonResponseMap.get("requestId")); connector.setVariable('requestby', jsonResponseMap.get("requestby")); connector.setVariable('requeststatus', jsonResponseMap.get("requeststatus")); //Return JSON to outpur variable S(result);
- Task "View Result" เป็น User Task ที่เอาผลลัพธ์ที่ได้จาก Task "Test REST-API (GET)" มาแสดงผลครับ
- Connector Id = "http-connector"
- Input มีค่าตามตาราง
์Name Type Script Format Data url script groovy "http://localhost:3000/requests/${RequestId}".toString() method text - GET header map - Key = "Accept"
Value = "application/json"Key ="Content-Type"
Value = "application/json"payload script groovy import groovy.json.JsonOutput; def payload = [ 'requeststatus': 'completed' ]; JsonOutput.toJson(payload);
- Task "REST-API(PATCH) request status" เป็น Service Task ที่ทำหน้าที่เปลี่ยน "requeststatus" ถูกแก้ไขค่าจาก "wait-for-review" เป็น "completed" ครับ โดยมี Config ดังนี้ครับ
- เมื่อสร้าง Task เสร็จแล้ว นำไฟล์ BPMN ที่ได้เตรียมไป Deploy ครับThis file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
<?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:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="1.11.3"> <bpmn:process id="HttpConnectorRequestPatch" name="HttpConnectorRequestPatch" isExecutable="true" camunda:versionTag="1"> <bpmn:startEvent id="StartEvent_1"> <bpmn:outgoing>SequenceFlow_1435fpg</bpmn:outgoing> </bpmn:startEvent> <bpmn:sequenceFlow id="SequenceFlow_1435fpg" sourceRef="StartEvent_1" targetRef="Task_0zq32cv" /> <bpmn:endEvent id="EndEvent_186wp1n"> <bpmn:incoming>SequenceFlow_1vry191</bpmn:incoming> </bpmn:endEvent> <bpmn:sequenceFlow id="SequenceFlow_03p4qxe" sourceRef="Task_1dkkumo" targetRef="Task_1sfjjen" /> <bpmn:serviceTask id="Task_1dkkumo" name="Test REST-API (GET) "> <bpmn:extensionElements> <camunda:connector> <camunda:inputOutput> <camunda:inputParameter name="url"> <camunda:script scriptFormat="groovy"><![CDATA["http://localhost:3000/requests/${RequestId}".toString() ]]></camunda:script> </camunda:inputParameter> <camunda:inputParameter name="method">GET</camunda:inputParameter> <camunda:inputParameter name="header"> <camunda:map> <camunda:entry key="Accept">application/json</camunda:entry> </camunda:map> </camunda:inputParameter> <camunda:outputParameter name="postResult"> <camunda:script scriptFormat="groovy"><![CDATA[import groovy.json.JsonSlurper; jsonResponse= connector.getVariable("response"); out:println "jsonResponse :" + jsonResponse.getClass(); JsonSlurper jsonSlurper = new JsonSlurper(); Object result = jsonSlurper.parseText(jsonResponse); //Convert to MAP Map jsonResponseMap = (Map)result ; //Step Value to Process Engine connector.setVariable('id', jsonResponseMap.get("id")); connector.setVariable('projectId', jsonResponseMap.get("projectId")); connector.setVariable('requestId', jsonResponseMap.get("requestId")); connector.setVariable('requestby', jsonResponseMap.get("requestby")); connector.setVariable('requeststatus', jsonResponseMap.get("requeststatus")); //Return JSON to outpur variable postResult = result;]]></camunda:script> </camunda:outputParameter> </camunda:inputOutput> <camunda:connectorId>http-connector</camunda:connectorId> </camunda:connector> </bpmn:extensionElements> <bpmn:incoming>SequenceFlow_13f8xbw</bpmn:incoming> <bpmn:outgoing>SequenceFlow_03p4qxe</bpmn:outgoing> </bpmn:serviceTask> <bpmn:userTask id="Task_1sfjjen" name="View Result" camunda:assignee="mary"> <bpmn:extensionElements> <camunda:formData> <camunda:formField id="projectId" label="projectId" type="string" /> <camunda:formField id="requestId" label="requestId" type="string" /> <camunda:formField id="requestby" label="requestby" type="string" /> <camunda:formField id="requeststatus" label="requeststatus" type="string" /> <camunda:formField id="id" label="id" type="string" /> </camunda:formData> </bpmn:extensionElements> <bpmn:incoming>SequenceFlow_03p4qxe</bpmn:incoming> <bpmn:outgoing>SequenceFlow_1x13z2l</bpmn:outgoing> </bpmn:userTask> <bpmn:sequenceFlow id="SequenceFlow_13f8xbw" sourceRef="Task_0zq32cv" targetRef="Task_1dkkumo" /> <bpmn:userTask id="Task_0zq32cv" name="Enter Request Id" camunda:assignee="mary"> <bpmn:extensionElements> <camunda:formData> <camunda:formField id="RequestId" label="RequestId" type="long" defaultValue="2" /> </camunda:formData> </bpmn:extensionElements> <bpmn:incoming>SequenceFlow_1435fpg</bpmn:incoming> <bpmn:outgoing>SequenceFlow_13f8xbw</bpmn:outgoing> </bpmn:userTask> <bpmn:serviceTask id="Task_1y1oxu5" name="REST-API (PATCH) request status"> <bpmn:extensionElements> <camunda:connector> <camunda:inputOutput> <camunda:inputParameter name="url"> <camunda:script scriptFormat="groovy"><![CDATA["http://localhost:3000/requests/${id}".toString()]]></camunda:script> </camunda:inputParameter> <camunda:inputParameter name="method">PATCH</camunda:inputParameter> <camunda:inputParameter name="header"> <camunda:map> <camunda:entry key="accept">application/json</camunda:entry> <camunda:entry key="Content-Type">application/json</camunda:entry> </camunda:map> </camunda:inputParameter> <camunda:inputParameter name="payload"> <camunda:script scriptFormat="groovy"><![CDATA[import groovy.json.JsonOutput; def payload = [ 'requeststatus': 'completed' ]; //JsonOutput.prettyPrint(JsonOutput.toJson(payload)); JsonOutput.toJson(payload);]]></camunda:script> </camunda:inputParameter> <camunda:outputParameter name="statusCode"> <camunda:script scriptFormat="groovy"><![CDATA[out:println "response:" + response; out:println "statusCode:" + statusCode;]]></camunda:script> </camunda:outputParameter> </camunda:inputOutput> <camunda:connectorId>http-connector</camunda:connectorId> </camunda:connector> </bpmn:extensionElements> <bpmn:incoming>SequenceFlow_1x13z2l</bpmn:incoming> <bpmn:outgoing>SequenceFlow_1vry191</bpmn:outgoing> </bpmn:serviceTask> <bpmn:sequenceFlow id="SequenceFlow_1x13z2l" sourceRef="Task_1sfjjen" targetRef="Task_1y1oxu5" /> <bpmn:sequenceFlow id="SequenceFlow_1vry191" sourceRef="Task_1y1oxu5" targetRef="EndEvent_186wp1n" /> </bpmn:process> <bpmndi:BPMNDiagram id="BPMNDiagram_1"> <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="HttpConnectorRequestPatch"> <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1"> <dc:Bounds x="-101" y="94" width="36" height="36" /> <bpmndi:BPMNLabel> <dc:Bounds x="-128" y="130" width="90" height="20" /> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNEdge id="SequenceFlow_1435fpg_di" bpmnElement="SequenceFlow_1435fpg"> <di:waypoint xsi:type="dc:Point" x="-65" y="112" /> <di:waypoint xsi:type="dc:Point" x="-35" y="112" /> <bpmndi:BPMNLabel> <dc:Bounds x="-95" y="91" width="90" height="12" /> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNShape id="EndEvent_186wp1n_di" bpmnElement="EndEvent_186wp1n"> <dc:Bounds x="491" y="94" width="36" height="36" /> <bpmndi:BPMNLabel> <dc:Bounds x="464" y="134" width="90" height="12" /> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNEdge id="SequenceFlow_03p4qxe_di" bpmnElement="SequenceFlow_03p4qxe"> <di:waypoint xsi:type="dc:Point" x="192" y="112" /> <di:waypoint xsi:type="dc:Point" x="225" y="112" /> <bpmndi:BPMNLabel> <dc:Bounds x="163.5" y="91" width="90" height="12" /> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNShape id="ServiceTask_01g1tty_di" bpmnElement="Task_1dkkumo"> <dc:Bounds x="92" y="72" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="UserTask_0dz9bh6_di" bpmnElement="Task_1sfjjen"> <dc:Bounds x="225" y="72" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNEdge id="SequenceFlow_13f8xbw_di" bpmnElement="SequenceFlow_13f8xbw"> <di:waypoint xsi:type="dc:Point" x="65" y="112" /> <di:waypoint xsi:type="dc:Point" x="92" y="112" /> <bpmndi:BPMNLabel> <dc:Bounds x="33.5" y="91" width="90" height="12" /> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNShape id="UserTask_03xo9g6_di" bpmnElement="Task_0zq32cv"> <dc:Bounds x="-35" y="72" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="ServiceTask_07lxnv4_di" bpmnElement="Task_1y1oxu5"> <dc:Bounds x="352" y="72" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNEdge id="SequenceFlow_1x13z2l_di" bpmnElement="SequenceFlow_1x13z2l"> <di:waypoint xsi:type="dc:Point" x="325" y="112" /> <di:waypoint xsi:type="dc:Point" x="352" y="112" /> <bpmndi:BPMNLabel> <dc:Bounds x="338.5" y="91" width="0" height="12" /> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="SequenceFlow_1vry191_di" bpmnElement="SequenceFlow_1vry191"> <di:waypoint xsi:type="dc:Point" x="452" y="112" /> <di:waypoint xsi:type="dc:Point" x="491" y="112" /> <bpmndi:BPMNLabel> <dc:Bounds x="426.5" y="91" width="90" height="12" /> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> </bpmndi:BPMNPlane> </bpmndi:BPMNDiagram> </bpmn:definitions>
ทดสอบ
- เตรียมข้อมูลสำหรับ Mock Server กันก่อนครับ โดยข้อมูลที่ได้มีหน้าตา ดังนี้ (ถูกเก็บไว้ในไฟล์ db.json ครับ)
{ "requests": [ { "id": 1, "projectId": 123, "requestId": "CUQ-5248", "requestby": "mary", "requesttime": "2018-05-23T18:25:43.511Z", "requeststatus": "wait-for-review", }, { "id": 2, "projectId": 124, "requestId": "CUQ-5249", "requestby": "mary", "requesttime": "2018-05-23T18:25:43.511Z", "requeststatus": "wait-for-review", }, { "id": 3, "projectId": 124, "requestId": "CUQ-52489", "requestby": "mary", "requesttime": "2018-05-23T18:25:43.511Z", "requeststatus": "wait-for-review", } ] }
- Start JSON Server ด้วยคำสั่ง json-server --watch db.json
- เข้าไปที่ Camunda Task List จากนั้น Execute Task ชื่อ "HttpConnectorRequestPatch"
- กรอก Request Id = 2
- ดูรายการ Request จากนั้นกดปุ่ม Complete
- ลองไปดูที่ Console ครับ พบว่า ช่อง "requeststatus" ถูกแก้ไขค่าจาก "wait-for-review" เป็น "completed" แล้วครับ
- กรอก Request Id = 2