工作流引擎Activiti 专题

https://github.com/Activiti/Activiti

Quick Start Guide

This quick start assumes:

  • Familiarity with Maven and Java
  • A development environment with Java

The following variables will be referenced in this tutorial

Variable Description
$mvnProject The root location of the maven project
$actUnzipedPack The root location of the unzipped file downloaded from http://www.activiti.org/download.html.
$quickStartJavaProjectName The name of the Quick Start Java Project. This is recommended to be “ActivitiDeveloperQuickStart”.
... Refers to information being skipped, for brevity sake.
$actVer The version of Activiti currently being run.

1. Introduction

This Quick Start shows the simplicity of embedding Business Process Management (BPM) into your application using Activiti. You will build a command-line application that embeds standards-based Business Process Modeling Notation (BPMN) logic into your application.

Activiti has advanced process design tools for embedding more sophisticated BPM logic into your application. These tools include an Eclipse-based and Web-Based BPMN Editor to name a few. For brevity, this Quick Start only uses Activiti’s Java APIs.

For an introduction to additional Activiti BPM tooling, see:

  • Sample Onboarding Quick Start
  • Activiti User’s Guide

This Quick Start

  • In general, stays away from IDE-specific illustrations (though, they are done sparingly). Activiti works with any Java-friendly IDE.
  • Uses Maven, but other build and dependencies management systems like Gradle and Ivy work too.

2. Create and Setup Maven Project

Create a Java project called “ActivitiDeveloperQuickStart” (onwards referred to as $quickStartJavaProjectName) with the following Maven dependencies:

File: $mvnProject/pom.xml

<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>$quickStartJavaProjectName</groupId>
  <artifactId>$quickStartJavaProjectName</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <!-- ... other configurations may exist, such as a build stanza, depending your environment ... -->

  <dependencies>
      <dependency>
          <groupId>org.activiti</groupId>
          <artifactId>activiti-engine</artifactId>
          <version>$actVer</version>
      </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.h2database</groupId>
          <artifactId>h2</artifactId>
          <version>1.4.193</version>
      </dependency>
  </dependencies>
</project>

Of course, $actVer will be replaced with the downloaded Activiti version. For instance, if your downloaded Activiti package is “activiti-5.22.0” than the value of $actVer will be 5.22.0.

Notice the following dependencies:

  • Activiti (org.activiti) – Activiti’s BPM engine
  • Database (com.h2database) – the H2 database
  • Logging (org.slf4j) – Simple Logging Facade for Java

When referring to build directories, the tutorial assumes the standard Maven build paths for your maven project:

Path Description
$mvnProject/src/main/java Java source directory
$mvnProject/src/main/resources Resource directory
$mvnProject/src/test/java Java test directory
$mvnProject/src/test/resources Resource test directory

 

You should be able to build the blank project. Please ensure that the overall state is “BUILD SUCCESS” before continuing.

Command: mvn compile

Base Path: $mvnProject

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building $quickStartJavaProjectName 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ $quickStartJavaProjectName ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.5.1:compile (default-compile) @ HelloProcess2 ---
[INFO] Nothing to compile - all classes are up to date
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.592s
[INFO] Finished at: Sun Nov 27 05:09:59 EST 2016
[INFO] Final Memory: 10M/309M
[INFO] ------------------------------------------------------------------------

Notes:

  • Your output may look different. Most notably, maven may need retrieve the project dependencies.

3. Create Process Engine

As suggested earlier in the summary of the maven dependencies, Activiti leverages Simple Logging Facade for Java (slf4j) for logging. In this example application we’ll use the log4j logging implementation. Add the log4j.properties file to your project.

File: $mvnProject/src/main/resources/log4j.properties

log4j.rootLogger=DEBUG, 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

Create a new Java class with a blank main.

File: $mvnProject/src/main/java/com/example/OnboardingRequest.java

package com.example;

public class OnboardingRequest {
    public static void main(String[] args) {

    }
}

Adding to the main entry point is the creation of the Process Engine. Add to OnboardingRequest.java as illustrated below:

Adding to the main entry point is the creation of the Process Engine. Add to OnboardingRequest.java as illustrated below:

package com.example;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration;

public class OnboardingRequest {
  public static void main(String[] args) {
    ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
      .setJdbcUrl("jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000")
      .setJdbcUsername("sa")
      .setJdbcPassword("")
      .setJdbcDriver("org.h2.Driver")
      .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
    ProcessEngine processEngine = cfg.buildProcessEngine();
    String pName = processEngine.getName();
    String ver = ProcessEngine.VERSION;
    System.out.println("ProcessEngine [" + pName + "] Version: [" + ver + "]");
  }
}

File: $mvnProject/src/main/java/com/example/OnboardingRequest.java

Add Lines Explanation
3-4 Activiti Process Engine and Configuration.
5,9 Configuration helper for standalone environments (e.g. not using a dependency manager).
9-15 Creates the Process Engine using a memory-based h2 embedded database.
16-18 Displays the Process Engine configuration and Activiti version.

Activiti Supports Dependency Injection

  • Activiti is built for and can easily leverage dependency injection. Check the Activiti User’s Guide for more information.

