Activiti - Motor de procesos comerciales

Activiti framework (Java): descripción del flujo de tareas XML (bpm) y su gestión. Aquí describiré los conceptos básicos básicos y cómo construir procesos comerciales simples.

El concepto principal de Activiti es un proceso y una tarea. Un proceso es todas las tareas interconectadas por flujos y ramas dirigidas.

Tocaré tales aspectos:

  • - Activiti en estado puro
  • - Usuarios, roles
  • - Conecte SpringBoot
  • - API REST
  • - Trabajo y delegado

El movimiento de los flujos va en pasos de una tarea a otra, cada uno de estos pasos detiene el proceso mientras espera la entrada y la finalización de la tarea, todas las acciones intermedias se almacenan en la base de datos.

Dónde, qué llevar, lo indicaré a continuación. Comencemos con un ejemplo simple: el proceso de desarrollo del programa, que consiste en escribir código y probarlo. A continuación se muestra un diagrama de proceso.

imagen

Todo esto es un proceso, tiene una identificación, nombre y otras características.

imagen

Tiene:

El comienzo del proceso, dos tareas "Desarrollar" y "Probar", una rama (puerta de enlace) y el final del proceso. En palabras, todo sucede así:

  • Descripción de bpm de carga
  • comenzar el proceso
  • después del comienzo, inmediatamente caemos en la tarea Desarrollar
  • después de la ejecución de Develop, pasa a las pruebas y, según el resultado de las pruebas, el proceso finaliza o vuelve nuevamente al desarrollo.

Activiti consiste en un conjunto de servicios

Aquí están los principales:

  • RepositoryService: controla la carga de descripciones de procesos
  • RuntimeService: inicia procesos
  • TaskService: realiza tareas
  • FormService: acceso a variables de tarea
  • HistoryService: acceso al historial del proceso
  • IdentityService: usuarios y roles

Activiti en estado puro


Pero todo comienza con la configuración y el archivo: activiti.cfg.xml.

De esto

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

Si no usa su configuración, Activiti desplegará la base de datos en la memoria H2, esto no me conviene, pero mi querido Oracle está lleno, hay opciones para conectar diferentes bases de datos.

Aquí está mi configuración

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> 


Cambiamos los valores en "property name = jdbc *" y conectamos otra base de datos

Estructura del proyecto



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 presencia del complemento "maven-assembly-plugin" en el POM le permitirá construir (empaquetar) un jar que se inicia con dependencias y ejecutar:
 java -jar DemoActiviti-1.0-SNAPSHOT-jar-with-dependencies.jar 

Controlador jdbc para Oracle instalado en el repositorio local de Maven

 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 


Para este proceso, definimos 4 acciones: carga de bpm, inicio del proceso, desarrollo y pruebas. Cada acción tendrá un parámetro correspondiente: desplegar, iniciar, desarrollar, probar.

Tomamos scripts para una base de datos de
activiti-get-begin
allí en la carpeta \ activiti-6.0.0 \ activiti-6.0.0 \ database \ create - scripts para crear una base de datos

Usuarios, roles


Prepare usuarios y roles:

Identidad
 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"); } } } 


Crear usuarios y grupos, desarrollador y probador, respectivamente.

En la base de datos, todas las tablas están divididas por los servicios correspondientes y tienen prefijos.

ACT_RE_ *: repositorio.
ACT_RU_ *: tiempo de ejecución.
ACT_ID_ *: identidad.
ACT_HI _ *: historial
y así sucesivamente

Después de crear usuarios desde, puedes ver aquí

imagen

Asignaremos nuestras tareas en la descripción a los grupos correspondientes (CandidateGroup), por ejemplo, la tarea Desarrollar al grupo - programadores

imagen

Entonces, lo primero que hacemos es colocar en la base de datos "MyProcess.bpmn", ejecutar el programa con el comando de despliegue

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

a continuación, inicie el proceso de inicio

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

Después del proceso de inicio e inicio, las entradas correspondientes aparecerán en la base de datos.

Repositorio

imagen

Tiempo de ejecución qué tarea está en ejecución

imagen

a quien se le asigna

imagen

En el código, se ve así (el código completo estará debajo):

desplegar

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

empezar

 ProcessInstance myProcess = runtimeService.startProcessInstanceByKey(DEV_PROCESS); 

desarrollar

Después de eso, puede comenzar a completar la tarea de desarrollo.

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

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

En la tarea Desarrollar, se define una variable de "problema"

imagen

