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 |
Account name for sending urgent emails |
|
mail.password |
sdbsupport |
Prompt email sender account password |
mail.from |
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 |
|
|
|
|
|
|
|
|
|
|
|
|
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:
|
|
|
TestActivityPermission () tests process dynamic authorization |
|
TestAlarm () tests the prompt function |
|
TaskDefinition testCachedDefinitions () test |
|
TestDelegation () tests the delegation functionality |
|
TestInsertTasksAfter () is checked after the test |
|
TestInsertTasksBefore () Checks before the test |
|
The persistence of testInsertTasksWithPersistence () the signature of the test function |
|
TestModelDeployment () tests the process model deployment |
|
TestMove () tests free jumps |
|
TestMultiInstancesLoop () tests the multi-instance node |
|
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, |
|
|
CreateNewModel (java.lang.String Name, java.lang.String Description) creates a blank Model object |
|
DeployModel (java.lang.string modelId) deploys a registered model |
|
GetActivity (java.lang.String processDefId, java.lang.String activityId) gets the activity with the specified name |
|
GetHistoricProcessVariables (Java. Lang. String processId) to obtain a list of designated historical process variables |
|
GetProcessDefinition (java.lang.string processDefId) gets the process definition for the specified ID |
|
|
|
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 |
|
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 |
|
|
Rule 3.4.3 various Utils
OpenWebFlow provides some common utility classes, as follows:
Classes in this paper, |
|
|
|
|
|
|
|
|
|
|
|
3.4.4 TaskFlowControlService
TaskFlowControlService provides the following methods to control the flow:
Methods in this paper, |
|
|
insertTasksAfter(java.lang.String targetTaskDefinitionKey, java.lang.String… After the signature of the assignees) |
|
insertTasksBefore(java.lang.String targetTaskDefinitionKey, java.lang.String… Signature of the assignees) before |
|
MoveBack () take a step back |
|
MoveBack (org) activiti) engine. Impl. Persistence. The entity. The TaskEntity currentTaskEntity) back to specify the activity |
|
MoveForward ( |
|
MoveForward (org) activiti) engine. Impl. Persistence. The entity. The TaskEntity currentTaskEntity) forward to specify the activity |
|
MoveTo (java.lang.String targetTaskDefinitionKey) redirects (either fallback or forward) to the specified active node |
|
MoveTo (java.lang.String currentTaskId, java.lang.String targetTaskDefinitionKey) moves (either fallback or forward) to the specified active node |
|
moveTo(org.activiti.engine.impl.persistence.entity.TaskEntity currentTaskEntity, Java.lang.String targetTaskDefinitionKey) Jumps (either back or forward) to the specified active node |
|
split(java.lang.String targetTaskDefinitionKey, boolean isSequential, java.lang.String… Assignees splits a node into multi-instance nodes |
|
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:
|
|
|
List () gets all the activity definition information that the engine loads and registers at startup |
|
RemoveAll () removes all activity definitions |
|
Save (RuntimeActivityDefinitionEntity entity) a new definition of information |
5.1.2 RuntimeActivityDefinitionEntity
RuntimeActivityDefinitionEntity corresponds to an activity definition of information:
|
||
|
DeserializeProperties () deserializes PropertiesText to Map |
|
|
GetFactoryName () gets the factory name |
|
|
GetProcessDefinitionId () Gets the ID of the process definition |
|
|
GetProcessInstanceId () gets the ID of the process instance |
|
|
GetPropertiesText () gets the PropertiesText, which is a JSON string |
|
|
GetProperty (java.lang.string Name) gets the specified property value |
|
|
SerializeProperties () serializes the Map to PropertiesText |
|
|
SetFactoryName (java.lang.String factoryName) sets the factoryName |
|
|
SetProcessDefinitionId (java.lang.string processDefinitionId) sets the processDefinitionId |
|
|
SetProcessInstanceId (java.lang.String processInstanceId) sets the processInstanceId |
|
|
SetPropertiesText (java.lang.String propertiesText) Sets the propertiesText |
|
|
|
5.2 Activity Rights Management
5.2.1 ActivityPermissionManager
Permissions management interface for ActivityPermissionManager, its definition is as follows:
|
|
|
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:
|
|
|
GetAssignee () obtains the direct authorizer |
|
GetGrantedGroupIds () gets the list of candidate groups |
|
GetGrantedUserIds () gets the list of candidate users |
5.2.3 requires ActivityPermissionManagerEx
ActivityPermissionManagerEx implementation of activities permissions table “write” operation:
|
|
|
RemoveAll () deletes all permission definition information |
|
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:
|
|
|
IsNotified (java.lang.string taskId) determines whether a specified task isNotified |
|
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:
|
|
|
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:
|
|
|
GetDelegates (java.lang.String Delegated) Retrieves the delegate list of the assigned user |
|
ListDelegationEntities () gets a list of all broker information that the engine will load at startup |
5.4.2 DelegationEntity
DelegationEntity describes a proxy relationship:
|
|
|
GetDelegate () Gets the delegate for the current delegate record |
|
GetDelegated () Captures the client of the current delegated record |
5.4.3 DelegationManagerEx
DelegationManagerEx is used to “write” a proxy record:
|
|
|
RemoveAll () Deletes all proxy information |
|
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:
|
|
|
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:
|
||
|
GetProperty (java.lang.string Name) gets the value of the specified property |
|
|
GetPropertyNames () gets all property names |
|
|
GetUserId () gets the user ID |
|
|
SetProperty (java.lang.String name, T value) Sets the value of the specified property |
UserDetailsEntity provides several string constants simultaneously:
|
|
|
STRING_PROPERTY_EMAIL Specifies the name of the EMAIL property |
|
STRING_PROPERTY_MOBILE_PHONE_NUMBER Mobile phone number property name |
|
STRING_PROPERTY_NICK_NAME Nickname property name |
|
STRING_PROPERTY_USER_ID User ID property name |
5.5.3 UserDetailsManagerEx
UserDetailsManagerEx Used to write user information:
|
|
|
RemoveAll () Deletes all user information |
|
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.
|
|
|
FindGroupIdsByUser (java.lang.String userId) Retrieves the list of group ids to which the specified user belongs |
|
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:
|
|
|
RemoveAll () removes all member relationships |
|
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.