Gestion des processus métiers : embarquez un moteur BPM dans votre application JHipster !

JHipster nous permet de générer un socle applicatif. Nous avons des entités, des utilisateurs, des droits, un front end en Angular… Mais qu’en est-il des processus métiers ? Qu’en est-il du cycle de vie de nos entités ?

Trop souvent, les processus métiers sont gérés “à la main” dans notre code Java. En conséquence, nous faisons notre possible pour les simplifier au maximum, le principe agile du KISS (Keep It Simple Stupid) devant rester à la base de nos applications.

Malheureusement, l’expérience montre que les processus en entreprise ne vont pas toujours vers la simplification et que leur maintenance devient parfois un vrai casse-tête lorsqu’ils sont gérés (plus ou moin bien) au niveau du code. En effet, il est nécessaire de les spécifier (d’en extraire de bonnes user stories), de les modéliser, de les coder, de les tester. Mais nous manquons cruellement d’outils communs entre les business analysts et les développeurs. Alors, ne laissons pas le code de nos applications métiers devenir inextricable et pour celà pensons BPM.

Pendant longtemps, les BPM (Business Process Manager) ou moteurs de workflow ont été synonymes d’usines à gaz propriétaires, zéro-code, coûteuses, non modulaires. Elles ont de ce fait mauvaise presse chez les développeurs. Ce n’est plus vrai aujourd’hui : il existe des BPM légers, embarquables et qui ressemblent à une librairie pour les développeurs. Grâce à Spring Boot et aux spring boot starters, les BPMs ont droit à une nouvelle chance ! J’espère que cet article aidera à leur démystification et vous donnera envie de les essayer. Recentrons nos applications sur les processus métiers pour mieux répondre aux besoins métiers !

Rappels : Qu’est ce qu’un moteur de workflow, ou BPM ?

Définitions

La gestion de processus (ou Process Management) représente les techniques d'organisation par la décomposition en différents stades de réalisation d'une opération économique.

Un moteur de workflow est un dispositif logiciel permettant d'exécuter des instances de workflow.

Un workflow est l'enchaînement de plusieurs activités décrites au sein d’une définition de processus.

Il existe des processus purement techniques et des processus mixtes (techniques et humains)

Un exemple de workflow technique :

  • Le processus de création de compte utilisateur sur un portail bancaire

Un exemple de workflow mixte :

  • Une demande de congés, avec validation du manager (le classique !)

Les normes en vigueur

BPMN

"Business Process Model and Notation" (BPMN en anglais) est un standard pour la représentation des processus métiers. Les moteurs de workflow actuels sont compatibles avec la version 2 de ce standard ISO/CEI 1951 (depuis 2013). Il permet de modéliser les processus métiers de manière à ce que cette modélisation soit indépendante du moteur de workflow utilisé. Par contre, BPMN ne comprend que des éléments de représentation, et chaque moteur étend le modèle pour y ajouter des éléments d’implémentation (par exemple : quel service appeler pour chaque tâche ?). En pratique, il s’agit d’un schéma XML associé à une représentation visuelle.

Un exemple de BPMN

Un process simple pour approuver un tweet !

twitter-camunda

Il existe bien sûr des outils pour modéliser les processus. Le BPMN est un outil pour aider les gens du métier dans la modélisation de leurs processus. Il permet au développeur de disposer d’un modèle utilisable pour l’implémentation. Le BPMN s’intègre bien dans un mode de développement multidisciplinaire.

En pratique, on a toujours deux versions des définitions :

  • Une version “métier” aux mains des business analysts, descriptive.
  • Une version d'exécution “technique”, qui contient les éléments d’implémentation.

Il existe même des outils pour synchroniser et faire vivre ces deux versions, par exemple l’outil Cycle de camunda : https://docs.camunda.org/manual/7.8/webapps/cycle/#bpmn-2-0-roundtrip

Pour simplifier, le métier va orchestrer les processus et le développeur va les implémenter unitairement.

DMN

Les moteurs de workflow ne font pas que du BPM ! Il est en effet fréquent, lors d’un processus métiers, de recourir à des étapes de décision. Ces étapes sont difficilement modélisables en BPMN. C’est pour cela qu'a été conçu Decision Model and Notation (DMN), ce sont des tables de décision.

Une table de décision est une représentation tabulaire d'un ensemble d'expressions, organisées dans des règles métiers indiquant quelles données en entrée vont s'appliquer au système.

La table de décision contient toutes les expressions nécessaires pour déterminer les données en sortie. De plus, une table complète contient toutes les combinaisons possibles d'expressions. Un des buts de DMN est de normaliser des formes différentes et les types de tables de décision.

