Open source: gitee.com/bluejoe/ope… (Welcome star)

1. OpenWebFlow overview

OpenWebFlow is a workflow engine based on the Activiti extension. Activiti (Official activiti.org/, code hosted at github.com/Activiti/Ac…) BPMN is an emerging open source BPM product under the Apache license that supports the BPMN 2.0 standard. It is a lightweight, embeddable BPM engine that provides feature-rich development and process design tools. The relationship between OpenWebFlow and business application system is shown in the following figure.

Compared to Activiti, the OpenWebFlow extension features include:

1) Take over all activity permissions from Activiti. Activiti allows you to specify execution permissions for each activity at model design time, but business systems may need to dynamically set execution permissions for these tasks (for example, dynamic groups) depending on the situation. OpenWebFlow is fully decoupled from the process definition period, that is, users manage the access control information of activities separately (instead of pre-writing it in the process definition), which is conducive to dynamic adjustment of permissions. See Custom activity permission Management for details.

2) Take over Activiti’s management of user tables (IDENTITY_XXX). In standard workflow definitions, each node can specify its candidate and candidate user group, but unfortunately Activiti has hijacked the design of the user information sheet! This is really fatal because almost every business system has its own User information structure (including User/Group/Membership), but it doesn’t have to be stored in Activiti’s preferred library. The table structure doesn’t have to be the same, and sometimes some information (e.g. Dynamic groups are not stored in tables at all. OpenWebFlow removes the unified management of user information tables. Clients can forget Activiti’s user tables, group tables, and membership tables. See Custom User membership management.

3) Allow the runtime to define the activity! Completely meet the “Chinese characteristics”, and provide a safe (but also elegant) prompt, agent, sign (including before sign/after sign), free jump (including forward/after), split nodes and other functions;

2. Get started

2.1 Introduction of OpenWebFlow framework

2.1.1 Introduce OpenWebFlow by JAR

OpenWebFlow is published as a set of normal JARS, in which OpenWebflow-core.xxx. jar contains the core workflow control module and the memory-based manager implementation module.

In addition, OpenWebFlow provides several JARS: Jar, openWebflow-Mgr-hibernate.xxx. jar, openWebflow-Mgr-mybatis. Another is OpenWebflow-Mgr-test.xxx. jar, which contains several test classes.

To download the latest version:

In accordance with the https://gitee.com/bluejoe/openwebflow/blob/master/openwebflow-core/target/openwebflow-core-0.9-SNAPSHOT.jar note these jar with more Lai, https://gitee.com/bluejoe/openwebflow/tree/master/openwebflow-core/target/lib lists all depend on the package is as follows:

  • Activation – 1.1. The jar
  • Activiti – BPMN – converter – 5.16.1. Jar
  • Activiti – BPMN – layout – 5.16.1. Jar
  • Activiti – BPMN – model – 5.16.1. Jar
  • Activiti crystalball – 5.16.1. Jar
  • Activiti engine – 5.16.1. Jar
  • Activiti explorer – 5.16.1. Jar
  • Activiti – image – generator – 5.16.1. Jar
  • Activiti – json – converter – 5.16.1. Jar
  • Activiti – process – the validation – 5.16.1. Jar
  • Activiti – simple – workflow – 5.16.1. Jar
  • Activiti – spring – 5.16.1. Jar
  • Aopalliance – 1.0. The jar
  • The Commons – the collections – 2.0. The jar
  • Commons DBCP – 1.4. The jar
  • The Commons – email – 1.2. The jar
  • Commons – IO – 2.4. The jar
  • Commons – lang – 2.6. The jar
  • The Commons – lang3-3.3.2 rainfall distribution on 10-12. Jar
  • Commons logging – 1.1.1. The jar
  • The Commons – the pool – 1.5.4. Jar
  • Dcharts widgets – 0.10.0. Jar
  • Groovy – all – 2.1.3. Jar
  • H2-1.3.168. Jar
  • Hamcrest – core – 1.3. The jar
  • Imgscalr – lib – 4.2. The jar
  • Jackson – annotations – 2.2.3. Jar
  • Jackson – core – 2.2.3. Jar
  • Jackson — databind 2.2.3. Jar
  • JavaGeom – 0.11.1. Jar
  • The JCL – over – slf4j – 1.7.6. Jar
  • Jgraphx – 1.10.4.1. Jar
  • Joda – time – 2.1. The jar
  • Junit 4.12. The jar
  • Log4j – 1.2.17. Jar
  • The mail – 1.4.1. Jar
  • Mybatis – 3.2.8. Jar
  • Mybatis – spring – 1.2.2. Jar
  • Mysql connector – Java – 5.1.32. Jar
  • The servlet API – 2.5. The jar
  • Slf4j – API – 1.7.2. Jar
  • Slf4j jdk14-1.7.2. Jar
  • Slf4j log4j12-1.7.6. Jar
  • Spring aop — 3.2.4. RELEASE. The jar
  • Spring beans – 3.2.4. RELEASE. The jar
  • Spring – the context – 3.2.4. RELEASE. The jar
  • Spring – the core – 3.2.4. RELEASE. The jar
  • Spring – expression – 3.2.4. RELEASE. The jar
  • Spring – JDBC – 3.2.4. RELEASE. The jar
  • Spring – the orm – 3.2.4. RELEASE. The jar
  • Spring – tx – 3.2.4. RELEASE. The jar
  • Spring – web – 3.2.4. RELEASE. The jar
  • Spring – webmvc – 3.2.4. RELEASE. The jar
  • Vaadin – 6.8.8. Jar

