Activiti - Moteur de processus métier

Framework Activiti (Java) - description du flux de tâches XML (bpm) et de sa gestion. Je décrirai ici les concepts de base et comment construire des processus métier simples.

Le concept principal d'Activiti est un processus et une tâche. Un processus est l'ensemble des tâches interconnectées par des flux et des branches dirigés.

Je vais aborder ces aspects:

  • - Activiti dans sa forme la plus pure
  • - Utilisateurs, rôles
  • - Connecter SpringBoot
  • - API REST
  • - Emploi et délégué

Le mouvement des flux se fait par étapes d'une tâche à l'autre, chacune de ces étapes suspend le processus en attendant la saisie et la fin de la tâche, toutes les actions intermédiaires sont stockées dans la base de données.

Où, quoi prendre, je vais l'indiquer ci-dessous. Commençons par un exemple simple - le processus de développement de programme, qui consiste à écrire du code et à tester. Voici un diagramme de processus.

image

Tout cela est un processus, il a un ID, un nom et d'autres caractéristiques.

image

Il a:

Le début du processus, deux tâches «Développer» et «Tester», une branche (passerelle) et la fin du processus. En mots, tout se passe comme ceci:

  • chargement de la description du bpm
  • démarrer le processus
  • après le début, nous tombons immédiatement dans la tâche de développement
  • après l'exécution de Develop, il passe en test et selon le résultat du test, le processus se termine ou revient au développement.

Activiti se compose d'un ensemble de services

En voici les principaux:

  • RepositoryService: contrôle le chargement des descriptions de processus
  • RuntimeService: démarre les processus
  • TaskService: effectue des tâches
  • FormService: accès aux variables de tâches
  • HistoryService: accès à l'historique des processus
  • IdentityService: utilisateurs et rôles

Activiti dans sa forme la plus pure


Mais tout commence par la configuration et le fichier - activiti.cfg.xml.

De cela

ProcessEngineConfiguration cfg = ProcessEngineConfiguration .createProcessEngineConfigurationFromResource("activiti.cfg.xml"); 

Si vous n'utilisez pas votre configuration, Activiti déploiera la base de données dans la mémoire H2 elle-même, cela ne me convient pas, mais mon cher Oracle est plein, il existe des options pour connecter différentes bases de données.

Voici ma configuration

activiti.cfg.xml
 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration"> <property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:xe" /> <property name="jdbcDriver" value="oracle.jdbc.driver.OracleDriver" /> <property name="jdbcUsername" value="BPM" /> <property name="jdbcPassword" value="1" /> <!-- Database configurations --> <property name="databaseSchemaUpdate" value="false" /> <property name="asyncExecutorActivate" value="false" /> <!-- mail server configurations --> <property name="mailServerPort" value="5025" /> </bean> </beans> 


Nous modifions les valeurs dans "nom de la propriété = jdbc *" et connectons une autre base de données

Structure du projet



POM
 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>DemoActiviti</groupId> <artifactId>DemoActiviti</artifactId> <version>1.0-SNAPSHOT</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.activiti</groupId> <version>6.0.0</version> <artifactId>activiti-spring-boot-starter-integration</artifactId> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.21</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.21</version> </dependency> <dependency> <groupId>com.oracle</groupId> <artifactId>ojdbc6</artifactId> <version>11.2.0</version> </dependency> </dependencies> <build> <plugins> <!-- Maven Assembly Plugin --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>2.4.1</version> <configuration> <!-- get all project dependencies --> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <!-- MainClass in mainfest make a executable jar --> <archive> <manifest> <mainClass>com.example.DemoActiviti</mainClass> </manifest> </archive> </configuration> <executions> <execution> <id>make-assembly</id> <!-- bind to the packaging phase --> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project> 


La présence du plugin "maven-assembly-plugin" dans le POM vous permettra de construire (empaqueter) un jar qui sera lancé avec des dépendances et exécuté -
 java -jar DemoActiviti-1.0-SNAPSHOT-jar-with-dependencies.jar 

pilote jdbc pour Oracle installé dans le référentiel maven local

 mvn install:install-file -Dfile={Path/to/your/ojdbc6.jar} -DgroupId=com.oracle -DartifactId=ojdbc6 -Dversion=11.2.0 -Dpackaging=jar 