Activiti Ships with a number of Database Providers

  • Database scripts at “$actUnzipedPack/database/create”
  • Activiti User’s Guide (various development and administration sections)

Supporting IDE and platform independent as well as simplicity for this Quick Start, add a “fat jar”configuration as illustrated below in lines 1-28 to the pom.xml.

File: $mvnProject/pom.xml

<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">
...
  <build>
...
    <plugins>
...
      <!-- Maven Assembly Plugin -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>2.4.1</version>
        <configuration>
          <!-- get all project dependencies -->
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
          <!-- MainClass in mainfest make a executable jar -->
          <archive>
            <manifest>
              <mainClass>com.example.OnboardingRequest</mainClass>
            </manifest>
          </archive>
        </configuration>
        <executions>
          <execution>
            <id>make-assembly</id>
            <!-- bind to the packaging phase -->
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
...
    </plugins>
...
  </build>
...
</project>

Package up your code by running “mvn package”.

Command: mvn package

Base Path: $mvnProject

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building $quickStartJavaProjectName 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ $quickStartJavaProjectName ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.5.1:compile (default-compile) @ HelloProcess2 ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ HelloProcess2 ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.5.1:testCompile (default-testCompile) @ HelloProcess2 ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ HelloProcess2 ---
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ HelloProcess2 ---
[INFO] Building jar: $mvnProject/target/$quickStartJavaProjectName-0.0.1-SNAPSHOT.jar
[INFO] META-INF/maven/$quickStartJavaProjectName/HelloProcess2/pom.xml already added, skipping
[INFO] META-INF/maven/$quickStartJavaProjectName/$quickStartJavaProjectName/pom.properties already added, skipping
[INFO]
[INFO] --- maven-assembly-plugin:2.4.1:single (make-assembly) @ $quickStartJavaProjectName ---
[INFO] Building jar: $mvnProject/target/$quickStartJavaProjectName-0.0.1-SNAPSHOT-jar-with-dependencies.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.029s
[INFO] Finished at: Sun Nov 27 07:23:43 EST 2016
[INFO] Final Memory: 33M/702M
[INFO] ------------------------------------------------------------------------

Notes:

  • Your output may look different. The important output here is the line just above “BUILD SUCCESS” showing success of the jar with dependencies: 
  • “[INFO] Building jar: $mvnProject/target/$quickStartJavaProjectName-0.0.1-SNAPSHOT-jar-with-dependencies.jar”

Supporting IDE and platform independent as well as simplicity for this Quick Start, run your Java program from the command line as illustrated below.

Command: java -jar target/ActivitiDeveloperQuickStart-0.0.1-SNAPSHOT-jar-with-dependencies.jar

-or-

java -jar target/$quickStartJavaProjectName-0.0.1-SNAPSHOT-jar-with-dependencies.jar

11:45:32,849 [main] DEBUG org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl  - initializing datasource to db: jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000
11:45:32,856 [main] DEBUG org.apache.ibatis.logging.LogFactory  - Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter.

...

11:45:33,777 [main] DEBUG org.activiti.engine.impl.db.DbSqlSession  - SQL: create table ACT_PROCDEF_INFO (
ID_ varchar(64) not null,
PROC_DEF_ID_ varchar(64) not null,
REV_ integer,
INFO_JSON_ID_ varchar(64),
primary key (ID_)
)

...

11:45:33,835 [main] DEBUG org.activiti.engine.impl.db.DbSqlSession  - activiti db schema create for component identity successful
11:45:33,835 [main] DEBUG org.activiti.engine.impl.db.DbSqlSession  - flush summary: 0 insert, 0 update, 0 delete.
11:45:33,835 [main] DEBUG org.activiti.engine.impl.db.DbSqlSession  - now executing flush...
11:45:33,835 [main] DEBUG org.activiti.engine.impl.cfg.standalone.StandaloneMybatisTransactionContext  - firing event committing...
11:45:33,835 [main] DEBUG org.activiti.engine.impl.cfg.standalone.StandaloneMybatisTransactionContext  - committing the ibatis sql session...
11:45:33,835 [main] DEBUG org.activiti.engine.impl.cfg.standalone.StandaloneMybatisTransactionContext  - firing event committed...
11:45:33,836 [main] DEBUG org.apache.ibatis.transaction.jdbc.JdbcTransaction  - Resetting autocommit to true on JDBC Connection [conn0: url=jdbc:h2:mem:activiti user=SA]
11:45:33,836 [main] DEBUG org.apache.ibatis.transaction.jdbc.JdbcTransaction  - Closing JDBC Connection [conn0: url=jdbc:h2:mem:activiti user=SA]
11:45:33,836 [main] DEBUG org.apache.ibatis.datasource.pooled.PooledDataSource  - Returned connection 667346055 to pool.
11:45:33,836 [main] DEBUG org.activiti.engine.impl.interceptor.LogInterceptor  - --- SchemaOperationsProcessEngineBuild finished --------------------------------------------------------
11:45:33,836 [main] DEBUG org.activiti.engine.impl.interceptor.LogInterceptor  - 

11:45:33,836 [main] INFO  org.activiti.engine.impl.ProcessEngineImpl  - ProcessEngine default created
ProcessEngine [default] Version: [$actVer]

