Introduzione ad Activiti con Spring

1. Panoramica

In poche parole, Activiti è una piattaforma di workflow e Business Process Management.

Possiamo iniziare rapidamente creando un ProcessEngineConfiguration (in genere basato su un file di configurazione). Da questo, possiamo ottenere un ProcessEngine e attraverso ProcessEngine possiamo eseguire operazioni di flusso di lavoro e BPM.

L'API fornisce vari servizi che possono essere utilizzati per accedere e gestire i processi. Questi servizi possono fornirci informazioni sulla cronologia dei processi, su ciò che è attualmente in esecuzione e sui processi distribuiti ma non ancora in esecuzione.

I servizi possono essere utilizzati anche per definire la struttura del processo e manipolare lo stato del processo, ad esempio eseguire, sospendere, annullare, ecc.

Se non conosci l'API, dai un'occhiata alla nostra Introduzione all'API Activiti con Java . In questo articolo, discuteremo di come impostare l'API Activiti all'interno di un'applicazione Spring Boot.

2. Installazione con Spring Boot

Vediamo come possiamo configurare Activiti come applicazione Spring Boot Maven e iniziare a usarlo.

2.1. Configurazione iniziale

Come al solito, dobbiamo aggiungere la dipendenza Maven:

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

L'ultima versione stabile dell'API può essere trovata qui. Funziona con Spring Boot fino alla v1.5.4. Non funziona ancora con v2.0.0.M1.

Possiamo anche generare un progetto Spring Boot utilizzando //start.spring.io e selezionare Activiti come dipendenza.

Semplicemente aggiungendo questa dipendenza e l' annotazione @EnableAutoConfiguration all'applicazione Spring Boot, eseguirà la configurazione iniziale:

  • Crea origine dati (l'API richiede un database per creare ProcessEngine )
  • Crea ed esponi il bean ProcessEngine
  • Crea ed esponi i bean dei servizi Activiti
  • Crea lo Spring Job Executor

2.2. Creazione ed esecuzione di un processo

Costruiamo un esempio di creazione e gestione di un processo aziendale.

Per definire un processo avremo bisogno di creare un file BPMN. Per questo, possiamo utilizzare //activiti.alfresco.com/activiti-app/editor per creare una definizione di processo.

Quindi, scarica il file BPMN. Avremo bisogno di mettere questo file nella cartella src / main / resources / processi . Per impostazione predefinita, Spring Boot cercherà in questa cartella per distribuire la definizione del processo.

Creeremo un processo demo contenente le attività di un utente:

L'assegnatario dell'attività utente viene impostato come iniziatore del processo. Il file BPMN per questa definizione di processo ha il seguente aspetto:

Ora creeremo un controller REST per gestire le richieste per avviare questo processo:

@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(); }

Qui, runtimeService.startProcessInstanceByKey ("my-process") avvia l'esecuzione del processo la cui chiave è "my-process" . runtimeService.createProcessInstanceQuery (). count () ci fornirà il numero di istanze di processo.

Ogni volta che raggiungiamo il percorso "/ start-process" , verrà creata una nuova ProcessInstance e vedremo un incremento nel conteggio dei processi attualmente in esecuzione.

Un test case JUnit ci mostra questo comportamento:

@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. Giocare con i processi

Ora che abbiamo un processo in esecuzione in Activiti che utilizza Spring Boot, estendiamo l'esempio sopra per dimostrare come possiamo accedere e manipolare il processo.

3.1. Ottieni l'elenco delle attività per un determinato ProcessInstance

Abbiamo due attività utente A e B . Quando iniziamo un processo, sarà attendere che il primo compito Un essere completato e quindi eseguirà compito B . Creiamo un metodo gestore che accetti richieste per visualizzare le attività relative a un dato processInstance .

Gli oggetti, come Task , non possono essere inviati direttamente come risposta e quindi dobbiamo creare un oggetto personalizzato e convertire il Task nel nostro oggetto personalizzato. Chiameremo questa classe TaskRepresentation :

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

Il metodo del gestore sarà simile a:

@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()); } 

Qui, taskService.createTaskQuery (). ProcessInstanceId (processInstanceId) .list () usa TaskService e ci fornisce l'elenco delle attività relative al dato processInstanceId . Possiamo vedere che quando iniziamo a eseguire il processo che abbiamo creato, otterremo l'attività A facendo una richiesta al metodo che abbiamo appena definito:

@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. Il completamento di un compito

Ora, vedremo cosa succede quando si completa compito A . Creiamo un metodo di gestore che gestirà le richieste per completare il compito A per il dato processInstance :

@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 questo articolo, abbiamo esaminato la panoramica dell'utilizzo dell'API Activiti con Spring Boot . Ulteriori informazioni sull'API sono disponibili nella guida dell'utente. Abbiamo anche visto come creare un processo ed eseguire varie operazioni su di esso utilizzando i servizi Activiti.

Spring Boot lo rende facile da usare poiché non dobbiamo preoccuparci di creare il database, distribuire i processi o creare ProcessEngine .

Tieni presente che l'integrazione di Activiti con Spring Boot è ancora in fase sperimentale e non è ancora supportata da Spring Boot 2.

Come sempre, l'implementazione di tutti gli esempi che abbiamo visto può essere trovata su GitHub.