log4j
 log4j.rootLogger=WARN, ACT log4j.appender.ACT=org.apache.log4j.ConsoleAppender log4j.appender.ACT.layout=org.apache.log4j.PatternLayout log4j.appender.ACT.layout.ConversionPattern= %d{hh:mm:ss,SSS} [%t] %-5p %c %x - %m%n 


Pour ce processus, nous définissons 4 actions: chargement bpm, démarrage du processus, développement et test. Chaque action aura un paramètre correspondant: déployer, démarrer, développer, tester.

Nous prenons des scripts pour une base de données de
activiti-get-started
là dans le dossier \ activiti-6.0.0 \ activiti-6.0.0 \ database \ create - scripts pour créer une base de données

Utilisateurs, rôles


Préparez les utilisateurs et les rôles:

Identité
 public class DemoActiviti { private static final String DEV_PROCESS = "devProcess"; public static void main(String[] args) { Locale.setDefault(Locale.ENGLISH); ProcessEngineConfiguration cfg = ProcessEngineConfiguration .createProcessEngineConfigurationFromResource("activiti.cfg.xml"); ProcessEngine processEngine = cfg.buildProcessEngine(); createIdentity(processEngine, "programmer", "programmers"); createIdentity(processEngine, "tester", "testers"); } public static void createIdentity(ProcessEngine processEngine, String userName, String userGroup) { IdentityService identityService = processEngine.getIdentityService(); String userId = userName + "Id"; if (identityService.createUserQuery().userId(userId).count() == 0) { User user = identityService.newUser(userName); user.setId(userId); user.setEmail(userName + "@gmail.com"); identityService.saveUser(user); System.out.println("user created success fully"); } String groupId = userGroup + "Id"; if (identityService.createGroupQuery().groupId(groupId).count() == 0) { Group group = identityService.newGroup(userGroup); group.setName(userGroup); group.setId(groupId); identityService.saveGroup(group); System.out.println("group created success fully"); } if (identityService.createGroupQuery().groupId(groupId).list().size() > 0) { identityService.createMembership(userId, groupId); System.out.println("user to group success fully"); } } } 


Créez respectivement des utilisateurs et des groupes, développeur et testeur.

Dans la base de données, toutes les tables sont divisées par les services correspondants et ont des préfixes

ACT_RE_ *: référentiel.
ACT_RU_ *: runtime.
ACT_ID_ *: identité.
ACT_HI _ *: historique
et ainsi de suite

Après avoir créé des utilisateurs à partir de, vous pouvez voir ici

image

Nous assignerons nos tâches dans la description aux groupes correspondants (CandidateGroup), par exemple, la tâche Développer au groupe - programmeurs

image

Et donc la première chose que nous faisons est de placer dans la base de données "MyProcess.bpmn", exécutez le programme avec la commande deploy

 java -jar DemoActiviti-1.0-SNAPSHOT-jar-with-dependencies.jar deploy 

ensuite, démarrez le processus de démarrage

 java -jar DemoActiviti-1.0-SNAPSHOT-jar-with-dependencies.jar start 

Après le processus de lancement et de démarrage, les entrées correspondantes apparaîtront dans la base de données.

Dépôt

image

Exécuter quelle tâche est en cours d'exécution

image

à qui est attribué

image

Dans le code, cela ressemble à ceci (le code complet sera ci-dessous):

déployer

 deployment = repositoryService.createDeployment() .addClasspathResource("processes/MyProcess.bpmn").deploy() 

commencer

 ProcessInstance myProcess = runtimeService.startProcessInstanceByKey(DEV_PROCESS); 

développer

Après cela, vous pouvez commencer à terminer la tâche de développement.

 java -jar DemoActiviti-1.0-SNAPSHOT-jar-with-dependencies.jar develop 

  //    tasks = taskService.createTaskQuery().taskCandidateGroup("programmers").list(); 

Dans la tâche de développement, une variable «problème» est définie

image