Notes:

  • The key output of interest is the printing of your Activiti version: $actVer It should match the version configured in
  • “[INFO] Building jar: $mvnProject/target/$quickStartJavaProjectName-0.0.1-SNAPSHOT-jar-with-dependencies.jar”

Or, of course, you can run the same program can be run from within your IDE. For instance, from within Eclipse, choose the OnboardingRequest.java file, then right mouse clicking for “Run As > Java Application”. Should you run the program from within your IDE, the result should be the same (usually displayed in the IDE’s console view).

You’ve successfully embedded Activiti’s BPM Engine within this simple Java program.
4. Deploy Process Definition

We’re now ready to add additional BPM logic to our Activiti Engine.

For this, as suggested by the name of our OnboardingRequest Java class, we’ll use a simple Onboarding process. In this example, we’ll enter data. Then, if the years of experience are above 3, a task for a personalized onboarding welcome message will be issued. In that task, the user will manually enter data into a faux backend system. If the years of experience are 3 years or below, then simply, generically, and automatically integrate data with a faux backend system.

Activiti’s Process Engine is a BPMN 2.0 compliant. Visually, the process above can be modeled like so:

 

 

This example is purposely simple. And, depending on the requirements, it can be modeled a few different ways. While it can orchestrate simple process too, note that Activiti can handle very sophisticated processes with dozens, hundreds, or even thousands of steps.

Underlying the visual process model above is the XML structure of BPMN. The XML document in this case is onboarding.bpmn20.xml. This quick start will not go into the depths of the underlying XML BPMN structure to focus on the mechanics of developing against the Activiti APIs and embedding Activiti into your application. Yet, to support the logic that follows, here is a summary of the relevant BPMN shapes and the defined logic codified in the underlying XML:

 

 

 

BPMN Shapes Onboarding.bpmn20.xml Lines Comments

 

8 Start Event

 

9-15 User Task collecting 2 form properties: “fullName” and “yearsOfExperience”. Note the candidate groups on line 9 are set to “managers”.

 

21-27 User Task collecting 1 form property: “personalWelcomeTime”. Note the candidate groups on line 22 are set to “managers”.

 

31-35 Script Task representing Automated Data Entry to a faux backend. Notice while simple, there is a simple script that sets a process variable autoWelcomeTime (line 34-35):var dateAsString = new Date().toString(); execution.setVariable("autoWelcomeTime", dateAsString);

 

18 Defines the “Years of Experience” exclusive gateway. (A decision will yield one path or the other.)
37-39 Represents the “>3” logic using the yearsOfExperience variable:${yearsOfExperience > 3}
18,36 On the exclusive gateway (line 18), note the default stanza pointing to “automatedIntroPath (line 36) representing a logical “else” to the condition “>3”.

 

298 End Event

File: $mvnProject/src/main/java/com/example/OnboardingRequest.java

Add Lines Explanation
25-27 Loads the supplied BPMN model and deploys it to Activiti Process Engine.
28-33 Retrieves the deployed model, proving that it is in the Activiti repository.

See various sections in the Activiti User’s Guide for more information on BPMN and its use in Activiti.

Download the onboarding.bpmn20.xml file, the entire XML structure below, and copy the onboarding.bpmn20.xml file to the path $mvnProject/src/main/resources/.
 