2.1.2 Introducing OpenWebFlow in the way of Maven

Importing OpenWebFlow as Maven is relatively easy. The dependencies in POM.xml are written as follows:

<dependency> <groupId>org.openwebflow</groupId> <artifactId>openwebflow-core </artifactId> < version > 0.9 - the SNAPSHOT < / version > < / dependency >Copy the code

You may need to install the OpenWebFlow project in a local repository before importing dependencies. The specific operation is to select the OpenWebFlow project in Eclipse, [right-click menu] [Maven] [install].

2.2 Configuration File

Prepare the SpringIoC configuration files, settings.properties, Activiti.cfg.core. XML and Activiti.cfg.mem. XML (or activiti.cfg.sql.xxx.xml) :

  • Settings. properties: Public property Settings
  • Activiti.cfg.core. XML: Basic configuration information used to configure the workflow engine.
  • Activiti. CFG. Mem. XML: To define some of the managers that support OpenWebFlow work, note the mem in the name, which implies that only memory-based versions of those managers are provided. Similar configuration files can also be activiti.cfg.sqL.xxx. XML.

2.2.1 Settings. The properties

The settings.properties file is a normal properties file that is loaded with the Spring IOC file. Here is the contents of a properties file:

mail.host=smtp.bluejoe.cn mail.port=25 [email protected] mail.password=sdbsupport [email protected] model.dir=.. /models alarm.mail.template=classpath:/alarm-template.txt hibernate.dialect=org.hibernate.dialect.MySQLDialect hibernate.hbm2ddl.auto=none activitidb.url=jdbc:h2:mem:activiti; DB_CLOSE_DELAY=1000 activitidb.driver=org.hDriver activitidb.username=sa activitidb.password= owfdb.url=jdbc:mysql://localhost:3306/openwebflow? useUnicode=true&characterEncoding=UTF-8 owfdb.driver=com.mysql.jdbc.Driver owfdb.username=root owfdb.password=1Copy the code

The meanings of each attribute are as follows:

The property name

The sample value

meaning

mail.host

smtp.bluejoe.cn

The host address of the prompt mail sending server

mail.port

25

Port number of the dispatch server

mail.username

[email protected]

Account name for sending urgent emails

mail.password

sdbsupport

Prompt email sender account password

mail.from

[email protected]

Prompt email sender

model.dir

../models

Path to the auto-loaded BPMN model

alarm.mail.template

classpath:/alarm-template.txt

Prompt message body template

hibernate.dialect

org.hibernate.dialect.MySQLDialect

Hibernate dialect

hibernate.hbm2ddl.auto

none

Hibernate DDL set

activitidb.url

jdbc:h2:mem:activiti; DB_CLOSE_DELAY

Activiti database JDBC URL

activitidb.driver

org.h2.Driver

Activiti database JDBC driver

activitidb.username

sa

Activiti database account name

activitidb.password

 

Activiti database account password

owfdb.url

jdbc:mysql://localhost:3306/openwebflow? useUnicode

OpenWebFlow DATABASE JDBC URL

owfdb.driver

com.mysql.jdbc.Driver

OpenWebFlow database JDBC driver

owfdb.username

root

OpenWebFlow database account name

owfdb.password

1

Password of the OpenWebFlow database account

2.2.2 activiti. CFG. Core. The XML configuration

The activiti.cfg.core.xml configuration is similar to the one required by Activiti, but with more content. Here is an example:

