Einführung in Activiti mit Frühling

1. Übersicht

Einfach ausgedrückt ist Activiti eine Workflow- und Business Process Management-Plattform.

Wir können schnell loslegen, indem wir eine ProcessEngineConfiguration erstellen (normalerweise basierend auf einer Konfigurationsdatei). Daraus können wir eine ProcessEngine erhalten - und über die ProcessEngine können wir Workflow- und BPM-Operationen ausführen.

Die API bietet verschiedene Dienste, mit denen auf Prozesse zugegriffen und diese verwaltet werden können. Diese Dienste können uns Informationen über den Verlauf von Prozessen, die aktuell ausgeführten Prozesse und die Prozesse liefern, die bereitgestellt, aber noch nicht ausgeführt werden.

Die Dienste können auch verwendet werden, um die Prozessstruktur zu definieren und den Status des Prozesses zu manipulieren, dh Ausführen, Anhalten, Abbrechen usw.

Wenn Sie mit der API noch nicht vertraut sind, lesen Sie unsere Einführung in die Activiti-API mit Java . In diesem Artikel wird erläutert, wie wir die Activiti-API in einer Spring Boot-Anwendung einrichten können.

2. Setup mit Spring Boot

Mal sehen, wie wir Activiti als Spring Boot Maven-Anwendung einrichten und verwenden können.

2.1. Ersteinrichtung

Wie üblich müssen wir die Maven-Abhängigkeit hinzufügen:

 org.activiti activiti-spring-boot-starter-basic 

Die neueste stabile Version der API finden Sie hier. Es funktioniert mit Spring Boot bis v1.5.4. Es funktioniert noch nicht mit v2.0.0.M1.

Wir können auch ein Spring Boot-Projekt mit //start.spring.io generieren und Activiti als Abhängigkeit auswählen.

Durch Hinzufügen dieser Abhängigkeit und der Annotation @EnableAutoConfiguration zur Spring Boot-Anwendung wird die anfängliche Einrichtung durchgeführt:

  • Datenquelle erstellen (Die API benötigt eine Datenbank zum Erstellen der ProcessEngine. )
  • Erstellen und verfügbar machen Sie die ProcessEngine- Bean
  • Erstellen und verfügbar machen Sie die Activiti Services Beans
  • Erstellen Sie den Spring Job Executor

2.2. Erstellen und Ausführen eines Prozesses

Lassen Sie uns ein Beispiel für das Erstellen und Ausführen eines Geschäftsprozesses erstellen.

Um einen Prozess zu definieren, müssen wir eine BPMN-Datei erstellen. Dazu können wir //activiti.alfresco.com/activiti-app/editor verwenden, um eine Prozessdefinition zu erstellen.

Laden Sie dann einfach die BPMN-Datei herunter. Wir müssen diese Datei im Ordner src / main / resources / process ablegen. Standardmäßig sucht Spring Boot in diesem Ordner, um die Prozessdefinition bereitzustellen.

Wir erstellen einen Demo-Prozess mit Aufgaben eines Benutzers:

Der Verantwortliche der Benutzeraufgabe wird als Initiator des Prozesses festgelegt. Die BPMN-Datei für diese Prozessdefinition sieht folgendermaßen aus:

Jetzt erstellen wir einen REST-Controller, um Anforderungen zum Starten dieses Prozesses zu verarbeiten:

@Autowired private RuntimeService runtimeService; @GetMapping("/start-process") public String startProcess() { runtimeService.startProcessInstanceByKey("my-process"); return "Process started. Number of currently running" + "process instances = " + runtimeService.createProcessInstanceQuery().count(); }

Hier startet runtimeService.startProcessInstanceByKey ("mein Prozess") die Ausführung des Prozesses, dessen Schlüssel "mein Prozess" ist . Mit runtimeService.createProcessInstanceQuery (). count () erhalten wir die Anzahl der Prozessinstanzen.

Jedes Mal, wenn wir auf den Pfad "/ start-process" klicken, wird eine neue ProcessInstance erstellt, und die Anzahl der aktuell ausgeführten Prozesse wird erhöht.

Ein JUnit-Testfall zeigt uns dieses Verhalten:

@Test public void givenProcess_whenStartProcess_thenIncreaseInProcessInstanceCount() throws Exception { String responseBody = this.mockMvc .perform(MockMvcRequestBuilders.get("/start-process")) .andReturn().getResponse().getContentAsString(); assertEquals("Process started. Number of currently running" + " process instances = 1", responseBody); responseBody = this.mockMvc .perform(MockMvcRequestBuilders.get("/start-process")) .andReturn().getResponse().getContentAsString(); assertEquals("Process started. Number of currently running" + " process instances = 2", responseBody); responseBody = this.mockMvc .perform(MockMvcRequestBuilders.get("/start-process")) .andReturn().getResponse().getContentAsString(); assertEquals("Process started. Number of currently running" + " process instances = 3", responseBody); } 