File: $mvnProject/src/main/resources/onboarding.bpmn20.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
<?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/processdef">
  <process id="onboarding" name="Onboarding" isExecutable="true">
    <startEvent id="startOnboarding" name="Start" activiti:initiator="initiator"></startEvent>
    <userTask id="enterOnboardingData" name="Enter Data" activiti:assignee="${initiator}" activiti:candidateGroups="managers">
      <extensionElements>
        <activiti:formProperty id="fullName" name="Full Name" type="string"></activiti:formProperty>
        <activiti:formProperty id="yearsOfExperience" name="Years of Experience" type="long" required="true"></activiti:formProperty>
      </extensionElements>
    </userTask>
    <sequenceFlow id="sid-1337EA98-7364-4198-B5D9-30F5341D6918" sourceRef="startOnboarding" targetRef="enterOnboardingData"></sequenceFlow>
    <exclusiveGateway id="decision" name="Years of Experience" default="automatedIntroPath"></exclusiveGateway>
    <sequenceFlow id="sid-42BE5661-C3D5-4DE6-96F5-73D34822727A" sourceRef="enterOnboardingData" targetRef="decision"></sequenceFlow>
    <userTask id="personalizedIntro" name="Personalized Introduction and Data Entry" activiti:assignee="${initiator}" activiti:candidateGroups="managers">
      <extensionElements>
        <activiti:formProperty id="personalWelcomeTime" name="Personal Welcome Time" type="date" datePattern="MM-dd-yyyy hh:mm"></activiti:formProperty>
      </extensionElements>
    </userTask>
    <endEvent id="endOnboarding" name="End"></endEvent>
    <sequenceFlow id="sid-37A73ACA-2E23-400B-96F3-71F77738DAFA" sourceRef="automatedIntro" targetRef="endOnboarding"></sequenceFlow>
    <scriptTask id="automatedIntro" name="Generic and Automated Data Entry" scriptFormat="javascript" activiti:autoStoreVariables="false">
      <script><![CDATA[var dateAsString = new Date().toString();
execution.setVariable("autoWelcomeTime", dateAsString);]]></script>
    </scriptTask>
    <sequenceFlow id="automatedIntroPath" sourceRef="decision" targetRef="automatedIntro"></sequenceFlow>
    <sequenceFlow id="personalizedIntroPath" name="&gt;3" sourceRef="decision" targetRef="personalizedIntro">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${yearsOfExperience > 3}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="sid-BA6F061B-47B6-428B-8CE6-739244B14BD6" sourceRef="personalizedIntro" targetRef="endOnboarding"></sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_onboarding">
    <bpmndi:BPMNPlane bpmnElement="onboarding" id="BPMNPlane_onboarding">
      <bpmndi:BPMNShape bpmnElement="startOnboarding" id="BPMNShape_startOnboarding">
        <omgdc:Bounds height="30.0" width="30.0" x="155.0" y="145.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="enterOnboardingData" id="BPMNShape_enterOnboardingData">
        <omgdc:Bounds height="80.0" width="100.0" x="240.0" y="120.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="decision" id="BPMNShape_decision">
        <omgdc:Bounds height="40.0" width="40.0" x="385.0" y="140.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="personalizedIntro" id="BPMNShape_personalizedIntro">
        <omgdc:Bounds height="80.0" width="100.0" x="519.0" y="15.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="endOnboarding" id="BPMNShape_endOnboarding">
        <omgdc:Bounds height="28.0" width="28.0" x="725.0" y="165.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="automatedIntro" id="BPMNShape_automatedIntro">
        <omgdc:Bounds height="80.0" width="100.0" x="520.0" y="255.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="sid-37A73ACA-2E23-400B-96F3-71F77738DAFA" id="BPMNEdge_sid-37A73ACA-2E23-400B-96F3-71F77738DAFA">
        <omgdi:waypoint x="570.0" y="255.0"></omgdi:waypoint>
        <omgdi:waypoint x="570.0" y="179.0"></omgdi:waypoint>
        <omgdi:waypoint x="725.0" y="179.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-1337EA98-7364-4198-B5D9-30F5341D6918" id="BPMNEdge_sid-1337EA98-7364-4198-B5D9-30F5341D6918">
        <omgdi:waypoint x="185.0" y="160.0"></omgdi:waypoint>
        <omgdi:waypoint x="240.0" y="160.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="automatedIntroPath" id="BPMNEdge_automatedIntroPath">
        <omgdi:waypoint x="405.0" y="180.0"></omgdi:waypoint>
        <omgdi:waypoint x="405.0" y="295.0"></omgdi:waypoint>
        <omgdi:waypoint x="520.0" y="295.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="personalizedIntroPath" id="BPMNEdge_personalizedIntroPath">
        <omgdi:waypoint x="405.0" y="140.0"></omgdi:waypoint>
        <omgdi:waypoint x="405.0" y="55.0"></omgdi:waypoint>
        <omgdi:waypoint x="519.0" y="55.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-42BE5661-C3D5-4DE6-96F5-73D34822727A" id="BPMNEdge_sid-42BE5661-C3D5-4DE6-96F5-73D34822727A">
        <omgdi:waypoint x="340.0" y="160.0"></omgdi:waypoint>
        <omgdi:waypoint x="385.0" y="160.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-BA6F061B-47B6-428B-8CE6-739244B14BD6" id="BPMNEdge_sid-BA6F061B-47B6-428B-8CE6-739244B14BD6">
        <omgdi:waypoint x="619.0" y="55.0"></omgdi:waypoint>
        <omgdi:waypoint x="739.0" y="55.0"></omgdi:waypoint>
        <omgdi:waypoint x="739.0" y="165.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

 

Add to OnboardingRequest.java as illustrated below:

File: $mvnProject/src/main/java/com/example/OnboardingRequest.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.example;

import java.text.ParseException;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;

public class OnboardingRequest {
  public static void main(String[] args) throws ParseException {
    ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
        .setJdbcUrl("jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000")
        .setJdbcUsername("sa")
        .setJdbcPassword("")
        .setJdbcDriver("org.h2.Driver")
        .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
    ProcessEngine processEngine = cfg.buildProcessEngine();
    String pName = processEngine.getName();
    String ver = ProcessEngine.VERSION;
    System.out.println("ProcessEngine [" + pName + "] Version: [" + ver + "]");

    RepositoryService repositoryService = processEngine.getRepositoryService();
    Deployment deployment = repositoryService.createDeployment()
        .addClasspathResource("onboarding.bpmn20.xml").deploy();
    ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
        .deploymentId(deployment.getId()).singleResult();
    System.out.println(
        "Found process definition [" 
            + processDefinition.getName() + "] with id [" 
            + processDefinition.getId() + "]");
  }
}

 

File: $mvnProject/src/main/java/com/example/OnboardingRequest.java

Add Lines Explanation
25-27 Loads the supplied BPMN model and deploys it to Activiti Process Engine.
28-33 Retrieves the deployed model, proving that it is in the Activiti repository.

Package up your code by running “mvn package”.

Run your Java program as before. Sample output noted below.