<! - core workflow database configuration - > < bean id = "activitiDataSource" class = "HTTP: / / org.apache.com mons. DBCP. BasicDataSource" destroy - method = "close" > <property name="driverClassName" value="${activitidb.driver}" /> <property name="url" value="${activitidb.url}" /> <property name="username" value="${activitidb.username}" /> <property name="password" value="${activitidb.password}" /> <property name="initialSize" value="20" /> <property name="maxActive" value="50" /> <property name="maxIdle" value="20" /> <property name="minIdle" value="10" /> </bean> <! - task CuiBan configuration - > < bean id = "myTaskAlarmService" class = "org. Openwebflow. Alarm. Impl. TaskAlarmServiceImpl" > <! <property name="periodInAdvance" value="P2D" /> <! <property name="messageNotifier"> <! - the email - - > < bean class = "org. Openwebflow. Alarm. Impl. MailMessageNotifier" > < property name = "subjectTemplate" /> <property name="messageTemplateResource" value="${alarm.mail.template}" /> <property  name="mailSender"> <bean class="org.openwebflow.alarm.impl.MailSender"> <property name="serverHost" value="${mail.host}" /> <property name="serverPort" value="${mail.port}" /> <property name="authUserName" value="${mail.username}" /> <property name="authPassword" value="${mail.password}" /> <property name="mailFrom" value="${mail.from}" /> </bean> </property> </bean> </property> <property name="membershipManager" ref="myMembershipManager" /> <property name="userDetailsManager" ref="myUserDetailsManager" /> <property name="taskNotificationManager" ref="myTaskNotificationManager" /> </bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="activitiDataSource" /> </bean> <tx:annotation-driven transaction-manager="transactionManager" /> <! - the configuration object - > < bean id = "processEngineConfiguration" class = "org. Openwebflow. CFG. ProcessEngineConfigurationEx" > < property name="dataSource" ref="activitiDataSource" /> <property name="transactionManager" ref="transactionManager" /> <property name="databaseSchemaUpdate" value="true" /> <property name="jobExecutorActivate" value="false" /> <property name="startEngineEventListeners"> <list> <! - loading custom form elements types - > < bean class = "org. Openwebflow. CFG. LoadDummyFormTypes" > < property name = "typeNames" value = "user" / > </bean> <! - members of the custom relationship management - > < bean class = "org. Openwebflow. CFG. ReplaceMembershipManager" > < property name = "customMembershipManager" ref="myMembershipManager" /> </bean> <! - custom permissions management - > < bean class = "org. Openwebflow. CFG. ReplaceTaskAssignmentHandler" > <! Handlers: a list of authorized handlers, which form a chain with higher priority as far back as possible --> < handlers > <list> <! - custom authorization list - > < bean class = "org. Openwebflow. Assign. Permission. ActivityPermissionAssignmentHandler" > < property name="activityPermissionManager" ref="myActivityPermissionManager" /> </bean> <! - allows authorized agent - > < bean class = "org. Openwebflow. Assign. Delegation. TaskDelagationAssignmentHandler" > < property name="delegationManager" ref="myDelegationManager" /> <property name="membershipManager" ref="myMembershipManager" /> <property name="hideDelegated" value="false" /> </bean> </list> </property> </bean> <! - automatic import process model - > < bean class = "org. Openwebflow. CFG. ImportDefinedProcessModels" > < property name = "modelDir" value="${model.dir}" /> </bean> <! - start CuiBan manager - > < bean class = "org. Openwebflow. CFG. StartTaskAlarmService" > < property name = "taskAlarmService" ref="myTaskAlarmService" /> <property name="runOnStartup" value="false" /> </bean> <! - loading custom activity - > < bean class = "org. Openwebflow. CFG. LoadRuntimeActivityDefinitions" > < property name="activityDefinitionManager" ref="myActivityDefinitionManager" /> </bean> </list> </property> </bean> <! -- processEngine --> <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean"> <property name="processEngineConfiguration" ref="processEngineConfiguration" /> </bean> <! Workflow circulation service object factory - - - > < bean class = "org. Openwebflow. CTRL. Impl. DefaultTaskFlowControlServiceFactory" / > <! -- processEngineTool --> <bean id="processEngineTool" class="org.openwebflow.util.ProcessEngineTool" />Copy the code

The processEngineConfiguration is enhanced workflow engine configuration object, you can set a custom user group members relationship management strategy, the custom activities, rights management, etc.

Complete example see: https://gitee.com/bluejoe/openwebflow/blob/master/openwebflow-test/src/test/resources/activiti.cfg.core.xml

2.2.3 activiti. CFG. Mem. XML configuration

XML defines a memory-based manager implementation. The default activiti.mem.xml content is as follows:

<! - members of the custom relationship management - > < bean id = "myMembershipManager" class = "org. Openwebflow. MGR. Mem. InMemoryMembershipManager" / > < bean id="myUserDetailsManager" class="org.openwebflow.mgr.mem.InMemoryUserDetailsManager" /> <! - custom activities permissions table management - > < bean id = "myActivityPermissionManager" class="org.openwebflow.mgr.mem.InMemoryActivityPermissionManager" /> <! - agency relationship management - > < bean id = "myDelegationManager" class = "org. Openwebflow. MGR. Mem. InMemoryDelegationManager" / > <! - custom dynamic custom activity management - > < bean id = "myActivityDefinitionManager" class="org.openwebflow.mgr.mem.InMemoryRuntimeActivityDefinitionManager" /> <bean id="myTaskNotificationManager" class="org.openwebflow.mgr.mem.InMemoryTaskNotificationManager" />Copy the code

There are six managers defined:

Manager category

meaning

myMembershipManager

Custom membership management

myUserDetailsManager

Custom user details management

myActivityPermissionManager

Custom active permission table management

myDelegationManager

Agency relationship management

myActivityDefinitionManager

Custom dynamic custom activity management

myTaskNotificationManager

Task notification information management

Complete example see: https://gitee.com/bluejoe/openwebflow/blob/master/openwebflow-test/src/test/resources/activiti.cfg.mem.xml

With activiti. CFG. Core. Similar alternative XML file for activiti. CFG. SQL. Hibernate. XML and activiti. CFG. SQL. Mybatis. XML.

2.2.4 activiti. CFG. SQL. Hibernate. XML configuration

Activiti. SQL. Hibernate. XML provides manager based on SQL implementation, using ORM framework of hibernate 4.

The definition of each manager is as follows:

<! - proxy records management - > < bean id = "myDelegationManager" class = "org. Openwebflow. MGR. Hibernate. Service. SqlDelegationManager" / > <! - members of the custom relationship management - > < bean id = "myMembershipManager" class = "org. Openwebflow. MGR. Hibernate. Service. SqlMembershipManager" / > <! - custom user table - > < bean id = "myUserDetailsManager" class = "org. Openwebflow. MGR. Hibernate. Service. SqlUserDetailsManager" / > <! - custom activities permissions table management - > < bean id = "myActivityPermissionManager" class="org.openwebflow.mgr.hibernate.service.SqlActivityPermissionManager" /> <! - custom dynamic custom activity management - > < bean id = "myActivityDefinitionManager" class="org.openwebflow.mgr.hibernate.service.SqlRuntimeActivityDefinitionManager" /> <bean id="myTaskNotificationManager" class="org.openwebflow.mgr.hibernate.service.SqlTaskNotificationManager" />Copy the code

In addition, you need to define data sources, Hibernate Session factories, and transactions.

<! -- see openwebflow database scripts. SQL - > < bean id = "owfDataSource" class = "org.apache.com mons. DBCP. BasicDataSource." " destroy-method="close"> <property name="driverClassName" value="${owfdb.driver}" /> <property name="url" value="${owfdb.url}" /> <property name="username" value="${owfdb.username}" /> <property name="password" value="${owfdb.password}" /> <property name="initialSize" value="20" /> <property name="maxActive" value="50" /> <property name="maxIdle" value="20" /> <property name="minIdle" value="10" /> </bean> <! SessionFactory - configuration - > < bean id = "SessionFactory" class = "org. Springframework. Orm. Hibernate4. LocalSessionFactoryBean" > <property name="dataSource" ref="owfDataSource" /> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <! -- <prop key="hibernate.dialect">org.hibernate.dialect.SQLServer2008Dialect</prop> --> <! <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.format_sql">true</prop> <prop key="hibernate.jdbc.batch_size">20</prop> <prop key="hibernate.connection.release_mode">auto</prop> <prop key="hibernate.autoReconnect">false</prop> <prop key="hibernate.connection.autocommit">true</prop> <prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop> <prop key="hibernate.jdbc.use_streams_for_binary">true</prop> <prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext </prop> <! <prop key="hibernate.cglib.use_reflection_optimizer">true</prop> </ properties > <! - automatic scanning for annotation entity - > < property name = "packagesToScan" > < list > < value > org. Openwebflow. MGR. Hibernate. The entity value > < / a > < / list </property> </bean> <! - configure a transaction manager - > < bean id = "transactionManager" class = "org. Springframework. Orm. Hibernate4. HibernateTransactionManager" > <property name="sessionFactory" ref="sessionFactory" /> </bean> <tx:annotation-driven transaction-manager="transactionManager" />Copy the code

The code structure of OpenWebflow-Mgr-Hibernate in HibernateORM is as follows:

The DAO class, entity class, and service class are stored under DAO, Entity, and Service package respectively. The transaction declaration of the Service class and the entity mapping are annotated.

See also: https://gitee.com/bluejoe/openwebflow/blob/master/openwebflow-test/src/test/resources/activiti.cfg.sql.hibernate.xml

2.2.5 activiti. CFG. SQL. Mybatis. XML configuration

Activiti.sql.mybatis. XML provides manager implementation based on SQL, using THE ORM framework of MyBatis 3.

The definition of each manager is as follows:

<! - proxy records management - > < bean id = "myDelegationManager" class = "org. Openwebflow. MGR. Mybatis. Service. SqlDelegationManager" / > <! - members of the custom relationship management - > < bean id = "myMembershipManager" class = "org. Openwebflow. MGR. Mybatis. Service. SqlMembershipManager" / > <! - custom user table - > < bean id = "myUserDetailsManager" class = "org. Openwebflow. MGR. Mybatis. Service. SqlUserDetailsManager" / > <! - custom activities permissions table management - > < bean id = "myActivityPermissionManager" class="org.openwebflow.mgr.mybatis.service.SqlActivityPermissionManager" /> <! - custom dynamic custom activity management - > < bean id = "myActivityDefinitionManager" class="org.openwebflow.mgr.mybatis.service.SqlRuntimeActivityDefinitionManager" /> <bean id="myTaskNotificationManager" class="org.openwebflow.mgr.mybatis.service.SqlTaskNotificationManager" />Copy the code

In addition, you need to define the data source, SqlSessionFactory, and transaction.

<! -- see openwebflow database scripts. SQL - > < bean id = "owfDataSource" class = "org.apache.com mons. DBCP. BasicDataSource." " destroy-method="close"> <property name="driverClassName" value="${owfdb.driver}" /> <property name="url" value="${owfdb.url}" /> <property name="username" value="${owfdb.username}" /> <property name="password" value="${owfdb.password}" /> <property name="initialSize" value="20" /> <property name="maxActive" value="50" /> <property name="maxIdle" value="20" /> <property name="minIdle" value="10" /> </bean> <! Create SqlSessionFactory Specify the data source at the same time - > < bean id = "owlSqlSessionFactory" class = "org. Mybatis. Spring. SqlSessionFactoryBean" > < property name = "dataSource"  ref="owfDataSource" /> </bean> <! - configure a transaction manager - > < bean id = "transactionManager" class = ". Org. Springframework. JDBC datasource. DataSourceTransactionManager ">  <property name="dataSource" ref="owfDataSource" /> </bean> <tx:annotation-driven transaction-manager="transactionManager" />Copy the code

Using Mybatis ORM, openWebflow-Mgr-MyBatis code structure is as follows:

The Mapper interface, entity class, and service class are stored under the Mapper, Entity, and Service packages respectively. The transaction declaration of the Service class and the mapping of the Mapper are annotated.

See also: https://gitee.com/bluejoe/openwebflow/blob/master/openwebflow-test/src/test/resources/activiti.cfg.sql.mybatis.xml

2.3 Database Design

First, the Activiti engine itself uses a series of tables that are automatically generated by Activiti when the data source is set up.

Activiti tables all begin with ACT_, and the second part is a two-letter identifier that indicates the purpose of the table. The purpose also corresponds to the service API.

  • ACT_RE_*: ‘RE’ stands for repository. This prefixed table contains process definitions and process static resources (images, rules, and so on).
  • ACT_RU_*: ‘RU’ stands for Runtime. These run-time tables contain running data for process instances, tasks, variables, asynchronous tasks, and more. Activiti saves this data only during the process instance execution and deletes the records at the end of the process. This way the table can stay very small and very fast at runtime.
  • ACT_ID_*: ‘ID’ stands for identity. These tables contain identity information, such as users, groups, and so on.
  • ACT_HI_*: ‘HI’ stands for history. These tables contain historical data, such as historical process instances, variables, tasks, and so on.
  • ACT_GE_*: universal data used in different scenarios.

OpenWebFlow offers a series of manager based on the realization of the database, need to use some of the data table, see https://gitee.com/bluejoe/openwebflow/tree/master/doc for the corresponding database scripts directory:

  • Openwebflow-mysql4.sql: mysql4 script
  • Openwebflow-mysql5.sql: mysql5 script
  • Openwebflow -sqlServer2008. SQL: sqlServer2008 script
  • Openwebflow-oracle10g. SQL: Oracle script

Six tables are defined:

  • OWF_ACTIVITY_CREATION: Stores custom activity definition information
  • OWF_ACTIVITY_PERMISSION: Stores custom activity permission information
  • OWF_DELEGATION: Stores user agent information
  • OWF_NOTIFICATION: Stores reminder notification records
  • OWF_MEMBERSHIP: Stores user group membership
  • OWF_USER: stores user information

Note: OWF_MEMBERSHIP and OWF_USER are for test use only, and it is recommended that users use their own data tables (one of OpenWebFlow’s own efforts is to separate user and membership management from the workflow engine) and wrap their own managers.

2.4 Beans defined using ApplicationContext

