Activiti - Mecanismo de processo de negócios

Estrutura da Activiti (Java) - descrição do fluxo de tarefas XML (bpm) e seu gerenciamento. Aqui vou descrever os conceitos básicos básicos e como construir processos de negócios simples.

O principal conceito da Activiti é um processo e uma tarefa. Um processo é todas as tarefas interconectadas por fluxos e ramificações direcionadas.

Vou abordar esses aspectos:

  • - Activiti em sua forma mais pura
  • - Usuários, funções
  • - Conecte o SpringBoot
  • - API REST
  • - Trabalho e delegado

O movimento dos fluxos segue etapas de tarefa para tarefa, cada uma dessas etapas pausa o processo enquanto aguarda a conclusão da entrada e da tarefa, todas as ações intermediárias são armazenadas no banco de dados.

Onde, o que levar, vou indicar abaixo. Vamos começar com um exemplo simples - o processo de desenvolvimento do programa, que consiste em escrever código e testar. Abaixo está um diagrama de processo.

imagem

Tudo isso é um processo, possui um ID, nome e outras características.

imagem

Tem:

O início do processo, duas tarefas “Desenvolver” e “Teste”, uma ramificação (gateway) e o final do processo. Em palavras, tudo acontece assim:

  • loading bpm description
  • iniciar o processo
  • após o início, caímos imediatamente na tarefa de desenvolvimento
  • após a execução do Develop, ele entra em teste e, de acordo com o resultado do teste, o processo termina ou retorna novamente ao desenvolvimento.

Activiti consiste em um conjunto de serviços

Aqui estão os principais:

  • RepositoryService: controla o carregamento de descrições de processo
  • RuntimeService: inicia processos
  • TaskService: executa tarefas
  • FormService: acesso a variáveis ​​de tarefa
  • HistoryService: acesso ao histórico do processo
  • IdentityService: usuários e funções

Activiti em sua forma mais pura


Mas tudo começa com a configuração e o arquivo - activiti.cfg.xml.

A partir disso

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

Se você não usar sua configuração, o Activiti implantará o banco de dados na própria memória H2, isso não combina comigo, mas meu amado Oracle está cheio, há opções para conectar bancos de dados diferentes.

Aqui está minha configuração

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> 


Alteramos os valores em "nome da propriedade = jdbc *" e conectamos outro banco de dados

Estrutura do projeto



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> 


A presença do plugin "maven-assembly-plugin" no POM permitirá criar (empacotar) um jar que é iniciado com dependências e executado -
 java -jar DemoActiviti-1.0-SNAPSHOT-jar-with-dependencies.jar 

Driver jdbc para Oracle instalado no repositório 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 


Para esse processo, definimos 4 ações: carregamento de bpm, início do processo, desenvolvimento e teste. Cada ação terá um parâmetro correspondente: implantar, iniciar, desenvolver, testar.

Tomamos scripts para um banco de dados de
activiti-começar
lá na pasta \ activiti-6.0.0 \ activiti-6.0.0 \ database \ create - scripts para criar um banco de dados

Usuários, Funções


Prepare usuários e funções:

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


Crie usuários e grupos, desenvolvedor e testador, respectivamente.

No banco de dados, todas as tabelas são divididas pelos serviços correspondentes e têm prefixos

ACT_RE_ *: repositório.
ACT_RU_ *: tempo de execução.
ACT_ID_ *: identidade.
ACT_HI _ *: histórico
e assim por diante

Depois de criar usuários, você pode ver aqui

imagem

Atribuiremos nossas tarefas na descrição aos grupos correspondentes (CandidateGroup), por exemplo, a tarefa Desenvolver ao grupo - programadores

imagem

E assim, a primeira coisa que fazemos é colocar no banco de dados "MyProcess.bpmn", executar o programa com o comando deploy

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

Em seguida, inicie o processo de início

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

Após o processo delpoy e start, as entradas correspondentes aparecerão no banco de dados.

Repositório

imagem

Tempo de execução que tarefa está em execução

imagem

a quem está designado

imagem

No código, fica assim (o código completo estará abaixo):

implantar

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

iniciar

 ProcessInstance myProcess = runtimeService.startProcessInstanceByKey(DEV_PROCESS); 

desenvolver

Depois disso, você pode começar a concluir a tarefa de desenvolvimento.

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

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