Command: java -jar target/ActivitiDeveloperQuickStart-0.0.1-SNAPSHOT-jar-with-dependencies.jar

-or-

java -jar target/$quickStartJavaProjectName-0.0.1-SNAPSHOT-jar-with-dependencies.jar

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
...

02:01:19,277 [main] INFO  org.activiti.engine.impl.ProcessEngineImpl  - ProcessEngine default created
processEngine [default] version: [5.22.0.0]

...

02:01:19,327 [main] DEBUG org.activiti.engine.impl.bpmn.deployer.BpmnDeployer  - Processing deployment null
02:01:19,327 [main] INFO  org.activiti.engine.impl.bpmn.deployer.BpmnDeployer  - Processing resource onboarding.bpmn20.xml
02:01:19,444 [main] DEBUG org.activiti.engine.impl.bpmn.parser.handler.ProcessParseHandler  - Parsing process 

...

02:01:21,696 [main] DEBUG org.apache.ibatis.datasource.pooled.PooledDataSource  - Returned connection 667346055 to pool.
02:01:21,696 [main] DEBUG org.activiti.engine.impl.interceptor.LogInterceptor  - --- DeployCmd finished --------------------------------------------------------

...

02:01:21,696 [main] DEBUG org.activiti.engine.impl.interceptor.LogInterceptor  - --- starting ProcessDefinitionQueryImpl --------------------------------------------------------

...

02:01:21,710 [main] DEBUG org.apache.ibatis.datasource.pooled.PooledDataSource  - Returned connection 667346055 to pool.
02:01:21,710 [main] DEBUG org.activiti.engine.impl.interceptor.LogInterceptor  - --- ProcessDefinitionQueryImpl finished --------------------------------------------------------
02:01:21,710 [main] DEBUG org.activiti.engine.impl.interceptor.LogInterceptor  - 

Found process definition [Onboarding] with id [onboarding:1:4]

 

Notes:

  • The key output of interest here is the list line that notes the process name “Onboarding” and the unique process id (including a deployment version) of “onboarding:1:4”

Your application now deploys the Onboarding process upon running.

5. Run Process Instance

Deployed processes can use the Activiti API to initiate, run, view history, and otherwise manage process instances. This Quick Start run process instances using Java code.

See Sample Onboarding Quick Start for an example of managing Process Instances using Restful Services.

Set the logging level of Activiti from DEBUG to WARN as illustrated in line 1 below.

File: $mvnProject/src/main/resources/log4j.properties

1
2
3
4
5
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

 

Important:  The following example code illustrates the flexibility and powerful of Activiti’s standards-based embeddable Process Engine. However, this code does not represent itself as best practices in terms of error handling, code organization, and general design. Rather, the purpose is to illustrate many ideas quickly so to gain familiarity with the power of Activiti. Re-factor the below example for your own needs.

Add to OnboardingRequest.java as illustrated below:

File: $mvnProject/src/main/java/com/example/OnboardingRequest.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package com.example;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

import org.activiti.engine.FormService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.form.FormData;
import org.activiti.engine.form.FormProperty;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration;
import org.activiti.engine.impl.form.DateFormType;
import org.activiti.engine.impl.form.LongFormType;
import org.activiti.engine.impl.form.StringFormType;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;