After loading the XML configuration file using the Spring IoC framework, the ApplicationContext contains the following variables that the client can use:

  • ProcessEngine: Workflow engine object, standard Activiti object
  • ProcessEngineTool: There are several tool methods available for processEngine
  • DefaultTaskFlowControlServiceFactory: task flow controller factory object
  • RepositoryService: Provides operations to manage and control distribution packages and process definitions
  • RuntimeService: Responsible for starting a new instance of a process definition
  • TaskService: operations related to tasks
  • IdentityService: Manage (create, update, delete, query… Groups and Users
  • FormService: Provides the concepts of a start form and a task form
  • HistoryService: Provides all historical data for Activiti engine phones
  • ManagementService: Can query database tables and table metadata

Here is a sample code using OpenWebFlow, which you can see is exactly the same as Activiti:

ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:activiti.cfg.mem.xml"); ProcessEngineTool tool = ctx.getBean(ProcessEngineTool.class); ProcessEngine processEngine = tool.getProcessEngine(); / / start a process instance ProcessInstance instance = processEngine. GetRuntimeService () startProcessInstanceByKey (" test1 "); TaskService taskService = processEngine.getTaskService(); Assert.assertEquals(1, taskService.createTaskQuery().taskCandidateGroup("management").count());Copy the code

 

2.5 Running Test Cases

In the OpenWebflow-Test project source code, users can find a set of test cases to test the functionality of the workflow engine. They are:

  • MemProcessEngineTest: Memory-based Manager test
  • SqlHibernateProcessEngineTest: hibernateORM based test manager
  • SqlMybatisProcessEngineTest: mybatisORM based test manager

The above three test class are inherited from AbstractProcessEngineTest:

AbstractProcessEngineTest provides the test method:

Methods in this paper,

void

TestActivityPermission () tests process dynamic authorization

 void

TestAlarm () tests the prompt function

 void

TaskDefinition testCachedDefinitions () test

 void

TestDelegation () tests the delegation functionality

 void

TestInsertTasksAfter () is checked after the test

 void

TestInsertTasksBefore () Checks before the test

 void

The persistence of testInsertTasksWithPersistence () the signature of the test function

 void

TestModelDeployment () tests the process model deployment

 void

TestMove () tests free jumps

 void

TestMultiInstancesLoop () tests the multi-instance node

 void

TestSplit () Tests node splitting

A complex flow (Models/test2.bPMn) is designed to match the test, as shown below:

 

Select the specified test unit (such As MemProcessEngineTest) and Run it As “JUnit Tests” (Run As…) , the test results can be observed:

 

Alternatively, you can run AllTests:

 

3. Familiar with OpenWebFlow code

3.1 Downloading Source Code

Users can download OpenWebFlow zip package, download address is: https://gitee.com/bluejoe/openwebflow/archive/master.zip

But can be by way of git access to the latest source code, the git repository address is: https://gitee.com/bluejoe/openwebflow.git

3.2 Code Structure

OpenWebFlow source code contains five Maven projects, including OpenWebFlow project is the parent project, It declares four models including OpenWebflow-core, OpenWebflow-Mgr-Hibernate, OpenWebflow-Mgr-mybatis and OpenWebflow-test.

  • Openwebflow-core: Core project, containing all the core content of the OpenWebFlow extension engine, as well as the memory-based Manager implementation.
  • Openwebflow-mgr-hibernate: Relies on OpenWebflow-core, provides a database-based manager implementation, ORM framework uses Hibernate.
  • Openwebflow-mgr-mybatis: Relies on OpenWebflow-core, provides manager implementation based on database, ORM framework uses MyBatis.
  • Openwebflow-test: relies on the above project and provides test cases, including configuration files, test classes, etc.

3.3 build project

Maven can be used to complete build and install the obtained project source code, as shown in the build screenshot below:

 

3.4 Core Objects

3.4.1 track ProcessEngineConfigurationEx

ProcessEngineConfigurationEx is aimed at Activiti ProcessEngineConfiguration class derived class:

 

The two most parameters are identical, the only difference is that ProcessEngineConfigurationEx provides an attribute: startEngineEventListeners.

StartEngineEventListeners used to define the workflow engine startup needs to start other tasks at the same time, startEngineEventListeners is a List, so feel free to add new tasks, the default core. The XML will load the following tasks: LoadDummyFormTypes, ReplaceMembershipManager, ReplaceTaskAssignmentHandler, ImportDefinedProcessModels, StartTaskAlarmServic E, LoadRuntimeActivityDefinitions. The list of tasks and class attributes is as follows:

The task class

use

The property name

Attribute meaning

LoadDummyFormTypes

Load some useless Form types to shield some custom forms from errors

typeNames

The name of the Form type to mask to; Separate, for example, user

ReplaceMembershipManager

Take over user group membership directly

customMembershipManager

Specifies a custom manager for the client

ReplaceTaskAssignmentHandler

Take over Activiti’s user rights management, which must be enabled if you want to implement dynamic node rights assignment.

handlers

Define a List of authorized processors with a value of type List. At runtime, the List of authorized processors will form a chain. The farther the List is, the higher the priority is.

ImportDefinedProcessModels

Automatically import BPMN models from the specified directory

modelDir

The path to specify the model can be CLASspath: isopath

StartTaskAlarmService

Start the task prompt service

taskAlarmService

Set the prompt service object

 

 

runOnStartup

Whether to start at first (default: true)

LoadRuntimeActivityDefinitions

Load node definitions at run time, mainly to support defining new nodes at run time

activityDefinitionManager

Specifies the node definition manager

3.4.2    ProcessEngineTool

ProcessEngineTool provides some utility methods whose functionality is not readily available through ProcessEngine:

Methods in this paper,

 org.activiti.engine.repository.Model

CreateNewModel (java.lang.String Name, java.lang.String Description) creates a blank Model object

 org.activiti.engine.repository.Deployment

DeployModel (java.lang.string modelId) deploys a registered model

 org.activiti.engine.impl.pvm.process.ActivityImpl

GetActivity (java.lang.String processDefId, java.lang.String activityId) gets the activity with the specified name

 java.util.Map<java.lang.String,java.lang.Object>

GetHistoricProcessVariables (Java. Lang. String processId) to obtain a list of designated historical process variables

 org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity

GetProcessDefinition (java.lang.string processDefId) gets the process definition for the specified ID

 org.activiti.engine.ProcessEngine

getProcessEngine() 

           

 void

grantPermission(org.activiti.engine.impl.pvm.process.ActivityImpl activity, java.lang.String assigneeExpression, Java. Lang. String candidateGroupIdExpressions, Java. Lang. String candidateUserIdExpressions) sets the user permissions, the specified activities including the authorised users, the candidate, the candidate set

 void

grantPermission(java.lang.String processDefId, java.lang.String activityId, java.lang.String assigneeExpression, Java. Lang. String candidateGroupIdExpressions, Java. Lang. String candidateUserIdExpressions) sets the user permissions, the specified activities including the authorised users, the candidate, the candidate set

 void

setProcessEngine(org.activiti.engine.ProcessEngine processEngine) 

Rule 3.4.3 various Utils

OpenWebFlow provides some common utility classes, as follows:

Classes in this paper,

CloneUtils

Implement object clone function

ExpressionUtils

Wrapper and transform common types of expression

IdentityUtils

Implement operations related to users and members

ModelUtils

It wraps the deployment, registration, and other functions of BPMN models

ProcessDefinitionUtils

A process defines the encapsulation of related operations

3.4.4    TaskFlowControlService

TaskFlowControlService provides the following methods to control the flow:

Methods in this paper,

 org.activiti.engine.impl.pvm.process.ActivityImpl[]

insertTasksAfter(java.lang.String targetTaskDefinitionKey, java.lang.String… After the signature of the assignees)

 org.activiti.engine.impl.pvm.process.ActivityImpl[]

insertTasksBefore(java.lang.String targetTaskDefinitionKey, java.lang.String… Signature of the assignees) before

 void

MoveBack () take a step back

 void

MoveBack (org) activiti) engine. Impl. Persistence. The entity. The TaskEntity currentTaskEntity) back to specify the activity

 void

