Activiti - محرك عمليات الأعمال

إطار عمل Activiti (Java) - وصف تدفق مهمة XML (bpm) وإدارته. هنا سأصف المفاهيم الأساسية الأساسية وكيفية بناء العمليات التجارية البسيطة.

المفهوم الرئيسي لـ Activiti هو عملية ومهمة. العملية هي جميع المهام المترابطة مع التدفقات والفروع الموجهة.

سوف أتطرق إلى هذه الجوانب:

  • - أكتيفيتي في أنقى صوره
  • - المستخدمون والأدوار
  • - قم بتوصيل SpringBoot
  • - REST API
  • - الوظيفة والمندوب

تنتقل حركة التدفقات في خطوات من مهمة إلى مهمة ، كل خطوة من هذه الخطوات توقف العملية مؤقتًا أثناء انتظار الإدخال وإكمال المهمة ، ويتم تخزين جميع الإجراءات الوسيطة في قاعدة البيانات.

أين ، وماذا اتخاذ ، وسأشير أدناه. لنبدأ بمثال بسيط - عملية تطوير البرنامج ، والتي تتكون من كتابة التعليمات البرمجية والاختبار. أدناه مخطط عملية.

الصورة

هذه كلها عملية ، لها معرف واسم وخصائص أخرى.

الصورة

لديها:

بداية العملية ، مهمتان "تطوير" و "اختبار" ، فرع واحد (بوابة) ونهاية العملية. في الكلمات ، كل شيء يحدث على هذا النحو:

  • تحميل وصف نبضة في الدقيقة
  • ابدأ العملية
  • بعد البداية ، نقع على الفور في مهمة التطوير
  • بعد تنفيذ Develop ، تذهب إلى الاختبار ووفقًا لنتائج الاختبار ، تنتهي العملية أو تعود مرة أخرى إلى التطوير.

يتكون Activiti من مجموعة من الخدمات

فيما يلي أهمها:

  • RepositoryService: يتحكم في تحميل أوصاف العملية
  • RuntimeService: يبدأ العمليات
  • TaskService: يقوم بالمهام
  • FormService: الوصول إلى متغيرات المهمة
  • HistoryService: الوصول إلى تاريخ المعالجة
  • IdentityService: المستخدمون والأدوار

Activiti في أنقى صوره


ولكن كل شيء يبدأ بالتهيئة والملف - activiti.cfg.xml.

من هذا

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

إذا كنت لا تستخدم التكوين الخاص بك ، فستقوم Activiti بنشر قاعدة البيانات في ذاكرة H2 نفسها ، وهذا لا يناسبني ، لكن Oracle المحبوب الخاص بي ممتلئ ، فهناك خيارات لتوصيل قواعد بيانات مختلفة.

هنا التكوين الخاص بي

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> 


نقوم بتغيير القيم في "اسم الخاصية = jdbc *" وربط قاعدة بيانات أخرى

هيكل المشروع



بوم
 <?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> 


سيسمح لك وجود المكون الإضافي "maven-assembly-plugin" في POM ببناء (تغليف) برطمان يتم تشغيله باستخدام التبعيات وتشغيله -
 java -jar DemoActiviti-1.0-SNAPSHOT-jar-with-dependencies.jar 

برنامج تشغيل jdbc لـ Oracle مثبتًا في مستودع مخضرم محلي

 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 


لهذه العملية ، نحدد 4 إجراءات: تحميل نبضة في الدقيقة ، بدء العملية ، التطوير والاختبار. سيكون لكل إجراء معلمة مقابلة: النشر والبدء والتطوير والتطوير والاختبار.

نأخذ البرامج النصية لقاعدة بيانات من
Activiti- ابدأ
هناك في مجلد \ activiti-6.0.0 \ activiti-6.0.0 \ قاعدة بيانات \ إنشاء - نصوص لإنشاء قاعدة بيانات

المستخدمون والأدوار


تحضير المستخدمين والأدوار:

الهوية
 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"); } } } 


إنشاء المستخدمين والمجموعات ، المطور والمختبر ، على التوالي.

في قاعدة البيانات ، يتم تقسيم جميع الجداول حسب الخدمات المقابلة ولها بادئات

ACT_RE_ *: مستودع.
ACT_RU_ *: وقت التشغيل.
ACT_ID_ *: الهوية.
ACT_HI _ *: التاريخ
وهكذا دواليك

بعد إنشاء المستخدمين من ، يمكنك أن ترى هنا

الصورة

سنقوم بتعيين مهامنا في الوصف إلى المجموعات المقابلة (CandidateGroup) ، على سبيل المثال ، مهمة التطوير للمجموعة - المبرمجون

الصورة

لذا أول شيء نقوم به هو وضع قاعدة البيانات "MyProcess.bpmn" ، قم بتشغيل البرنامج باستخدام أمر النشر

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

بعد ذلك ، ابدأ عملية البدء

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

بعد عملية النقل والبدء ، ستظهر الإدخالات المقابلة في قاعدة البيانات.

المستودع

الصورة

وقت التشغيل ما هي المهمة في التنفيذ

الصورة

لمن تم تعيينه

الصورة

في الرمز ، يبدو هذا (الرمز الكامل سيكون أدناه):

نشر

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

ابدأ

 ProcessInstance myProcess = runtimeService.startProcessInstanceByKey(DEV_PROCESS); 

تطوير

بعد ذلك ، يمكنك البدء في إكمال مهمة التطوير.

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

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

في مهمة التطوير ، يتم تحديد متغير "مشكلة" واحد

الصورة

