1. Integrate activiti6 0
Add dependency
Add activiti6.0 to maven in spring boot 0 dependency
<dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring-boot-starter-basic</artifactId> <version>6.0.0</version> </dependency>
activiti configuration
In application Add in yaml
activiti: check-process-definitions: false # Does activti deploy automatically without loading bpmn files db-identity-used: true #Whether to use the user system provided by activti. There can be no data in the user table provided by activt, but the table must exist database-schema-update: true #Update database every time history-level: full #full highest level
The startup class @ SpringBootApplication of spring boot needs to exclude Security, otherwise an error will be reported when starting the project, which may affect Shiro or other plug-ins.
@SpringBootApplication(exclude = SecurityAutoConfiguration.class)
actiBPM plug-in use, process testing
After completing the above steps, you can use the workflow. If you test the workflow, you can test it together after integrating and completing the online design. Because the experience of the plug-in activiti process in idea is not very good. If you use plug-ins to draw flow charts, you might as well use eclipse.
If the online design is not integrated in the idea editor, you can test whether the integration is successful in the following way.
Install the plug-in actiBPM.
idea2020 doesn't seem to be able to search this plug-in. You can only download it from the plug-in market and add it manually.
Link: https://plugins.jetbrains.com/search?products=idea&search=actiBPM .
New bpmn file
Create a new test01.0 in the resources directory BPMN file. Draw a simple process as follows. (why is it that this plug-in is not easy to use? Because many events can't be found, such as signal start event, signal end event, sub process, etc. and I don't know where to set the node's properties, monitor, etc. strange, I can't understand it. I don't know if my opening method is wrong. I can't understand this plug-in anyway)
This bpmn file can be opened in notepad++da
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:tns="http://www.activiti.org/testm1604023359723" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1604023359723" name="" targetNamespace="http://www.activiti.org/testm1604023359723" typeLanguage="http://www.w3.org/2001/XMLSchema"> <process id="myProcess_1" isClosed="false" isExecutable="true" processType="None"> <startEvent id="_2" name="StartEvent"/> <userTask activiti:exclusive="true" id="_3" name="apply"/> <userTask activiti:exclusive="true" id="_4" name="Approval"/> <endEvent id="_5" name="EndEvent"/> <sequenceFlow id="_6" sourceRef="_2" targetRef="_3"/> <sequenceFlow id="_7" sourceRef="_3" targetRef="_4"/> <sequenceFlow id="_8" sourceRef="_4" targetRef="_5"/> </process> <bpmndi:BPMNDiagram documentation="background=#3C3F41;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram"> <bpmndi:BPMNPlane bpmnElement="myProcess_1"> <bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2"> <dc:Bounds height="32.0" width="32.0" x="300.0" y="50.0"/> <bpmndi:BPMNLabel> <dc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="_3" id="Shape-_3"> <dc:Bounds height="55.0" width="85.0" x="275.0" y="135.0"/> <bpmndi:BPMNLabel> <dc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="_4" id="Shape-_4"> <dc:Bounds height="55.0" width="85.0" x="285.0" y="250.0"/> <bpmndi:BPMNLabel> <dc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="_5" id="Shape-_5"> <dc:Bounds height="32.0" width="32.0" x="330.0" y="365.0"/> <bpmndi:BPMNLabel> <dc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNEdge bpmnElement="_6" id="BPMNEdge__6" sourceElement="_2" targetElement="_3"> <di:waypoint x="316.0" y="82.0"/> <di:waypoint x="316.0" y="135.0"/> <bpmndi:BPMNLabel> <dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="_7" id="BPMNEdge__7" sourceElement="_3" targetElement="_4"> <di:waypoint x="322.5" y="190.0"/> <di:waypoint x="322.5" y="250.0"/> <bpmndi:BPMNLabel> <dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="_8" id="BPMNEdge__8" sourceElement="_4" targetElement="_5"> <di:waypoint x="346.0" y="305.0"/> <di:waypoint x="346.0" y="365.0"/> <bpmndi:BPMNLabel> <dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> </bpmndi:BPMNPlane> </bpmndi:BPMNDiagram> </definitions>
Look at this tag. id="myProcess_1" is used when starting the process (roast again. I can't find the plug-in. I can't set this id there. I modify this id directly by opening this file. I really don't understand.)
<process id="myProcess_1" isClosed="false" isExecutable="true" processType="None">
Deployment file
Once the process file is available, it needs to be deployed. After deployment, it will be displayed in act_re_procdef (insert process definition in the process definition table). KEY_ This field is the key to start the process
Start the process and complete the task
@Autowired private TaskService taskService; @Autowired private RuntimeService runtimeService; /** * Test start */ public void testStart(String key){ ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(key); System.out.println("Process started successfully, process id: "+processInstance.getId()); } /** * Test task completed */ public void testCompleteTask(String processInstanceId){ //Get the current task according to the process id org.activiti.engine.task.Task task = taskService.createTaskQuery() .processInstanceId(processInstanceId) .active() .singleResult(); taskService.complete(task.getId()); System.out.println(); System.out.println("Complete the task, task name:"+task.getName()+"task id: "+task.getId()); //Get the task node behind the current task List<Task> nextTask = taskService.createTaskQuery().processInstanceId(processInstanceId).list(); if(nextTask!=null && nextTask.size() > 0){ System.out.println(); System.out.println("Next task name:"+nextTask.get(0).getName()+"Next task id: "+nextTask.get(0).getId()); }else { System.out.println(); System.out.println("End of process"); } }
2. Integrated online design
Online design component Download
Download link: https://github.com/Activiti/Activiti/releases/tag/activiti-5.22.0
Import components
Download activiti-5.22.0 and unzip it
Imported Java classes: unzip activiti-modeler-5.22.0-sources Jar (in activiti-5.22.0\activiti-5.22.0\libs directory). After decompression, copy the three classes under activiti-modeler-5.22.0-sources\org\activiti\rest\editor into the project! [insert picture description here]( https://img-blog.csdnimg.cn/20201117112203390.png#pic_center
Import static resources: unzip activiti explorer War (in activiti-5.22.0\activiti-5.22.0\wars directory), unzip it and ask for the price folder and modeler of diagram viewer, editor app html,stencilest. Copy JSON to the project static directory. It is necessary to modify stencelest JSON, baidu by version.
Confirm app CFG The value of the contextRoot in JS is the same as that of the @ RequestMapping of the three classes in the first step of importing java classes. These three default @ RequestMapping(value = "services"). If you modify this url, APP CFG The contextRoot in JS also needs to be modified to the same value.
Access online design
Visit online design and directly visit modeler Html is OK. Note: in direct access to modeler HTML
You must bring the parameter modelId=xxxx (example: http://localhost:8080/modeler.html?modelId=7501 ). Otherwise, the open page will be blank, because the online design will only know to modify the model after passing in the modelid
When online design is opened without modelId, a blank will appear, and the model can be created through java code
public ModelAndView newModel() throws UnsupportedEncodingException { //Initialize an empty model Model model = repositoryService.newModel(); //Set some default information, which can be received with parameters int revision = 1; String key = "process"; String name = "new-process"; String description = ""; ObjectNode modelNode = objectMapper.createObjectNode(); modelNode.put(ModelDataJsonConstants.MODEL_NAME, name); modelNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description); modelNode.put(ModelDataJsonConstants.MODEL_REVISION, revision); model.setName(name); model.setKey(key); model.setMetaInfo(modelNode.toString()); repositoryService.saveModel(model); String id = model.getId(); //ModelEditorSource ObjectNode editorNode = objectMapper.createObjectNode(); editorNode.put("id", "canvas"); editorNode.put("resourceId", "canvas"); ObjectNode stencilSetNode = objectMapper.createObjectNode(); stencilSetNode.put("namespace","http://b3mn.org/stencilset/bpmn2.0#"); editorNode.put("stencilset" , stencilSetNode); repositoryService.addModelEditorSource(id, editorNode.toString().getBytes("utf-8")); return new ModelAndView("redirect:/modeler.html?modelId=" + id); }
In this way, if you need to modify the model, you need to find the modelId manually, which is not very convenient. You can write a model list yourself html. Show all models, provide new buttons, etc.
model-list. The HTML code is as follows:
<!DOCTYPE html> <html lang="zh" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>model list</title> </head> <body> <div class="info"><span th:text="${info}"></span></div> <a href="/activiti/page/create">newly build</a> <table class="table"> <thead> <tr> <th>ID</th> <th>Model name</th> <th>key</th> <th>edition</th> <th>deploy ID</th> <th>Creation time</th> <th>Last update time</th> <th>operation</th> </tr> </thead> <tbody> <tr th:each="data : ${models}"> <td th:text="${data.id}"></td> <td><a th:href="@{/modeler.html(modelId=${data.id})}" class="font-blue" th:text="${data.name}"></a> </td> <td th:text="${data.key}"></td> <td th:text="${data.version}"></td> <td th:text="${data.deploymentId}"></td> <td th:text="${data.createTime}"> 2018-02-25 17:28:35</td> <td th:text="${data.lastUpdateTime}"> 2018-02-25 17:28:35</td> <td> <a th:href="${'/activiti/deploy/'+data.key}" th:attrappend="objectId=${data.id}" lass="font-blue deployBtn">release</a> <a th:href="${'/activiti/exportXML/'+data.id}" class="font-blue">export</a> </td> </tr> </tbody> </table> </body> </html>
@Controller @RequestMapping("activiti/page") public class PageController { @Autowired private RepositoryService repositoryService; @Autowired private ObjectMapper objectMapper; /** * Query all models and return to the default model list view * @param model * @return */ @GetMapping public String toModelListPage(org.springframework.ui.Model model){ List<Model> models = repositoryService.createModelQuery().orderByCreateTime().desc().list(); model.addAttribute("models",models); return "page/model/model-list"; } /** * Create an empty model and redirect to modeler html * @return * @throws UnsupportedEncodingException */ @GetMapping("/create") public ModelAndView newModel() throws UnsupportedEncodingException { //Initialize an empty model Model model = repositoryService.newModel(); //Set some default information, which can be received with parameters int revision = 1; String key = "process"; String name = "new-process"; String description = ""; ObjectNode modelNode = objectMapper.createObjectNode(); modelNode.put(ModelDataJsonConstants.MODEL_NAME, name); modelNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description); modelNode.put(ModelDataJsonConstants.MODEL_REVISION, revision); model.setName(name); model.setKey(key); model.setMetaInfo(modelNode.toString()); repositoryService.saveModel(model); String id = model.getId(); //ModelEditorSource ObjectNode editorNode = objectMapper.createObjectNode(); editorNode.put("id", "canvas"); editorNode.put("resourceId", "canvas"); ObjectNode stencilSetNode = objectMapper.createObjectNode(); stencilSetNode.put("namespace","http://b3mn.org/stencilset/bpmn2.0#"); editorNode.put("stencilset" , stencilSetNode); repositoryService.addModelEditorSource(id, editorNode.toString().getBytes("utf-8")); return new ModelAndView("redirect:/modeler.html?modelId=" + id); } }
Export model as xml method
public void export(@PathVariable("modelId") String modelId, HttpServletResponse response) { response.setContentType("text/html; charset=UTF-8"); //transcoding try { Model modelData = repositoryService.getModel(modelId); BpmnJsonConverter jsonConverter = new BpmnJsonConverter(); JsonNode editorNode = new ObjectMapper().readTree(repositoryService.getModelEditorSource(modelData.getId())); BpmnModel bpmnModel = jsonConverter.convertToBpmnModel(editorNode); BpmnXMLConverter xmlConverter = new BpmnXMLConverter(); byte[] bpmnBytes = xmlConverter.convertToXML(bpmnModel); ByteArrayInputStream in = new ByteArrayInputStream(bpmnBytes); String filename = bpmnModel.getMainProcess().getId() + ".bpmn20.xml"; response.setContentType("application/xml"); response.setHeader("Content-Disposition", "attachment; filename=" + filename); IOUtils.copy(in, response.getOutputStream()); //Otherwise, the above sentence of set xml cannot be exported, response.flushBuffer(); } catch (Exception e) { throw new BaseException("activiti model export xml abnormal"); } }
Error saving model
Save model calls the saveModel method in the ModelSaveRestResource class. Serialize @ RequestBody in method. Therefore, if there is a problem that the parameters cannot be accepted when saving the model, you need the code here
test
Save after drawing process
You can see the modelId in the model list, and you can also edit and create a new model
The deployment process code is as follows. Start the process and complete the task, just like the actiBPM plug-in
/** * Deploy process according to modelId */ public String deploy(String id){ //Get model Model modelData = repositoryService.getModel(id); byte[] bytes = repositoryService.getModelEditorSource(modelData.getId()); if (bytes == null) { return "The model data is empty. Please design the process and save it successfully before publishing."; } JsonNode modelNode = null; try { modelNode = new ObjectMapper().readTree(bytes); } catch (IOException e) { e.printStackTrace(); } BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode); if(model.getProcesses().size()==0){ return "The data model does not meet the requirements, please design at least one main process."; } byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(model); //Release process String processName = modelData.getName() + ".bpmn20.xml"; Deployment deployment = null; try { deployment = repositoryService.createDeployment() .name(modelData.getName()) .addString(processName, new String(bpmnBytes, "UTF-8")) .deploy(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } modelData.setDeploymentId(deployment.getId()); repositoryService.saveModel(modelData); return "Process published successfully"; }