Une table de décision consiste en :

  • Un nom : usuellement c'est le nom du modèle de connaissance métier pour lequel la table de décision fournit la logique de décision.
  • Un libellé, décrivant les données produites par la table de décision. Le résultat d'une table de décision est référencé en utilisant le nom de l'information.
  • Un ensemble d'expressions en entrée.
  • Un ensemble de données en sortie. Chaque donnée produite en sortie sera nommée.
  • Une liste de règles (une ou plusieurs) en lignes (ou en colonnes) de la table (selon l'orientation), où chaque règle est composée des expressions en entrée spécifiques et les données produites en sortie. Si les règles sont exprimées comme des lignes, les colonnes sont des clauses et vice versa.

Un exemple de DMN

Comment choisir son plat, en fonction des invités et de la saison ?
S-lection_019
De plus, il est possible de chaîner ensemble plusieurs tables de décision, afin de connaître le menu complet !
S-lection_020
Vous pouvez tester ce modèle DMN à l’adresse : https://camunda.com/dmn/simulator/

CMMN

BPMN est un outil très adapté pour les processus structurés, mais dans le cas de processus moins structurés il y a besoin de plus de flexibilité. Un autre standard a été créé en 2005, il s’agit de CMMN : Case Management Model and Notation.
CMNN est centré sur les tâches, alors que BPMN est centré sur le processus.

Un exemple de CMMN

La maintenance d’une chambre d’hôtel !
camunda-cmmn

Avantages à utiliser un moteur de workflow ?

Lorsque vous utilisez un moteur de workflow, vous bénéficiez de plusieurs avantages :

  • Explicit processes : Les processus deviennent explicites au lieu d'être “enterrés” quelque part dans votre code et peuvent donc être modifiés beaucoup plus facilement et dynamiquement sans relancer votre application.
  • Gestion de l’état : Le moteur de workflow est en charge de la persistance de chaque instance.
  • Transparence du statut : le statut de chaque instance peut être vérifié à chaque instant en requêtant simplement le moteur de workflow. Le monitoring peut se faire directement sur le diagramme graphique.
  • Visibilité : la modélisation graphique peut être utilisée pour discuter du processus entre les personnes du métier et les développeurs, ainsi qu’entre les développeurs et les Ops.
  • Gestion des erreurs : Dès qu’une erreur survient dans un processus, il est possible de spécifier le comportement à avoir. Il est aussi possible de relancer et de visualiser les instances en erreurs.
  • Gestion des timeout : Le moteur peut prendre une décision ou changer son chemin dans le processus si un message n’arrive pas dans les temps par exemple :
    S-lection_027

Camunda : un moteur embarquable

Camunda ?

Camunda est un moteur de workflow Open Source (Apache 2 License), qui peut être embarqué dans vos applicatifs et vos microservices. Il est léger, facile à intégrer. C’est un fork du BPM Activiti, qui est présent dans la GED Alfresco. Il est plus vivant, et soutenu par des références solides comme Zalando, Allianz, ou Deutsch Bahn. Il possède une version Enterprise avec support. Celle-ci s’appuie sur le même moteur que la version Open Source, mais fournit des outils de suivi plus complets (voir ici).

Bien sûr il en existe d’autres dans le monde Open Source comme Flowable, JBPM ou Bonita.

Camunda est constitué de plusieurs briques/services indépendants :

  • Un moteur (camunda-engine)
  • Des applications web pour le suivi et l’instanciation des process. Celles-ci sont optionnelles !

camunda-archi

Pour la partie scalabilité je vous invite à lire la page : https://camunda.org/scalability/#clustering

Du concret : Embarquons le moteur de BPM camunda dans JHipster

Créons un projet JHipster dans lequel il sera possible de lancer un workflow technique simple avec une étape technique de type “hello world”, le tout bien sûr propulsé par camunda !

Voici donc notre premier workflow cible :

test-1

Ce workflow sera déclenché par un “signal” de type “SayHello”.
Le code source de l’application de test se trouve sur https://gitlab.ippon.fr/hfongarnand/jhipster-bpm-camunda

Génération d’un projet JHipster

Comme toujours avec JHipster, l’histoire commence avec la commande ‘jhipster’ (une fois JHipster installé bien évidemment !).

S-lection_021
Enfin, on va ajouter dans le build Maven, les dépendances nécessaires pour le starter camunda

<properties>
   <camunda.springboot.version>2.3.0</camunda.springboot.version>
</properties>


<dependency>
   <groupId>org.camunda.bpm.springboot</groupId>
   <artifactId>camunda-bpm-spring-boot-starter</artifactId>
   <version>${camunda.springboot.version}</version>
</dependency>
<dependency>
   <groupId>org.camunda.bpm.springboot</groupId>
   <artifactId>camunda-bpm-spring-boot-starter-webapp</artifactId>
   <version>${camunda.springboot.version}</version>
</dependency>

Il est ensuite nécessaire de faire quelques modifications dans la classe fr.ippon.jhipster.bpm.config.SecurityConfiguration, afin de nous laisser accéder aux interfaces de suivi de camunda.
Ajouter :

.antMatchers("/api/cockpit/**").permitAll()
.antMatchers("/api/tasklist/**").permitAll()
.antMatchers("/api/engine/**").permitAll()
.antMatchers("/api/admin/**").permitAll()

dans la méthode protected void configure(HttpSecurity http) throws Exception

Ajouter ensuite dans votre application.yml

camunda:
    bpm:
        admin-user:
            id: admin
            password: admin

Ceci fait, vous pouvez lancer votre application et accéder à l’URL
http://localhost:8080/app/

camunda-welcome

Une fois l’utilisateur admin et le mot de passe admin entrés, vous accédez à l’écran suivant :

camunda-screen1

Création de la définition de notre processus.

Tout d’abord, il vous faut récupérer l’outil “modeler”, qui vous permettra d’éditer vos définitions de workflow sur : https://camunda.com/download/modeler/

Une fois installé, vous pouvez commencer à dessiner votre premier process.

  1. Un process commence toujours par un “Start Event” (il est déjà créé). Il suffit de changer son type en “Signal Start Event”
    Dans la section détail de l'événement, saisir sayHello dans la partie Signal Name
    camunda-start-event

  2. Ajouter une tâche et changer son type en “Service Task”
    Dans la section détail, choisir l’implémentation “expression” et saisir #{printer.printMessage(execution)}
    Ceci revient à dire : appelle la méthode printMessage du bean nommé printer en passant le contexte d'exécution du workflow
    camunda-task

  3. Ajouter un End Event à la fin du workflow

  4. Enregistrer la définition du workflow (Save file as) dans le répertoire src/main/resources/ de notre projet jhipster

Relancer le projet et aller dans l’application cockpit : http://localhost:8080/app/cockpit/default/, votre définition de processus devrait être déployée !

S-lection_026

Camunda déploie au lancement de l’application tous les fichiers en .bpmn et .dmn qu’il va trouver dans votre classpath.

Il est possible de déployer vos définitions à chaud, soit via l’API REST https://docs.camunda.org/manual/7.8/reference/rest/deployment/post-deployment/
soit via l’API Java. En version entreprise cette mise à jour peut se faire directement dans Cockpit.

Implémentation de notre Service “task” technique.

Il suffit juste de créer un classique bean Spring !

@Service
public class Printer {

   private final Logger log = LoggerFactory.getLogger(this.getClass());

   public void printMessage(DelegateExecution execution) {
       log.info("Hello world " + execution.getVariable("date"));
   }
}

Cet tâche crée un log en récupérant une variable de l’instance de workflow.
Le paramètre “execution” permet de récupérer le contexte de l’instance courante.

Implémentation d’un service REST pour lancer un signal au moteur de workflow

Là aussi, il suffit de créer un simple contrôleur REST.
On lui injecte le RuntimeService camunda, qui permet de piloter le moteur de workflow.

@RestController
@RequestMapping("/api/bpm")
public class BPMResource {

   private final RuntimeService runtimeService;

   public BPMResource(RuntimeService runtimeService) {
       this.runtimeService = runtimeService;
   }

   @PostMapping("/signals")
   @Timed
   public ResponseEntity<Void> sendSignal(@RequestBody String signal) {
       SignalEventReceivedBuilder signalEvent = runtimeService.createSignalEvent(signal);
       signalEvent.setVariables(ImmutableMap.of("date", LocalDateTime.now()));
       signalEvent.send();
       return ResponseEntity.noContent().build();
   }
}

Lancer notre workflow via Swagger

Vous pouvez tester votre API REST via Swagger à l’URL : http://localhost:9000/swagger-ui/index.html#!/bpm45resource/sendSignalUsingPOST

Passez en paramètre sayHello, vous devriez voir apparaître dans les logs :

[aTaskExecutor-2] fr.ippon.jhipster.bpm.tasks.Printer : Hello world 2017-12-19T17:31:27.647

Les tests

Camunda fournit un framework de test pour JUnit.
Une bibliothèque d’assertion pour vos workflows :
https://github.com/camunda/camunda-bpm-assert

Un outil permettant de vérifier graphiquement la couverture de vos tests :
https://github.com/camunda/camunda-bpm-process-test-coverage

camunda-test-coverage

Un test unitaire avec couverture est présent dans l’exemple : https://gitlab.ippon.fr/hfongarnand/jhipster-bpm-camunda/blob/master/src/test/java/fr/ippon/jhipster/bpm/process/TestProcessTest.java

Pour aller plus loin !

Des livres blancs

L’utilisation d’un BPM dans un contexte Microservices :
https://camunda.com/learn/whitepapers/microservices-and-bpm/

La référence BPMN V2

https://docs.camunda.org/manual/7.8/reference/bpmn20/

Un plugin JHipster ?...