MoveForward (

 void

MoveForward (org) activiti) engine. Impl. Persistence. The entity. The TaskEntity currentTaskEntity) forward to specify the activity

 void

MoveTo (java.lang.String targetTaskDefinitionKey) redirects (either fallback or forward) to the specified active node

 void

MoveTo (java.lang.String currentTaskId, java.lang.String targetTaskDefinitionKey) moves (either fallback or forward) to the specified active node

 void

moveTo(org.activiti.engine.impl.persistence.entity.TaskEntity currentTaskEntity, Java.lang.String targetTaskDefinitionKey) Jumps (either back or forward) to the specified active node

 org.activiti.engine.impl.pvm.process.ActivityImpl

split(java.lang.String targetTaskDefinitionKey, boolean isSequential, java.lang.String… Assignees splits a node into multi-instance nodes

 org.activiti.engine.impl.pvm.process.ActivityImpl

split(java.lang.String targetTaskDefinitionKey, java.lang.String… Assignee) splits a node into multi-instance nodes

A TaskFlowControlServiceFactory TaskFlowControlService needed to create, can get the factory object from the applicationcontext.

4. Design and use of core functions [Omitted]

5. Implement custom extensions using the manager interface

OpenWebFlow requires the user to provide six types of manager interfaces:

  • RuntimeActivityDefinitionManager: responsible for the definition of information access activities to support the running period of the new activities
  • ActivityPermissionManager: take charge of access permissions
  • TaskNotificationManager: Is responsible for accessing task notification information
  • DelegationManager: Is responsible for getting the user’s proxy information
  • UserDetailsManager: Obtains user information (including E-mail, nickname, and mobile phone number), which is used to send reminders
  • IdentityMembershipManager: responsible for get the user group membership, access to a user’s task queue, the candidate need to get to groups of users through user name

In addition to these managers, users will find that OpenWebFlow provides a series of ManagerEx interfaces:

  • ActivityPermissionManagerEx: responsible for permissions information preservation activities
  • TaskNotificationManagerEx: responsible for saving task CuiBan notification
  • DelegationManagerEx: Holds the user’s proxy information
  • UserDetailsManagerEx: Saves user information
  • IdentityMembershipManagerEx: responsible for save user group membership

The Manager interface is mainly used for reading and the ManagerEx interface is mainly used for writing. Note that the Implementation of ManagerEx is not required to use OpenWebFlow. All operations of the OpenWebFlow engine are called only to the Manager, not to The ManagerEx, which is provided only for testing purposes (if there are no writes, reads always return blank, and testing will not work).

5.1 Activity Definition Management

Clients often need to adjust the flow of a workflow at runtime. For example, when an activity step5 is completed and then step2 is completed, a new path needs to be created. To ensure the normal execution of the flow (especially after the application is restarted), such a path needs to be saved and loaded.

5.1.1    RuntimeActivityDefinitionManager

RuntimeActivityDefinitionManager contains the following methods:

Methods in this paper,

java.util.List <RuntimeActivityDefinitionEntity>

List () gets all the activity definition information that the engine loads and registers at startup

 void

RemoveAll () removes all activity definitions

 void

Save (RuntimeActivityDefinitionEntity entity) a new definition of information

5.1.2    RuntimeActivityDefinitionEntity

RuntimeActivityDefinitionEntity corresponds to an activity definition of information:

 

Methods in this paper,

 void

DeserializeProperties () deserializes PropertiesText to Map

 java.lang.String

GetFactoryName () gets the factory name

 java.lang.String

GetProcessDefinitionId () Gets the ID of the process definition

 java.lang.String

GetProcessInstanceId () gets the ID of the process instance

 java.lang.String

GetPropertiesText () gets the PropertiesText, which is a JSON string

<T> T

GetProperty (java.lang.string Name) gets the specified property value

 void

SerializeProperties () serializes the Map to PropertiesText

 void

SetFactoryName (java.lang.String factoryName) sets the factoryName

 void

SetProcessDefinitionId (java.lang.string processDefinitionId) sets the processDefinitionId

 void

SetProcessInstanceId (java.lang.String processInstanceId) sets the processInstanceId

 void

SetPropertiesText (java.lang.String propertiesText) Sets the propertiesText

<T> void

setProperty(java.lang.String name, T value) 

5.2 Activity Rights Management

5.2.1    ActivityPermissionManager

Permissions management interface for ActivityPermissionManager, its definition is as follows:

Methods in this paper,

 ActivityPermissionEntity

Load (java.lang.String processDefinitionId, java.lang.String taskDefinitionKey, Boolean addOrRemove) Gets permission definition information for the specified activity

5.2.2    ActivityPermissionEntity

Very simple, all it takes is a method that returns an ActivityPermissionEntity, defined as follows:

Methods in this paper,

 java.lang.String

GetAssignee () obtains the direct authorizer

 java.lang.String[]

GetGrantedGroupIds () gets the list of candidate groups

 java.lang.String[]

GetGrantedUserIds () gets the list of candidate users

5.2.3 requires ActivityPermissionManagerEx

ActivityPermissionManagerEx implementation of activities permissions table “write” operation:

Methods in this paper,

void

RemoveAll () deletes all permission definition information

 void

save(java.lang.String processDefId, java.lang.String taskDefinitionKey, java.lang.String assignee, Java.lang.String[] candidateGroupIds, java.lang.String[] candidateUserIds) saves a permission definition

5.3 Task notification management

5.3.1    TaskNotificationManager

The TaskNotificationManager is responsible for reading and setting the status of the task prompt. This interface is also simple:

Methods in this paper,

 boolean

IsNotified (java.lang.string taskId) determines whether a specified task isNotified

 void

SetNotified (java.lang.string taskId) sets the notification status for a specified task

The TaskNotificationManager maintains a queue that records the notification status of each task (true notified, false unnotified).

5.3.2    TaskNotificationManagerEx

TaskNotificationManagerEx implements the “write” operation to inform records:

Methods in this paper,

 void

RemoveAll () deletes all notification records

5.4 User Agent Relationship Management

5.4.1    DelegationManager

The DelegationManager is used to maintain proxy relationships between users. The interface contains two methods:

Methods in this paper,

 java.lang.String[]

GetDelegates (java.lang.String Delegated) Retrieves the delegate list of the assigned user

 java.util.List<DelegationEntity>

ListDelegationEntities () gets a list of all broker information that the engine will load at startup

5.4.2    DelegationEntity

DelegationEntity describes a proxy relationship:

Methods in this paper,

 java.lang.String

GetDelegate () Gets the delegate for the current delegate record

 java.lang.String

GetDelegated () Captures the client of the current delegated record

5.4.3    DelegationManagerEx

DelegationManagerEx is used to “write” a proxy record:

Methods in this paper,

 void

RemoveAll () Deletes all proxy information

 void

SaveDelegation (java.lang.String String delegate) saves an agent information

5.5 User Details Management

5.5.1    UserDetailsManager

The UserDetailsManager obtains user information (including E-mail, nickname, and mobile phone number), which is used to send reminders. The UserDetailsManager interface contains the following methods:

Methods in this paper,

 UserDetailsEntity

FindUserDetails (java.lang.string userId) retrieves user details based on the user name

5.5.2    UserDetailsEntity

UserDetailsEntity is used to describe user details. Note that it does not force a method such as getName(), but instead provides a getProperty(Stringname) method:

Methods in this paper,

<T> T

GetProperty (java.lang.string Name) gets the value of the specified property

 java.lang.String[]

GetPropertyNames () gets all property names

 java.lang.String

GetUserId () gets the user ID

<T> void

SetProperty (java.lang.String name, T value) Sets the value of the specified property

UserDetailsEntity provides several string constants simultaneously:

Field in this paper,

static java.lang.String

STRING_PROPERTY_EMAIL Specifies the name of the EMAIL property

static java.lang.String

STRING_PROPERTY_MOBILE_PHONE_NUMBER Mobile phone number property name

static java.lang.String

STRING_PROPERTY_NICK_NAME Nickname property name

static java.lang.String

STRING_PROPERTY_USER_ID User ID property name

5.5.3    UserDetailsManagerEx

UserDetailsManagerEx Used to write user information:

Methods in this paper,

 void

RemoveAll () Deletes all user information

 void

SaveUserDetails (UserDetailsEntity userDetails) Saves information about a user

 

5.6 User Group Membership Management

5.6.1    IdentityMembershipManager

IdentityMembershipManager responsible for get the user group membership, simple point, is to obtain a list of designated user’s group ID, as well as the member within a specified set of ID list.

Methods in this paper,

java.util.List <java.lang.String>

FindGroupIdsByUser (java.lang.String userId) Retrieves the list of group ids to which the specified user belongs

 java.util.List <java.lang.String>

FindUserIdsByGroup (java.lang.String groupId) retrieves a list of user ids that are members of the specified group

5.6.2    IdentityMembershipManagerEx

IdentityMembershipManagerEx provides the “write” operation of membership information:

Methods in this paper,

 void

RemoveAll () removes all member relationships

 void

SaveMembership (java.lang.String userId, java.lang.String groupId) saves the membership

6. Other help

This document download address is: https://gitee.com/bluejoe/openwebflow/tree/master/doc, can pass the address timely access to the latest version.

If the user needs to consult OpenWebFlow’s Java API, You can refer to the javadoc (https://gitee.com/bluejoe/openwebflow/tree/master/openwebflow-core/doc/javadoc).

Also can focus on the Wiki (https://gitee.com/bluejoe/openwebflow/wiki), submit a topic (https://gitee.com/bluejoe/openwebflow/issues), And direct contact with the author [email protected].

7. Activiti bugs and countermeasures

The Activiti framework has two bugs:

The first bug is that when BaseBpmnJsonConverter saves the BPMN model to JSON format, it ignores the output of the true Boolean value. This bug can cause JsonConverterUtil. GetPropertyValueAsBoolean () get to false value (since the judgment criteria into a Yes or No). The bug report address: https://github.com/Activiti/Activiti/pull/464#event-204722250

Another bug is that model loading errors occur when BPMN files are loaded when the local character set is not UTF-8 (e.g. GB2312). The bug report address: https://github.com/Activiti/Activiti/pull/486#event-220121880

So far (2014) the author has submitted bugfixes for the above two bugs and merged them with the Master version. However, considering version stability, the latest version of OpenWebFlow still adopts other methods to avoid the occurrence of the above bugs.