بعد معالجة المتغيرات باستخدام FormService ، يتم تشغيل المهمة

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

الصورة

بالنسبة لمهمة التطوير ، ستتم مطالبتك بإدخال متغير.

في الجدول التاريخي يمكنك أن ترى متغيرات وقيم المهمة ، العملية

الصورة

وبالتالي ، ستتوقف العملية بعد مهمة التطوير عليها ، سيتم حفظ الحالة في قاعدة البيانات.

بشكل عام ، تبدو الحلقة كما يلي:

طلب مهمة لمنفذ

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

تعريف المتغيرات

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

تنفيذ المهمة

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

التحقق من نهاية العملية

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

بعد تنفيذ كل مهمة ، يتم تعليق العملية حتى تكتمل مهمة جديدة.
لذا ، بعد تنفيذ Develop ، دعنا ننتقل إلى مهمة Test ، هنا سيُطلب منا أيضًا إدخال المتغير "devResult" - نتيجة التطوير (لم تنجح بشكل صحيح ، حتى قبل بدء الاختبار ، أدخل النتيجة) ، وبعد ذلك ستكون النتيجة متفرعة أو تنتهي (Ok) أو التنمية مرة أخرى (لا) ، انظر مخطط العملية.

الصورة

في هذه الحالة ، التطوير ، إلخ. إذا طلبت الآن مهام للمطور ، فستكون كذلك ، ولكن للاختبار - لا.

كود البرنامج
 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(); } } } 


ربط SpringBoot


نقوم بتعديل المشروع باستخدام الربيع

إضافة تبعيات إلى POM

POM مع 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> .... 


أصبحت فئة DemoActiviti من هذا القبيل
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); } } 


أستخدم نموذجًا مختلطًا - عندما يتم وصف جزء من الفاصوليا في تكوين xml (ImportResource ("classpath: activiti.cfg.xml")) ، ويتم تعريف الآخر من خلال التعليقات التوضيحية.

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" 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> 


الآن الربيع هو المسؤول عن التكوين ، ويمكن رؤيته

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

أضف معالجة سطر الأوامر القياسية لـ SpringBoot كمكون

سطر الأوامر
 @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(); } } } 


الذي سيعالج كل هذه الأوامر ، لن أقوم بتنفيذها جميعًا ، كل شيء بسيط هناك ، سأظهر اثنين: الاختبار والتطوير. وإضافة خدمة لمعالجتها

خدمة 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) { ......    ,  } 


في مكون CommandWine Autowir ، لديهم خدمة DemoService ، وفيها خدمات Spring Activiti المعدة بالفعل

 @Autowired private TaskService taskService; 

نقوم بجمع ، تشغيل كما كان من قبل من سطر الأوامر.

إذا أردنا استخدام تنفيذ المهام من الويب ، فإننا نربط REST API.

REST API


سيوفر SpringBoot خادم Tomcat مضمنًا بشكل افتراضي ، ثم مسألة فنية.
في POM ، إلى ما هو عليه ، أضف تبعية الويب الربيعية

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

نقوم بإزالة مكون CommandLine ، والآن سيأتي كل شيء من خلال عنوان URL عبر HTTP. إضافة 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; } } 


نقوم بتنفيذ نفس الأوامر ، وقمنا بتغيير استجابات خدمة DemoService قليلاً ، والتي توجد Autowire في وحدة التحكم.

خدمة 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); } } } 


اختبار باستخدام الضفيرة ، هنا هي النتيجة:

الصورة

لقد غيرت منفذ Tomcat إلى 8081 في application.properties
server.port = 8081

وظيفة Activiti


لدى Activiti العديد من التصاميم ، على سبيل المثال ، إطلاق المهام المجدولة هو "TimerStartEvent". لكي يبدأ Job في التنفيذ في الحصر ، يجب أن تحدد
property name="asyncExecutorActivate" value="true" (انظر activiti.cfg.xml) ، ستظل عملية جافا قيد التشغيل property name="asyncExecutorActivate" value="true" من الجدول الزمني وتقوم بتشغيل المهام.

سأعود إلى المشروع الأولي ، حيث يتم استخدام Activiti في أنقى صوره.

في فئة DemoActiviti ، سأترك الدعم لأمرين فقط: النشر والبدء

الصورة

بعد بدء العملية ، سيذهب إلى المؤقت ، والذي وفقًا للجدول الزمني سيطلق مهمة "تطوير". سيكون للمؤقت جدول زمني - يبدأ كل 10 ثوانٍ ، تعبير cron - "0/10 * * * * *؟".

الصورة

لننشر العملية الجديدة كما كان من قبل ، ثم نبدأ العملية (ابدأ). الكل - يتم تشغيل المهمة كل 10 ثوانٍ.

كمهمة ، يتم تحديد مكون Activiti - ServiceTask ، الذي يمكنك تحديده كتطبيق فئة Java

الصورة

فصل تجريبي
 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); } } 


في الجدول في قاعدة البيانات (حدد * من ACT_RU_TIMER_JOB t) يمكنك أن ترى

الصورة

النشاط الوظيفي ، في حقل DUEDATE_ سيكون هناك وقت من البداية القادمة.

سيتم تسجيل متغير "المسألة" من المفوض في سجل التنفيذ

 select * from ACT_HI_VARINST t 

الصورة

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


لا يزال هناك الكثير وراء: الأحداث ، المستمع ، JPA ، وما إلى ذلك ، ربما سأعود إليها.

المواد
Activiti
مصمم الكسوف

devPocess في الدقيقة
 <?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/ar416491/


All Articles