public class OnboardingRequest {
  public static void main(String[] args) throws ParseException {
    ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
        .setJdbcUrl("jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000")
        .setJdbcUsername("sa")
        .setJdbcPassword("")
        .setJdbcDriver("org.h2.Driver")
        .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
    ProcessEngine processEngine = cfg.buildProcessEngine();
    String pName = processEngine.getName();
    String ver = ProcessEngine.VERSION;
    System.out.println("ProcessEngine [" + pName + "] Version: [" + ver + "]");

    RepositoryService repositoryService = processEngine.getRepositoryService();
    Deployment deployment = repositoryService.createDeployment()
        .addClasspathResource("onboarding.bpmn20.xml").deploy();
    ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
        .deploymentId(deployment.getId()).singleResult();
    System.out.println(
        "Found process definition [" 
            + processDefinition.getName() + "] with id [" 
            + processDefinition.getId() + "]");
  
    RuntimeService runtimeService = processEngine.getRuntimeService();
    ProcessInstance processInstance = runtimeService
        .startProcessInstanceByKey("onboarding");
    System.out.println("Onboarding process started with process instance id [" 
        + processInstance.getProcessInstanceId()
        + "] key [" + processInstance.getProcessDefinitionKey() + "]");
    
    TaskService taskService = processEngine.getTaskService();
    FormService formService = processEngine.getFormService();
    HistoryService historyService = processEngine.getHistoryService();

    Scanner scanner = new Scanner(System.in);
    while (processInstance != null && !processInstance.isEnded()) {
      List<Task> tasks = taskService.createTaskQuery()
          .taskCandidateGroup("managers").list();
      System.out.println("Active outstanding tasks: [" + tasks.size() + "]");
      for (int i = 0; i < tasks.size(); i++) {
        Task task = tasks.get(i);
        System.out.println("Processing Task [" + task.getName() + "]");
        Map<String, Object> variables = new HashMap<String, Object>();
        FormData formData = formService.getTaskFormData(task.getId());
        for (FormProperty formProperty : formData.getFormProperties()) {
          if (StringFormType.class.isInstance(formProperty.getType())) {
            System.out.println(formProperty.getName() + "?");
            String value = scanner.nextLine();
            variables.put(formProperty.getId(), value);
          } else if (LongFormType.class.isInstance(formProperty.getType())) {
            System.out.println(formProperty.getName() + "? (Must be a whole number)");
            Long value = Long.valueOf(scanner.nextLine());
            variables.put(formProperty.getId(), value);
          } else if (DateFormType.class.isInstance(formProperty.getType())) {
            System.out.println(formProperty.getName() + "? (Must be a date m/d/yy)");
            DateFormat dateFormat = new SimpleDateFormat("m/d/yy");
            Date value = dateFormat.parse(scanner.nextLine());
            variables.put(formProperty.getId(), value);
          } else {
            System.out.println("<form type not supported>");
          }
        }
        taskService.complete(task.getId(), variables);

        HistoricActivityInstance endActivity = null;
        List<HistoricActivityInstance> activities = 
            historyService.createHistoricActivityInstanceQuery()
            .processInstanceId(processInstance.getId()).finished()
            .orderByHistoricActivityInstanceEndTime().asc()
            .list();
        for (HistoricActivityInstance activity : activities) {
          if (activity.getActivityType() == "startEvent") {
            System.out.println("BEGIN " + processDefinition.getName() 
                + " [" + processInstance.getProcessDefinitionKey()
                + "] " + activity.getStartTime());
          }
          if (activity.getActivityType() == "endEvent") {
            // Handle edge case where end step happens so fast that the end step
            // and previous step(s) are sorted the same. So, cache the end step 
            //and display it last to represent the logical sequence.
            endActivity = activity;
          } else {
            System.out.println("-- " + activity.getActivityName() 
                + " [" + activity.getActivityId() + "] "
                + activity.getDurationInMillis() + " ms");
          }
        }
        if (endActivity != null) {
          System.out.println("-- " + endActivity.getActivityName() 
                + " [" + endActivity.getActivityId() + "] "
                + endActivity.getDurationInMillis() + " ms");
          System.out.println("COMPLETE " + processDefinition.getName() + " ["
                + processInstance.getProcessDefinitionKey() + "] " 
                + endActivity.getEndTime());
        }
      }
      // Re-query the process instance, making sure the latest state is available
      processInstance = runtimeService.createProcessInstanceQuery()
          .processInstanceId(processInstance.getId()).singleResult();
    }
    scanner.close();
  }
}

 

File: $mvnProject/src/main/java/com/example/OnboardingRequest.java

Add Lines Explanation
12-13, 17-21, 28-39 Major service imports within the Activiti APIs for process management.
54-59 Starts an instance of the Onboarding process.
61-62, 67, 71-93 SCollect command line input from tasks eligible for "managers" role and complete tasks.
23-25, 76,80, 84 Based on defined form property types from the process model, prompt the user for type-specific input.
63, 95-125 Show the process history.
23-25 Retrieves the deployed model, proving that it is in the Activiti repository

Package up your code by running “mvn package”.

Run your Java program as before. Notice Sample output noted below.

Command: java -jar target/ActivitiDeveloperQuickStart-0.0.1-SNAPSHOT-jar-with-dependencies.jar

-or-

java -jar target/$quickStartJavaProjectName-0.0.1-SNAPSHOT-jar-with-dependencies.jar

Base Path: $mvnProject

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ProcessEngine [default] Version: [5.22.0.0]
Found process definition [Onboarding] with id [onboarding:1:4]
Onboarding process started with process instance id [5] key [onboarding]
Active outstanding tasks: [1]
Processing Task [Enter Data]
Full Name?
John Doe
Years of Experience? (Must be a whole number)
2
BEGIN Onboarding [onboarding] Sun Nov 27 21:36:21 EST 2016
-- Start [startOnboarding] 4 ms
-- Enter Data [enterOnboardingData] 16855 ms
-- Years of Experience [decision] 3 ms
-- Generic and Automated Data Entry [automatedIntro] 322 ms
-- End [endOnboarding] 0 ms
COMPLETE Onboarding [onboarding] Sun Nov 27 21:36:38 EST 2016

 

Notes:

  • Observe that 2 years-experience sees the process path following the Script Task “Generic and Automated Data Entry” after the “Years of Experience” decision then the process ends.

Command: java -jar target/ActivitiDeveloperQuickStart-0.0.1-SNAPSHOT-jar-with-dependencies.jar

-or-

java -jar target/$quickStartJavaProjectName-0.0.1-SNAPSHOT-jar-with-dependencies.jar