Après avoir traité les variables à l'aide de FormService, la tâche s'exécute

 for (Task task : tasks) { System.out.println("Task:" + task.getTaskDefinitionKey() + ", id=" + task.getId()); FormData formData = formService.getTaskFormData(task.getId()); Map<String, Object> variables = new HashMap<String, Object>(); //   for (FormProperty formProperty : formData.getFormProperties()) { System.out.println("Enter varName <" + formProperty.getName() +">:"); String value = scanner.nextLine(); variables.put(formProperty.getId(), value); } //   taskService.complete(task.getId(), variables); System.out.println("Task complete success:" + task.getTaskDefinitionKey()); } 

image

Pour la tâche de développement, vous serez invité à entrer une variable.

Dans le tableau historique, vous pouvez voir les variables et les valeurs de la tâche, du processus

image

Ainsi, le processus après que la tâche de développement s'arrête dessus, l'état sera enregistré dans la base de données.

En général, la boucle ressemble à ceci:

Demander une tâche pour un exécuteur testamentaire

 tasks = taskService.createTaskQuery().taskCandidateGroup("...").list(); 

Définition des variables

 Map<String, Object> variables = new HashMap<String, Object>(); ... variables.put("var_1", value); 

Exécution de tâche

 taskService.complete(task.getId(), variables); 

Vérification de la fin du processus

 ProcessInstance processInstance = runtimeService.createProcessInstanceQuery() .processInstanceId(processInstance.getId()).singleResult(); if (processInstance != null && !processInstance.isEnded()) 

Après chaque exécution de tâche, le processus est suspendu jusqu'à ce qu'une nouvelle tâche soit terminée.
Donc, après avoir exécuté Develop, passons à la tâche Test, ici on nous demandera également d'entrer la variable "devResult" - le résultat de développement (cela n'a pas fonctionné tout à fait correctement, même avant le démarrage de Test, entrez le résultat), puis le résultat sera de ramification ou de fin (Ok) ou développement à nouveau (Non), voir diagramme de processus.

image

Dans ce cas, le développement, etc. Si vous demandez maintenant des tâches pour le développeur, elles le seront, mais pour les tests - non.

