??xml version="1.0" encoding="utf-8" standalone="yes"?>
扩展q移逻辑
The migration logic is written in such a way, that it is easy to extend to suit your needs. The source code is available as a Maven 2 project in the srcsubfolder of the downloaded zip file. To build a new zip file, after having changed or extended the logic, simply execute a
q移逻辑可以~写Q以便轻村֜满你的需求。源代码在所下蝲zip文g里src子文件夹里作一个Maven 2目来用。ؓ(f)了构Z个新的zip文gQ在已经改变或者扩展逻辑之后Q简单执行下面指?/p>
to produce a new zip file in the target folder.
在target文g下生一个新的zip文g?
Following picture gives a high-level overview of the classes in the migration logic.
下图提供了在q移逻辑里类的高层次概貌?
ServiceFactory.configureFromProperties(jbpmDbProperties, activitiDbProperties);
1 public void execute() throws IOException {
2
3 // convert processes
4 ServiceFactory serviceFactory = createServiceFactory();
5 ProcessConversionService processConversionService = serviceFactory.getProcessConversionService();
6 Map<String, Document> migratedProcesses = processConversionService.convertAllProcessDefinitions();
7
8 // write results to bpmn20.xml files
9 writeConvertedProcesses(migratedProcesses, workingDir);
10
11 // Deploy processes to Activiti
12 ActivitiService activitiService = serviceFactory.getActivitiService();
13 activitiService.deployConvertedProcesses(migratedProcesses);
14
15 // data migration
16
17 }
The ActivitiService offers operation needed to get the migrated data in the Activiti tables. For example, deploying the converted process definitions is such an operation
ProcessConversionService 是一个包含流E{换和数据(g)索的程定义借口。它使用?Jbpm3Dao.的实现。这个类的缺省实C用了Hibernate?strong>SessionFactory从jBPM 3的数据库表里(g)索所有的数据?
ActivitiService 提供需要从Activiti数据库表q移数据的操作。例如,部v转换之后的流E定义就是如此的操作?
1 public ProcessConversionService getProcessConversionService() {2 if (processConversionService == null) {
3 this.processConversionService = createDefaultProcessConversionService();
4 }
5 return processConversionService;
6 }
7
8 protected ProcessConversionService createDefaultProcessConversionService() {
9 ProcessConversionServiceImpl service = new ProcessConversionServiceImpl(getJbpm3Dao());
10 return service;
11 }
Table of Contents
目录?
数据q移
程转换
扩展q移逻辑
The jBPM migration is considered [EXPERIMENTAL].
jBPMq移仅作[EXPERIMENTAL]之用?
It is possible to migrate an existing installation of jBPM version 3 to Activiti. The migration includes both process definition conversion (ie. from JPDL 3 to BPMN 2.0) and data migration.
一个已安装的jBPM 版本3q移到Activiti是有可能的。迁Ud括流E定义{换(例如从JPDL3到BPMN 2.0Q和数据q移?
The migration tool is currently offered as a 'preview' only! The migration coverage is at this point in time not sufficient to be usable on production process definitions and databases. Also note that the migration is a 'best effort', which means that you may need to extend the migration logic to cover all your use cases.
q移工具目前只作?#8216;预览’之用Q?/strong>当前q移不能覆盖C品的程定义和数据。也要注意迁UL‘最大的努力’Q这意味着你可以需?#8216;扩展q移逻辑’来控制你所有的用例?
The migration tool is separately availbale as a zip file from the activiti.org download site. Once you have unzipped this file, you will see following files and folders:
q移工具?a >activiti.org下蝲站点以zip文g方式分开下蝲。一旦加压这个文Ӟ文g和文件夹如下所C:(x)
数据库迁U?/strong>
It is possible to migrate the data in the jBPM 3 database tables to the Activiti database schema. To do this, following properties files must be changed to point at the right database:
jBPM3数据库表q移到Activiti数据库schema是有可能的。ؓ(f)了完成这个Q务,必须改变下面的properties文gQ指向正的数据库:(x)
The database migration will use the data in the jBPM 3 tables to:
数据q移用jBPM3数据库表的数据来做:(x)
The data is retrieved from the jBPM 3 tables using Hibernate queries and the Hibernate mappings of jBPM itself.
使用Hibernate查询和jBPM自n的Hibernate?
,可以从jBPM 3数据库表里检索到q些数据?
程转换
It is possible to only convert the process definitions xml from JPDL to BPMN 2.0 that can be executed on the Activiti engine. To do this, place the jBPM 3 processes inside the processes folder. There can be any number of (nested) subfolders, the tool will scan every (sub)folder inside processes to discover processdefinition.xml files (file name must be processdefinition.xml!).
只将JPDL的流E定义xml转换在Activiti引擎执行的BPMN 2.0是有可能的。ؓ(f)了完成这个Q务,请将jBPM 3攄到process 文g夏V可以有M数量Q内|)子文件夹Q工具将扫描process每个Q子Q文件夹Q来发现processdefinition.xml文gQ文件名必须是processfinition.xml!Q?
The discovered processes will be parsed and deployed to an in-memory databse, such that the logic of reverse engineering the process definition from the jBPM deployment tables contained in the database migration is used for both cases.
被发现的程被解析q|到一个内存数据库Q以便对包含在数据库q移的jBPM部v数据库表的流E定义进行反向工E,以ؓ(f)解析和部|之用?
Once the jBPM 3 processes are placed in the processes folder, execute the convert.processes target in the root of the unzipped migration tool folder:
一旦jBPM 3程被放|到process文g夹,那么执行在解压之后的q移工具文gҎ(gu)目录下的convert.processes目标?
ant convert.processes
During conversion, you will see plenty logging passing by describing where and how the process conversion is being executed. At the end of the conversion, you will see following logging appear:
在{换过E中Q通过描述程转换执行是何地和何时转换的方式,可以观察到大量的日志。在转换的末,观察到下列日志出现Q?
As shown in the logging, the resulting BPMN 2.0 processes can be find in the converted-process-xxxx folder, where the xxxx is the timestamp of the conversion.
正如日志所C,BPMN 2.0程的结果可以在converted-process-xxxx文g多w扑ֈQ这里xxxx是{换的旉戟?
In this release, only limited support for start, end, wait state and task-nodes is implemented. In the future, this coverage will expand.
在本ơ发布里Q只实现了对开始,l束Q等待和d节点的有限支持。在来Q这个覆盖范围将要扩充?
Table of Contents
OverviewQ概qͼ
Changing the databaseQ变更数据库Q?
Activiti KickStart is a webbased tool to quickly create 'adhoc' business processes using a subset of constructs available to the Activiti engine. KickStart provides a simple UI that doesn't require to learn BPMN or any modeling environment, as it works with concepts that are familiar to every business user. However, the processes that are created using KickStart, are fully BPMN 2.0 compliant and can be used as a starting point for more complex BPM endeavours.
Activiti KickStart的是一个基于Web的工P用Activiti引擎可用的构ӞconstructsQ的子集提供l快速创?#8220;卛_QadhocQ?#8221;的业务流E。Kickstart提供了不必学?fn)BPMN或者Q何徏模环境的单UIQ因为它?wi)立了每个业务用户都熟(zhn)的概c(din)但是,通过KickStart创徏的的程Q是和BPMN 2.0兼容Qƈ可作为更为复杂BPM努力的v炏V?
KickStart integrates perfectly with the Activiti engine. As such, processes created with KickStart are immediataly usable in Activiti Explorer and are visible in Probe.
KickStart能和Activiti引擎完美集成。因此,采用KickStart创徏的流E在Activiti Explorer立即可用Qƈ在Probe里面可见?
KickStart serves many business cases, but the following three are probably the most common:
KickStart服务许多商业案例Q但以下三个可能是最常见Q?
Following screenshots show the capabilities of Activiti KickStart. Take for example the next picture. It shows how an expense process is created in a matter of a few minutes.
下列屏幕截图展示了Activiti KickStart的能力。下图作为示例。它展示如何在几分钟之内创徏一个付Ҏ(gu)E?
After clicking the save button, the process is immediately usable in Activiti Explorer:
在点?#8220;保存”按钮之后Q这个流E立卛_Activiti Explorer可用?
KickStart also allows to define forms for every task:
KickStart也允ؓ(f)每个d定义表单Q?
Which are obviously directly usable in Activiti Explorer:
q些明显直接在Activiti Explorer可用Q?
At any time during process creation, it is possible to view the corresponding BPMN 2.0 diagram of the business process:
在流E徏立的L旉Q它可以查看相应的BPMN2.0业务程图?
Whenever it is required, the processes defined with KickStart can be opened up and modified:
每当它是必需Q与KickStart的定义的程可被打开和修改:(x)
Processes created with KickStart are fully compliant with the BPMN 2.0 XML, which means that the process can be imported into any BPMN 2.0 editor:
用KickStart的创建的程是完全符合BPMN2.0的XMLQ这意味着该流E可以由M兼容的BPMN2.0~辑器输入:(x)
Changing the databaseQ变更数据库Q?/strong>
Activiti KickStart is currently not yet using the REST API, but uses the service API by including the Activiti engine as a library. While Explorer, Probe and Cycle use the same mechanism for changing the database (see here), the same does not yet apply for KickStart.
Activiti KickStart当前q没有用REST APIQ而是通过包括了Activiti引擎作ؓ(f)cd使用服务API。虽然ExplorerQProbe和Cycle使用相同的机制改变数据(参见q里Q,但这不适于KickStart?
To change the database that KickStart uses in the demo setup, generate a new activiti.cfg.jar, and place it in the apps/apache-tomcat-6.x/webapps/activiti-kickstart/WEB-INF/lib folder.
Z改变演示安装里KickStart使用的数据库Q生一个新的activiti.cfg.jar,q将它放|到apps/apache-tomcat-6.x/webapps/activiti-kickstart/WEB-INF/lib文g夏V?
Table of Contents
Activiti is distributed under the Apache V2 license.
http://activiti.org/download.html
The distribution contains most of the sources as jar files. To find and build the full source codebase, please read the
JVM 5+
Ant 1.7.1+
Every self respecting developer should have read How to ask questions the smart way
每个自重的开发h与应当阅?How to ask questions the smart way ?
After you've done that you can post questions and comments on the Users forum and create issues in our JIRA issue tracker
?a >the Users forum上完成粘贴问题和意见之后Q在our JIRA issue tracker 上徏立问题(issues).
Sections marked with [EXPERIMENTAL] should not be considered stable.
Q标Cؓ(f) [EXPERIMENTAL] 的小节应当视ZE_的?/p>
Table of Contents
Setup is an ant script located in directory setup
that helps you get up and running with Activiti quickly.
安装是一个放|在目录里的脚本。它帮助用户快速徏立ƈq行Activiti?
To run the script, you'll need a working Java runtime and Ant installation. Also make sure that the JAVA_HOME and ANT_HOME system variables are correctly set. The way to do this depends on your operating system, but the manual of ant gives a description on how to do this. The demo setup script is tested with Ant 1.7.1.
Zq行脚本Q需要一个可以工作的安装。也要确?em>JAVA_HOME ?ANT_HOMEpȝ变量讄正确。虽然具体的讄方式Ҏ(gu)操作pȝ不同而相异,但是为如何完成这些设|提供了描述。演C安装脚本在下测试通过?
To configure setup for your environment, update property files build.properties
and build.{your-database}.properties
. Check those files for more information on configurable properties and potential values.
Z针对你的环境配置安装Q请更新属性文?code>build.properties ?build.{your-database}.properties
。ؓ(f)了获取更多可配置属性和潜在的值的信息Q请仔细(g)查这些文件?
The easiest target to get started is open a command prompt in de setup
folder and type:
入门最Ҏ(gu)的目标是在setup文gҎ(gu)开一个命令提Cƈ键入Q?pre>ant demo.start
This target will start tomcat and if you're using h2, it will also start the h2 database. The first time when that is executed, it will also perform the installation:
q个目标启动Tomcat。如果正在用H2数据库,它也启动H2数据库。若是第一ơ执行安装,它也执行下列安装:(x)
(*) Build the webapps. All libraries are stored in ${actviti.home}/setup/files/dependencies/libs
The webapps without the libs are stored in ${actviti.home}/setup/files/webapps
. Building the webapps means that webapps are combined with the necessary libraries in ${actviti.home}/setup/build/webapps
(*)构徏webapps。所有的库保存在${actviti.home}/setup/files/dependencies/libs
。没带库的保存在${actviti.home}/setup/files/webapps
。构建意味着在组合webapp和必ȝ库在${actviti.home}/setup/build/webapps
目录里?/p>
(*) Install the H2 in ${activiti.home}/apps/h2. This only happens if you're using h2 as your database. H2 is the default database.
(*) H2安装至目录里。只是采用H2数据库时才发生。H2是缺省的数据库?/p>
Start the H2 database. Again, this is only done if using h2 as the database. If you're using a different database it is assumed that it is already up and running.
启动H2数据库。对了,如果采用H2数据库时Q才完成q一步。如果采用不同的数据库,那么假定数据库已l启动ƈq行了?/p>
(*) Create the Activiti tables in the database
(*) 在数据库里徏立Activiti库表
(*) Insert the demo users and groups in the Activiti identity tables (see below)
(*) 示例用户和l插入到 Activiti identity表(见下Q?/p>
(*) Deploy the example processes to the Activiti Engine DB
(*) 示例流E部|至Activiti Engine DB?/p>
(*) Download Tomcat if not available in the ${downloads.dir}
(*) 如果在目录里面没有TomcatQ就下蝲Tomcat
(*) Install Tomcat in ${activiti.home}/apps/apache-tomcat-${tomcat.version}
(*) Tomcat安装?{activiti.home}/apps/apache-tomcat-${tomcat.version}
(*) Create an Activiti configuration jar
建立一?Activiti 配置jar?/p>
(*) Deploy the REST interface webapp into tomcat
(*)部vREST接口webapp值Tomcat
(*) Download the Activiti Modeler webapp to ${activiti.home}/webapps
(*) Activiti Modeler webapp下蝲?{activiti.home}/webapps目录?/p>
(*) Deploy the Probe, Explorer and Modeler webapps into tomcat.
(*) Probe, Explorer and Modeler webapps部v至Tomcat?/p>
Start tomcat
启动Tomcat
(*) only performed the first time when running ant demo.start
After running this target H2 and Tomcat will be running in the background. To stop those processes run ant demo.stop
.
The other targets in that build script can also be called individually and they will take the configurable properties into account. Run ant -p
for more details.
在运行目标H2之后QTomcat在后台q行。ؓ(f)了停止这些进E,误?ant demo.stop
。在构徏脚本里的其它目标也能够单个调用。它们将考虑考虑可配|属性。详情可以运?code>ant -p 得到?
These are the demo users:
q些事示例用P(x)
Table 1.1. The demo usersQ示例用P
UserId
Password
Security roles
kermit
kermit
admin
gonzo
gonzo
manager
fozzie
fozzie
user
Now you can access following web applications:
现在Q你能访问下列web 应用E序:
Table 1.2. The webapp toolsQwebapp工具Q?/b>
Webapp Name
URL
Description
Activiti Probe
http://localhost:8080/activiti-probe
The admin management console. Use this tool to see if the configured process engine is correctly initialized, DB tables contents.
Activiti Explorer
http://localhost:8080/activiti-explorer
The process engine user console. Use this tool to view your personal and candidate task lists and to complete tasks.
Activiti Cycle
http://localhost:8080/activiti-cycle
The process cycle layer. Use this to browse repositories, execute transformations between model formats.
Activiti Modeler powered by Signavio
http://localhost:8080/activiti-modeler
The web based process designer tool. Use this tool to graphically author BPMN 2.0 compliant process definitions files.
Note that the Activiti demo setup is a way of showing the capabilities and functionality of Activiti as easy and as fast as possible. This does however, not mean that it is the only way of using Activiti. As Activiti is 'just a jar', it can be embedded in any Java environment: with swing or on a Tomcat, JBoss, WebSphere, etc. Or you could very well choose to run Activiti as a typical, standalone BPM server. If it is possible in Java, it is possible with Activiti!
注意ActivitiCZ安装时ؓ(f)了尽快,容易展现Activiti功能和能力的一U方式。但是这q不意味着q是采用Activiti的唯一方式。Activiti只是一个jar包,它可以嵌入到MJava环境QSwing或者TomcatQJBoss,WebSphere{等。或者你能选择Activiti作ؓ(f)一个典型的Q独立的BPM服务器。Java若在QActiviti在Q?
The distribution contains a workspace directory containing a couple of example java projects:
发行包包含一个许多java目的工作区目录?
activiti-engine-examples: This set of examples show the most common usage of Activiti: BPMN process definitions and process executions are stored in a DB and the examples make use of the persistent API.
This project contains the eclipse project files, an ant build file and a maven pom file. The ant build file is independent of the maven pom. Both are there to show how you can use ant and maven respectively for building and deploying processes as part of your build.
activiti-engine-examples: 把这一pdCZ展示了Activiti的通用用法Q保存在DB里的BPMN程定义和流E执行。还有持久化API使用的示例?
q个目包含了eclipse的项目文Ӟ一个ant构徏文g和一个maven pom文g。ant 构徏文g和maven pom文g怺独立。作Z的构建部分,Z构徏和部|流E,两者展CZ能够使用ant和mavenq行构徏?/p>
activiti-spring-examples: These examples show how you can use the Activiti Engine in a Spring environment.
activiti-spring-examples: q些CZ展示在Spring环境下如何用Activiti引擎?/p>
activiti-groovy-examples: These examples show the library dependencies for groovy and an example process with groovy scripting.
activiti-groovy-examples: ddq些CZ展示了groovy的依赖库和用groovy脚本处理的示例流E?/p>
activiti-jpa-examples: These examples show library dependencies and how you can work with JPA in Activiti.
activiti-jpa-examples: q些CZ展示了JPA的依赖库Q以?qing)在Activiti里采用JPA是如何工作的?/p>
activiti-cycle-examples: This is a project containing an demo example project for Activiti Cycle
activiti-cycle-examples: q是一个包含针对Activiti Cycle的示例项目?/p>
activiti-modeler-examples: This is a file based model repository to which the Activiti Modeler is configured in the demo setup.
activiti-modeler-examples:
activiti-modeler-examples: q是一个在CZ安装里配|Activiti Modeler所需的基于模型的仓库?/p>
the section called “Eclipse setupQEclipse下的安装Q?/a> shows how you can set up your eclipse environment to play with these example projects.
the section called “Eclipse setupQEclipse下的安装Q?/a> 展示了如何安装eclipse环境来熟(zhn)这些示例项目?
As part of the 作ؓ(f) Once you've done that the 一旦完Q将包含 In order to prevent that the distribution file becomes too big by libraries that are included multiple times, all the libraries are grouped into a single directory somewhere in the 吧ؓ(f)了防止由于库包含多次而发布文g变得太大Q所有的库被分组到setup/files下单个的目录?
The ant scripts in the ? All the libs are located in 所有库攄? To run and play with the examples in your eclipse, follow these simple instructions:
Z在eclipse里运行示例,遵从q些单的指o(h)Q?
File --> Import...
File --> Import...
Select 选择 Click 'Browse...', select the directory 点击 'Browse...'Q选择目录 Then you can click 吧然后你在输出对话框能点?yn)L钮,所有都讄好了?
For more convenience, open the ant view (Window --> Show View --> Ant) and drag the file Z更加方便赯Q打开ant视图QWindow --> Show View --> AntQƈ文件拽至antH口。通过在它们上面双击,现在你能ȀzL建目标?
If you want BPMN 2.0 XML auto-completion and validation while typing, you can add the BPMN 2.0 XML Schema to the XML catalog. Go to 如果你想当输入时QBPMN 2.0 XML自动完成和校验,可以BPMN 2.0 XML Schema 加入到XML分类里面。导航至 To check out the database while trying out the demo setup, run the following Ant target in the setup folder:
当尝试示例安装时Qؓ(f)了检查数据库Q运行在文g夹下的Ant目标Q?pre>ant h2.console.start
This will boot the H2 web console. Note that the Ant target doesn't return, so a 'CTRL + C' is required to shutdown the console. Fill in the following URL in the JDBC URL field and click connect:
q将引导H2 Web控制台。注意Ant 目标q不q回Q所以ؓ(f)了关闭控制台Q需要键?em>'CTRL + C'。在 JDBC URL字段里填入URLQƈ点击“connect”:(x) You are now able to browse the Activiti database schema and check the content of the tables.
现在你能览Activiti数据库结构ƈ(g)查数据库表里面的内容?
To change the database, see ???
Z改变数据库,参见 ????img src ="http://www.aygfsteel.com/lewhwa/aggbug/339824.html" width = "1" height = "1" />demo.start
, the examples will be inflated. This means that all the libs and configuration files will be put in place. If you don't run the demo.start
and you want to inflate the examples with libs in the appropriate place, run this command in the setup directory:
demo.start
的部分,展开q些事例?q意味着所有的库和配置文g安|就位。如果不q行demo.start
而将CZ和库展开到合适的位置Q运行安装目录下的这个命令:(x)ant inflate.examples
activiti-engine-examples
and activiti-spring-examples
will contain libs-runtime
and libs-test
directories containing the runtime dependency jars and test time dependency jars respectively.
activiti-engine-examples ?code>activiti-spring-examples
目录。这些目录相应地包含而来q行时所依赖的jar包和试时依赖的jar包?
Library dependenciesQ库依赖Q?/h4>
setup/files
.
setup/build.xml
can inflate the examples (target inflate.examples
) with the libs and they will include the appropriate libs when building the webapps.
setup/build.xml
文g里面的ant 脚本能够展开CZ (target inflate.examples
) ?qing)其库。当构徏webappӞ它们包含合适的库?
setup/files/dependencies/libs
And the following files in setup/files/dependencies
describe the library dependencies:
setup/files/dependencies/libs
Qƈ且在setup/files/dependencies
目录里下列文件描qC库依赖:(x)
libs.engine.runtime.txt
: The library runtime dependencies to run the Activiti Engine.
libs.engine.runtime.txt
: q行Activiti引擎的运行时依赖库?/p>
libs.engine.runtime.test.txt
: The libraries that need to be added to the ones in libs.engine.runtime.txt
to run the tests
libs.engine.runtime.test.txt
: Zq行试Q需要加入到libs.engine.runtime.txt
的库libs.engine.runtime.feature.groovy.txt
: The libraries that need to be added to the ones in libs.engine.runtime.txt
to use the groovy scripting capabilities.
libs.engine.runtime.feature.groovy.txt
: Z使用groovy脚本能力Q需要加入到libs.engine.runtime.txt
的库?/p>
libs.engine.runtime.txt
: The libraries that need to be added to the ones in libs.engine.runtime.txt
to use the JPA variable reference capabilities.
libs.engine.runtime.txt
: Z使用JPA变量引用能力Q需要加入到libs.engine.runtime.txt
的库?/p>
libs.spring.runtime.txt
: The library runtime dependencies to run the Activiti Engine in a Spring environment. (This list includes the libs in libs.engine.runtime.txt
)
libs.spring.runtime.txt
: 在Spring环境下运行Activiti引擎的运行期依赖库。(q个列表包含?code>libs.engine.runtime.txtQ?/p>
libs.spring.runtime.test.txt
: The libraries that need to be added to the ones in libs.spring.runtime.txt
to run tests in a Spring environment
libs.spring.runtime.test.txt
: 在Spring环境下,Z试Q需要加入到libs.spring.runtime.txt
下的库?/p>
libs.cycle.runtime.test.txt
, libs.webapp.rest.txt
and libs.webapp.ui.txt
: The full list of libraries dependencies for the respective components cycle, the rest webapp and the UI webapps like Activiti Explorer, Activiti Probe and Activiti Cycle
libs.cycle.runtime.test.txt
, libs.webapp.rest.txt
?libs.webapp.ui.txt
: 相关lgcycleQrest webapp和像Activiti Explorer, Activiti Probe ?Activiti Cycle之类的UI Webapp所需依赖库的全部列表?Eclipse setupQEclipse下的安装Q?/h4>
General --> Existing Projects into Workspace
and click Next
General --> Existing Projects into Workspace
q点?code>Next
${activiti.home}/workspace
and you'll see the example projects being automatically selected.
${activiti.home}/workspace
Q那么将自动选择CZ目?
Finish
in the Import dialog and you're all set.
activiti-engine-examples/build.xml
into the ant window. Now you'll be able to activate the build targets by just double clicking on them.
Preferences --> XML --> XML Catalog --> Add
, and select the XML Schema from the file system in the folder docs/xsd/BPMN20.xsd
.
Preferences --> XML --> XML Catalog --> Add
Q从文gpȝ里的文g多w?code>docs/xsd/BPMN20.xsd选择XML Schema?
Inspecting the databaseQ检查数据库Q?/h4>
jdbc:h2:tcp://localhost/activiti
Table of Contents
The Activiti process engine is configured through a xml file called activiti.cfg.xml
. Note that this is not applicable if you're using the Spring style of building a process engine.
Activiti程引擎通过一个叫做的xml文g来配|。注意你采用构徏程引擎的Spring风格的方?a href="file:///G:/作品/userguide/src/Zh_CN.html/#">the Spring style of building a process engineQ这U方式ƈ不适合
The easiest way to obtain a ProcessEngine
, is to use the org.activiti.engine.ProcessEngines
class:
获取ProcessEngine最Ҏ(gu)的方式是使用org.activiti.engine.ProcessEngines
c:(x)
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine()
This will look for an activiti.cfg.xml
file on the classpath and construct an engine based on the configuration in that file. The following snippet shows an example configuration. The following sections will give a detailed overview of the configuration properties.
q将在classpath上寻?activiti.cfg.xml
文gQƈ在那个文件的配置之上构徏一个引擎。下列片D|CZ一个示例配|。下面部分将l出详细的配|特性的M概观?/p>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration"> <property name="databaseType" value="h2" /> <property name="jdbcUrl" value="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000" /> <property name="jdbcDriver" value="org.h2.Driver" /> <property name="jdbcUsername" value="sa" /> <property name="jdbcPassword" value="" /> <property name="databaseSchemaUpdate" value="true" /> <property name="jobExecutorActivate" value="false" /> <property name="mailServerHost" value="mail.my-corp.com" /> <property name="mailServerPort" value="5025" /> </bean> </beans>
Note that the configuration xml is in fact a Spring configuration. This does not mean that Activiti can only be used in a Spring environment! We are simply leveraging the parsing and dependency injection capabilitities of Spring internally for building up the engine.
注意配置文g事实上是一个Spring配置?strong>qƈ不意味着Activiti只能在Spring环境下? Z构徏引擎Q我们在内部单地q了解析和Spring的依赖注入的能力?
The ProcessEngineConfiguration object can also be created programmatically using the configuration file. It is also possible to use a different bean id (eg. see line 3).
通过使用配置文gQ也能通过~程方式建立ProcessEngineConfiguration对象。用一个不同的bean id也是可能的。(例如Q见W?行)?/p>
ProcessEngineConfiguration.createProcessEngineConfigurationFromResourceDefault(); ProcessEngineConfiguration.createProcessEngineConfigurationFromResource(String resource); ProcessEngineConfiguration.createProcessEngineConfigurationFromResource(String resource, String beanName); ProcessEngineConfiguration.createProcessEngineConfigurationFromInputStream(InputStream inputStream); ProcessEngineConfiguration.createProcessEngineConfigurationFromInputStream(InputStream inputStream, String beanName);
It is also possible not to use a configuration file, and create a configuration based on defaults (see the different supported classes for more information).
不用配|文件也是可能的Q基于缺省徏立一个配|(详情参见不同支持的类Q?a href="file:///G:/作品/userguide/src/Zh_CN.html/#configurationClasses">the different supported classesQ)
ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration(); ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration();
All these ProcessEngineConfiguration.createXXX()
methods return a ProcessEngineConfiguration
that can further be tweaked if needed. After calling the buildProcessEngine()
operation, aProcessEngine
is created:
如果需要所?ProcessEngineConfiguration.createXXX()
的方法返回一个能q一步配|的ProcessEngineConfiguration
。在调用操作之后Q徏立一?code>ProcessEngine ?/p>
ProcessEngine processEngine = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration() .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_FALSE) .setJdbcUrl("jdbc:h2:mem:my-own-db;DB_CLOSE_DELAY=1000") .setJobExecutorActivate(true) .buildProcessEngine();
The activiti.cfg.xml
must contain a bean that has the id 'processEngineConfiguration'
.
dd activiti.cfg.xml
必须包括hid 'processEngineConfiguration'
的bean?/p>
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
This bean is then used to construct the ProcessEngine
. There are multiple classes available that can be used to define the processEngineConfiguration
. These classes represent different environments, and set defaults accordingly. It's a best practice to select the class the matches (the most) your environment, to minimalise the number of properties needed to configure the engine. Following classes are currently available (more will follow in future releases):
得到q个bean然后用来构徏e ProcessEngine
。可以定?code>processEngineConfiguration的类有多个。这些类表示不同的环境,响应地设|ؓ(f)~省。ؓ(f)了减需要配|引擎的属性数量,选择的类以匹配环境是最?jng)_c(din)当前可获得的类如下Q将来的版本推出新的类Q?
org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration: the process engine is used in a standalone way. Activiti will take care of the transactions. By default, the database will only be checked when the engine boots (and an exception is thrown if there is no Activiti schema or the schema version is incorrect).
org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration:以独立方式运行的程引擎。Activiti考虑事务。缺省地Q只有在引擎引导时检查数据库Q如果没有Activiti schema或者schema版本不正,抛出异常)?/p>
org.activiti.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration: this is a convience class for unit testing purposes. Activiti will take care of the transactions. An H2 in-memory database is used by default. The database will be created and dropped when the engine boots and shuts down. When using this, probably no additional configuration is needed (except when using for example the job executor or mail capabilities).
org.activiti.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration: q是一个针对单元测试目的的便捷cRActiviti考虑事务。缺省用H2内存数据库。当引擎引导q关闭时Q数据库被建立和删除。当使用Ӟ可能需要额外的配置Q当使用作业执行器或者邮件能力的CZ除外Q?/p>
org.activiti.spring.SpringProcessEngineConfiguration: To be used when the process engine is used in a Spring environment. See the Spring integration section for more information.
org.activiti.spring.SpringProcessEngineConfiguration: 当在Spring环境下用流E引擎时使用。详情参见Spring集成部分the Spring integration section?/p>
org.activiti.engine.impl.cfg.JtaProcessEngineConfiguration: ([EXPERIMENTAL]) to be used when the engine runs in standalone mode, with JTA transactions.
org.activiti.engine.impl.cfg.JtaProcessEngineConfiguration: ([EXPERIMENTAL])当引擎以带有JTA事务的单独模式运行时使用?/p>
There are two ways to configure the database that the Activiti engine will use. The first option is to define the jdbc properties of the database:
有两U方式类配置引擎用的数据库。第一个选项是定义数据库的jdbc属性:(x)
jdbcUrl: jdbc url of the database.
jdbcUrl: 数据库的jdbc url?/p>
jdbcDriver: implementation of the driver for the specific database type.
jdbcDriver: 特定数据库驱动的实现?/p>
jdbcUsername: username to connect to the database.
jdbcUsername: q接到数据的用户名?/p>
jdbcPassword: password to connect to the database.
jdbcPassword: q接到数据库的密码?/p>
The datasource that is constructed based on the provided jdbc properties will have the default MyBatis connection pool settings. Following attributes can optionally be set to tweak that connection pool (taken from the MyBatis documentation):
Z所提供的jdbc属性所构徏的数据源有的连接池讄?
jdbcMaxActiveConnections: The number of active connections that the connection pool at maximum at any time can contain. Default is 10.
jdbcMaxActiveConnections: 在Q何时刻连接池最大能够包含的可以Ȁzȝq接数。缺省ؓ(f)10.
jdbcMaxIdleConnections: The number of idle connections that the connection pool at maximum at any time can contain.
jdbcMaxIdleConnections:在Q何时刻连接池最大能够包含的I闲的连接数
jdbcMaxCheckoutTime: The amount of time in milliseconds a connection can be 'checked out' from the connection pool before it is forcefully returned. Default is 20000 (20 seconds).
jdbcMaxCheckoutTime: 在连接强制返回之前,能够从连接池(g)Z个连接所需的以毫秒计算的时间倹{?/p>
jdbcMaxWaitTime: This is a low level setting that gives the pool a chance to print a log status and re-attempt the acquisition of a connection in the case that it’s taking unusually long (to avoid failing silently forever if the pool is misconfigured) Default is 20000 (20 seconds).
jdbcMaxWaitTime: q是一个底层的讄Q给q接池一个打印日志状态ƈ重试q接获取的机?x)。在q种情况下通常占用很长旉Q以避免如果q接池位|不好导致导致?zhn)无声息地p|Q,~省?0000Q?0U)?/p>
Example database configuration:
CZ数据库配|:(x)
<property name="databaseType" value="h2" /> <property name="jdbcUrl" value="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000" /> <property name="jdbcDriver" value="org.h2.Driver" /> <property name="jdbcUsername" value="sa" /> <property name="jdbcPassword" value="" />
Alternatively, a javax.sql.DataSource
implementation can be used (eg. DBCP from ):
可选,可以使用 javax.sql.DataSource
的实玎ͼ例如Apache Commons的DBCPQ:(x)
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" > <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/activiti" /> <property name="username" value="activiti" /> <property name="password" value="activiti" /> <property name="defaultAutoCommit" value="false" /> </bean> <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration"> <property name="dataSource" ref="dataSource" /> ...
Note that Activiti does not ship with a library that allows to define such datasource. So you have to make sure that the libraries (eg. from DBCP) are on your classpath.
注意Activitiq不包含允许定义如此数据源的Java库。所以,保q些Q例如,从DBCP而来Q在你的classpath里面?
Following properties can be set, regardless of using the jdbc or datasource approach:
不管采用jdbcq是数据源方法,可以讄下列属性:(x)
databaseType: indicates the type of database. This property is required when not using the default H2 database This setting will determine which create/drop scripts and queries will be used. See the 'supported databases' section for an overview of which types are supported.
databaseType: 指示数据库类型。当不是采用~省的H2数据库时xuyao 需要。这个设|将军_要使用哪个建立/删除脚本。要了解支持哪些cd的概要,请参?a href="file:///G:/作品/userguide/src/Zh_CN.html/#supporteddatabases">the 'supported databases' section ?/p>
databaseSchemaUpdate: allows to set the strategy to handle the database schema on process engine boot and shutdown.
databaseSchemaUpdateQ允许当程引擎引导和关闭时Q设|处理数据库l构采取的策略?
false
(default): Checks the version of the DB schema against the library when the process engine is being created and throws an exception if the versions don't match.
false
Q缺省)Q当程引擎建立Ӟ(g)查DB和库的版本。如果版本不匚wQ将抛出异常?/p>
true
: Upon building of the process engine, a check is performed and an update of the schema is performed if it is necessary. If the schema doesn't exist, it is created.
true
:一旦流E引擎构建完成,执行一个检查。如果有必要Q更新数据库的结构。如果结构不存在Q就创徏它?/p>
create-drop
: Creates the schema when the process engine is being created and drops the schema when the process engine is being closed.
create-drop
Q在程引擎创徏时创建结构;当流E引擎时到达删除l构?/p>
The JobExecutor is a component that manages a couple of threads to fire timers (and later also asynchronous messages). For unit testing scenarios, it is cumbersome to work with multiple threads. Therefor the API allows to query for (ManagementService.createJobQuery
) and execute jobs (ManagementService.executeJob
) through the API so that job execution can be controlled from within a unit test. To avoid that the job executor interferes, it can be turned off.
作业执行器是一个管理点火定时器一对线E的lgQ之后也叫异步消息)。对于单元测试场景,和多个线E一道工作是ȝ(ch)的。所以API允许通过API查询 (ManagementService.createJobQuery
) q执行作?(ManagementService.executeJob
) 以便从一个单元测试里控制作业执行。ؓ(f)了避免作业干扎ͼ可以x它?
By default, the JobExecutor is activated when the process engine boots. Specify
~省圎ͼ当流E引擎引导时ȀzJobExecutor。指?/p>
<property name="jobExecutorActivate" value="false" />
when you don't want the JobExecutor to be activated upon process engine boot.
当流E引擎引导时Qƈ不想Ȁz?JobExecutor?
Optional. Activiti supports sending e-mails in business processes. To actually send an e-mail, a valid SMTP mail server configuration is required. See the e-mail task for the configuration options.
可选? Activiti 支持在业务流E里发送电(sh)子邮件。事实上Qؓ(f)了发送邮Ӟ需要配|一个有效的SMTP邮g服务器配|。这个配|可选项参见e-mail task ?
Optional. Allows to tweak settings that influence the history capabilities of the engine. See history configuration for more details.
可选项。允许媄(jing)响引擎的历史能力history capabilities的设|。详情参?a href="file:///G:/作品/userguide/src/Zh_CN.html/#">history configuration ?/p>
<property name="history" value="audit" />
Following are the types (case sensitive!) that Activiti uses to refer to databases.
下表是Activiti所使用的数据库表类型(大小写敏感的Q?
Table 1.1. Supported databases
Activiti database type
Versions tested
Notes
h2
1.2.132
Default configured database
mysql
5.1.11
oracle
10.2.0
postgres
8.4
db2
not yet supported (coming soon, see ACT-330)
mssql
not yet supported (coming soon)
One of the things you probably want to do at some point, is configuring Activiti to use a different database. To configure the demo setup or to generate a configuration file for a different database, follow these steps:
在某些点你可能想做的其中一件事是配|来使用不同的数据库。ؓ(f)了配|演C安装或者ؓ(f)不同数据库生一个配|文Ӟ遵从q些步骤Q?
Edit setup/build.properties
and change the db
parameter to your type of database {oracle | mysql | postgresql | h2
}.
~辑 setup/build.properties
q将db
参数变ؓ(f)你的数据库的cd {oracle | mysql | postgresql | h2
}?/p>
Edit setup/build.${db}.properties
and change the JDBC connection parameters to those of your database installation.
~辑setup/build.${db}.properties
q将JDBCq接参数变ؓ(f)你所安装数据库的那些参数?/p>
To create a configuration file for your database based on the properties you've specified in the build.*.properties files run
Z建立一个基于你所指定build.*.properties 文g的属性的配置文g。请q行
ant cfg.create
from within the setup
folder. The generate configuration file can now be found in setup/build/activiti-cfg
. Also, for convenience, a jar called containing the configuration file can be found in setup/build
?code>setup 文g夏V生的配置文g?code>setup/build/activiti-cfg里能够找到?Z方便赯Q一个叫activiti-cfg.jar
的jar包包含了能够?code>setup/build 里找到的配置文g?
If you want to run the demo setup on another database, first stop the demo setup with
如果你想在另一个数据库上运行演C安装,首先用下面的命o(h)停止CZ安装
ant demo.stop demo.clean demo.start
Then clean and re-start the demo setup with
然后清除q新启动演C安装:(x)
ant demo.clean demo.start
When you want to run the demo setup using oracle as datasource, an extra step is required BEFORE you call the ant target demo.start
.
当你想用oracle作ؓ(f)数据源来q行演示安装Q在调用ant目标 demo.start
?strong>?/strong>Q必要有额外的步骤Q?
Since we cannot redistribute the Oracle JDBC driver due to its licence, you should download it manually: http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-112010-090769.html. Make sure you download ojdbc5.jar (our tests run against 10g ojdbc using version 11.2.0.1).
因ؓ(f)׃Oracle JDBC Driver的授权原因,我们不能重新分发它,所以你应当手动下蝲Q?a >http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-112010-090769.html。确保下载的是ojdbc5.jarQ)
Copy the downloaded ojdbc5.jar to setup/files/dependencies/libs/
This filename is
拯下蝲的ojdbc5.jar至setup/files/dependencies/libs/?/p>
Table of Contents
While you definitely can use Activiti without Spring, we've provided some very nice integration features that are explained in this chapter.
管你肯定能够不用用Spring而用ActivitiQ但是本章将解释一些优U的Spring集成Ҏ(gu)?
The ProcessEngine
can be configured as a regular Spring bean. The starting point of the integration is the class org.activiti.spring.ProcessEngineFactoryBean
. That bean takes a process engine configuration and creates the process engine. This means that the way and all configuration properties documented in the configuration section are exactly the same as for Spring:
ProcessEngine
能够配置Z个普通的Spring bean。集成的开始点是类org.activiti.spring.ProcessEngineFactoryBean。那个bean提取一个流Eƈ建立程引擎。这意味着Ҏ(gu)和所有在配置部分的归的配置属性,完全和Spring相同Q?/p>
<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration"> ... </bean> <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean"> <property name="processEngineConfiguration" ref="processEngineConfiguration" /> </bean>
Do note that the processEngineConfiguration
bean now uses the org.activiti.spring.SpringProcessEngineConfiguration
class.
一定要注意QprocessEngineConfiguration bean现在使用org.activiti.spring.SpringProcessEngineConfiguration
cR?
We'll explain the SpringTransactionIntegrationTest
found in the spring examples of the distribution step by step. Here is the spring configuration file that we use in this example (located in SpringTransactionIntegrationTest-context.xml). The quoted section contains the dataSource, transactionManager, processEngine and the Activiti Engine services.
我们一步一步地解释在发行包中的SpringCZ?code>SpringTransactionIntegrationTest 。这里是q个CZ里所使用的配|文?位置在SpringTransactionIntegrationTest-context.xmlQ。引号部分包含了数据源,事务理器,程引擎和Activiti引擎服务?/p>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> <bean id="dataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy"> <property name="targetDataSource"> <bean class="org.springframework.jdbc.datasource.SimpleDriverDataSource"> <property name="driverClass" value="org.h2.Driver" /> <property name="url" value="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000" /> <property name="username" value="sa" /> <property name="password" value="" /> </bean> </property> </bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration"> <property name="databaseType" value="h2" /> <property name="dataSource" ref="dataSource" /> <property name="transactionManager" ref="transactionManager" /> <property name="databaseSchemaUpdate" value="true" /> <property name="jobExecutorActivate" value="false" /> </bean> <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean"> <property name="processEngineConfiguration" ref="processEngineConfiguration" /> </bean> <bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService" /> <bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService" /> <bean id="taskService" factory-bean="processEngine" factory-method="getTaskService" /> <bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService" /> <bean id="managementService" factory-bean="processEngine" factory-method="getManagementService" /> ...
The remainder of that spring configuration file contains the beans and configuration that we'll use in this particular example:
Spring配置文g的其余部分包含了bean和在q个CZ所使用的配|:(x)
<beans> ... <tx:annotation-driven transaction-manager="transactionManager"/> <bean id="userBean" class="org.activiti.spring.test.UserBean"> <property name="runtimeService" ref="runtimeService" /> </bean> <bean id="printer" class="org.activiti.spring.test.Printer" /> </beans>
First the application context is created with any of the Spring ways to do that. In this example you could use a classpath XML resource to configure our Spring application context:
首先Q用MSpring方式建立应用E序上下文。在本例Q能够用一个classpath XML 资源来配|我们的Spring应用E序上下文:(x)
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("org/activiti/examples/spring/SpringTransactionIntegrationTest-context.xml");
or since it is a test:
或者它是一个测试:(x)
@ContextConfiguration("classpath:org/activiti/spring/test/transaction/SpringTransactionIntegrationTest-context.xml")
Then we can get the service beans and invoke methods on them. The ProcessEngineFactoryBean will have added an extra interceptor to the services that applies Propagation.REQUIRED transaction semantics on the Activiti service methods. So we can use for example the repositoryService to deploy a process like this:
然后我们能够得到服务beanq调用它们之上的Ҏ(gu)。将对一个应用繁D的Q在Activiti服务Ҏ(gu)之上必要的事务语义服务增加一个额外的拦截器。所以我们能够像下面来部|一个流E来使用 repositoryServiceQ?/p>
RepositoryService repositoryService = (RepositoryService) applicationContext.getBean("repositoryService"); String deploymentId = repositoryService .createDeployment() .addClasspathResource("org/activiti/spring/test/hello.bpmn20.xml") .deploy() .getId();
The other way around also works. In this case, the Spring transaction will be around the userBean.hello() method and the Activiti service method invocation will join that same transaction.
其它Ҏ(gu)也可工作。在q种情况下, Spring事务包围在Ҏ(gu)附近。Activiti服务Ҏ(gu)调用加入同一事务?/p>
UserBean userBean = (UserBean) applicationContext.getBean("userBean"); userBean.hello();
The UserBean looks like this. Remember from above in the Spring bean configuration we injected the repositoryService into the userBean.
UserBean看v来如此。记得吗Q在上面的Spring bean配置里,已将repositoryService注入到userBean?/p>
public class UserBean { /** injected by Spring */ private RuntimeService runtimeService; @Transactional public void hello() { // here you can do transactional stuff in your domain model // and it will be combined in the same transaction as // the startProcessInstanceByKey to the Activiti RuntimeService runtimeService.startProcessInstanceByKey("helloProcess"); } public void setRuntimeService(RuntimeService runtimeService) { this.runtimeService = runtimeService; } }
When using the ProcessEngineFactoryBean, by default, all expressions in the BPMN processes will also 'see' the Spring beans. For example, the SpringTransactionIntegrationTest hello.bpmn20.xml
shows how a method on a Spring bean can be invoked using a UEL method expression:
当用ProcessEngineFactoryBeanӞ ~省圎ͼ在BPMN程的所有表辑ּ也将看见Spring beans。例如,SpringTransactionIntegrationTest hello.bpmn20.xml
展示了如何能用一个UELҎ(gu)表达式调?在Spring bean上一个方法?/p>
<definitions id="definitions" ...> <process id="helloProcess"> <startEvent id="start" /> <sequenceFlow id="flow1" sourceRef="start" targetRef="print" /> <serviceTask id="print" activiti:expression="#{printer.printMessage()}" /> <sequenceFlow id="flow2" sourceRef="print" targetRef="end" /> <endEvent id="end" /> </process> </definitions>
Where Printer
looks like this:
q里 Printer
看v来如下:(x)
public class Printer { public void printMessage() { System.out.println("hello world"); } }
And the Spring bean configuration (also shown above) looks like this:
Spring bean配置Q如上所C)看v来如下:(x)
<beans ...> ... <bean id="printer" class="org.activiti.examples.spring.Printer" /> </beans>
Spring integration also has a special feature for deploying resources. In the process engine configuration, you can specify a set of resources. When the process engine is created, all those resources will be scanned and deployed. There is filtering in place that prevents duplicate deployments. Only when the resources actually have changed, will new deployments be deployed to the Activiti DB. This makes sense in a lot of use case, where the Spring container is rebooted often (eg testing).
Spring集成也ؓ(f)部v资源提供一个特D的Ҏ(gu)。在程引擎配置里,你能指定一pd资源。当建立资源引擎Ӟ扫描ƈ部v所有这些资源。存在一个防止复刉|的qo(h)器。只有当资源实际上已l发生变化时Q才新的部|才部v到Activiti 数据库里。这个需要Spring容器需要经帔R新引|比如试Q的地方才有意义?
Here's an example
q里有个CZ
<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration"> ... <property name="deploymentResources" value="classpath*:/org/activiti/spring/test/autodeployment/autodeploy.*.bpmn20.xml" /> </bean> <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean"> <property name="processEngineConfiguration" ref="processEngineConfiguration" /> </bean>
When integrating with Spring, business processes can be tested very easily using the standard Activiti testing facilities. Following example shows how a business process is tested in a typical Spring-based unit test:
当和Spring集成Ӟ采用标准的测试设?a href="file:///G:/作品/userguide/src/Zh_CN.html/#">Activiti testing facilities让业务流E的试轻而易举。下例展C在一个典型基于Spring的单元测试里面一个业务流E是如何试的?/p>
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:org/activiti/spring/test/junit4/springTypicalUsageTest-context.xml") public class MyBusinessProcessTest { @Autowired private RuntimeService runtimeService; @Autowired private TaskService taskService; @Autowired @Rule public ActivitiRule activitiSpringRule; @Test @Deployment public void simpleProcessTest() { runtimeService.startProcessInstanceByKey("simpleProcess"); Task task = taskService.createTaskQuery().singleResult(); assertEquals("My Task", task.getName()); taskService.complete(task.getId()); assertEquals(0, runtimeService.createProcessInstanceQuery().count()); } }
Note that for this to work, you need to define a org.activiti.engine.test.ActivitiRule bean in the Spring configuration (which is injected by auto-wiring in the example above).
注意Qؓ(f)了让q个能够工作Q需要在Spring配置里面 定义一?em>org.activiti.engine.test.ActivitiRule beanQ在上例里通过auto-wiring 注入Q?/p>
<bean id="activitiRule" class="org.activiti.engine.test.ActivitiRule"> <property name="processEngine" ref="processEngine" /> </bean>
Table of Contents
The engine API is the most common way of interacting with Activiti. The central starting point is the ProcessEngine
, which can be created in several ways as described in theconfiguration section. From the ProcessEngine, you can obtain the various services that contain the workflow/BPM methods. ProcessEngine and the services objects are thread safe. So you can keep a reference to 1 of those for a whole server.
引擎API是与Activiti交互的最公共的方式?ProcessEngine
是中心启动点。如?configuration section章节里描q的那样Q它可以用几U方法徏立。从 ProcessEngine
里能够获得包括工作流/BPMҎ(gu)的各U各L(fng)服务?因ؓ(f)ProcessEngine
和服务对象是U程安全的,所以能够ؓ(f)整个服务器范围保留这些服务的引用??
ProcessEngine processEngine = new ProcessEngineBuilder() .configureFromPropertiesResource(configurationResource) .buildProcessEngine(); RuntimeService runtimeService = processEngine.getRuntimeService(); RepositoryService repositoryService = processEngine.getRepositoryService(); TaskService taskService = processEngine.getTaskService(); ManagementService managementService = processEngine.getManagementService(); IdentityService identityService = processEngine.getIdentityService(); HistoryService historyService = processEngine.getHistoryService(); FormService formService = processEngine.getFormService();
The names of the service are quite self-explanatory. For detailed information on the services and the engine API, see the javadocs.
服务名是自解释的Q相当明了。要了解服务和引擎API的详情,参见 the javadocs.
The base exception in Activiti is the org.activiti.engine.ActivitiException
, an unchecked exception. This exception can be thrown at all times by the API, but 'expected' exceptions that happen in specific methods are documented in the the javadocs. For example, an extract from TaskService
:
Activiti的基本异常是org.activiti.engine.ActivitiException, 一个unchecked异常。尽在所有时间API都可抛出q个异常Q但?某些Ҏ(gu)产生'expected'异常。在 the javadocs里面对这U异常进行了文化。例如,下面是一个从 TaskService
抽取一D代码:(x)
/** * Called when the task is successfully executed. * @param taskId the id of the task to complete, cannot be null. * @throws ActivitiException when no task exists with the given id. */ void complete(String taskId);
In the example above, when an id is passed for which no task exists, an exception will be thrown. Also, since the javadoc explicitly states that taskId cannot be null, anActivitiException
will be thrown when null
is passed.
在上例,当传递一个不存在的Q务的idQ将?x)抛Z个异常。当?dng)javadoc 明明白白说明taskId不能为nullQ当传递nullӞ抛?ActivitiException
?
Even though we want to avoid a big exception hierarchy, the following subclasses were added which are thrown in specific cases:
管我们竭力避免一个庞大的异常层次体系Q但q是在特D情况下增加了如下的子类?
ActivitiWrongDbException:
Thrown when the Activiti engine discovers a mismatch between the database schema version and the engine version.
ActivitiWrongDbException:
当Activiti引擎发现数据库结构版本和引擎版本之间不匹配时Q将抛出q个异常?/p>
ActivitiOptimisticLockingException:
Thrown when an optimistic locking occurs in the datastore caused by concurrent access of the same data entry.
ActivitiOptimisticLockingException:
当数据库里由对相同的数据ƈ发访问导致乐观锁定时发生?/p>
Business processes are an integral part of software projects and they should be tested in the same way normal application logic is tested: with unit tests. Since Activiti is an embeddable Java engine, writing unit test for business processes is as simple as writing regular unit tests.
业务程是Y仉目的一个集成部分,那么应当采用正常应用逻辑试 Q采用单元测试。因为Activiti是一个嵌入式Java引擎Q所以编写业务流E的单元试像编写正常的单元试一L(fng)单?
Activiti supports both Junit versions 3 and 4 style of unit testing. In the Junit 3 style, the org.activiti.engine.test.ActivitiTestCase must be extended. This will make the processEngine and the services available through protected member fields. In the setup() of the test, the processEngine will be initialized by default with the activiti.cfg.xmlresource on the classpath. To specify a different configuration file, override the getConfigurationResource() method. Process engines are be cached statically over multiple unit tests when the configuration resource is the same.
Activiti支持单元试的Junit版本3?风格。在Junit 3风格里,必须扩展org.activiti.engine.test.ActivitiTestCase。这得通过保护成员字段获得程引擎和服务。在试的setup()里,~省地流E引擎将通过classpath上的 activiti.cfg.xml 资源初始化流E引擎。ؓ(f)了指定不同的 配置文gQ覆?getConfigurationResource() Ҏ(gu)。当配置资源是相同时Q流E引擎静态地~存多个单元试?
By extending ActivitiTestCase, you can annotate test methods with org.activiti.engine.test.Deployment. Before the test is run, a resource file of the formtestClassName.testMethod.bpmn20.xml in the same package as the test class, will be deployed. At the end of the test, the deployment will be deleted, including all related process instances, tasks, etc. The Deployment annotation also supports setting the resource location explicitly. See the Javadocs for more details.
通过扩展 ActivitiTestCase Q你能用org.activiti.engine.test.Deployment标注试Ҏ(gu)。在q行试以前Q将同一包里部v?testClassName.testMethod.bpmn20.xml作ؓ(f)试cR在试l束Q将删除包括所有相关的程实例QQ务等{部|Ӏ?em>Deployment 标注也支持显式设|资源的位置。详情参?the Javadocs?
Taking all that in account, a Junit 3 style test looks as follows.
上面所有的情况考虑q去QJunit 3风格的测试方式如下所C?/p>
public class MyBusinessProcessTest extends ActivitiTestCase { @Deployment public void testSimpleProcess() { runtimeService.startProcessInstanceByKey("simpleProcess"); Task task = taskService.createTaskQuery().singleResult(); assertEquals("My Task", task.getName()); taskService.complete(task.getId()); assertEquals(0, runtimeService.createProcessInstanceQuery().count()); } }
To get the same functionality when using the Junit 4 style of writing unit tests, the org.activiti.engine.test.ActivitiRule Rule must be used. Through this rule, the process engine and services are available through getters. As with the ActivitiTestCase (see above), including this Rule will enable the use of the org.activiti.engine.test.Deploymentannotation (see above for an explanation of its use and configuration) and it will look for the default configuration file on the classpath. Process engines are statically cached over multiple unit tests when using the same configuration resource.
当用Junit 4风格~写单元试ӞZ获得相同的功能,必须使用 org.activiti.engine.test.ActivitiRule 规则。采用这个规则,通过getter获得程引擎和服务。采?ActivitiTestCaseQ如上)Q包括?org.activiti.engine.test.Deployment Q它的用和配置如上Q标注的q个规则Q它?yu)在classpath上寻扄省的配置。当使用相同配置资源Ӟ程引擎静态地~存多个单元试?
Following code snippet shows an example of using the Junit 4 style of testing and the usage of the ActivitiRule.
下面代码片段展示了采用的Junit 4风格的测试和 ActivitiRule用法的示例?/p>
public class MyBusinessProcessTest { @Rule public ActivitiRule activitiRule = new ActivitiRule(); @Test @Deployment public void ruleUsageExample() { RuntimeService runtimeService = activitiRule.getRuntimeService(); runtimeService.startProcessInstanceByKey("ruleUsage"); TaskService taskService = activitiRule.getTaskService(); Task task = taskService.createTaskQuery().singleResult(); assertEquals("My Task", task.getName()); taskService.complete(task.getId()); assertEquals(0, runtimeService.createProcessInstanceQuery().count()); } }
The ProcessEngine
is a thread-safe class and can easily be shared among multiple threads. In a webapplication, this means it is possible to create the process engine when the container boots and shut down the engine when the container goes down.
ProcessEngine
是一个线E安全的cdƈ能在多个U程里面L׃n。在一个Web应用里面Q这意味着当容器引导和关闭引擎Ӟ可能建立q个程引擎?
The following code snippet how this is done in a regular Servlet environment, using a ServletContextListener:
下列代码通过使用 ServletContextListenerQ展CZ在一个普通的 Servlet 环境下如何完成这个工作的?/p>
public class ProcessEnginesServletContextListener implements ServletContextListener { public void contextInitialized(ServletContextEvent servletContextEvent) { ProcessEngines.init(); } public void contextDestroyed(ServletContextEvent servletContextEvent) { ProcessEngines.destroy(); } }
The contextInitialized will delegate to ProcessEngines.init()
. That will look for activiti.cfg.xml
resource files on the classpath, and create a ProcessEngines
for the given configurations (eg. multiple jars with a configuration file). If you have multiple such resource files on the classpath, make sure they all have different names. When the process engine is needed, it can be fetched using
contextInitialized委托l?ProcessEngines.init()
。它?yu)在classpath上寻?activiti.cfg.xml
资源文gQƈ且ؓ(f)l定的配|徏?ProcessEngines
。如果在classpath上具有多个如此的资源文gQ确保它们都h不同的名字。当需要流E引擎时Q它?yu)采用下面的?gu)来取?/p>
ProcessEngines.getDefaultProcessEngine()
or
?/p>
ProcessEngines.getProcessEngine("myName");
Of course, it is also possible to use any of the variants of creating a process engine, as described in the configuration section.
当然Q采用徏立流E引擎的变体也是可能的。如 configuration section所C?
The contextDestroyed of the context-listener delegates to ProcessEngines.destroy()
. That will properly close all initialized process engines.
context-listener 的contextDestroyed 委托l?code>ProcessEngines.destroy()
。那正常关闭所有以初始化的程引擎?
The API exposes the POJO core of the Process Virtual Machine. Reading and playing with it is interesting for education purposes to understand the internal workings of Activiti. And the POJO API can also be used to build new process languages.
程虚拟机(Process Virtual Machine QAPI暴露程虚拟机的POJO核心。ؓ(f)了理解Activiti的内部工作机制的教育目的Q阅dƈ把玩API是有的?q且POJO API也能用来构徏新的程语言?
For example:
例如Q?/p>
PvmProcessDefinition processDefinition = new ProcessDefinitionBuilder() .createActivity("a") .initial() .behavior(new WaitState()) .transition("b") .endActivity() .createActivity("b") .behavior(new WaitState()) .transition("c") .endActivity() .createActivity("c") .behavior(new WaitState()) .endActivity() .buildProcessDefinition(); PvmProcessInstance processInstance = processDefinition.createProcessInstance(); processInstance.start(); PvmExecution activityInstance = processInstance.findExecution("a"); assertNotNull(activityInstance); activityInstance.signal(null, null); activityInstance = processInstance.findExecution("b"); assertNotNull(activityInstance); activityInstance.signal(null, null); activityInstance = processInstance.findExecution("c"); assertNotNull(activityInstance);
Activiti uses UEL for expression-resolving. UEL stands for Unified Expression Language and is part of the EE6 specification ()see the EE6 specification for detailed information). To support all features of latest UEL spec on ALL environements, we use a modified version of JUEL.
Activiti使用UELq行表达式解析。UEL代表l一表达式(Unified Expression Language Q,它是JAVA EE 6规范Q?the EE6 specification Q的一部分。ؓ(f)了在所有环境支持最新的UEL规范Q我们采用了JUEL的修改版本?
Expressions can be used in for example Java Service tasks, Execution Listeners, Task Listeners and Conditional sequence flows. Although there are 2 types of expressions, value-expression and method-expression, activiti makes abstraction of this and they can both be used where an expression
is needed.
表达式能够在下列CZ中用:(x) Java Service tasks, Execution Listeners, Task Listeners ?Conditional sequence flows。尽存在两U表辑ּQD辑ּ和方法表辑ּ。但是,ActivitiҎ(gu)q行了抽象,在需要表辑ּ的地方两者均可用?
Value expression: resolves to a value. By default, all process variables are available to use. Also all spring-beans (if using Spring) are available to use in expressions. On top of that, the DelegateExecution
is also available in the expression-context and can be accessed using the name execution
. Since the execution is exposed as execution
, all variables and spring-beans with name execution
are hidden and cannot be used in an expression. Some examples:
D辑ּQValue expressionQ?/strong>: 解析Z个倹{缺省地Q所有的程均可使用。表辑ּ里也可用所有的spring beanQ如果用SpringQ?strong>在此之上Q在表达式上下文里也可获得DelegateExecution。因为,执行暴露?code>executionQ带有名U?code>execution的所有变量和spring-beans被隐藏Qƈ且不能在表达式里使用。例如:(x)
${myVar} ${myBean.myProperty}
Method expression: invokes a method, with or without parameters. When invoking a method without parameters, be sure to add empty parentheses after the method-name. The passed parameters can be literal values or expressions that are resolved themselves. Examples:
Ҏ(gu)表达式:(x)调用一个方法,带不带参数均可。当 调用没有参数的方法,保在方法名之后加入I括受这些传入的参数可以字面值或者被解析解释的表辑ּ。例如:(x)
Method expression:
Ҏ(gu)表达式:(x)
${printer.print()} ${myBean.addNewOrder('orderName')} ${myBean.doSomething(myVar, execution)}
Note that these expressions support resolving primitives (incl. comparing them), beans, lists, arrays and maps.
注意q些表达式支持解析原型(包括对它们进行比较)QbeansQ列表,数组和map.
For more concrete usage and examples, check out Expressions in Spring, Java Service tasks, Execution Listeners, Task Listeners or Conditional sequence flows.
Z更多的具体的用法和示例,h?Expressions in SpringQ?a href="file:///G:/作品/userguide/src/Zh_CN.html/#">Java Service tasksQ?a href="file:///G:/作品/userguide/src/Zh_CN.html/#">Execution ListenersQ?Task Listeners 或?a href="file:///G:/作品/userguide/src/Zh_CN.html/#">Conditional sequence flows?
Table of Contents
To deploy processes, they have to be wrapped in a business archive. A business archive is the unit of deployment to an Activiti Engine. Basically a business archive is equivalent to a zip file. It can contain BPMN 2.0 processes, task forms, rules and any other type of file. In general, a business archive contains a collection of named resources.
Z部v程Q必d程打包为流E案。一个流E档案是Activiti引擎的部|单元。基本来_(d)一个流E案等价于一个zip文g。它包含了BPMN 2.0程QQ务表单,规则和其它文件类型。通常Q流E案包含一个命名资源的集合?
When a business archive is deployed, it is scanned for BPMN files with a extension. Each of those will be parsed and potentially contains multiple process definitions.
当部|业务档案时Q以.bpmn20.xml
扩展名ؓ(f)的BPMN文g方式扫描来扫描它。每个BMPN文g被扫描,它包含多个流E定义?
Note that Java classes present in the business archive will not be added to the classpath. All custom classes used in process definitions in the business archive (for example Java service tasks or event listener implementations) should be present on the activiti-engine's classpath in order to run the processes.
注意业务案存在的Javac?strong>不?x)加入到classpath。ؓ(f)了运行流E,业务案里面的流E定义的所有定制类Q例如Java服务cL者事件监听器实现Q应当包含在Activiti引擎的classpath里面?
All custom classes that are used in your process (eg. JavaDelegates used in servicetaks or event-listeners, TaskListeners, ...) should be present on the engine's classpath when an instance of the process is started. It's not nessecairy to have those classes on the classpath when deploying the process-definition into the engine.
当启动一个流E实例(例如serviceTask或者event-listenerQTaskListenerQ时Q定义在程里面的所有定制类应当包含在引擎的classpath上面 。当把流E定义部|到引擎Ӟ不必哪些类攑ֈclasspath上?
When you are using the demo setup and you want to add your custom classes, you should add a jar containing your classes to the activiti-rest webapp lib. Don't forget to include the dependencies of your custom classes (if any) as wel. This is the same location where the activiti-engine jar is located. You can find this folder inside your distro at the folowing location:
当正在用demo setupq要加入你自q定制cLQ你应当包含这些类的jar包添加至activiti-rest webapp lib里面。也不要忘记包含定制cȝ依赖包(如果有的话)Q这个和activiti-engine.jar位置相同。在发行版本中的如下位置扑ֈq个文g夹:(x)
${activiti distro}/apps/apache-tomcat-6.0.29/webapps/activiti-rest/lib/
Deploying a business archive from a zip file can be done like this:
以如下方式完成从zip文g来部|流E档案:(x)
String barFileName = "path/to/process-one.bar"; ZipInputStream inputStream = new ZipInputStream(new FileInputStream(barFileName)); repositoryService.createDeployment() .name("process-one.bar") .addZipInputStream(inputStream) .deploy();
It's also possible to build a deployment from individual resources. See javadocs for more details.
也可能从单个资源来构建部|Ӏ详情参见javadoc?
To deploy a business archive with ant, first the deploy-bar
task needs to be defined. Make sure that the configuration jar is on the classpath, as well as the Activiti jar and all its dependencies:
Z以ant方式来部|业务档案,首先需要定?deploy-bar
d。确保配|jar包,Activiti jar?qing)其所有的依赖都在classpath路径里面?/p>
<taskdef name="deploy-bar" classname="org.activiti.engine.impl.ant.DeployBarTask"> <classpath> <fileset dir="..."> <include name="activiti-cfg.jar"/> <include name="your-db-driver.jar"/> </fileset> <fileset dir="${activiti.home}/lib"> <include name="activiti-engine-${activiti.version}.jar"/> <include name="ibatis-sqlmap-*.jar"/> </fileset> </classpath> </taskdef> <deploy-bar file=".../yourprocess.bar" />
It's possible to deploy process definitions through probe, this is described in Activiti Probe - Deployments.
通过Probe也可以部|流E定义,q在Activiti Probe - Deployments里面描述?
BPMN doesn't have a notion of versioning. And that is good because the executable BPMN process file will probably live in an SVN repository as part of your development project. Versions of process definitions are created during deployment. During deployment, Activiti will assign a version to the ProcessDefinition
before it is stored in the Activiti DB.
BPMN没有版本理的概c(din)这是好事,因ؓ(f)可执行的BPMN程文g作为开发项目的一部分ȝ在一个SVN的仓库里Q所以在部vӞ才徏立流E定义的版本。在部v期间Q在ProcessDefinition
保存到Activiti DB之前QActivitiؓ(f)它分布一个版本号?
For each process definition in a business archive the following steps are performed to initialize the properties key
, version
, name
and id
:
对于业务档案里的每个程定义Q执行下列步骤初始化 key
, version
, name
?id
q些属性:(x)
The process id
attribute is used as the process definition key
property
程id
属?用作为流E定义的key
Ҏ(gu)?/p>
The process name
attribute is used as the process definition name
property. If the name attribute is not specified, then id attribute is used as the name.
程name
属?用作为流E定义的Ҏ(gu)?name
。如果没有指定name属性,那么id属性作为名UC用?/p>
The first time a process with a particular key is deployed, version 1 is assigned. For all subsequent deployments of process definitions with the same key, the version will be set 1 higher then the max currently deployed version. The key property is used to distinct process definitions.
当一个带有特Dkey的流E第一ơ部|时Q版本分配ؓ(f)1。对带有相同key的流E定义,在后l部|时Q每部v一ơ,在当前最大部|版本号上加1。keyҎ(gu)用来区分流E定义?/p>
The id property is set to {processDefinitionKey}:{processDefinitionVersion}
idҎ(gu)设|ؓ(f){processDefinitionKey}:{processDefinitionVersion}
Table of Contents
Activiti provides a convenient and flexible way to add forms for the manual steps of your business processes. We support two strategies to work with forms: Build-in form rendering and external form rendering
ActivitiZ的业务流E的手动步骤提供了一个方便和灉|的增加表单的Ҏ(gu)。我们ؓ(f)表单的工作支持两U策略:(x)内置渲染和外部渲染?
Build-in form rendering is the simplest to get started with. We'll explain it with an example.
最单的开始的方式是内|表单的渲染。我们将以一个示例进行解释?
The demo setup script installs the vacationRequest business process as an example of using task forms through Activiti Explorer. Please check the example for the complete source code. The business process diagram looks like this:
作ؓ(f)通过Activiti Explorer使用d表单的一个示例,demo setup脚本安装了业务流E。请(g)查示例的完整的源代码。业务流E图如下所C:(x)
To use the build-in rendering, the form files have to be included in the deployment. That can be done programmatically like this:
Z使用内置的渲染,在部|中必须包括表单文g。通过如下的编E方式来完成Q?/p>
Deployment deployment = repositoryService.createDeployment() .addClasspathResource("org/activiti/examples/taskforms/VacationRequest.bpmn20.xml") .addClasspathResource("org/activiti/examples/taskforms/approve.form") .addClasspathResource("org/activiti/examples/taskforms/request.form") .addClasspathResource("org/activiti/examples/taskforms/adjustRequest.form") .deploy();
Or that can be done with an ant task by first building a business archive zip file that contains the process and forms like above and then deploy it like this:
或者,首先通过构徏一个包含如上所C的程和表单的业务案zip文gQ然后,如下部vq个文g。这些通过一个antd来完成?/p>
<taskdef name="deploy-bar" classname="org.activiti.engine.impl.ant.DeployBarTask"> <classpath> <pathelement path="files/demo"/> <fileset dir="build"> <include name="activiti-cfg.jar"/> </fileset> <fileset dir="${activiti.home}/examples/activiti-engine-examples/libs-runtime" /> <fileset dir="${activiti.home}/examples/activiti-engine-examples/libs-test" /> </classpath> </taskdef> <deploy-bar file="${activiti.home}/setup/build/activiti-examples.bar" />
The BPMN 2.0 specification does not specify how tasks or task forms should be rendered, as such forms are defined using Activiti specific constructs. There is the attributeuserTask
sthat can be specified on startEvent
s and userTask
s.
BPMN 2.0 规范q没有指明Q务或者Q务表单应当如何渲染,使用Activiti特定的构造型来定义如此的表单。在?startEvent
s?userTask
之上能够制定q个属?userTask
?/p>
<startEvent id="request" activiti:formKey="org/activiti/examples/taskforms/request.form" /> <sequenceFlow id="flow1" sourceRef="request" targetRef="handleRequest" /> <userTask id="handleRequest" name="Handle vacation request" activiti:formKey="org/activiti/examples/taskforms/approve.form" > <documentation> Vacation request by ${employeeName} </documentation> ... </userTask>
The activiti:formKey
attribute can contain any text value which you use to identify your form in case you do your own form rendering. But the build-in form rendering expects the activiti:formKey
to be a reference to a resource in the same business archive (= deployment).
当你采用自己的渲染时Q属性能够包含你所用来表明你的表单的Q何文本倹{但是内|的表单渲染器猜?code>activiti:formKey 引用到同一业务案Q?部vQ的一个资源?
Activiti Explorer uses the build-in form rendering engines. Currently, there is only one form rendering engine configured, which is Juel. So it resolves resource files as a Juel expression and the resulting HTML String is sent to the client. In the future, we hope to add a FreeMarker form engine, but that will require more library dependencies so we opt for Juel as the default form engine.
Activiti Explorer使用内置的表单渲染引擎。当前,只有一个以配置的表单渲染器。这个渲染器叫Juel。所以它把资源文件解析ؓ(f)a Juel expression 。解析结?HTML String 被发送到客户。未来,我们希望加入表单引擎Q但是它需要更多的库依赖,所以我们优选把Juel作ؓ(f)~省的表单引擎?
Here is the rendered form defined in resource org/activiti/examples/taskforms/request.form
. Its a form to capture the data necessary to start a new process instance.
q里是在资源org/activiti/examples/taskforms/request.form
里定义的渲染q的表单。它是一个捕获启动一个新的流E实例所必须的数据的表单?
And here is the contents of that form file:
q里是那个表单文件的内容Q?/p>
<h1>Vacation Request</h1> Employee Name:<br/> <input type="text" name="employeeName" value="" /> <input type="hidden" name="employeeName_required" value="true" /> Number of days:<br/> <input type="number" name="numberOfDays" value="1" /> <input type="hidden" name="numberOfDays_type" value="Integer" /> First day of vacation:<br/> <input type="date" name="startDate" /> <input type="hidden" name="startDate_type" value="Date" /> Date of return to work:<br/> <input type="date" name="returnDate" /> <input type="hidden" name="returnDate_type" value="Date" /> Vacation pay requested <input type="checkbox" name="vacationPay"/> Vacation pay requested <input type="hidden" name="vacationPay_boolean" value="true"/> Motivation:<br/> <textarea name="vacationMotivation" value=""></textarea>
<EXPERIMENTAL> The hidden fields provide extra information to the Activiti Explorer client application. So the Javascript in the browser will use the hidden fields and enhance the corresponding input fields. For example, it's possible to specify that a certain text field is a date and Activiti Explorer will add a date picker.
<EXPERIMENTAL> 隐藏字段提供Activiti Explorer 客户应用E序的额外信息。这h览器用这些隐藏字Dƈ加强相应输入字段。例如,制定某一文本字段是dateQActiviti Explorer 加入一个日期选取器是可能的?
Variable names must be camel-cased.
变量名必L骆驼方式的?/p>
The default type of the process variable that is stored is string. Use a hidden field with the input variable name followed by '_type' to define the type (and hence also the conversion from the HTML input to the variable):
保存的流E变量的~省值是 string。用一个输入变量后面跟?em>'_type' 的隐藏字D|定义cdQ这样将HTML的输入约定ؓ(f)q个变量Q:(x)
<input type="hidden" name="numberOfDays_type" value="Integer" />
Currently supported are String, Integer, Boolean, Date.
当前支持的类型ؓ(f)Q?em>String, Integer, Boolean, Date?/p>
Input variables can be made required by adding a hidden field with the input variable name followed by '_required':
通过使用一个输入变量后面跟?em>'_type' 的隐藏字D|产生必须的输入变量?/p>
<input type="hidden" name="employeeName_required" value="true" />
In Activiti-Explorer, the Date type validates to ISO 8601 (YYYY-MM-DD). This field will also use any native date picker tools in the browser (using the HTML5 input type="date") and fall back on a pop-up date picker using the YUI calendar widget. It is, of course still possible to manually enter your own date, which is validated as you type.
在Activiti-Explorer里,Datecd用ISO 8601 (YYYY-MM-DD)来验证。这个字D也用浏览器里的M本地日期拑֏器(使用HTML5?em>input type="date"Q。通过YUI calendar widgetq回一个弹出日期拾取器。当?dng)也可能手动输入你自己的日期,׃输入的验证方法?/p>
The Integer form field in the demo has also been enhanced to make use of HTML5 input type=number, which provides native validation and custom input fields in the supported browser(s), although Activiti-Explorer provides client side validation as well.
在demo里面的Integer表单字段也已l被加强产生HTML 5 input type=number。尽Activiti-Explorer 提供客户端验证,但是在可支持HTML5的浏览器也提供内|验证和定制输入字段?/p>
It is expected that Activiti Explorer in the future will use FormService.getStartFormData
instead of these hidden field values to enhance the form input fields. That's why the hidden fields part is marked as experimental. </EXPERIMENTAL>
可以预料Q?Activiti Explorer 在未来将?x)?FormService.getStartFormData
来代替这些隐藏字D值来加强表单输入字段。那是ؓ(f)什么隐藏字D被标记为实验性的原因? </EXPERIMENTAL>
Use FormService.getRenderedStartForm
to get the rendered form string with the API:
通过APIQ?FormService.getRenderedStartForm
来获取渲染表单字W串?/p>
String FormService.getRenderedStartForm(String processDefinitionId)
Use FormService.submitStartFormData
to start a new process instance with the properties that the user provided as input for the form:
以一个用户ؓ(f)表单输入的属性,采用 FormService.submitStartFormData
来启动一个新的流E实例?/p>
ProcessDefinition FormService.submitStartFormData(String processDefinitionId, Map<String, String> properties)
To learn about the difference between starting a new process instance with this FormService
method in comparison with the ProcessInstance RuntimeService.startProcessInstanceById(String processDefinitionId)
, read the section called “Form propertiesQ表单属性)”
Z了解?ProcessInstance RuntimeService.startProcessInstanceById(String processDefinitionId)
比较Q以q个 FormService
Ҏ(gu)启动一个新的流E实例之间的差异Q请参见 read the section called “Form propertiesQ表单属性)” ?
After submitting the form, a process instance is started and now someone of the management team needs to handle the request.
在提交这个表单之后,一个流E实例被启动。管理小l的有些人需要处理这个请求?
The corresponding user task has a task form attached to it, which uses the variables which were given as input by the employee in the start form. These variables are referenced as expressions and are resolved at runtime to their text representation.
相关的用户Q务具有和它绑定的d表单。。这些作辑ּ引用Q在q行期解析ؓ(f)它们的文本表C?/p>
<h1>Vacation Approval</h1> <p> ${employeeName} would like to take ${numberOfDays} day(s) of vacation. </p> <p> Motivation: ${vacationMotivation} </p> <p> Do you approve this? <select name="vacationApproved"> <option value="true">Yes</option> <option value="false">No</option> </select> <input type="hidden" name="vacationApproved_type" value="Boolean" /> </p> <p> <label> Motivation:<br/> <textarea name="managerMotivation" value=""></textarea> </label> </p>
The manager will now indicate in the form whether the vacation request is approved or not, by selecting the appropriate input in the form.
通过在表单里面选择合适的输入Q经理将在表单里面指CZ假请求是否批注?
The result is stored in as a process variable, which is then used in the exclusive gateway after the form is submitted.
l果作ؓ(f)一个流E变量保存,在表单提交之后在ȝ关里使用?/p>
<sequenceFlow id="flow5" sourceRef="requestApprovedDecision" targetRef="adjustVacationRequestTask"> <conditionExpression xsi:type="tFormalExpression">${!vacationApproved}</conditionExpression> </sequenceFlow>
Depending on the input of the manager in the user task, the employee will now get a new task in his personal task list, stating that the vacation request was disapproved and it needs can be refilled if wanted.
依赖在用户Q务里面经理的输入Q雇员现在将在他的个ZQ务列表里面得C个新的Q务。说明休假请求被拒绝。如果再想休假,需要重填?
The employee can now choose to resend the vacation request, which brings process execution again in the user task for the manager. Or the employee can throw away the request, ending the process.
雇员现在能够选择重发休假h。这栯l理的用hE重新执行。或者雇员可以抛弃这个请求,l止q个程?/p>
<h1>Adjust vacation Request</h1> <p> Your manager has disapproved your vacation request for ${numberOfDays} days. <br/> Reason: ${managerMotivation} </p> <p> Number of days:<br/> <input type="text" name="numberOfDays" value="${numberOfDays}" /> <input type="hidden" name="numberOfDays_type" value="Integer" /> </p ...
Above we showed the build-in task form rendering. But the API also allows for you to perform your own task form rendering outside of the Activiti Engine. These steps explain the hooks that you can use to render your task forms yourself.
上面我们展示了内|的d表单渲染。但是API也允怽?Activiti Engine之外执行你自qd表单渲染器。这些步骤解释了你能使用的渲染你的Q务表单的钩子?
Essentially, all the data that's needed to render a form is assembled in one of these two service methods: StartFormData FormService.getStartFormData(String processDefinitionId)
andTaskFormdata FormService.getTaskFormData(String taskId)
.
必要的,渲染一个表单所需的所有数据被l装在这q个服务Ҏ(gu)的其中之一Q?code>StartFormData FormService.getStartFormData(String processDefinitionId) ?code>TaskFormdata FormService.getTaskFormData(String taskId)
Submitting form properties can be done with ProcessInstance FormService.submitStartFormData(String processDefinitionId, Map<String,String> properties)
and void FormService.submitStartFormData(String taskId, Map<String,String> properties)
通过ProcessInstance FormService.submitStartFormData(String processDefinitionId, Map<String,String> properties)
?void FormService.submitStartFormData(String taskId, Map<String,String> properties)
Ҏ(gu)能够完成提交表单的属性?
To learn about how form properties map to process variables, see the section called “Form propertiesQ表单属性)”
Z学习(fn)表单属性如何映到程变量Q参?a href="file:///G:/作品/userguide/src/Zh_CN.html/#formProperties">the section called “Form propertiesQ表单属性)” ?
You can just stick any form template resource inside the business archives that you deploy (in case you want to store them versioned with the process). It will be available as a resource in the deployment. You can use the String ProcessDefinition.getDeploymentId()
and InputStream RepositoryService.getResourceAsStream(String deploymentId, String resourceName);
to obtain the file that you included in the deployments. That could be your form template definition file.
Btw, you can use this capability of accessing the deployment resources beyond task forms for any other purposes as well.
随便Qؓ(f)了其它Q何目的,你能使用出除了Q务表单之外访问部|资源的能力?
The attribute <userTask activiti:formKey="..."
is exposed by the API through String FormService.getStartFormData(String processDefinitionId).getFormKey()
and String FormService.getTaskFormData(String taskId).getFormKey()
. You could for instance store a generic key in the form attribute and apply an algorithm or transformation to get to the actual template that needs to be used. This might be handy when you want to render different forms for different UI technologies like e.g. one form for usage in a web app of normal screen size, one form for mobile phone's small screens and maybe even a template for a IM form or an email form.
属?<userTask activiti:formKey="..."
通过 String FormService.getStartFormData(String processDefinitionId).getFormKey()
?String FormService.getTaskFormData(String taskId).getFormKey()
被API 暴露。你可能为实例在表单里面保存一个通用键,应用一个算法或者{换来得到实际所需的模ѝ当你想从不同的UI技术渲染不同的表单Q这可能方便。例如,一个表单用来在正常屏幕大小的Web应用使用Q一个表单在手机屏q用,甚至是IM表单或者email表单的一个模ѝ?
All information relevant to a business process is either included in the process variables themselves or referenced through the process variables. Activiti supports complex Java objects to be stored as process variables like Serializable
objects, JPA entities or whole XML documents as String
s.
与业务流E相关的所有信息既可包含流E变量自己,也可通过程变量包括它们的引用。Activiti支持复杂的Java对象保存为像 Serializable
对象QJPA实体或者作为String 的整个XML文的流E变量?
Starting a process and completing tasks is where people are involved into a process. Communicating with people requires forms to be rendered in some UI technology. In order to facilitate multiple UI technologies easy, the process definition can includes the logic of transforming of the complex Java typed objects in the process variables to aMap<String,String>
of properties.
启动一个流E和完成d是h们介入到程的地斏V和人通信需要采用一些UI技术来渲染表单。ؓ(f)了让多个UI技术和q_处,程定义能够包含转化逻辑Q将程变量里面的复杂对象传化ؓ(f)一个属性的Map<String,String>
?
Any UI technology can then build a form on top of those properties. The properties can provide a dedicated (and more limited) view on the process variables. The properties needed to display a form are available in the FormData returnvalues of StartFormData FormService.getStartFormData(String processDefinitionId)
and TaskFormdata FormService.getTaskFormData(String taskId)
. Those properties are obtained from the process variables.
然后MUI技术能在这些属性之上构Z个表单。这些属性能在这些流E变量之上提供一个专有(有更多限Ӟ视图。显CZ个表单所需的属性在q回StartFormData FormService.getStartFormData(String processDefinitionId)
?TaskFormdata FormService.getTaskFormData(String taskId)
. 的FormData 值里。这些属性从程变量取得?
By default, the build-in form engines, will 'see' the properties as well as the process variables. So there is no need to declare task form properties if they match 1-1 with the process variables. For example, with the following declaration:
~省圎ͼ内置的表单引擎,?#8216;看见‘属性,正如看见程变量一栗所以,如果d表单属性和程变量?-1的匹配关p,没有必要对它声明?/p>
<startEvent id="start" />
A form will see all the process variables but the formService.getStartFormData(String processDefinitionId).getFormProperties()
will be empty.
In the above case, all the submitted properties will be stored as process variables. This means that by simply adding a new inputfield in the form, a new variable can be stored.
表单看见所有的程变量Q?formService.getStartFormData(String processDefinitionId).getFormProperties()
ؓ(f)I?
Properties are derived from process variables, but they don't have to be stored as process variables. For example, a process variable could be a JPA entity of class Address. And a form property StreetName
used by the UI technology could be linked with an expression #{address.street}
管属性从程变量l承而来Q但是它们不必存储ؓ(f)程变量。例如,一个流E变量可能是一个类Address的JPA实体。ƈ且,由UI技术用的表单属?StreetName
能够和一个表辑ּ#{address.street}
q接?
Analogue, the properties that a user is supposed to submit in a form can be stored as a process variable or as a nested property in one of the process variables with a UEL value expression like e.g. #{address.street}
.
Analogue the default behavior of properties that are submitted is that they will be stored as process variables unless a formProperty
declaration specifies otherwise.
Also type conversions can be applied as part of the processing between form properties and process variables.
cdU定能够应用作ؓ(f)表单属性和程变量之间处理环节的部分?
For example:
例如Q?/p>
<userTask id="task" <extensionElements> <activiti:formProperty id="room" /> <activiti:formProperty id="duration" type="long"/> <activiti:formProperty id="speaker" variable="SpeakerName" writable="false" /> <activiti:formProperty id="street" expression="#{address.street}" required="true" /> </extensionElements> </userTask>
Form property room
will be mapped to process variable room
as a String.
表单属?room
Q将作ؓ(f)一个String映射为流E变?room
?/p>
Form property duration
will be mapped to process variable duration
as a java.lang.Long
表单属?
Q将作ؓ(f)一个java.lang.Long映射为流E变?duration
duration
?/p>
Form property speaker
will be mapped to process variable SpeakerName
. It will only be available in the TaskFormData. If property speaker is submitted, an ActivitiException will be thrown. Analogue, with attribute readable="false"
, a property can be excluded from the FormData, but still be processed in the submit.
表单属性会(x)?speaker
映射为流E变?SpeakerName
。他只能在TaskFormData获得。如果提交属性speakerQ那么将?x)抛出ActivitiException。模拟地Q带有属?readable="false"
Q尽一个属性将?x)?FormData排除在外Q但是在提交里面仍将处理?/p>
Form property street
will be mapped to Java bean property street
in process variable address
as a String. And required="true" will throw an exception during the submit if the property is not provided.
表单属?street
在流E变量里面将?x)作为String映射为Java bean 属?street
。如果没有提供这个属性,在提交期_(d) required="true" 抛Z个异常?/p>
It's also possible to provide type meta data as part of the FormData that is returned from methods StartFormData FormService.getStartFormData(String processDefinitionId)
andTaskFormdata FormService.getTaskFormData(String taskId)
提供cd元数据作ZStartFormData FormService.getStartFormData(String processDefinitionId)
?TaskFormdata FormService.getTaskFormData(String taskId)
q回的FormData 的部分也是有可能的?
We support following form property types:
我们支持下列表单属性类型:(x)
string
(org.activiti.engine.impl.form.StringFormType)
long
(org.activiti.engine.impl.form.LongFormType)
enum
(org.activiti.engine.impl.form.EnumFormType)
date
(org.activiti.engine.impl.form.DateFormType)
For each form property declared, the following FormProperty
information will be made available through List<FormProperty> formService.getStartFormData(String processDefinitionId).getFormProperties()
and List<FormProperty> formService.getTaskFormData(String taskId).getFormProperties()
对于每个声明的表单属性,通过 List<FormProperty> formService.getStartFormData(String processDefinitionId).getFormProperties()
和and List<FormProperty> formService.getTaskFormData(String taskId).getFormProperties()
产生如下?FormProperty
信息?/p>
public interface FormProperty { /** the key used to submit the property in {@link FormService#submitStartFormData(String, java.util.Map)} * or {@link FormService#submitTaskFormData(String, java.util.Map)} */ String getId(); /** the display label */ String getName(); /** one of the types defined in this interface like e.g. {@link #TYPE_STRING} */ FormType getType(); /** optional value that should be used to display in this property */ String getValue(); /** is this property read to be displayed in the form and made accessible with the methods * {@link FormService#getStartFormData(String)} and {@link FormService#getTaskFormData(String)}. */ boolean isReadable(); /** is this property expected when a user submits the form? */ boolean isWritable(); /** is this property a required input field */ boolean isRequired(); }
For example:
例如Q?/p>
<startEvent id="start"> <extensionElements> <activiti:formProperty id="speaker" name="Speaker" variable="SpeakerName" type="string" /> <activiti:formProperty id="start" type="date" datePattern="dd-MMM-yyyy" /> <activiti:formProperty id="direction" type="enum"> <activiti:value id="left" name="Go Left" /> <activiti:value id="right" name="Go Right" /> <activiti:value id="up" name="Go Up" /> <activiti:value id="down" name="Go Down" /> </activiti:formProperty> </extensionElements> </startEvent>
All that information is accessible through the API. The type names can be obtained with formProperty.getType().getName()
. And even the date pattern is available withformProperty.getType().getInformation("datePattern")
and the enumeration values are accessible with formProperty.getType().getInformation("values")
通过API来访问那个信息。通过formProperty.getType().getName()
获取cd名;通过formProperty.getType().getInformation("datePattern")
获取旉模式Q通过formProperty.getType().getInformation("values")
获取枚D倹{?
Table of Contents
You can use JPA-Entities as process variables, allowing you to:
你能使用作ؓ(f)程变量的JPA-实体Q允?
Updating existing JPA-entities based on process variables, that can be filled in on a form in a userTask or generated in a serviceTask.
更新存在Z程变量的JPA-实体Q它被填充在userTask的表单里面,或者在serviceTask里面产生?/p>
Reusing existing domain model without having to write explicit services to fetch the entities and update the values
复用已存在的领域模型Q不必编写显式获取这些实体和更新q些数倹{?/p>
Make decisions (gateways) based on properties of existing entities.
Z存在实体属性作军_Q网养I
...
Only entities that comply to the following are supported:
只支持遵从下面标准的实体Q?
Entities should be configured using JPA-annotations, we support both field and property-access. Mapped super classes can also be used.
应当使用JPA-标注配置实体Q我们支持字D和属性方法。也能够使用已映的类?/p>
Entity should have a primary key annotated with @Id
, compound primary keys are not supported (@EmbeddedId
and @IdClass
). The Id field/property can be of any type supported in the JPA-spec: Primitive types and their wrappers (excluding boolean), String
, BigInteger
, BigDecimal
, java.util.Date
and java.sql.Date
.
实体应当h标注为@Id的主键,不支持组合主?(@EmbeddedId
and @IdClass
)。Id 字段/属性能够是JPA规范里Q何支持的cd:原子cd和它们的包装c(wrapper)Q排除booleanQ,, String
, BigInteger
, BigDecimal
, java.util.Date
and java.sql.Date
?/p>
To be able to use JPA-entities, the engine must have a reference to an EntityManagerFactory
. When JPA is enabled on the engine, JPA-entities used as variables will be detected automatically and will be handled accordingly.
Z能够使用JPA-实体Q引擎必d有一个到EntityManagerFactory
的引用。当在引擎上启用了JPAQ作为变量的JPA-实体被自动(g)ƈ作相应的处理?
When creating the ProcessEngine
using the ProcessEngineBuilder
, the method enableJPA
should be called.
当?ProcessEngineBuilder
建立 ProcessEngine
Ӟ必须调用Ҏ(gu)enableJPA
?/p>
ProcessEngine engine = new ProcessEngineBuilder() .configureFromPropertiesResource("activiti.properties") .enableJPA(entityManagerFactory, true, true) .buildProcessEngine();
This method accepts the following parameters:
q个Ҏ(gu)接受下列参数Q?
entityManagerFactory:
An instance of javax.persistence.EntityManagerFactory
that will be used to load the Entities and flushing the updates.
entityManagerFactory:
一?code>javax.persistence.EntityManagerFactory的实例,用作载入实体q刷新更新?/p>
handleTransaction:
Flag indicating that the engine should begin and commit/rollback the transaction on the used EntityManager
instances. Set to false when Java Transaction API (JTA)
is used.
handleTransaction:
指示引擎应当开始和提交/回滚所使用 EntityManager
的实例的事务标志。当使用时设|?code>Java Transaction API (JTA) 为false?/p>
closeEntityManager:
Flag indicating that the engine should close the EntityManager
instance that was obtained from the EntityManagerFactory
. Set to false when the EntityManager
is container-managed (e.g. when using an Extended Persistence Context which isn't scoped to a single transaction').
closeEntityManager:
指示引擎应当关闭?EntityManagerFactory
获得的实?EntityManager
的标志。当EntityManager
是容器托的讄为falseQ例如,当用不是作用到单个事物的扩展持久化上下文)
The EntityManagerFactory
should be set using the ProcessEngineFactoryBean
, which is described in the section called “ConfigurationQ配|)” As an example, we use OpenJPA as persistence-provider using a H2 datasource. The example below is only an extract from a spring configuration-file and only contains relevant beans.
应当使用 ProcessEngineFactoryBean
讄EntityManagerFactory
Q在the section called “ConfigurationQ配|)”描述。作为示例,我们使用OpenJPA作ؓ(f)使用H2数据源的持久化提供者。如下的CZ只从一个Spring配置文g提取出来Qƈ包含了相关的bean.
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.OpenJpaVendorAdapter"> <property name="databasePlatform" value="org.apache.openjpa.jdbc.sql.H2Dictionary" /> </bean> </property> </bean> <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean"> <property name="dataBaseType" value="h2" /> <property name="dataSource" ref="dataSource" /> <property name="transactionManager" ref="transactionManager" /> <property name="dbSchemaStrategy" value="create-drop" /> <property name="mailServerHost" value="localhost" /> <property name="mailServerPort" value="5025" /> <property name="jpaEntityManagerFactory" ref="entityManagerFactory" /> <property name="jpaHandleTransaction" value="true" /> <property name="jpaCloseEntityManager" value="true" /> </bean>
jpaEntityManagerFactory:
An reference to a bean implementing javax.persistence.EntityManagerFactory
that will be used to load the Entities and flushing the updates.
jpaEntityManagerFactory:
一个指向实?code>javax.persistence.EntityManagerFactory的bean的引用,用来载入和刷新更新?/p>
jpaHandleTransaction:
Flag indicating that the engine should begin and commit/rollback the transaction on the used EntityManager
instances. Set to false when Java Transaction API (JTA)
is used.
jpaHandleTransaction:
指示引擎应当开始和提交/回滚所使用 EntityManager
的实例的事务标志。当使用时设|?code>Java Transaction API (JTA) 为false?/p>
jpaCloseEntityManager:
Flag indicating that the engine should close the EntityManager
instance that was obtained from the jpaCloseEntityManager
. Set to false when theEntityManager
is container-managed (e.g. when using an Extended Persistence Context which isn't scoped to a single transaction').
jpaCloseEntityManager:
closeEntityManager:
指示引擎应当关闭?EntityManagerFactory
获得的实?EntityManager
的标志。当EntityManager
是容器托的讄为falseQ例如,当用不是作用到单个事物的扩展持久化上下文)?/p>
Examples for using JPA variables can be found in JPAVariableTest
. We'll explain JPAVariableTest.testUpdateJPAEntityValues
step by step.
?JPAVariableTest
里能扑ֈ使用JPA变量的示例。将一步一步解?code>JPAVariableTest.testUpdateJPAEntityValues ?
First of all, we create a EntityManagerFactory
for our persistence-unit, which is based on META-INF/persistence.xml
. This contains classes which should be included in the persistence unit and some vendor-specific configuration.
首先Q我们ؓ(f)我们的持久化单元建立 EntityManagerFactory
Q这ZMETA-INF/persistence.xml
。这包含了了持久化单元所需的类和一些数据库供应商相关的配置?
The EntityManagagerFactory
is set on the engine to enable JPA support. Please note that this is done using a shortcut for testing purposes, and should actually be set properly using one of the methods described in the section called “ConfigurationQ配|)”.
引擎讄 EntityManagagerFactory来支持JPA。请注意Q基于测试目的,通过快捷方式来完成,实际上,通过使用?a href="file:///G:/作品/userguide/src/Zh_CN.html/#jpaconfiguration">the section called “ConfigurationQ配|)”描述的方法之一来合理设|?
We are using a simple entity in the test, having an id and String
value property, which is also persisted. Before running the test, we create an entity and save this.
在测试里面,我们正用一个简单实体。这个实体具有一个id?code>String 值属性。实体也要被持久化。在q行试之前Q我们徏立一个实体ƈ保存它?/p>
@Entity(name = "JPA_ENTITY_FIELD") public class FieldAccessJPAEntity { @Id @Column(name = "ID_") private Long id; private String value; public FieldAccessJPAEntity() { // Empty constructor needed for JPA } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } }
We start a new process instance, adding the entity as a variable. As with other variables, they are stored in the persistent storage of the engine. When the variable is requested the next time, it will be loaded from the EntityManager
based on the class and Id stored.
我们启动一个新的流E实例,增加实体作ؓ(f)一个变量。和其它变量一P它们保存在引擎的持久化存储区。当下次hq个变量Ӟ从Zcd保存的Id的EntityManager载入?/p>
Map<String, Object> variables = new HashMap<String, Object>(); variables.put("entityToUpdate", entityToUpdate); ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("UpdateJPAValuesProcess", variables);
The first node in our process definition contains a serviceTask
that will invoke the method setValue
on entityToUpdate
, which resolves to the JPA variable we set earlier when starting the process instance and will be loaded from the EntityManager
associated with the current engine's context'.
我们程定义的第一个节点包含一?code>serviceTask。它?yu)调用?entityToUpdate
之上的方?code>setValue ?当启动这个流E实例时Q它?yu)解析我们先前设|的JPA变量。JPA变量从当前流E上下文兌?code>EntityManager 载入?/p>
<serviceTask id='theTask' name='updateJPAEntityTask' activiti:expression="${entityToUpdate.setValue('updatedValue')}" />
When the service-task is finished, the process instance waits in a userTask defined in the process definition, which allows us to inspect the process instance. At this point, theEntityManager
has been flushed and the changes to the entity have been pushed to the database. When we get the value of the variable entityToUpdate
, it's loaded again and we get the entity with it's value
property set to updatedValue
.
当服务Q务完成时Q流E实例在程定义里定义的userTask。userTask允许我们(g)查这个流E实例。在q时Q?code>EntityManager 已经被刷新ƈ且实体变更已l被推送到数据库。当我们获取变量entityToUpdate
的值时Q它再次载入。我们取得的 updatedValue
?code>value 属性?/p>
// Servicetask in process 'UpdateJPAValuesProcess' should have set value on entityToUpdate. Object updatedEntity = runtimeService.getVariable(processInstance.getId(), "entityToUpdate"); assertTrue(updatedEntity instanceof FieldAccessJPAEntity); assertEquals("updatedValue", ((FieldAccessJPAEntity)updatedEntity).getValue());
You can query for ProcessInstance
s and Execution
s that have a certain JPA-entity as variable value. Note that only variableValueEquals(name, entity)
is supported for JPA-Entities on ProcessInstanceQuery
and ExecutionQuery
. Methods variableValueNotEquals
, variableValueGreaterThan
, variableValueGreaterThanOrEqual
, variableValueLessThan
and variableValueLessThanOrEqual
are unsupported and will throw an ActivitiException
when an JPA-Entity is passed as value.
你能够查?ProcessInstance
s ?Execution
h某个作ؓ(f)变量值的JPA-bean。注意:(x)对于?ProcessInstanceQuery
?ExecutionQuery
上的JPA实体只支?variableValueEquals(name, entity)
。当JPA实体作ؓ(f)g送时Q不支持Ҏ(gu)variableValueNotEquals
, variableValueGreaterThan
, variableValueGreaterThanOrEqual
, variableValueLessThan
?and variableValueLessThanOrEqual
抛Z?ActivitiException
异常?/p>
ProcessInstance result = runtimeService.createProcessInstanceQuery().variableValueEquals("entityToQuery", entityToQuery).singleResult();
A more advanced example, JPASpringTest
, can be found in activiti-spring-examples
. It describes the following simple use case:
一个更加高U的CZQJPASpringTest Q能够在activiti-spring-examples
扑ֈ。它描述了下列简单的用例:
An existing Spring-bean which uses JPA entities already exists which allows for Loan Requests to be stored.
使用已存在JPA实体的已存在的Spring-bean允许保存Loan Request.
Using Activiti, we can use the existing entities, obtained through the existing bean, and use them as variable in our process.
使用ActivitiQ我们能够用存在的实体Q通过存在的bean来获取这个实体,q在我们的流E里面以变量方式使用它们?
Process is defined in the following steps:
程在下列步骤定义:(x)
Service task that creates a new LoanRequest, using the existing LoanRequestBean
using variables received when starting the process (e.g. could come from a start form). The created entity is stored as a variable, using activiti:resultVariableName
which stores the expression result as a variable.
建立一个新的的服务dQ通过
UserTask that allows a manager to review the request and approve/disapprove, which is stored as a boolean variable approvedByManager
允许l理审阅hq且批准/否决的UserTaskQ它作ؓ(f)一个布?yu)(dng)?code>approvedByManager保存?/p>
ServiceTask that updates the loan request entity so the entity is in sync with the process.
因ؓ(f)ServiceTask更新hh实体Q所以这个实体和程同步?/p>
Depending on the value of the entity property approved
, an exclusive gateway is used to make a decision about what path to take next: When the request is approved, process ends, otherwise, an extra task will become available (Send rejection letter), so the customer can be notified manually by a rejection letter.
依赖实体属?approved
的|所使用的一个d关下一步作出决{:(x)当请求被批准Q流E结束,否则Q另外的d成为可能(发送拒l函Q,q样通过拒绝函手动通知客户?/p>
Please note that the process doesn't contain any forms, since it is only used in a unit test.
h意这个流E不包括M表单Q因为它只是作ؓ(f)单元试使用?
<?xml version="1.0" encoding="UTF-8"?> <definitions id="taskAssigneeExample" xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn" targetNamespace="org.activiti.examples"> <process id="LoanRequestProcess" name="Process creating and handling loan request"> <startEvent id='theStart' /> <sequenceFlow id='flow1' sourceRef='theStart' targetRef='createLoanRequest' /> <serviceTask id='createLoanRequest' name='Create loan request' activiti:expression="${loanRequestBean.newLoanRequest(customerName, amount)}" activiti:resultVariableName="loanRequest"/> <sequenceFlow id='flow2' sourceRef='createLoanRequest' targetRef='approveTask' /> <userTask id="approveTask" name="Approve request" /> <sequenceFlow id='flow3' sourceRef='approveTask' targetRef='approveOrDissaprove' /> <serviceTask id='approveOrDissaprove' name='Store decision' activiti:expression="${loanRequest.setApproved(approvedByManager)}" /> <sequenceFlow id='flow4' sourceRef='approveOrDissaprove' targetRef='exclusiveGw' /> <exclusiveGateway id="exclusiveGw" name="Exclusive Gateway approval" /> <sequenceFlow id="endFlow1" sourceRef="exclusiveGw" targetRef="theEnd"> <conditionExpression xsi:type="tFormalExpression">${loanRequest.approved}</conditionExpression> </sequenceFlow> <sequenceFlow id="endFlow2" sourceRef="exclusiveGw" targetRef="sendRejectionLetter"> <conditionExpression xsi:type="tFormalExpression">${!loanRequest.approved}</conditionExpression> </sequenceFlow> <userTask id="sendRejectionLetter" name="Send rejection letter" /> <sequenceFlow id='flow5' sourceRef='sendRejectionLetter' targetRef='theOtherEnd' /> <endEvent id='theEnd' /> <endEvent id='theOtherEnd' /> </process> </definitions>
Although the example above is quite simple, it shows the power of using JPA combined with Spring and parametrized method-expressions. The process requires no custom java-code at all (except for the Spring-bean off course) and speeds up development drastically.
管上例相当单,但是它展CZl合Spring和参数化Ҏ(gu)表达式JPA的威力。流E不需要Q何Java代码Q当然Spring是例外)Qƈ?qing)大地加速了开发?
Table of Contents
History is the component that captures what happened during process execution and stores it permanently. In contrast to the runtime data, the history data will remain present in the DB also after process instances have completed.
历史是在程执行q程中抓取的事g以及(qing)把事件永久存储的部g。与q行时数据相比较Q历史数据既当前的数据也将程已经完成的数据保留在数据库中?
There are 3 history entities: HistoricProcessInstance
s containing information about current and past process instances, HistoricActivityInstance
s containing information about a single execution of an activity and HistoricDetail
containing various kinds of information related to either a historic process instances or an activity instance.
存在3U历史实体:(x)HistoricProcessInstance包含与当前和q去程CZ相关的信息;HistoricActivityInstance包含与一个活动的当个执行相关的信息;HistoricActivityInstance包含与历史流E实例或者一个活动示例相关的不同的信息?
In the API, the HistoryService exposes this information by offering methods createHistoricProcessInstanceQuery
, createHistoricActivityInstanceQuery
and createHistoricDetailQuery
.
在API里,历史服务QHistoryServiceQ通过提供createHistoricProcessInstanceQuery
, createHistoricActivityInstanceQuery
and createHistoricDetailQuery
Ҏ(gu)暴露q个信息?
Since the DB contains historic entities for past as well as ongoing instances, you might want to consider querying these tables in order to minimize access to the runtime process instance data and that way keeping the runtime execution performant.
因ؓ(f)DB包含q去的,正运行示例的历史实体Q所以ؓ(f)了最化讉Kq行程实例的数据,你也许考虑查询q些库表。这U方式保留了q行期执行的效率?
Later on, this information will be exposed in Activiti Explorer and Activiti Probe. Also, it will be the information from which the reports will be generated.
最后,q个信息会(x)?Activiti Explorer?and Activiti Probe里面暴露。这是报告会(x)产生信息的来源?
In the activiti.cfg.xml configuration file, you can configure the level of history archiving that needs to happen:
在activiti.cfg.xml配置文gQ你能配|需要的历史归档的别:(x)
<activiti-cfg> <history level="audit" /> ... </activiti-cfg>
Or if you're using the spring style of configuration:
或者如果你正用Spring风格的配|方式:(x)
<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean"> <property name="historyLevel" value="audit" /> ... </bean>
Following history levels can be configured:
可以配置如下的历史别:(x)
none
: skips all history archiving. This is the most performant for runtime process execution, but no historical information will be available.
忽略所有的历史归档。尽对于运行期程执行来说q是性能最高的Q但是没有历史信息保留?/p>
activity
: archives all process instances and activity instances. No details will be archived
归所有流E实例和zd实例。不归档l节?/p>
audit
: This is the default. It archives all process instances, activity instances and all form properties that are submitted so that all user interaction through forms is traceable and can be audited.
q是~省U别。它归所有流E实例,zd实例和提交的表单属性。以至于通过表单的所有用户交互都是可跟踪q可以被审计?/p>
full
: This is the highest level of history archiving and hence the slowest. This level stores all information as in the audit
level plus all other possible details like process variable updates.
q是历史归档的最高别。所以是最慢的。这个水q保存auditU别的所有信息加上像程变量的所有其它可能的l节?/p>
When configuring at least audit
level for configuration. Then all properties submitted through methods FormService.submitStartFormData(String processDefinitionId, Map<String, String> properties)
and FormService.submitTaskFormData(String taskId, Map<String, String> properties)
are recorded.
当配|?a href="file:///G:/作品/userguide/src/Zh_CN.html/#">configuring 臛_为auditU别Ӟ那么通过FormService.submitStartFormData(String processDefinitionId, Map<String, String> properties)
?FormService.submitTaskFormData(String taskId, Map<String, String> properties)
Ҏ(gu)提交的所有属性将?x)被记录?
[KNOWN LIMITATION] Currently the forms as worked out in Activiti Explorer do not yet use the submitStartFormData
and submitTaskFormData
. So the form properties are not yet archived when using the forms in Activity Explorer. @see ACT-294
[KNOWN LIMITATION] 当前在工作的表单 q没有?submitStartFormData
?submitTaskFormData
。所以当在用表单时Q表单属性还未被归。@参见 ACT-294
Form properties can be retrieved with the query API like this:
表单Ҏ(gu)能够像下面以查询API方式(g)索:(x)
historyService .createHistoricDetailQuery() .onlyFormProperties() ... .list();
In that case only historic details of type HistoricFormProperty
are returned.
在U情况下Q只q回 HistoricFormProperty
cd的历史细节?
If you've set the authenticated user before calling the submit methods with IdentityService.setAuthenticatedUserId(String)
then that authenticated user who submitted the form will be accessible in the history as well with HistoricProcessInstance.getStartFormUserId()
for start forms and HistoricActivityInstance.getAssignee()
for task forms.
如果在调用带?code>IdentityService.setAuthenticatedUserId(String) 提交Ҏ(gu)之前Q你已经讄认证用户Q那么提交这个表单的那个认证用户会(x)在历史里可访问。带?code>HistoricProcessInstance.getStartFormUserId() 讉K启动表单Q带?code>HistoricActivityInstance.getAssignee() 讉Kd表单?/p>
Activiti comes with an Eclipse plugin, the Activiti Eclipse Designer, that can be used to graphically model, test and deploy BPMN 2.0 processes Eclipse. The Activiti Eclipse Designer is started and maintained by Tijs Rademakers, Tiese Barrell, Ron van Liempd and Yvo Swillens.
Activiti携带了能够在Eclipse里面用来对BPMN 2.0程q行囑Ş化徏模的Eclipse插g。Activiti Eclipse Designer由Tijs Rademakers, Tiese Barrell, Ron van Liempd ?Yvo Swillens发vq维护?
The following installation instructions are verified on Eclipse Classic Helios.
下列安装指o(h)?classic Eclipse Helios 环境里面得到验证?
Go to Help -> Install New Software. In the following panel, click on Add button and fill in the following fields:
?Help -> Install New Software.在下面面杉K面,点击 Add 按钮q填充下面的字段Q?
Name: Activiti BPMN 2.0 designer
Location: http://activiti.org/designer/update/
Make sure the "Contact all updates sites.." checkbox is not checked, because all the necessary plugins can be downloaded from the Activiti update site.
保选择 "Contact all updates sites.."复选框Q这是因为所有必要的插g从Activiti的更新站点下载?
Create Activiti projects and diagrams.
建立Activiti目和流E图?
The Activiti project is generated as a Maven project. To configure the dependencies you need to run mvn eclipse:eclipse and the project dependencies will be configured as expected.
Activiti目作ؓ(f)一个Maven目而生。ؓ(f)了配|所需的依赖,误?mvn eclipse:eclipseQ那么项目依赖的配置如你所ѝ?
A BPMN 2.0 XML file and an image of the process are automatically generated after each save of the Activiti diagram (the automatic generation can be switched of in the Eclipse preferences in the Activiti tab).
在Activiti程图每ơ保存时自动生BPMN 2.0 XML文g和流E的囑փQ在Eclipse的preferences的Activiti标签里可以关闭自动产生的选项Q?
Generate a unit test (right click on a BPMN 2.0 XML file in the package explorer and select generate unit test) A unit test is generated with an Activiti configuration that runs on an embedded H2 database. You can now run the unit test to test your process definition.
产生单元试Q右dD器的BPMN 2.0 XML文gq择产生单元试Q?em>generate unit testQ)。Activiti配置产生的单元测试运行在嵌入式H2的数据库之上。现在能够运行单元测试来试程定义?
The BPMN 2.0 XML is opened in a Activiti XML editor which provides content assist. Note that there are 2 main XSDs configured, the BPMN 2.0 spec XSD and the Activiti extensions XSD. These two XSDs are not yet alligned in a good manneer.
Activiti XML~辑器提供内容辅助功能。可以在Activiti XML~辑器里面打开BPMN 2.0 XML文g。注意存在两U可配置的XSDQ符合BPMN 2.0规范的XSD和Activiti扩展的XSD。这两个q没有以良好的方式齐头ƈq?
A basic validation is performed after each save of the Activiti diagram and the errors are mentioned in the Eclipse problem view.
当Activiti程图每ơ保存时Q完成基本的校验。校验错误显C在Eclipse 问题视图里?
A basic deployment editor is available when right-clicking on an Activiti diagram in the package explorer. You see a Deployment property at the end of the pop-up items. The deployment editor currently supports saving a BAR file, and will be extended in the next release to also deploy the BAR file to the Activiti engine.
当右dD器的Activiti的流E图Ӟ显CZ个基本的部v~辑器。在弹出的的最下端显CZ?Deployment"属性。部|编辑器当前支持保存Z个BAR文g。在下一个版本将扩展为将BAR文g部v到Activiti引擎?
Support for start event, end event, sequence flow, parallel gateway, exclusive gateway, embedded subprocess, script task, user task, service task, mail task and manual tasks.
支持启动事gQ结束事Ӟ序,q行|关Q唯一|关Q嵌入式子流E,脚本dQ用户Q务,服务dQ邮件Q务和手动d?
Java class or expression configuration is supported for the Java service task. In addition field extensions can be configured.
支持对Java服务dq行JavacL者表辑ּ配置。能够配|另外的字段扩展?
Support for additional Activiti extensions like the Mail task, the candidate configuration of User tasks and Script task configuration.
支持像Maild的Activiti扩展dQ用户Q务的候选h配置和脚本Q务配|?/p>
Support for conditions on sequence flows.
支持序之上的条g表达式?
You can extend the default functionality offered by Activiti Designer. This section documents which extensions are available, how they can be used and provides some usage examples. Extending Activiti Designer is useful in cases where the default functionality doesn't suit your needs, you require additional capabilities or have domain specific requirements when modelling business processes. Extension of Activiti Designer falls into two distinct categories, extending the palette and extending output formats. Each of these extension ways requires a specific approach and different technical expertise.
你能够扩展由Activiti Designer提供的缺省功能。本章ؓ(f)哪些扩展可用Q如何用这些扩展问题提供一些有用的CZ。在~省功能不适合你的需求,你需要额外的能力Q或者当对业务流E徏模时h领域特定的需求的地方Q正是扩展Activiti Designer扩展有用武之地。Activiti Designer扩展有两个明昄分类Q扩展面板和扩展输入格式。每个扩展方式需要特定的Ҏ(gu)和不同的技术技巧?
Extending Activiti Designer requires technical knowledge and more specifically, knowledge of programming in Java. Depending on the type of extension you want to create, you might also need to be familiar with Maven, Eclipse, OSGi, Eclipse extensions and SWT.
注意
扩展需要技术基和更特别的Java~程基础。依赖ni ddddd所惛_立的扩展cdQ你也许需要熟(zhn)MavenQEclipseQOSGiQEclipse扩展和SWT?
You can customize the palette that is offered to users when modelling processes. The palette is the collection of shapes that can be dragged onto the canvas in a process diagram and is displayed to the right hand side of the canvas. As you can see in the default palette, the default shapes are grouped into compartments (these are called "drawers") for Events, Gateways and so on. There are two options built-in to Activiti Designer to customize the drawers and shapes in the palette:
当徏模时Q你可以l用h供一个定制的面板。面板是能够拉至
Adding your own shapes / nodes to existing or new drawers
增加你自q囑Ş或者节点到已存在或新的抽屉上?/p>
Disabling any or all of the default BPMN 2.0 shapes offered by Activiti Designer, with the exception of the connection and selection tools
j止MActiviti Designer提供的缺省BPMN 2.0囑ŞQ连接和选择
In order to customize the palette, you create a JAR file that is added to a specific installation of Activiti Designer (more on how to do that later). Such a JAR file is called anextension. By writing classes that are included in your extension, Activiti Designer understands which customizations you wish to make. In order for this to work, your classes should implement certain interfaces. There is an integration library available with those interfaces and base classes to extend which you should add to your project's classpath.
未来定制调色板,你徏立一个可以添加到Activiti DesignerQ后面将更多介绍how to do that Q里的JAR的文件。这L(fng)JAR文g叫一个扩展(extensionQ??
You can setup your project in whichever tool you prefer and build the JAR with your build tool of choice. For the instructions below, a setup is assumed with Eclipse Helios, using Maven (3.x) as build tool, but any setup should enable you to create the same results.
注意
ni你能够设|你喜欢的工h讄你的目。用q个工具来构个JAR包。对于下列指令,假定用Eclipse Helios讄Q采用MavenQ?.xQ作为构建工P但是M讄建立相同的结果?
Download and extract Eclipse (Galileo or Helios should both work) and a recent version (3.x) of Apache Maven. If you use a 2.x vesion of Maven, you will run into problems when building your project, so make sure your version is up to date. We assume you are familiar with using basic features and the Java editor in Eclipse. It's up to you whether your prefer to use Eclipse's features for Maven or run Maven commands from a command prompt.
下蝲q抽?和最新版本。如果你使用Maven 2.x版本Q在构徏目时将带来问题Q所以确保它的版本及(qing)时更新。我们假定你熟?zhn)Eclipse里面的基本特性和Java~辑器。是否你钟情在Eclipse里面使用Maven或者在命o(h)行提CZ使用MavenQ完全取决于你?
Create a new project in Eclipse. This can be a general project type. Create a pom.xml
file at the root of the project to contain the Maven project setup. Also create folders for the src/main/java
and src/main/resources
folders, which are Maven conventions for your Java source files and resources respectively. Open the pom.xml
file and add the following lines:
在Eclipse里面建立一个新目。这个项目可以是一个一般类型的目。ؓ(f)了包含Maven目讄Q在目的根目录下徏立一个pom.xml文g夏V也要徏?src/main/java
?src/main/resources
文g夹,q是Maven对Java源代码文件和相关资源文g的约定。打开pom.xml文gq增加下列行Q?pre><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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.acme</groupId>
<artifactId>money-tasks</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>Acme Corporation Money Tasks</name>
...
</pom>
As you can see, this is just a basic pom.xml file that defines a groupId
, artifactId
and version
for the project. We will create a customization that includes a single custom node for our money business.
正如你所见,q只是定义了目?一个基本的pom.xml文g。我?
Add the integration library to your project's dependencies by including this dependency in your pom.xml
file:
通过在pom.xml文g里包含项目的依赖库,集成的库加到项目里面?pre><dependencies> <dependency> <groupId>org.activiti.designer</groupId> <artifactId>org.activiti.designer.integration</artifactId> <version><!-- Current Activiti Designer Version --></version> <scope>compile</scope> </dependency> </dependencies>
At the moment, the dependency is not available from the Activiti Maven repository. To use it, you should download it from here and place it in your local Maven repository.
此时Q还未从Activiti的Maven仓库获得依赖。ؓ(f)了用它Q从q里下蝲 from hereQƈ把它攑ֈ你本地的Maven仓库里?
Finally, in the pom.xml
file, add the configuration for the maven-compiler-plugin
so the Java source level is at least 1.5 (see snippet below). You will need this in order to use annotations. You can also include instructions for Maven to generate the JAR's MANIFEST.MF
file. This is not required, but you can use a specific property in the manifest to provide a name for your extension (this name may be shown at certain places in the designer and is primarily intended for future use if you have several extensions in the designer). If you wish to do so, include the following snippet in pom.xml
:
最后,因ؓ(f)
<build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.5</source> <target>1.5</target> <showDeprecation>true</showDeprecation> <showWarnings>true</showWarnings> <optimize>true</optimize> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>2.3.1</version> <configuration> <archive> <index>true</index> <manifest> <addClasspath>false</addClasspath> <addDefaultImplementationEntries>true</addDefaultImplementationEntries> </manifest> <manifestEntries> <ActivitiDesigner-Extension-Name>Acme Money</ActivitiDesigner-Extension-Name> </manifestEntries> </archive> </configuration> </plugin> </plugins> </build>
The name for the extension is described by the ActivitiDesigner-Extension-Name
property. The only thing left to do now is tell Eclipse to setup the project according to the instructions in pom.xml
. So open up a command shell and go to the root folder of your project in the Eclipse workspace. Then execute the following Maven command:
扩展名由ActivitiDesigner-Extension-Name
属性描q。唯一剩下的d事实告诉EclipseҎ(gu)文g里指令徏立这个项目。所以打开一个命令shellq到Eclipse工作区的目Ҏ(gu)件夹。执行下面的Maven命o(h)Q?pre>mvn eclipse:eclipse
Wait until the build is successful. Refresh the project (use the project's context menu (right-click) and select Refresh
). You should now have the src/main/java
and src/main/resources
folders as source folders in the Eclipse project.
{到构徏成功完成。刷新项目(使用目的上下文菜单Q右击)q择“刷新”(Refresh
Q)。现在你应当在Eclipse目里看见文件夹src/main/java
?src/main/resources
作ؓ(f)源代码文件夹?
You can of course also use the m2eclipse plugin and simply enable Maven dependency management from the context menu (right-click) of the project. Then choose Maven
> Update project configuration
from the project's context menu. That should setup the source folders as well.
你当然也可?m2eclipse 插g。简单地从上目下文菜单Q右击)启动Maven依赖理。然后从目的上下文菜单选择?Maven
> Update project configuration
”。也要设|设|源代码?
That's it for the setup. Now you're ready to start creating customizations to Activiti Designer!
讄p样弄好了。徏立Activiti Designer的定制的准备工作qA?
You might be wondering how you can add your extension to Activiti Designer so your customizations are applied. These are the steps to do just that:
你可能疑惑如何才能把自己的定制加入到Activiti Designer以便让自q定制起作用呢。那么采取这些步骤可以解冻I(x)
Once you've created your extension JAR (for instance, by performing a mvn install in your project to build it with Maven), you need to transfer the extension to the computer where Activiti Designer is installed;
一旦你建立自己的扩展JARQ例如,通过Maven在你的项目里执行一个mvn install 来构建)。你需要将q个扩展攑ֈActiviti Designer安装的地斏V?/p>
Store the extension somewhere on the hard drive where it will be able to remain and remember the location;
ddd扩展存储在盘的某个地方,在那可以保存扩展?/p>
Start Activiti Designer and from the menu, select Window
> Preferences
首先启动Activiti DesignerQ然后在菜单里选择 Window
> Preferences
.
In the preferences screen, type user
as keyword. You should see an option to access the User Libraries
in Eclipse in the Java
section.
在preferences 屏幕Q键?user
作ؓ(f)关键字。你应当在Eclipse的Java部分看见讉K User Libraries
的选项?
Select the User Libraries item and a tree view shows up to the right where you can add libraries. You should see the default group where you can add extensions to Activiti Designer (depending on your Eclipse installation, you might see several others as well).
选择 User Libraries ,在右端将昄一个树(wi)形视图,在此可以d你自qJava库。你应当能看见扩展加入到Activiti Designer 的缺省组Q依赖于你的Eclipse的安装,你可能看到其它的情况Q?
Select the Activiti Designer Extensions
group and click the Add JARs...
button. Navigate to to folder where your extension is stored and select the extension file you want to add. After completing this, your preferences screen should show the extension as part of the Activiti Designer Extensions
group, as shown below.
选择l?code>Activiti Designer Extensionslƈ点击 Add JARs...
按钮。导航至你自己扩展所保存的文件夹q择所要添加的扩展。完成之后,你的 preference屏幕应当昄作ؓ(f) Activiti Designer Extensions
l的一部分的扩展,如下所C?
Click the OK
button to save and close the preferences dialog. The Activiti Designer Extensions
group is automatically added to new Activiti projects you create. You can see the user library as entry in the project's tree in the Navigator or Package Explorer. If you already had Activiti projects in the workspace, you should also see the new extensions show up in the group. An example is shown below.
点击OK按钮Q保存ƈ关闭preference对话框。组自动dC所建的Activiti目里面。在Navigator或者Package Explorer视图上的目?wi)书上,用户库作Z个条目显C。如果你在工作区上存在一个Activiti目Q那么你应当看见在组里显C的新的扩展。示例如下所C?
Diagrams you open will now have the shapes from the new extension in their palette (or shapes disabled, depending on the customizations in your extension). If you already had a diagram opened, close and reopen it to see the changes in the palette.
打开的流E图的有一个新的扩展,q能看见囑ŞQ依赖于你的定制Q这些图形可能被止Q。如果流E图已经打开Q关闭ƈ重新打开Q观察面板发生的变化?
With your project set up, you can now easily add shapes to the palette. Each shape you wish to add is represented by a class in your JAR. Take note that these classes are not the classes that will be used by the Activiti engine during runtime. In your extension you describe the properties that can be set in Activiti Designer for each shape. From these shapes, your refer to the runtime class that should be used by the engine. This class should implement JavaDelegate as for any ServiceTask in Activiti.
一旦项目设|好Q你能轻易把囑Şd到面ѝ你惛_入的囑Ş在Jar包里用一个类来表C。注意这些类不是Activiti引擎在运行期间所使用的类。在扩展里,描述了在Activiti Designer里可以设|的属性。通过q些囑ŞQ引用应当有引擎所使用的运行期cR这些类应当为Activiti里的ServiceTask实现JavaDelegte接口?
A shape's class is a simple Java class, to which a number of annotations are added. The class should implement the CustomServiceTask
interface, but you shouldn't implement this interface yourself. Extend the AbstractCustomServiceTask
base class instead (at the moment you MUST extend this class directly, so no abstract classes in between). In the Javadoc for that class you can find instructions on the defaults it provides and when you should override any of the methods it already implements.
囑ŞcL一个简单的Javac,加入了注释。尽这个类应当实现接口Q但是不应当你自己实现这个接口。而应当扩展这个基cMZ替(目前你必ȝ接扩展这个类Q所以没有抽象类Q。在那个cȝJavadoc里面Q可以找它提供的~省功能的指令。你应当复写它已l实现的MҎ(gu)?pre>/** * @author John Doe * @version 1 * @since 1.0.0 */ public class AcmeMoneyTask extends AbstractCustomServiceTask { ... }
You will need to implement the getName()
method to determine the name the node will have in the palette. You can also put the nodes in their own drawer and provide an icon. Override the appropriate methods from AbstractCustomServiceTask
. If you want to provide an icon, make sure it's in the src/main/resources
package in your JAR. The path you supply is relative to that folder.
需要实?getName()
Ҏ(gu)来决定将在面板中节点的名U。你也能节Ҏ(gu)|到它们的抽屉里q提供一个图标。复写AbstractCustomServiceTaskc里合适的Ҏ(gu)。如果你x供一个图标,定它在JAR包里?code>src/main/resources包。提供的路径是相对\径?
You can add properties to the shape by adding members to the class and annotating them with the @Property
annotation like this:
通过向类加入成员q以如下方式?@Property
标注标注它们可以l图形增加属性?pre>@Property(type = PropertyType.TEXT, displayName = "Account Number")
@Help(displayHelpShort = "Provide an account number", displayHelpLong = HELP_ACCOUNT_NUMBER_LONG)
private String accountNumber;
At the moment, there are just two PropertyType
values you can use, TEXT
and MULTILINE_TEXT
. Future releases will allow you to use other types. You can make a field required by setting the required attribute to true. A message and red background will appear if the user doesn't fill out the field.
当前Q只存在两种可以使用?code>PropertyType |(x) TEXT
?code>MULTILINE_TEXT。未来版本将允许你用其它的cd。通过讄必选的属性ؓ(f)true让字D必选。如果用h有填充字D,出C个消息,背景为红艌Ӏ?
As you can see, there's also an @Help
annotation that's used to provide the user some guidance when filling out the field. You can also use the @Help
annotation on the class itself - this information is shown at the top of the property sheet presented to the user.
如你所见,当填充字D|Q也有一个标注用来提供给用户一些指南的?@Help
标注。也可在c自w?@Help
标注--q个信息在属性表上提供给用户信息?
Below is the listing for a further elaboration of the MoneyTask
. A comment field has been added and you can see an icon is included for the node.
Z获得MoneyTask的详情,以下是列表。已l加入注释字D,q且在节点能看见图标?pre>/** * @author John Doe * @version 1 * @since 1.0.0 */ @Runtime(delegationClass = "org.acme.runtime.AcmeMoneyJavaDelegation") @Help(displayHelpShort = "Creates a new account", displayHelpLong = "Creates a new account using the account number specified") public class AcmeMoneyTask extends AbstractCustomServiceTask { private static final String HELP_ACCOUNT_NUMBER_LONG = "Provide a number that is suitable as an account number."; @Property(type = PropertyType.TEXT, displayName = "Account Number", required = true) @Help(displayHelpShort = "Provide an account number", displayHelpLong = HELP_ACCOUNT_NUMBER_LONG) private String accountNumber; @Property(type = PropertyType.MULTILINE_TEXT, displayName = "Comments") @Help(displayHelpShort = "Provide comments", displayHelpLong = "You can add comments to the node to provide a brief description.") private String comments; /* * (non-Javadoc) * * @see org.activiti.designer.integration.servicetask.AbstractCustomServiceTask #contributeToPaletteDrawer() */ @Override public String contributeToPaletteDrawer() { return "Acme Corporation"; } @Override public String getName() { return "Money node"; } /* * (non-Javadoc) * * @see org.activiti.designer.integration.servicetask.AbstractCustomServiceTask #getSmallIconPath() */ @Override public String getSmallIconPath() { return "icons/coins.png"; } }
If you extend Activiti Designer with this shape, The palette and corresponding node will look like this:
如果用这个图形扩展Activiti DesignerQ面板及(qing)其相兌点如下所C:(x)
The properties screen for the money task is shown below. Note the required message for the accountNumber
field.
moneyd的属性屏q如下所C。注?accountNumber
字段的必填的消息?
The help for fields is offered by the buttons to the right of each property. Clicking on the button shows a popup as displayed below.
在每个属性的右侧的按钮提供字D늚帮助信息。点?yn)L钮将昄如下弹出的信息?
The final step for your shape is to indicate the class that is instantiated by the Activiti engine when it reaches your node when executing a process instance. To do this, you use the @Runtime
annotation. The delegationClass
attribute you return should contain the canonical name of the runtime class. Note that the runtime class shouldn't be in your extension JAR, as it's dependent on the Activiti libraries.
当执行一个流E实例时QActiviti引擎到达你的节点。图形的最l步骤指明被Activiti引擎实例化的那个cR可?@Runtime
标注来完成这个功能。返回属性应当包含运行时期的正规名称。注意运行时期类不应当在扩展JAR包里Q因为它依赖于Activiticd?pre>@Runtime(delegationClass = "org.acme.runtime.AcmeMoneyJavaDelegation")
This customization requires you to include a class in your extension that implements the DefaultPaletteCustomizer
interface. You should not implement this interface directly, but subclass the AbstractDefaultPaletteCustomizer
base class. Currently, this class provides no functionality, but future versions of the DefaultPaletteCustomizer
interface will offer more capabilities for which this base class will provide some sensible defaults so it's best to subclass so your extension will be compatible with future releases.
q个定制需要你在扩展里包含实现接口的类。你不应当直接实现这个接口,而是子类?code>AbstractDefaultPaletteCustomizer 基类。当前,接口的未来版本将提供为那些基c通过更多功能Q所以最好子cdQ这P你的扩展会(x)和未来的版本?
Extending the AbstractDefaultPaletteCustomizer
class requires you to implement one method, disablePaletteEntries()
, from which you must return a list of PaletteEntry
values. For each of the default shapes, you can disable it by adding its corresponding PaletteEntry
value to your list. Note that if you remove shapes from the default set and there are no remaining shapes in a particular drawer, that drawer will be removed from the palette in its entirety. If you wish to disable all of the default shapes, you only need to addPaletteEntry.ALL
to your result. As an example, the code below disables the Manual task and Script task shapes in the palette.
扩展 AbstractDefaultPaletteCustomizer
c需要你实现一?code>disablePaletteEntries()Ҏ(gu)Q你必须q回一?PaletteEntry
值列表。对于每个缺省图形,通过增加相关?PaletteEntry
值到你的列表Q你能禁止它。注意如果从~省集合里删除图形,特别的抽屉里没有M囑ŞQ那么这个抽屉也从面板中删除。如果你想禁止所有缺省的囑ŞQ你只需要把加入PaletteEntry.ALL
到结果。作Z个示例,下列代码止了面板中的手动Q务和脚本d?pre>public class MyPaletteCustomizer extends AbstractDefaultPaletteCustomizer {
/*
* (non-Javadoc)
*
* @see org.activiti.designer.integration.palette.DefaultPaletteCustomizer#disablePaletteEntries()
*/
@Override
public List<PaletteEntry> disablePaletteEntries() {
List<PaletteEntry> result = new ArrayList<PaletteEntry>();
result.add(PaletteEntry.MANUAL_TASK);
result.add(PaletteEntry.SCRIPT_TASK);
return result;
}
}
The result of applying this extension is shown in the picture below. As you can see, the manual task and script task shapes are no longer available in the Tasks
drawer.
q个扩展的应用效果如下图所C。如你所见,手动d和脚本Q务的囑Ş不在Task抽屉上获取?
To disable all of the default shapes, you could use something similar to the code below.
Z止所有的~省囑ŞQ你可以应当使用和下列相似的代码?pre>public class MyPaletteCustomizer extends AbstractDefaultPaletteCustomizer { /* * (non-Javadoc) * * @see org.activiti.designer.integration.palette.DefaultPaletteCustomizer#disablePaletteEntries() */ @Override public List<PaletteEntry> disablePaletteEntries() { List<PaletteEntry> result = new ArrayList<PaletteEntry>(); result.add(PaletteEntry.ALL); return result; } }
The result will look like this (notice that the drawers the default shapes were in are no longer in the palette):
l果如下相|注意~省囑Ş原来所在的抽屉也不在面杉K面了Q?
You can extend Activiti Designer to publish to additional formats when saving diagrams. These extensions are called Export Marshallers
and are invoked automatically by Activiti Designer on each save action by the user. This behavior can be enabled or disabled by setting a preference in Eclipse's preferences dialog for each format to be saved.
当你保存?gu)程图时Q你能够扩展Activiti Designer 发表另外的格式。这些扩展被UCؓ(f)。当用户每次采取保存的行为时Q由Activiti Designer自动调用?
You can compare these extensions to the BPMN 2.0 export and process image saving that's performed during save actions by default in Activiti Designer. In fact, these functions use exactly the same extension features you can use to save to your own formats.
你能这些功能和BPMN 2.0输出和流E图像进行比较。缺省地Q后者在Activiti Designer里在保存动作期间完成?
事实上,q些功能完全使用你能使用的相同的扩展Ҏ(gu)。它通常保存Z自己的格式?
To create an Export Marshaller
, you need to create a different kind of extension than for extending the palette. The reason for this is simple: from your code you will need access to more APIs than are offered by the integration library. In particular, you will need classes that are available in Eclipse itself. The way to implement an Export Marshaller
is therefore to create an Eclipse plugin (which you can do by using Eclipse's PDE support) and package it in a custom Eclipse product. It's beyond the scope of this user guide to explain all the details involved in developing Eclipse plugins, so the instructions below are limited to the functionality for extending Activiti Designer.
Z建立一个输l( Export Marshaller
)Q你需要徏立不同种cȝ扩展Q而不是扩展面ѝ这个原因是单的Q从代码观点来看Q你需要比讉K比集成库需要更多的API。特别地Q你需要Eclipse里能够获取的cR实C?code>Export Marshaller Ҏ(gu)是徏立一个Eclipse的插Ӟ通过Eclipse的PDE支持Q,q且在一个定制的Eclipse产品里将它打包。解释所有关于开发Eclipse 插g的细节超q了本用h南的范围Q所以下列指令被限制为扩展Activiti Designer的功能?
Your bundle should be dependent on the following libraries:
你的bundle应当依赖下列库:(x)
Create an extension to the org.activiti.designer.eclipse.extension.export.ExportMarshaller
extension point. For this extension point, you are required to subclass the AbstractExportMarshaller
class. This abstract base class provides you with a number of useful methods when marshalling to your own format, such as adding markers to Eclipse's problems view and saving resources to the workspace.
建立一?code>org.activiti.designer.eclipse.extension.export.ExportMarshaller 扩展点的扩展。对于这个扩展点Q需要子cd AbstractExportMarshaller
q个cR当自己的格式时q个抽象基类提供了大量的有用的方法,诸如在Eclipse Problem视图d标记Qƈ把资源保存到工作区里面?
You are required to implement some methods, such as getMarshallerName()
and getFormatName()
. These methods are used to display options to the user and to show information in progress dialogs, so make sure the descriptions you return reflect the functionality you are implementing.
需要实现诸如这?code>getMarshallerName() ?getFormatName()
的方法。这些方法用来显C用L(fng)选项和显C度对话框的信息,q样保q回的描q反应了所实现的功能?
The bulk of your work is performed in the marshallDiagram(Diagram diagram, IProgressMonitor monitor)
method. You are provided with the diagram object, which contains all of the information about the objects in the diagram (BPMN constructs) and the graphical representation. If you want to access the diagram through its resource in Eclipse or you want to transform the diagram using XSLT, there are methods to get to Resources
and InputStreams
for the diagram in the AbstractExportMarshaller
class.
工作的大部分?marshallDiagram(Diagram diagram, IProgressMonitor monitor)
Ҏ(gu)里面执行。提供了程囑֯象,它包含关于流E图(BPMN构gQ对象和囑Ş表示的所有信息。如果你想通过Eclipse里的一栯问流E图Q或者你想采用XSLT来{换流E图Q在AbstractExportMarshaller
c里有ؓ(f)程图获?code>Resources 和的 InputStreams
Ҏ(gu)?
It's probably a good idea to invoke clearProblems()
as one of the first things you do; this will clear any previous markers for your marshaller. You should also use the progress monitor provided to report your progress back to the user. If you need examples on how to do this, take a look at the code of Activiti Designer itself.
首先调用 clearProblems()
Ҏ(gu)可能是个好主意;q将清除 marshaller先前的标记。你也应当所提供的进度监视器Q向用户报告q展情况。如果需要如何完成这样功能的CZQ请参考Activiti Designer 自n的代码?
Table of Contents
The Activiti Modeler is a web based process editor that can be used to author BPMN 2.0 process graphically using nothing more then a browser. The process files are stored by the server on a the file system, such that they are easily accessible and can be imported without hassles into any Java IDE.
Activiti建模?Activiti Modeler)是一个用来仅在浏览器里面以图形化~辑B(ti)PMN 2.0程的,ZWeb的流E编辑器。通过服务器流E文件存在文件系l,所以很Ҏ(gu)对它们进行访问,q无忧输入到MJavaIDE里面?
Bugs and issues can be reported on the Signavio core components issue tracker.
可以缺陷和问题报告?a >Signavio core components issue tracker.
The Activiti Modeler is automatically installed during the demo setup.
?a href="file:///G:/作品/userguide/src/Zh_CN.html/#">demo setupq程中自动安装Activiti Modeler?
After running the demo setup, process XML files are stored in the apps/activiti-model-repository folder. The location of the file-based repository can be switched by changing the fileSystemRootDirectory property in the (exploded)activiti-modeler.war/WEB-INF/classes/configuration.properties file.
在运行演C创建的q程之后Q流EXML文g会(x)保存在apps/activiti-model-repository文g夏V通过变更?strong>(exploded)activiti-modeler.war/WEB-INF/classes/configuration.properties文g里的 fileSystemRootDirectory 属性,来切换基于文件的仓库位置?
After running the demo setup, the Activiti Modeler will accessible only on the localhost address. When you want to change the host of the Modeler, e.g. to run it centrally on a server, change the host property in the (exploded)activiti-modeler.war/WEB-INF/classes/configuration.properties file.
在运行演C创Z后,只能从localhost地址讉KActiviti Modeler。当你想变更Modeler的主机,例如Q在一个服务器上集中运行。那么,请你变更?strong>(exploded)activiti-modeler.war/WEB-INF/classes/configuration.properties 文g?strong>host属性?/p>
> cat configuration.properties host = http://192.168.1.101:8080 fileSystemRootDirectory = /Users/jbarrez/Development/model-repo