3. Mit Prozessen spielen

Nachdem wir in Activiti einen laufenden Prozess mit Spring Boot ausgeführt haben, erweitern wir das obige Beispiel, um zu demonstrieren, wie wir auf den Prozess zugreifen und ihn bearbeiten können.

3.1. Rufen Sie die Liste der Aufgaben für eine bestimmte ProcessInstance ab

Wir haben zwei Benutzeraufgaben A und B . Wenn wir einen Prozess starten, wartet er darauf, dass die erste Aufgabe A abgeschlossen ist, und führt dann Aufgabe B aus . Erstellen wir eine Handler-Methode, die Anforderungen zum Anzeigen der Aufgaben für eine bestimmte processInstance akzeptiert .

Die Objekte können wie Task nicht direkt als Antwort gesendet werden. Daher müssen wir ein benutzerdefiniertes Objekt erstellen und die Task in unser benutzerdefiniertes Objekt konvertieren . Wir nennen diese Klasse TaskRepresentation :

class TaskRepresentation { private String id; private String name; private String processInstanceId; // standard constructors }

Die Handler-Methode sieht folgendermaßen aus:

@GetMapping("/get-tasks/{processInstanceId}") public List getTasks( @PathVariable String processInstanceId) { List usertasks = taskService.createTaskQuery() .processInstanceId(processInstanceId) .list(); return usertasks.stream() .map(task -> new TaskRepresentation( task.getId(), task.getName(), task.getProcessInstanceId())) .collect(Collectors.toList()); } 

Hier taskService.createTaskQuery (). ProcessInstanceId (processInstanceId) .list () verwendet Taskservice und bringt uns die Liste der Aufgaben an die gegebenen Zusammenhang processInstanceId . Wir können sehen, dass wir, wenn wir den von uns erstellten Prozess ausführen, die Aufgabe A erhalten, indem wir eine Anfrage an die gerade definierte Methode stellen:

@Test public void givenProcess_whenProcessInstance_thenReceivedRunningTask() throws Exception { this.mockMvc.perform(MockMvcRequestBuilders.get("/start-process")) .andReturn() .getResponse(); ProcessInstance pi = runtimeService.createProcessInstanceQuery() .orderByProcessInstanceId() .desc() .list() .get(0); String responseBody = this.mockMvc .perform(MockMvcRequestBuilders.get("/get-tasks/" + pi.getId())) .andReturn() .getResponse() .getContentAsString(); ObjectMapper mapper = new ObjectMapper(); List tasks = Arrays.asList(mapper .readValue(responseBody, TaskRepresentation[].class)); assertEquals(1, tasks.size()); assertEquals("A", tasks.get(0).getName()); }

3.2. Eine Aufgabe erledigen

Jetzt werden wir sehen, was passiert, wenn wir Aufgabe A abschließen . Wir erstellen eine Handler-Methode, die Anforderungen verarbeitet, um die Aufgabe A für die angegebene processInstance abzuschließen :

@GetMapping("/complete-task-A/{processInstanceId}") public void completeTaskA(@PathVariable String processInstanceId) { Task task = taskService.createTaskQuery() .processInstanceId(processInstanceId) .singleResult(); taskService.complete(task.getId()); }

taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult() creates a query on the task service and gives us the task of the given processInstance. This is the UserTask A. The next line taskService.complete(task.getId) completes this task.

Hence, now the process has reached the end and the RuntimeService doesn't contain any ProcessInstances. We can see this using the JUnit test case:

@Test public void givenProcess_whenCompleteTaskA_thenNoProcessInstance() throws Exception { this.mockMvc.perform(MockMvcRequestBuilders.get("/start-process")) .andReturn() .getResponse(); ProcessInstance pi = runtimeService.createProcessInstanceQuery() .orderByProcessInstanceId() .desc() .list() .get(0); this.mockMvc.perform(MockMvcRequestBuilders.get("/complete-task-A/" + pi.getId())) .andReturn() .getResponse() .getContentAsString(); List list = runtimeService.createProcessInstanceQuery().list(); assertEquals(0, list.size()); }

This is how we can use Activiti services work with processes.

4. Conclusion

In diesem Artikel haben wir die Übersicht über die Verwendung der Activiti-API mit Spring Boot durchgearbeitet . Weitere Informationen zur API finden Sie im Benutzerhandbuch. Wir haben auch gesehen, wie ein Prozess erstellt und verschiedene Vorgänge mit Activiti-Diensten ausgeführt werden.

Spring Boot macht die Verwendung einfach, da wir uns nicht um das Erstellen der Datenbank, das Bereitstellen der Prozesse oder das Erstellen der ProcessEngine kümmern müssen .

Beachten Sie, dass sich die Integration von Activiti in Spring Boot noch in der Versuchsphase befindet und von Spring Boot 2 noch nicht unterstützt wird.

Wie immer finden Sie die Implementierung aller Beispiele, die wir gesehen haben, auf GitHub.