Code de programme
 package com.example; import org.activiti.engine.*; import org.activiti.engine.form.FormData; import org.activiti.engine.form.FormProperty; import org.activiti.engine.repository.Deployment; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Task; import org.apache.commons.lang3.StringUtils; import java.util.*; public class DemoActiviti { private static final String DEV_PROCESS = "devProcess"; public static void main(String[] args) { Locale.setDefault(Locale.ENGLISH); ProcessEngineConfiguration cfg = ProcessEngineConfiguration .createProcessEngineConfigurationFromResource("activiti.cfg.xml"); ProcessEngine processEngine = cfg.buildProcessEngine(); RepositoryService repositoryService = processEngine.getRepositoryService(); String mode = StringUtils.EMPTY; if (args.length > 0) { mode = args[0]; } System.out.println("Processes mode: " + mode); Deployment deployment; if ("deploy".equals(mode)) { deployment = repositoryService.createDeployment() .addClasspathResource("processes/MyProcess.bpmn").deploy(); System.out.println("deploy process success"); System.exit(0); } else { List<Deployment> myProcesses = repositoryService.createDeploymentQuery() .processDefinitionKey(DEV_PROCESS).list(); deployment = myProcesses.get(myProcesses.size()-1); System.out.println("get process success:" + deployment.getId()); } // RuntimeService runtimeService = processEngine.getRuntimeService(); ProcessInstance processInstance; if ("start".equals(mode)){ ProcessInstance myProcess = runtimeService.startProcessInstanceByKey(DEV_PROCESS); System.out.println("start process success:" + myProcess.getName() +", id="+ myProcess.getId()); System.exit(0); } processInstance = runtimeService.createProcessInstanceQuery().deploymentId(deployment.getId()).singleResult(); TaskService taskService = processEngine.getTaskService(); FormService formService = processEngine.getFormService(); List<Task> tasks = new ArrayList<>(); if ("develop".equals(mode)) { System.out.println("develop mode"); //     tasks = taskService.createTaskQuery().taskCandidateGroup("programmers").list(); if (tasks.isEmpty()) { System.out.println("   "); System.exit(0); } } if ("test".equals(mode)) { System.out.println("test mode"); //     tasks = taskService.createTaskQuery().taskCandidateGroup("testers").list(); if (tasks.isEmpty()) { System.out.println("   "); System.exit(0); } } Scanner scanner = new Scanner(System.in); if (processInstance != null && !processInstance.isEnded()) { System.out.println("tasks count: [" + tasks.size() + "]"); for (Task task : tasks) { System.out.println("Task:" + task.getTaskDefinitionKey() + ", id=" + task.getId()); FormData formData = formService.getTaskFormData(task.getId()); Map<String, Object> variables = new HashMap<String, Object>(); //   for (FormProperty formProperty : formData.getFormProperties()) { System.out.println("Enter varName <" + formProperty.getName() +">:"); String value = scanner.nextLine(); variables.put(formProperty.getId(), value); } //   taskService.complete(task.getId(), variables); System.out.println("Task complete success:" + task.getTaskDefinitionKey()); } // Re-query the process instance, making sure the latest state is available //processInstance = runtimeService.createProcessInstanceQuery() // .processInstanceId(processInstance.getId()).singleResult(); } } } 


Connecter SpringBoot


Nous modifions le projet en utilisant Spring

Ajouter des dépendances à POM

POM avec SpringBoot
  <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.1.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencies> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring-boot-starter-basic</artifactId> <version>6.0.0</version> </dependency> <dependency> <groupId>org.activiti</groupId> <version>6.0.0</version> <artifactId>activiti-spring-boot-starter-integration</artifactId> </dependency> .... 


La classe DemoActiviti est devenue telle
DemoActiviti - SpringBootApplication
 @SpringBootApplication @ImportResource("classpath:activiti.cfg.xml") public class DemoActiviti { public static void main(String[] args) { Locale.setDefault(Locale.ENGLISH); SpringApplication.run(DemoActiviti.class, args); } } 


J'utilise un modèle mixte - lorsqu'une partie des beans est décrite dans la configuration xml (@ImportResource ("classpath: activiti.cfg.xml")), et l'autre est définie par des annotations.

activiti.cfg.xml - printemps
 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource"> <property name="url" value="jdbc:oracle:thin:@localhost:1521:xe" /> <property name="driverClass" value="oracle.jdbc.driver.OracleDriver" /> <property name="username" value="BPM" /> <property name="password" value="1" /> </bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration"> <property name="dataSource" ref="dataSource" /> <property name="transactionManager" ref="transactionManager" /> <property name="databaseSchemaUpdate" value="true" /> <property name="asyncExecutorActivate" value="false" /> </bean> </beans> 


Maintenant, Spring est responsable de la configuration, on peut le voir

 bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration" 

Ajouter un traitement de ligne de commande standard pour SpringBoot en tant que composant

Ligne de commande
 @Component public class CommandLine implements CommandLineRunner { @Autowired private DemoService demoService; public void run(String... args) { if ("test".equals(args[0])) { demoService.startTest(); } else if ("develop".equals(args[0])) { demoService.startDevelop(); } } } 


Qui traitera toutes ces commandes, je ne les implémenterai pas toutes, tout y est simple, j'en montrerai deux: tester et développer. Et ajoutez un service pour les traiter

DemoService
 @Service public class DemoService { @Autowired private TaskService taskService; @Autowired private FormService formService; public void startTest() { List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("testers").list(); if (tasks.isEmpty()) { System.out.println("   "); return; } processTasks(tasks); } public void startDevelop() { List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("develop").list(); if (tasks.isEmpty()) { System.out.println("   "); return; } processTasks(tasks); } private void processTasks(List<Task> tasks) { Scanner scanner = new Scanner(System.in); for (Task task : tasks) { ......    ,  } 


Dans le composant CommandLine Autowir, ils ont le service DemoService et les services Spring Activiti déjà préparés

 @Autowired private TaskService taskService; 

Nous collectons, exécutons comme auparavant à partir de la ligne de commande.

Si nous voulons utiliser l'exécution de tâches à partir du Web, nous connectons l'API REST.

API REST


SpringBoot fournira un serveur Tomcat intégré par défaut, puis une question technique.
Dans POM, à ce qu'il est, ajoutez une dépendance Web de printemps

  <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> 

Nous supprimons le composant CommandLine, maintenant tout passera par l'URL via HTTP. Ajouter RestController:

Restcontroller
 @RestController public class DemoRestController { @Autowired private DemoService demoService; @RequestMapping(value="/test", method= RequestMethod.GET, produces= {MediaType.APPLICATION_JSON_VALUE}) public List<String> startTest(@RequestParam String devResult) { List<String> strings = demoService.startTest(devResult); return strings; } @RequestMapping(value="/develop", method= RequestMethod.GET, produces= MediaType.APPLICATION_JSON_VALUE) public List<String> startDevelop(@RequestParam String issue) { List<String> strings = demoService.startDevelop(issue); return strings; } @RequestMapping(value="/start", method= RequestMethod.GET, produces= MediaType.APPLICATION_JSON_VALUE) public List<String> startProcess() { List<String> strings = demoService.startDevProcess(); return strings; } } 


Nous exécutons les mêmes commandes, changeant légèrement les réponses du service DemoService, qu'Autowire est dans le contrôleur.

DemoService
 @Service public class DemoService { @Autowired private TaskService taskService; @Autowired private FormService formService; @Autowired private RuntimeService runtimeService; public List<String> startTest(String devResult) { List<String> results = new ArrayList<>(); List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("testers").list(); if (tasks.isEmpty()) { results.add("The tasks for testing are not"); return results; } Object issue = runtimeService.getVariables(tasks.get(0).getProcessInstanceId()).get("issue"); processTasks(tasks, devResult); results.add("Task N " + issue + " - tested, result=" + devResult); return results; } public List<String> startDevelop(String issue) { List<String> results = new ArrayList<>(); List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("programmers").list(); if (tasks.isEmpty()) { results.add("There are no development tasks"); return results; } processTasks(tasks, issue); Object mIssue = runtimeService.getVariables(tasks.get(0).getProcessInstanceId()).get("issue"); results.add("Task N " + mIssue + " - taken in the develop"); return results; } public List<String> startDevProcess() { List<String> results = new ArrayList<>(); ProcessInstance myProcess = runtimeService.startProcessInstanceByKey("devProcess"); results.add("The process is started #"+myProcess.getId()); return results; } private void processTasks(List<Task> tasks, String param) { for (Task task : tasks) { FormData formData = formService.getTaskFormData(task.getId()); Map<String, Object> variables = new HashMap<>(); //   for (FormProperty formProperty : formData.getFormProperties()) { variables.put(formProperty.getId(), param); } //   taskService.complete(task.getId(), variables); } } } 


test en utilisant curl, voici le résultat:

image

J'ai changé le port pour Tomcat en 8081 dans application.properties
server.port = 8081

Emploi Activiti


Activiti a de nombreuses conceptions, par exemple, le lancement de tâches planifiées est «TimerStartEvent». Pour que Job commence à s'exécuter en confinement, vous devez spécifier
property name="asyncExecutorActivate" value="true" (voir activiti.cfg.xml), le processus java restera en cours d'exécution et vérifiera la planification et exécutera les tâches.

Je reviendrai sur le projet initial, où Activiti est utilisé dans sa forme la plus pure.

Dans la classe DemoActiviti je ne laisserai le support que pour deux commandes: déployer et démarrer je ferai un nouveau processus

image

Après le début du processus, il ira à la minuterie, qui selon le calendrier lancera la tâche «Développer». La minuterie aura un horaire - démarrer toutes les 10 secondes, expression cron - "0/10 * * * * *?".

image

Déployons le nouveau processus comme précédemment, puis démarrons le processus (démarrer). Tout - la tâche s'exécute toutes les 10 secondes.

En tant que tâche, le composant Activiti est sélectionné - ServiceTask, à partir duquel vous pouvez spécifier une implémentation de classe Java

image

classe DemoDelegate
 public class DemoDelegate implements JavaDelegate { @Override public void execute(DelegateExecution execution) { Date now = new Date(); execution.setVariable("issue", now.toString()); System.out.println("job start="+now); } } 


Dans le tableau de la base de données (sélectionnez * dans ACT_RU_TIMER_JOB t), vous pouvez voir

image

Activité de travail, dans le champ DUEDATE_ il y aura une heure du prochain démarrage.

La variable "issue" du Délégué sera enregistrée dans l'historique d'exécution

 select * from ACT_HI_VARINST t 

image

code pour Job DemoActiviti c
 public class DemoActiviti { private static final String DEV_PROCESS = "devProcessJob"; public static void main(String[] args) { Locale.setDefault(Locale.ENGLISH); ProcessEngineConfiguration cfg = ProcessEngineConfiguration .createProcessEngineConfigurationFromResource("activiti.cfg.xml"); ProcessEngine processEngine = cfg.buildProcessEngine(); RepositoryService repositoryService = processEngine.getRepositoryService(); String mode = StringUtils.EMPTY; if (args.length > 0) { mode = args[0]; } System.out.println("Processes mode: " + mode); Deployment deployment; if ("deploy".equals(mode)) { deployment = repositoryService.createDeployment() .addClasspathResource("processes/MyProcessJob.bpmn").deploy(); System.out.println("deploy process success"); System.exit(0); } else { List<Deployment> myProcesses = repositoryService.createDeploymentQuery() .processDefinitionKey(DEV_PROCESS).list(); deployment = myProcesses.get(myProcesses.size()-1); System.out.println("get process success:" + deployment.getId()); } // RuntimeService runtimeService = processEngine.getRuntimeService(); ProcessInstance processInstance; if ("start".equals(mode)){ ProcessInstance myProcess = runtimeService.startProcessInstanceByKey(DEV_PROCESS); System.out.println("start process success:" + myProcess.getName() +", id="+ myProcess.getId()); } } } 


Il reste encore beaucoup de choses derrière: Events, Listener, JPA, etc., je vais peut-être y revenir.

Matériaux
Activiti
Concepteur Eclipse

devProcess bpmn
 <?xml version="1.0" encoding="UTF-8"?> <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test"> <process id="devProcess" name="Dev process" isExecutable="true"> <startEvent id="startevent1" name="Start" activiti:initiator="programmerId"></startEvent> <userTask id="develop" name="Develop" activiti:candidateGroups="programmers"> <extensionElements> <activiti:formProperty id="issue" name="issue" type="string" required="true"></activiti:formProperty> </extensionElements> </userTask> <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="develop"></sequenceFlow> <userTask id="test" name="Test" activiti:candidateGroups="testers"> <extensionElements> <activiti:formProperty id="devResult" name="devResult" type="string" default="No" required="true"></activiti:formProperty> </extensionElements> </userTask> <sequenceFlow id="flow2" sourceRef="develop" targetRef="test"></sequenceFlow> <exclusiveGateway id="gateway" name="Exclusive Gateway" default="flowNo"></exclusiveGateway> <sequenceFlow id="flow3" sourceRef="test" targetRef="gateway"></sequenceFlow> <sequenceFlow id="flowOk" name="Ok" sourceRef="gateway" targetRef="endevent1"> <conditionExpression xsi:type="tFormalExpression"><![CDATA[${devResult == "Ok"}]]></conditionExpression> </sequenceFlow> <sequenceFlow id="flowNo" name="No" sourceRef="gateway" targetRef="develop"></sequenceFlow> <endEvent id="endevent1" name="End"></endEvent> </process> </definitions> 


devProcessJob bpmn
 <?xml version="1.0" encoding="UTF-8"?> <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test"> <process id="devProcessJob" name="Dev process Job" isExecutable="true"> <startEvent id="startevent" name="Start" activiti:initiator="programmerId"></startEvent> <sequenceFlow id="flow1" sourceRef="startevent" targetRef="timerstartevent"></sequenceFlow> <endEvent id="endevent" name="End"></endEvent> <startEvent id="timerstartevent" name="Timer start"> <extensionElements> <activiti:formProperty id="issue" name="issue" type="string"></activiti:formProperty> </extensionElements> <timerEventDefinition> <timeCycle>0/10 * * * * ?</timeCycle> </timerEventDefinition> </startEvent> <sequenceFlow id="flow2" sourceRef="timerstartevent" targetRef="servicetask1"></sequenceFlow> <sequenceFlow id="flow3" sourceRef="servicetask1" targetRef="endevent"></sequenceFlow> <serviceTask id="servicetask1" name="Develop" activiti:class="com.example.DemoDelegate"></serviceTask> </process> </definitions> 

Source: https://habr.com/ru/post/fr416491/


All Articles