Base Path: $mvnProject

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
ProcessEngine [default] Version: [5.22.0.0]
Found process definition [Onboarding] with id [onboarding:1:4]
Onboarding process started with process instance id [5] key [onboarding]
Active outstanding tasks: [1]
Processing Task [Enter Data]
Full Name?
John Doe
Years of Experience? (Must be a whole number)
5
BEGIN Onboarding [onboarding] Sun Nov 27 21:39:26 EST 2016
-- Start [startOnboarding] 5 ms
-- Enter Data [enterOnboardingData] 7810 ms
-- Years of Experience [decision] 2 ms
Active outstanding tasks: [1]
Processing Task [Personalized Introduction and Data Entry]
Personal Welcome Time? (Must be a date m/d/yy)
12/9/16
BEGIN Onboarding [onboarding] Sun Nov 27 21:39:26 EST 2016
-- Start [startOnboarding] 5 ms
-- Enter Data [enterOnboardingData] 7810 ms
-- Years of Experience [decision] 2 ms
-- Personalized Introduction and Data Entry [personalizedIntro] 20231 ms
-- End [endOnboarding] 0 ms
COMPLETE Onboarding [onboarding] Sun Nov 27 21:39:54 EST 2016

 

Notes:

  • Observe that 5 years-experience sees the process path following the user Task “Personalized Introduction and Data Entry” after the “Years of Experience” decision. The then the process ends.

While simple, this embedded example shows how your applications externalizing process logic into a standards-based modeling and code-friendly development model.

6. Writing Service Tasks in Java

As previously illustrated, our process has an activity “Generic and Automated Data Entry” (a faux backend call) that is conditionally exercised when the onboarding years of experience is not greater than 3. As supplied, this is a “script task”. In this case, a small piece of Javascript executed illustrating a system process step. We’re going migrate this script task into Java to illustrate how the full powerful of Java to various process requirements.

Create a new Java class as follows:

File: $mvnProject/src/main/java/com/example/AutomatedDataDelegate.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.example;

import java.util.Date;

import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.JavaDelegate;

public class AutomatedDataDelegate implements JavaDelegate {

  @Override
  public void execute(DelegateExecution execution) throws Exception {
    Date now = new Date();
    execution.setVariable("autoWelcomeTime", now);
    System.out.println("Faux call to backend for [" 
    + execution.getVariable("fullName") + "]");
  }

}

 

File: $mvnProject/src/main/java/com/example/OnboardingRequest.java

Add Lines Explanation
13 Shows setting a process variable. In this case, the variable autoWelcomeTime with the current time.
14 Shows retrieving a process variable.

Change the script task to a service task pointing to AutomatedDataDelegate.

Before:

File: $mvnProject/src/main/resources/onboarding.bpmn20.xml

1
2
3
4
5
6
7
8
9
<?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/processdef">
  <process id="onboarding" name="Onboarding" isExecutable="true">
...
    <scriptTask id="automatedIntro" name="Generic and Automated Data Entry" scriptFormat="javascript" activiti:autoStoreVariables="false">
      <script><![CDATA[var dateAsString = new Date().toString();
execution.setVariable("autoWelcomeTime", dateAsString);]]></script>
    </scriptTask>
...

 

After:

File: $mvnProject/src/main/resources/onboarding.bpmn20.xml

1
2
3
4
5
<?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/processdef">
  <process id="onboarding" name="Onboarding" isExecutable="true">
...
   <serviceTask id="automatedIntro" name="Generic and Automated Data Entry" activiti:class="com.example.AutomatedDataDelegate"></serviceTask>

 

Package up your code by running “mvn package”.

Run your Java program as before. Notice Sample output noted below.

Command: java -jar target/ActivitiDeveloperQuickStart-0.0.1-SNAPSHOT-jar-with-dependencies.jar

-or-

java -jar target/$quickStartJavaProjectName-0.0.1-SNAPSHOT-jar-with-dependencies.jar

Base Path: $mvnProject

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ProcessEngine [default] Version: [5.22.0.0]
Found process definition [Onboarding] with id [onboarding:1:4]
Onboarding process started with process instance id [5] key [onboarding]
Active outstanding tasks: [1]
Processing Task [Enter Data]
Full Name?
John Doe
Years of Experience? (Must be a whole number)
3
Faux call to backend for [John Doe]
BEGIN Onboarding [onboarding] Sun Nov 27 22:57:32 EST 2016
-- Start [startOnboarding] 4 ms
-- Enter Data [enterOnboardingData] 10153 ms
-- Years of Experience [decision] 2 ms
-- Generic and Automated Data Entry [automatedIntro] 0 ms
-- End [endOnboarding] 0 ms
COMPLETE Onboarding [onboarding] Sun Nov 27 22:57:42 EST 2016

 

Notes:

  • Observe the output “Faux call to backend for [John Doe]” illustrating accessing a previously set process variable.

This simple example shows the simplicity and power of adding process-driven abstractions in your application.

 

7. Conclusion

Observe the output “Faux call to backend for [John Doe]” illustrating accessing a previously set process variable.

 

https://www.activiti.org/quick-start

 

时间: 2024-09-10 17:49:16

工作流引擎Activiti 专题的相关文章

工作流引擎Activiti使用总结

1.简单介工作流引擎与Activiti 对于工作流引擎的解释请参考百度百科:工作流引擎 1.1 我与工作流引擎 在第一家公司工作的时候主要任务就是开发OA系统,当然基本都是有工作流的支持,不过当时使用的工作流引擎是公司一些牛人开发的(据说是用一个开源的引擎修改的),名称叫CoreFlow:功能相对Activiti来说比较弱,但是能满足日常的使用,当然也有不少的问题所以后来我们只能修改引擎的代码打补丁. 现在是我工作的第二家公司,因为要开发ERP.OA等系统需要使用工作流,在项目调研阶段我先搜索资

