إطار عمل 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" /> <property name="databaseSchemaUpdate" value="false" /> <property name="asyncExecutorActivate" value="false" /> <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> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>2.4.1</version> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <mainClass>com.example.DemoActiviti</mainClass> </manifest> </archive> </configuration> <executions> <execution> <id>make-assembly</id> <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>();

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

وبالتالي ، ستتوقف العملية بعد مهمة التطوير عليها ، سيتم حفظ الحالة في قاعدة البيانات.
بشكل عام ، تبدو الحلقة كما يلي:
طلب مهمة لمنفذ
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()); }
ربط SpringBoot
نقوم بتعديل المشروع باستخدام الربيع
إضافة تبعيات إلى POM
POM مع SpringBoot <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.1.RELEASE</version> <relativePath/> </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<>();
اختبار باستخدام الضفيرة ، هنا هي النتيجة:

لقد غيرت منفذ 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()); }
لا يزال هناك الكثير وراء: الأحداث ، المستمع ، 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>