Después de procesar las variables usando FormService, la tarea se ejecuta

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

imagen

Para la tarea Desarrollar, se le pedirá que ingrese una variable.

En la tabla histórica puedes ver las variables y valores de la tarea, proceso

imagen

Por lo tanto, el proceso después de que la tarea Desarrollar se detenga, el estado se guardará en la base de datos.

En general, el bucle se ve así:

Solicitar una tarea para un ejecutor

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

Definición de variables

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

Ejecución de tareas

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

Verificando el final del proceso

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

Después de la ejecución de cada tarea, el proceso se suspende hasta que se complete una nueva tarea.
Entonces, después de ejecutar Develop, pasemos a la tarea Prueba, aquí también se nos pedirá que ingresemos la variable "devResult": el resultado del desarrollo (no funcionó del todo bien, incluso antes de que comience la Prueba, ingrese el resultado), y luego el resultado se ramificará o terminará (Ok) o desarrollo nuevamente (No), ver diagrama de proceso.

imagen

En este caso, el desarrollo, etc. Si ahora solicita tareas para el desarrollador, serán, pero para pruebas, no.

Código del programa
 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(); } } } 


Connect SpringBoot


Modificamos el proyecto usando Spring

Agregar dependencias a POM

POM con 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 clase DemoActiviti ahora se ha convertido en tal
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); } } 


Utilizo un modelo mixto, cuando parte de los beans se describen en la configuración xml (@ImportResource ("classpath: activiti.cfg.xml")), y el otro se define a través de anotaciones.

activiti.cfg.xml - primavera
 <?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> 


Ahora Spring es responsable de la configuración, se puede ver

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

Agregue el procesamiento de línea de comando estándar para SpringBoot como componente

Línea de comandos
 @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(); } } } 


Que procesará todos esos comandos, no los implementaré todos, todo es simple allí, mostraré dos: probar y desarrollar. Y agregue un servicio para procesarlos

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) { ......    ,  } 


En el componente CommandLine Autowir, tienen el servicio DemoService, y en él los servicios Spring Activiti ya preparados.

 @Autowired private TaskService taskService; 

Recopilamos, corremos como antes desde la línea de comandos.

Si queremos usar la ejecución de tareas desde la Web, entonces conectamos la API REST.

API REST


SpringBoot proporcionará un servidor Tomcat incrustado de manera predeterminada, y luego una cuestión técnica.
En POM, a lo que es, agregue dependencia web de Spring

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

Eliminamos el componente CommandLine, ahora todo vendrá a través de la URL a través de HTTP. Añadir 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; } } 


Ejecutamos los mismos comandos, cambiamos ligeramente las respuestas del servicio DemoService, que Autowire está en el controlador.

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


prueba usando curl, aquí está el resultado:

imagen

Cambié el puerto de Tomcat a 8081 en application.properties
server.port = 8081

Trabajo Activiti


Activiti tiene muchos diseños, por ejemplo, el lanzamiento de tareas programadas es "TimerStartEvent". Para que Job comience a ejecutarse en confinamiento, debe especificar
property name="asyncExecutorActivate" value="true" (vea activiti.cfg.xml), entonces el proceso de Java seguirá ejecutándose y verificará la programación y ejecutará las tareas.

Volveré al proyecto inicial, donde Activiti se usa en su forma más pura.

En la clase DemoActiviti dejaré soporte solo para dos comandos: desplegar e iniciar Haré un nuevo proceso

imagen

Después del inicio del proceso, irá al temporizador, que de acuerdo con el cronograma iniciará la tarea "Desarrollar". El temporizador tendrá una programación: comenzará cada 10 segundos, expresión cron: "0/10 * * * * *?".

imagen

Implementemos el nuevo proceso como antes, luego comencemos el proceso (inicio). Todo: la tarea se ejecuta cada 10 segundos.

Como tarea, se selecciona el componente Activiti: ServiceTask, desde el cual puede especificar como implementación de clase Java

imagen

clase 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); } } 


En la tabla de la base de datos (seleccione * de ACT_RU_TIMER_JOB t) puede ver

imagen

Actividad laboral, en el campo DUEDATE_ habrá un momento del próximo inicio.

La variable "problema" del delegado se registrará en el historial de ejecución

 select * from ACT_HI_VARINST t 

imagen

código para DemoActiviti c Job
 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()); } } } 


Todavía queda mucho: Eventos, Listener, JPA, etc., tal vez volveré a ellos.

Materiales
Activiti
Diseñador de 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/es416491/


All Articles