Na tarefa Desenvolver, uma variável de "problema" é definida

imagem

Depois de processar as variáveis ​​usando o FormService, a tarefa é executada

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

imagem

Para a tarefa de Desenvolvimento, você será solicitado a inserir uma variável.

Na tabela histórica, você pode ver as variáveis ​​e os valores da tarefa, processo

imagem

Assim, o processo após a tarefa de Desenvolvimento parar nele, o estado será salvo no banco de dados.

Em geral, o loop se parece com isso:

Solicitar uma tarefa para um executor

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

Definição de Variáveis

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

Execução de tarefas

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

Verificando o final do processo

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

Após a execução de cada tarefa, o processo é suspenso até que uma nova tarefa seja concluída.
Portanto, depois de executar o Develop, vamos para a tarefa Test, aqui também será solicitado que você insira a variável "devResult" - o resultado do desenvolvimento (não funcionou muito bem, mesmo antes do Teste iniciar, digite o resultado) e o resultado será ramificado ou finalizado (Ok) ou desenvolvimento novamente (Não), consulte o diagrama do processo.

imagem

Nesse caso, o desenvolvimento etc. Se você agora solicitar tarefas para o desenvolvedor, elas serão, mas para teste - não.

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


Conecte o SpringBoot


Modificamos o projeto usando o Spring

Adicionar dependências ao POM

POM com 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> .... 


A classe DemoActiviti tornou-se agora
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); } } 


Uso um modelo misto - quando parte dos beans é descrita na configuração xml (@ImportResource ("classpath: activiti.cfg.xml")) e a outra é definida por meio de anotações.

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


Agora o Spring é responsável pela configuração, pode ser visto

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

Adicionar processamento de linha de comando padrão para SpringBoot como um componente

Linha de Comando
 @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 processará todos esses comandos, não implementarei todos, tudo é simples por lá, mostrarei dois: testar e desenvolver. E adicione um serviço para processá-los

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


No componente CommandLine Autowir, eles têm o serviço DemoService e nele os serviços Spring Activiti já preparados

 @Autowired private TaskService taskService; 

Nós coletamos, executamos como antes na linha de comando.

Se quisermos usar a execução de tarefas da Web, conecte a API REST.

API REST


O SpringBoot fornecerá um servidor Tomcat incorporado por padrão e, depois, um problema técnico.
No POM, para o que é, adicione dependência da Web da primavera

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

Removemos o componente CommandLine, agora tudo passará pela URL via HTTP. Adicione 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; } } 


Executamos os mesmos comandos, alteramos ligeiramente as respostas do serviço DemoService, que o Autowire está no 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); } } } 


testando usando curl, aqui está o resultado:

imagem

Alterei a porta do Tomcat para 8081 em application.properties
server.port = 8081

Activiti job


A Activiti possui muitos designs, por exemplo, o lançamento de tarefas agendadas é "TimerStartEvent". Para que o Job comece a executar em limites, você deve especificar
property name="asyncExecutorActivate" value="true" (consulte activiti.cfg.xml), o processo java permanecerá em execução e verificará o agendamento e as tarefas de execução.

Voltarei ao projeto inicial, onde o Activiti é usado em sua forma mais pura.

Na classe DemoActiviti, deixarei o suporte para apenas dois comandos: deploy e start farei um novo processo

imagem

Após o início do processo, ele irá para o cronômetro, que de acordo com o cronograma iniciará a tarefa "Desenvolver". O cronômetro terá uma programação - inicie a cada 10 segundos, expressão cron - "0/10 * * * * *?".

imagem

Vamos implantar o novo processo como antes, e então iniciar o processo (start). Tudo - a tarefa é executada a cada 10 segundos.

Como tarefa, o componente Activiti é selecionado - ServiceTask, a partir do qual você pode especificar como uma implementação de classe Java

imagem

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


Na tabela no banco de dados (selecione * de ACT_RU_TIMER_JOB t), você pode ver

imagem

Atividade do trabalho, no campo DUEDATE_, haverá um horário para o próximo início.

A variável "issue" do Delegado será registrada no histórico de execução

 select * from ACT_HI_VARINST t 

imagem

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


Ainda resta muito: Eventos, Ouvinte, JPA, etc., talvez eu volte a eles.

Materiais
Activiti
Designer 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/pt416491/


All Articles