Activiti工作流引擎使用

Activiti 工作流引擎使用 1.简单介工作流引擎与Activiti 对于工作流引擎的解释请参考百度百科:工作流引擎 1.1 我与工作流引擎 在第一家公司工作的时候主要任务就是开发OA系统,当然基本都是有工作流的支持,不过当时使用的工作流引擎是公司一些牛人开发的(据说是用一个开源的引擎修改的),名称叫CoreFlow:功能相对Activiti来说比较弱,但是能满足日常的使用,当然也有不少的问题所以后来我们只能修改引擎的代码打补丁. 现在是我工作的第二家公司,因为要开发ERP.OA等系统需要使

工作流引擎核心调度算法与PetriNet

算法 文章分析了六大开源工作流引擎的调度机制和执行机制.包括OBE,Shark,OSWorkflow,jBpm,YAWL,Bossa.由于文章篇幅过长,请访问 http://javafox.vip.myrice.com/mywf/fox999_workflow_kernel_pn_20050417.pdf 下载.文章目录摘抄如下:声明... 2 前言废话... 2 进入正题... 3 先说说四个非PetriNet调度算法的开源引擎... 4 OBE的引擎调度机制... 4 Shark的引擎调度机

动态业务工作流引擎Superflow研究概要

第一章 背景及目标 本人研究了多年的工作流引擎技术,作为研究成果的Superflow,已经有许多成熟的应用.我愿意把这些点滴的积累奉献出来,与大家共享作学问的乐趣与辛酸. 有人说,35岁一个程序员的暮年,我今年36了,才刚刚领悟到程序人生的真谛. §1-1 研制背景 企业的运作过程本质上是人.财.物等资源的优化和配置,形式上无一不体现为信息流.资金流.物流.价值流等合理的流动:随着社会分工的日益具体化,合作已成为主题,合作的体现形式必然是一个完整而高效的工作流程:有管理的企业的活动过程必然是有序

土制状态机在工作流引擎中的应用

/**   * @author : ahuaxuan   * @date 2009-10-27   */ 很早之前(应该是一年以前),ahuaxuan在用dfa实现文字过滤一文中使用确定有限自动机实现了词典的高速查询.其实在当时那段时间里,由于对状态机有了一定的研究,ahuaxuan也触类旁通的理解了工作流引擎的核心体制.于是当时就用python写了一个小巧的工作流引擎的示例,在这之前ahuaxuan没有看过任何工作流引擎的实现,该实现纯属思维的自我延伸. 现在我来说说我的实现. 状态机的本质是

工作流引擎在视频网站架构中的应用

如果对工作流引擎没有了解过的同学可以先看前一篇文章: 土制状态机在工作流引擎中的应用http://ahuaxuan.iteye.com/blog/505124 /** * @author: ahuaxuan(张荣华) * @date: 2009-11-23 */ [size=medium] 在一个视频网站中,用户从上传一个视频,一直到视频能够正确的被其他用户下载观看,其中经历了一个很长的流程. 下面ahuaxuan来画一张图来表示这个简要的流程,但是实际上不同视频网站由于其架构的不同,可能也会导

几种开源工作流引擎的简单比较(转)

摘要:目前开源工作流引擎用的最多的是jbpm , 各种特性都不错, 文档也比较多, 下面只简单列举一下 目前开源工作流引擎用的最多的是jbpm , 各种特性都不错, 文档也比较多, 下面只简单列举一下 其他几种工作流引擎的特性.   Apache ODE Enhydra Shark Bonita Open Business Engine Eclipse JWT  支持的流程建模标准  WS-BPEL 2.0,流程定义必须使用该标准编写才能执行 WfMC和OMG标准 符合WfMC规范 遵循WfMC

使用KNIME工作流引擎让数据分析变得更敏捷

在 developerWorks 文章 分析敏捷世界中的数据 中,我解释了数据分析变得敏捷需要满足的三个主要特征: 分析组件需要模块化,以便在许多不同的情形中使用它们. 要处理的数据需要看起来像一个矩形表,以便最大限度地降低组件之间的数据格式不兼容性. 各个分析组件需要能够利用极少的编程工作组合在一起,形成一个完整的分析. 工作流工具(比如用于数据挖掘.生物信息学和业务分析的工具)需要满足这些要求.与单个分析软件相比,实现数据分析的工作流引擎提供了许多优势. 运行一个工作流不是单个整体性的操作.

大家用什么工作流引擎呢?

问题描述 各位好,向大家请教个问题,我目前在开发一个OA系统,里面有一些工作流,想问问大家用什么工流引擎来开发比较好呢?谢谢! 解决方案 解决方案二:你可以了解下workflow解决方案三:还有没有其它介绍呢解决方案四:K2工作流引擎解决方案五:自己研发的工作流系统,跟其它许多层次配合使用,觉得概念简单且功能丰富.解决方案六:暂时不想评论商品化的工作流系统的好坏,如果你有一个技术设计上的问题(而不是发广告的问题)那么可以提出来交流.可以讨论一些技术问题本身.工作流系统应该用来做一些业务操作,例如