Introduction à Activiti avec Spring

Introduction à Activiti avec Spring

1. Vue d'ensemble

En termes simples,Activiti is a workflow and Business Process Management platform.

Nous pouvons commencer rapidement en créant unProcessEngineConfiguration (généralement basé sur un fichier de configuration). À partir de là, nous pouvons obtenir unProcessEngine - et grâce auxProcessEngine,, nous pouvons exécuter des opérations de flux de travail et BPM.

L'API fournit divers services pouvant être utilisés pour accéder aux processus et les gérer. Ces services peuvent nous fournir des informations sur l'historique des processus, ce qui est en cours d'exécution et les processus qui sont déployés mais pas encore en cours d'exécution.

Les services peuvent également être utilisés pour définir la structure du processus et manipuler l’état du processus, c.-à-d. exécuter, suspendre, annuler, etc.

Si vous êtes nouveau dans l'API, consultez nosIntroduction to Activiti API with Java. Dans cet article, nous verrons comment nous pouvons configurer l'API Activiti dans une application Spring Boot.

2. Configuration avec Spring Boot

Voyons comment nous pouvons configurer Activiti en tant qu'application Spring Boot Maven et commencer à l'utiliser.

2.1. La configuration initiale

Comme d'habitude, nous devons ajouter la dépendance maven:


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

La dernière version stable de l'API peut être trouvéehere. Cela fonctionne avec Spring Boot up à travers v1.5.4. Cela ne fonctionne pas encore avec la v2.0.0.M1.

Nous pouvons également générer un projet Spring Boot en utilisanthttps://start.spring.io et sélectionner Activiti comme dépendance.

En ajoutant simplement cette dépendance et l'annotation@EnableAutoConfiguration à l'application Spring Boot, il effectuera la configuration initiale:

  • Créer une source de données (l'API nécessite une base de données pour créer lesProcessEngine)

  • Créer et exposer le beanProcessEngine

  • Créer et exposer les beans services Activiti

  • Créer le programme d'exécution de travaux de printemps

2.2. Créer et exécuter un processus

Construisons un exemple de création et d’exécution d’un processus métier.

Pour définir un processus, nous devrons créer un fichier BPMN. Pour cela, nous pouvons utiliserhttps://activiti.alfresco.com/activiti-app/editor pour créer une définition de processus.

Ensuite, il suffit de télécharger le fichier BPMN. Nous aurons besoin de mettre ce fichier dans le dossiersrc/main/resources/processes. Par défaut, Spring Boot examinera ce dossier pour déployer la définition du processus.

Nous allons créer un processus de démonstration contenant une tâche utilisateur:

image

Le destinataire de la tâche utilisateur est défini en tant qu'initiateur du processus. Le fichier BPMN de cette définition de processus se présente comme suit:

 
     
     
     
     
     
     
     
     
     
     

Nous allons maintenant créer un contrôleur REST pour gérer les demandes de démarrage de ce processus:

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

Ici,runtimeService.startProcessInstanceByKey(“my-process”) démarre l'exécution du processus dont la clé est“my-process”. runtimeService.createProcessInstanceQuery().count() nous donnera le nombre d'instances de processus.

Chaque fois que nous atteignons le chemin“/start-process”, un nouveauProcessInstance sera créé et nous verrons un incrément du nombre de processus en cours d'exécution.

Un cas de test JUnit nous montre ce comportement:

@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. Jouer avec les processus

Maintenant que nous avons un processus en cours dans Activiti à l'aide de Spring Boot, étendons l'exemple ci-dessus pour montrer comment nous pouvons accéder et manipuler le processus.

3.1. Obtenir la liste desTasks pour unProcessInstance donné

Nous avons deux tâches utilisateurA etB. Lorsque nous démarrons un processus, il attend que la première tâcheA soit terminée, puis exécute la tâcheB. Créons une méthode de gestion qui accepte les requêtes pour afficher les tâches liées à unprocessInstance donné.

Les objets, commeTask, ne peuvent pas être envoyés directement en tant que réponse et nous devons donc créer un objet personnalisé et convertir lesTask en notre objet personnalisé. Nous appellerons cette classeTaskRepresentation:

class TaskRepresentation {
    private String id;
    private String name;
    private String processInstanceId;

    // standard constructors
}

La méthode du gestionnaire ressemblera à:

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

Ici,taskService.createTaskQuery().processInstanceId(processInstanceId).list() utiliseTaskService et nous donne la liste des tâches liées auxprocessInstanceId donnés. Nous pouvons voir que lorsque nous commencerons à exécuter le processus que nous avons créé, nous obtiendrons la tâcheA en faisant une requête à la méthode que nous venons de définir:

@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. Terminer unTask

Maintenant, nous allons voir ce qui se passe lorsque nous terminons la tâcheA. Nous créons une méthode de gestion qui gérera les demandes pour terminer la tâcheA pour lesprocessInstance donnés:

@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() crée une requête sur le service de tâche et nous donne la tâche desprocessInstance donnés. Ce sont lesUserTask A. La ligne suivantetaskService.complete(task.getId) termine cette tâche. Par conséquent, maintenant le processus a atteint la fin et leRuntimeService ne contient aucunProcessInstances. Nous pouvons le voir à l'aide du scénario de test JUnit:

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

Voici comment nous pouvons utiliser les services Activiti avec les processus.

4. Conclusion

Dans cet article, nous avons parcouru la vue d'ensemble de l'utilisation de l'API Activiti avec Spring Boot. Pour plus d'informations sur l'API, consultez lesuser guide. Nous avons également vu comment créer un processus et y exécuter diverses opérations à l'aide des services Activiti.

Spring Boot le rend facile à utiliser car nous n'avons pas à nous soucier de la création de la base de données, du déploiement des processus ou de la création desProcessEngine.

N'oubliez pas que l'intégration d'Activiti avec Spring Boot en est encore à la phase expérimentale et qu'elle n'est pas encore prise en charge par Spring Boot 2.

Comme toujours, l'implémentation de tous les exemples que nous avons vus peut être trouvéeover on GitHub.