Upload
leonardojlbcyahoocombr
View
1.348
Download
17
Embed Size (px)
Citation preview
jBPM User Guide
1. Introduction1.1. License and EULA1.2. Downloads
1.3. Sources1.4. What is it
1.5. Contents of this userguide1.6. Migration from jBPM 31.7. Reporting problems
2. Installation2.1. The distribution
2.2. Required software2.3. Getting started quickly
2.4. Install scripts2.5. Library dependencies and configuration files2.6. JBoss
2.7. Tomcat2.8. Signavio web based process editor
2.9. User webapp2.10. Database
2.10.1. Creating or dropping the database schema
2.10.2. Upgrading an existing database2.11. Graphical Process Designer (GPD)
2.11.1. Get Eclipse2.11.2. Install the GPD plugin into eclipse
2.11.3. Configuring the jBPM runtime2.11.4. Define the jBPM User Library2.11.5. Adding jPDL 4 schema to the catalog
2.11.6. Importing the Examples2.11.7. Adding deployment with ant
3. Graphical Process Designer (GPD)3.1. Creating a new process file
3.2. Editing the process source
4. Deploying business archives4.1. Deploying process files and process resources
4.2. Deploying classes
5. Services
5.1. Process definition, process instance and executions5.2. ProcessEngine
5.3. Deploying a process5.4. Deleting a deployment
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
1 de 75 08/09/2010 14:51
5.5. Starting a new process instance
5.5.1. In latest5.5.2. Specific process version
5.5.3. With a key5.5.4. With variables
5.6. Signalling a waiting execution
5.7. TaskService5.8. HistoryService
5.9. ManagementService5.10. Query API
6. jPDL6.1. process
6.2. Control flow activities
6.2.1. start
6.2.2. state
6.2.3. decision
6.2.4. concurrency
6.2.5. end
6.2.6. task
6.2.7. sub-process
6.2.8. custom
6.3. Automatic activities
6.3.1. java
6.3.2. script
6.3.3. hql
6.3.4. sql
6.3.5. mail
6.4. Common activity contents6.5. Events
6.5.1. Event listener example6.5.2. Event propagation
6.6. Asynchronous continuations
6.6.1. Async activity6.6.2. Async fork
6.7. User code6.7.1. User code configuration6.7.2. User code classloading
7. Variables7.1. Variable scoping
7.2. Variable types7.3. Updating serialized process variables
7.4. Declared variables7.5. Variables history
8. Scripting
9. Configuration
9.1. Business calendar9.2. Console9.3. Email
Chapter 1. Introduction
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
2 de 75 08/09/2010 14:51
1.1. License and EULA1.2. Downloads1.3. Sources
1.4. What is it1.5. Contents of this userguide
1.6. Migration from jBPM 31.7. Reporting problems
This documentation is best viewed in firefox. There are some known issues with internet explorer.
1.1. License and EULA
jBPM is distributed under the terms of the GNU Lesser General Public License (LGPL) and the JBoss End UserLicense Agreement (EULA). See the full LGPL license text and the full End User License Agreement.
1.2. Downloads
The distribution packages can be downloaded from sourceforge
http://sourceforge.net/projects/jbpm/files/
1.3. Sources
The source code for this component can be found in the jBPM SVN repository:
https://anonsvn.jboss.org/repos/jbpm/jbpm4/
1.4. What is it
jBPM is an extensible and flexible process engine that can run as a standalone server or embedded in any
Java application.
1.5. Contents of this userguide
In this user guide, we'll describe the jPDL process language in persistent execution mode. Persistent
execution mode means that process definitions, process executions and process history is stored in arelational DB. This is the common way of how jBPM is used in practice.
This user guide explains the supported way on how to use jBPM. The developers guide explains moreadvanced customization options that are not part of the support offerings.
1.6. Migration from jBPM 3
Migration from jBPM 3 to jBPM 4 is not supported. Check out the developers guide for hints on how to
perform the migration.
1.7. Reporting problems
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
3 de 75 08/09/2010 14:51
When reporting a problem in the user forum or in our support portal, please use the following snippet as atemplate:
=== Environment ==============================- jBPM Version : which version of jBPM are you using?- Database : which database and which version of that database- JDK : which Java version are you using? use 'java -version' to find out- Container : which container are you using? (JBoss, Tomcat, etc.)- Configuration : is your jbpm.cfg.xml only using imports from the jbpm.jar lib itself? or did you create a custom config file?- Libraries : are you using the exact versions of the libs from inside the jbpm distribution of the version that you're using? or did you change some of the libs?
=== Process ==================================paste jPDL process here
=== API ===================================paste the relevant code snippet that you use to invoke jBPM
=== Stacktrace ==============================paste full stack trace here
=== Debug logs ==============================paste debug logs here
=== Problem description =========================Keep this part short and to the point. E.g. API doesn't work as expected. or e.g. method ExecutionService.signalExecutionById throws exception.
Clever readers will have noticed that some of these questions point to probably causes :-) Especially
tweaking the libs and configuration can easily lead to trouble. That's why we have spend a great deal ofeffort to include default installations and a simplified configuration mechanism with imports. Think twice
before you start to customize configurations beyond what is indicated in this userguide. Also think twicebefore replacing libs with other versions.
Chapter 2. Installation
2.1. The distribution2.2. Required software
2.3. Getting started quickly2.4. Install scripts
2.5. Library dependencies and configuration files2.6. JBoss2.7. Tomcat
2.8. Signavio web based process editor2.9. User webapp
2.10. Database2.10.1. Creating or dropping the database schema2.10.2. Upgrading an existing database
2.11. Graphical Process Designer (GPD)2.11.1. Get Eclipse
2.11.2. Install the GPD plugin into eclipse2.11.3. Configuring the jBPM runtime2.11.4. Define the jBPM User Library
2.11.5. Adding jPDL 4 schema to the catalog2.11.6. Importing the Examples
2.11.7. Adding deployment with ant
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
4 de 75 08/09/2010 14:51
2.1. The distribution
Unzip the jBPM download (jbpm-4.X.zip) to some location on your hard drive. You'll see following
subdirectories:
doc: User guide, javadocs and developers guide
examples: Example processes that are used in the user guide
install: Installation scripts for several environments
lib: Third party libs and some special jBPM libraries
src: Source files
migration: see developers guide
jbpm.jar: The jBPM main library archive
2.2. Required software
jBPM requires a JDK (standard java) version 5 or higher.
http://java.sun.com/javase/downloads/index.jsp
To execute the ant scripts, you'll need apache ant version 1.7.0 or higher:
http://ant.apache.org/bindownload.cgi
2.3. Getting started quickly
The demo setup is the simplest way to get started. This section describes the steps to complete the demosetup.
If you have previously downloaded jboss-5.0.0.GA.zip, you can drop it in the
${jbpm.home}/install/downloads directory. Otherwise the script will download it for you, but it will take
some time (depending on your connection). The same is holds for eclipse-jee-galileo-win32.zip (or eclipse-
jee-galileo-linux-gtk(-x86_64).tar.gz on Linux and eclipse-jee-galileo-macosx-carbon.tar.gz on Mac OSX)
Open a command prompt and go do directory ${jbpm.home}/install. Then run
ant demo.setup.jboss
or
ant demo.setup.tomcat
That will
Install JBoss into the ${jbpm.home}/jboss-5.0.0.GA directory
Install jBPM into that JBoss installation.
Install hsqldb and start it in the background
Create the DB Schema
Start JBoss in the background.
Create an examples.bar business archive from the examples and deploy it to the jBPM DB.
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
5 de 75 08/09/2010 14:51
Load the example users and groups from ${jbpm.home}/install/src/demo/example.identities.sql
Install eclipse into ${jbpm.home}/eclipse
Install the jBPM web console
Install the Signavio web modeler
Start eclipse
After this is done, JBoss (or Tomcat, depending on which demo.setup script you chose) will be running in the
background. Once eclipse has started, you can continue to follow the instructions of Section 2.11, “GraphicalProcess Designer (GPD)” to start coding your jBPM business processes.
Or you can start modeling processes through the Signavio web editor.
Or surf to the jBPM console. You can login as one of the following users:
Table 2.1. Example console users:
Username Password
alex password
mike password
peter password
mary password
Known console limitation: Currently, the timeout of the console is too tight for the reporting to initializeon slower machines. So the first time when you access the reporting the request will timeout and the console
crashes. Logging out and login again works around this problem. It's being addressed as issue JBPM-2508
2.4. Install scripts
The jBPM download contains an install directory with an ant build.xml file in it. You can use that to install
jBPM into your application environment.
It's best to stick to the installations and jBPM configuration files as done with these installation scripts.Customizing jBPM configuration files directly, is possible, but not supported.
To invoke the install script, open a command line and go to the ${jbpm.home}/install directory. With
ant -p you can find out what each of these scripts can do. The scripts are parametrized with default values
to get going quickly. The following list gives an overview of the available scripts:
demo.setup.jboss: installs jboss, installs jbpm into jboss, starts jboss, creates the jBPM DB schema,
deploys examples, loads example identities, installs and starts eclipse
demo.setup.tomcat: installs tomcat, installs jbpm into tomcat, starts tomcat, creates the jBPM DB
schema, deploys examples, loads example identities, installs and starts eclipse
clean.cfg.dir: Deletes the ${jbpm.home}/install/generated/cfg folder.
create.cfg: Creates a configuration in ${jbpm.home}/install/generated/cfg based on the current
parameters.
create.jbpm.schema: creates the jbpm tables in the database
create.user.webapp: Generates a basic webapp in ${jbpm.home}/install/generated/user-webapp
delete.jboss: Deletes the JBoss installation
delete.tomcat: Deletes the Tomcat installation
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
6 de 75 08/09/2010 14:51
demo.teardown.jboss: Drops the jbpm db schema and stops jboss
demo.teardown.tomcat: Stops tomcat and then the hsqldb server (if needed)
drop.jbpm.schema: Drops the jbpm tables from the database
get.eclipse: Downloads eclipse if it is not available
get.jboss: Downloads a JBoss AS which was tested against the current jBPM version if it is not available
get.tomcat: Downloads tomcat which was tested against the current jBPM version if it is not available
hsqldb.databasemanager: Starts the hsqldb database manager
install.eclipse: Unzips eclipse, downloads eclipse if it is not available
install.jboss: Downloads JBoss if its not available and then unzips it
install.jbpm.into.jboss: Installs jBPM into JBoss
install.tomcat: Downloads tomcat to ${tomcat.distro.dir} if its not available and then unzips tomcat
install.jbpm.into.tomcat: Installs jBPM into tomcat
install.examples.into.tomcat: Deploys all the example processes
install.signavio.into.jboss: Installs signavio into jboss
install.signavio.into.tomcat: Installs signavio into tomcat
load.example.identities: Loads the example users and groups into the database
reinstall.jboss: Deletes the previous jboss installation and re-installs jboss
reinstall.jboss.and.jbpm: Deletes the previous jboss installation and re-installs jboss and installs
jbpm in it
reinstall.tomcat: Deletes the previous tomcat installation and re-installs tomcat
reinstall.tomcat.and.jbpm: Deletes the previous tomcat installation and re-installs tomcat and
installs jbpm in it
start.eclipse: Starts eclipse
start.jboss: Starts jboss and waits till jboss is booted, then lets jboss run in the background
start.tomcat: Starts Tomcat and waits till it is booted, then lets Tomcat run in the background
stop.jboss: signals jboss to stop, but doesn't wait till its finished
stop.tomcat: Signals Tomcat to stop, but doesn't wait till its finished
upgrade.jbpm.schema: Upgrades the jBPM tables in the database to the current version
To specify your jdbc properties that are used in the scripts above (eg.DB schema generation), the easiest is
to update the appropriate properties file in directory ${jbpm.home}/install/jdbc. The appropriate
properties file will be loaded by the scripts that are DB related.
Also following properties are customizeable
database : Default value is hsqldb. Alternative values are mysql, oracle and postgresql
jboss.version : Default value is 5.0.0.GA. Alternative value is 5.1.0.GA
To customize the values for these properties, just use -D like this
ant -Ddatabase=postgresql demo.setup.jboss
Alternatively you can specify the customized values in ${user.home}/.jbpm4/build.properties
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
7 de 75 08/09/2010 14:51
2.5. Library dependencies and configuration files
We provide support for installations of jBPM through our automatic ant scripts. Those scripts will put the right
libs and the right configuration files in the right location for you. If you want to create your own installation ofjBPM in your application, see the developers guide for more information.
2.6. JBoss
The target install.jbpm.into.jboss will install jBPM into your JBoss 5 installation. Navigate to the install
directory and run ant -p for more details. This install script will install jBPM as a JBoss-wide service so that
all applications can use the same jBPM ProcessEngine.
Specify property -Djboss.home=PathToYourJBossInstallation to customize the path to your JBoss
installation.
In JBoss, the ProcessEngine can be obtained from JNDI with
new InitialContext().lookup("java:/ProcessEngine"). The same ProcessEngine can be obtained with
Configuration.getProcessEngine()
2.7. Tomcat
The target install.jbpm.into.tomcat will install jBPM into your JBoss 5 installation.
2.8. Signavio web based process editor
The targets install.signavio.into.jboss and install.signavio.into.tomcat will install the Signavio
web based process editor into JBoss or Tomcat respectively.
2.9. User webapp
If you want to deploy jBPM as a part of your web application, use the install target create.user.webapp.
That will create a web application with jBPM in it, in the location${jbpm.home}/install/generated/user-webapp.
In case you deploy your app on JBoss or another appserver that has the jta.jar classes, then you need todelete the ${jbpm.home}/install/generated/user-webapp/WEB-INF/lib/jta.jar
2.10. Database
The install script is also capable of performing database operations such as creating the schema, if you are
installing jBPM for the first time, or upgrading the database used with a previous version to the currentschema. Dropping the schema is an option as well.
The prerrequisite for any database operation is to specify your database connection parameters in${jbpm.home}/install/jdbc.
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
8 de 75 08/09/2010 14:51
2.10.1. Creating or dropping the database schema
To create the schema, run target create.jbpm.schema in the ${jbpm.home}/install directory. Apart from
creating tables and constraints, the mentioned target will initialize table JBPM4_PROPERTY with the current
engine version (key db.version) and the ID generator base value (key next.dbid).
To drop the schema, simply run target drop.jbpm.schema. Be aware that this operation will destroy any
data present in the jBPM tables.
2.10.2. Upgrading an existing database
To upgrade, run target upgrade.jbpm.schema in the ${jbpm.home}/install directory.
Upgrading is a two-fold operation. The foremost step is to add any extra tables, columns or constraints thatwere introduced in newer versions. Afterwards, seed data is inserted.
Between 4.0 and 4.1, table JBPM4_VARIABLE got a new column CLASSNAME_ used to support setting process
variables to values of custom types mapped with Hibernate. This column is nullable and left uninitialized
since the feature was not operational in 4.0.
From 4.1 to 4.2 the upgrade procedure got more interesting.
A new table JBPM4_PROPERTY was introduced for storing engine-wide values.
The jBPM version is saved in table JBPM4_PROPERTY under key db.version to allow for precise
identification in future releases.
The ID generation strategy is consistent across databases. The next available ID is calculated by querying
all tables having an identifier column, and stored under key next.dbid in the JBPM4_PROPERTY table.
The process language is set to jpdl-4.0 for all existing process definitions under key langid in table
JBPM4_DEPLOYPROP. The jPDL parser employs the langid property to read process documents in a
backwards-compatible manner.
2.11. Graphical Process Designer (GPD)
Eclipse is used as the platform to host the jPDL graphical process designer. This section will describe how to
obtain and install Eclipse and how to install the GPD plugin in Eclipse.
2.11.1. Get Eclipse
You'll need Eclipse 3.5.0.
Use the demo setup or download eclipse manually: Eclipse IDE for Java EE Developers (163 MB).
The classic version of eclipse will not be sufficient as it does not have an XML editor. Eclipse for Javadevelopers should also work.
2.11.2. Install the GPD plugin into eclipse
The installation of the GPD uses the Eclipse Software Update mechanism and is pretty straightforward. Thereis an archived update site included in the runtime installation of jBPM when you unzip it at
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
9 de 75 08/09/2010 14:51
install/src/gpd/jbpm-gpd-site.zip
To add the update site to eclipse:
Help --> Install New Software...
Click Add...
In dialog Add Site dialog, click Archive...
Navigate to install/src/gpd/jbpm-gpd-site.zip and click 'Open'
Clicking OK in the Add Site dialog will bring you back to the dialog 'Install'
Select the jPDL 4 GPD Update Site that has appeared
Click Next... and then Finish
Approve the license
Restart eclipse when that is asked
Figure 2.1. Adding the GPD local archive site
2.11.3. Configuring the jBPM runtime
Click Window --> Preferences
Select JBoss jBPM --> jBPM 4 --> Runtime Locations
Click Add...
In the Add Location dialog, enter a name like e.g. jbpm-4.0 and then click Search...
In the Browse For Folder dialog, select your jbpm home directory and click OK
Click OK in the Add Location dialog
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
10 de 75 08/09/2010 14:51
Figure 2.2. Defining jBPM Libraries
2.11.4. Define the jBPM User Library
This section shows how to define a user library for your workspace that is a placeholder for the jBPM libraryas well as its dependencies. If you create a new Java project, it will be sufficient to add this user library tothe build path.
Click Window --> Preferences
Select Java --> Build Path --> User Libraries
Click New...
Type name jBPM Libraries
Click Add JARs...
Navigate to the 'lib' folder of your jBPM installation
Select all jar files and click Open
Select the jBPM Libraries entry
Click Add JARs... again
Select the jbpm.jar file in the root of your jBPM installation
Click Open
Select entry Source attachment under jbpm.jar
Click Edit
In dialog Source Attachment Configuration, click External Folder...
Navigate to the src folder in your jBPM installation
Click Choose
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
11 de 75 08/09/2010 14:51
Click OK twice to close all the open dialogs
Figure 2.3. Defining jBPM Libraries
2.11.5. Adding jPDL 4 schema to the catalog
In case you want to edit the process XML sources directly, it is best to specify your schema in the XML
catalog. This will give you better code completion while editing the process sources.
Click Window --> Preferences
Select XML --> XML Catalog
Click 'Add...'
The 'Add XML Catalog Entry' dialog opens
Click the button with the map-icon next to location and select 'File System...'
In the dialog that opens, select file jpdl-4.0.xsd in the src directory of the jBPM installation root.
Click 'Open' and close all the dialogs
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
12 de 75 08/09/2010 14:51
Figure 2.4. Adding jPDL 4 schema to the Catalog
2.11.6. Importing the Examples
In this section we will import the examples project in the installation in Eclipse
Select File --> Import...
Select General --> Existing Projects into Workspace
Click Next
Click Browse... to select a root directory
Navigate to the jBPM root installation directory
Click OK
The examples project is automatically found and selected
Click Finish
After setting the jBPM User Libraries and importing the examples, all the examples can be run as JUnit tests.
Right click on a test and select 'Run As' --> 'JUnit Test'.
You're all set to start playing with the coolest Java process technology!
2.11.7. Adding deployment with ant
You can leverage the eclipse ant integration to ease deployment of processes. We'll show you how it workswith the examples. Then you can copy this practice in your own project. First, open up the Ant view.
Select Window --> Show View --> Other... --> Ant --> Ant
Then drag the build file build.xml in the examples project from the package explorer to the Ant view
Chapter 3. Graphical Process Designer (GPD)
3.1. Creating a new process file3.2. Editing the process source
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
13 de 75 08/09/2010 14:51
This chapter will explain how to work with the Graphical Process Designer. After installing the GPD andsetting up the examples, you'll see that the jPDL process files will get a special icon. Double clicking such afile in the package view will open up the jPDL process in the GPD.
Figure 3.1. The GPD
3.1. Creating a new process file
CRTL+N will open up the wizard selector.
Figure 3.2. Select wizard dialog
Select jBPM --> jPDL 4 File. Click 'Next >'. Then the 'New jPDL 4 File' wizard opens.
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
14 de 75 08/09/2010 14:51
Figure 3.3. Create a new process dialog
Select the parent directory, enter a file name and click 'Finish'. Voila, you've created your first jPDL processfile.
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
15 de 75 08/09/2010 14:51
3.2. Editing the process source
The GPD contains a 'Source' tab with the XML sources. These are directly editable in this tab and the
graphical view will reflect the changes when you switch back to the diagram.
Figure 3.4. Editing jPDL using the source view
Chapter 4. Deploying business archives
4.1. Deploying process files and process resources4.2. Deploying classes
A business archive is a collection of files assembled in a jar formatted file. The files in a business archive canbe jPDL process files, forms, classes, process image and other process resources.
4.1. Deploying process files and process resources
Process files and process resources have to be deployed in the process repository which is stored in thedatabase.
There is a jBPM ant task to deploy business archives (org.jbpm.pvm.internal.ant.JbpmDeployTask). The
JbpmDeployTask can deploy individual process files and business archives. They are deployed directly to the
database over a JDBC connection. So it is a requirement that the database is up and running before you candeploy processes.
An example of creating and deploying a business archive can be found in the ant build script (build.xml) inthe examples directory of the distribution. Let's look at the relevant parts. First a path is declared that
includes the jbpm.jar and all its dependencies.
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
16 de 75 08/09/2010 14:51
<path id="jbpm.libs.incl.dependencies"> <pathelement location="${jbpm.home}/examples/target/classes" /> <fileset dir="${jbpm.home}"> <include name="jbpm.jar" /> </fileset> <fileset dir="${jbpm.home}/lib" /></path>
The JDBC driver jar(s) for your database should also be included in the path. MySQL, PostgreSQL andHSQLDB are in the distribution. But the Oracle driver you have to download separately from the oracle site
since we're not allowed to redistribute that file.
When a business archive is deployed, jBPM scans for all the files with the .jpdl.xml extension in the
business archive. All those files will be parsed as jPDL processes and made available to the runtime engine.All other resources in the business archive will also be stored as resources in that deployment and made
accessible through InputStream getResourceAsStream(long deploymentDbid, String resourceName);
in class RepositoryService
For creating a business archives, the jar task can be used.
<jar destfile="${jbpm.home}/examples/target/examples.bar"> <fileset dir="${jbpm.home}/examples/src"> <include name="**/*.jpdl.xml" /> ... </fileset></jar>
Before the jbpm-deploy task can be used it need to be declared like this:
<taskdef name="jbpm-deploy" classname="org.jbpm.pvm.internal.ant.JbpmDeployTask" classpathref="jbpm.libs.incl.dependencies" />
Then the ant task can be used like this
<jbpm-deploy file="${jbpm.home}/examples/target/examples.bar" />
Table 4.1. jbpm-deploy attributes:
Attribute Type Default Required? Description
file file optional
A file to be deployed. Files ending with .xml will be
deployed as process files. Files ending with ar like .bar or
.jar will be deployed as business archives.
cfg file jbpm.cfg.xml optionalPoints to the jbpm configuration file that has to be on the
classpath in which the jbpm-deploy task was defined.
Table 4.2. jbpm-deploy elements:
Element Multiplicity Description
fileset 0..*
files to be deployed expressed as a plain ant fileset. Files ending with .xml will
be deployed as process files. Files ending with ar like .bar or .jar will be
deployed as business archives.
4.2. Deploying classes
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
17 de 75 08/09/2010 14:51
Since version 4.2 jBPM has a process classloading mechanism as in jBPM 3.
Classes that are referenced from processes must be made available in one of 3 ways:
as .class files in your business archive. Unlike in jBPM 3, now the root of the archive file is used as theroot for searching class resources. So when class com.superdeluxsandwiches.Order is referenced in the
process file, it will be found when it is in the same business archive with entry namecom/superdeluxsandwiches/Order.class Classes are cached (key is a combination of deployment and
context classloader), so it should perform better then in jBPM 3.
as classes available in the web application that calls jBPM. Even when jBPM is deployed server-wide on
jboss or tomcat, jBPM will find the classes in your web application or enterprise application that callsjBPM. That's because we use the current context classloader when searching for classes during processexecution.
as class files that are available server-wide. E.g. like the jars in the lib directories in tomcat and jboss.
In case of the examples, an examples.jar file is created with all the classes and it is put in the lib directory
of the JBoss server configuration. Similarly for tomcat. See target install.examples.into.tomcat and
install.examples.into.jboss. In one of the future releases we might switch to include the classes in the
business archive itself.
Chapter 5. Services
5.1. Process definition, process instance and executions5.2. ProcessEngine
5.3. Deploying a process5.4. Deleting a deployment
5.5. Starting a new process instance5.5.1. In latest5.5.2. Specific process version
5.5.3. With a key5.5.4. With variables
5.6. Signalling a waiting execution5.7. TaskService5.8. HistoryService
5.9. ManagementService5.10. Query API
5.1. Process definition, process instance and executions
A process definition is description of the steps in a procedure. For example, an insurance company could havea loan process definition that describes the steps of how the company deals with loan requests.
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
18 de 75 08/09/2010 14:51
Figure 5.1. The loan process definition example
One process instance represents one particular run of a process definition. For example, the loan request of
John Doe last Friday to finance his new boat is represented in one process instance of the loan processdefinition.
A process instance contains all the runtime state. The most prominent property is the pointer that keepstrack of the current activity.
Figure 5.2. The loan process instance example
Suppose that wiring the money and archiving can be done in parallel. Then the main process instance will
have two child executions to keep track of the state like this:
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
19 de 75 08/09/2010 14:51
Figure 5.3. The loan executions example
More general, a process instance is the root of a tree of executions. When a new process instance is started,the process instance is in fact the root execution scope. Only leaf executions can be active.
The motivation to work with a tree structure like this is that this conceptually remains simple in the casewhere there is only one path of execution. The services API doesn't need to make a functional difference
between process instances and executions. Therefore, the API has only one Execution type to refer to bothProcessInstances and Executions.
5.2. ProcessEngine
Interacting with jBPM occurs through services. The service interfaces can be obtained from theProcessEngine which is build from a Configuration.
A ProcessEngine is thread safe and can be stored in a static member field or even better in JNDI or some
other central location. One ProcessEngine object can be used by all requests and threads in an application.
Here's how you can obtain a ProcessEngine
The code snippets in this section and the next section about process deployments are taken from theexample org.jbpm.examples.services.ServicesTest
ProcessEngine processEngine = new Configuration() .buildProcessEngine();
The previous code snippet shows how to build a ProcessEngine from the default configuration file
jbpm.cfg.xml which is expected in the root of the classpath. If you want to specify another resource
location, use the setResource method like this:
ProcessEngine processEngine = new Configuration() .setResource("my-own-configuration-file.xml") .buildProcessEngine();
There are other setXxxx methods that allow to specify the configuration content as an InputStream, an
xmlString, InputSource, URL or File.
From a ProcessEngine the following services can be obtained:
RepositoryService repositoryService = processEngine.getRepositoryService();ExecutionService executionService = processEngine.getExecutionService();TaskService taskService = processEngine.getTaskService();HistoryService historyService = processEngine.getHistoryService();ManagementService managementService = processEngine.getManagementService();
Process engine objects defined in the configuration can also be retrieved by type
(processEngine.get(Class<T>)) or by name (processEngine.get(String))
5.3. Deploying a process
The RepositoryService groups all methods to manage the repository of deployments. In this first example,
we'll deploy one process resource from the classpath with the RepositoryService:
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
20 de 75 08/09/2010 14:51
String deploymentId = repositoryService.createDeployment() .addResourceFromClasspath("org/jbpm/examples/services/Order.jpdl.xml") .deploy();
Analogue to the addResourceFromClasspath method above, the source of the processes definitions XML can
be picked up from a file, url, string, input stream or zip input stream.
Each deployment is composed of a set of named resources. The content of each resource is a byte array.jPDL process files are recognized by their extension .jpdl.xml. Other resource types are task forms and
java classes.
A deployment works with a set of named resources and can potentially contain multiple process descriptions
and multiple other artifact types. The jPDL deployer will recognise process files based on the .jpdl.xml
extension automatically.
During deployment, an id is assigned to the process definitions. The id will have format {key}-{version}
with a dash between key and version
If key is not provided, it is generated automatically based on the name. All non alpha numeric characters in
the name will be replaced by underscores to generate the key.
The same name can only be associated to one key and vice versa.
If version is not provided, a version will be automatically be assigned. For version assignment, the
versions of all deployed process definitions with the same name will be taken into account. The assigned
version will be one higher than the highest version number of deployed process definitions with the same
key. If no process definitions with a similar key have been deployed, version number 1 is assigned.
In this first example, we'll supply a name and nothing else.
<process name="Insurance claim">...</process>
Let's assume that this is the first time that this process gets deployed. Then it will get the followingproperties:
Table 5.1. Process properties without key
Property Value Source
name Insurance claim process xml
key Insurance_claim generated
version 1 generated
id Insurance_claim-1 generated
And as a second example, we'll show how you can get shorter ids by specifying a process key:
<process name="Insurance claim" key="ICL">...</process>
Then the process definition properties look like this:
Table 5.2. Process properties with key
Property Value Source
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
21 de 75 08/09/2010 14:51
Property Value Source
name Insurance claim process xml
key ICL process xml
version 1 generated
id ICL-1 generated
5.4. Deleting a deployment
Deleting a deployment will remove it from the DB.
repositoryService.deleteDeployment(deploymentId);
That method will throw an exception when there are still active process executions for process definitions in
that deployment.
If you want to cascade deletion of a deployment to all the process instances of all the process definitions, use
deleteDeploymentCascade.
5.5. Starting a new process instance
5.5.1. In latest
Simplest and most common way to start a new process instance for a process definition is like this:
ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL");
In this case, the service method will first look up the latest version of the processes with key ICL. Then a
new process instance is started in that latest process definition.
When a new version of the insurance claim process is deployed, all invocations of
startProcessInstanceByKey will automatically switch to the newly deployed version.
5.5.2. Specific process version
If instead you want to start a new process instance in a very specific version, you can use the id of the
process definition like this:
ProcessInstance processInstance = executionService.startProcessInstanceById("ICL-1");
5.5.3. With a key
A new process instance can optionally be given a key. This key is a user defined reference to the executionand is sometimes referred to as the 'business key'. A business key must be unique within the scope of all
versions of a process definition. Typically it is easy to find such a key in the domain of the business process.For example, an order id or an insurance claim number.
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
22 de 75 08/09/2010 14:51
ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL", "CL92837");
The key is used to create the id of the process instance. The format used is
{process-key}.{execution-id}. With a dot between process-key and execution-id. So execution created
in the previous code snippet will have id ICL.CL92837.
If no user defined key is provided, the DB primary key is taken as the key. In that case, the id can beretrieved like this:
ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL");String pid = processInstance.getId();
It is a best practice to use a user defined business key. Typically in your application domain, finding such akey is not difficult. By providing a user defined key, you can then compose the id of the execution, rather
then performing a query based on the process variables - which is also more costly performance-wise.
5.5.4. With variables
A map of named parameter objects can be provided when starting a new process instance. These
parameters will be set as variables on the process instance between creation and start of the processinstance.
Map<String,Object> variables = new HashMap<String,Object>();variables.put("customer", "John Doe");variables.put("type", "Accident");variables.put("amount", new Float(763.74));
ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL", variables);
5.6. Signalling a waiting execution
When using a state activity, the execution (or process instance) will halt when it arrives in a state, waiting
for a signal (aka external trigger). The method signalExecution and alike can be used for that. Executions
are referenced by an execution id (String).
In some cases, the execution that arrives in a state will be the process instance itself. But that is not alwaysthe case. In case of timers or concurrency, a process is the root execution of a tree of executions. So you
have to make sure that you signal the right path of execution.
The preferred way to capture the right execution is by associating an event listener to the state activity like
this:
<state name="wait"> <on event="start"> <event-listener class="org.jbpm.examples.StartExternalWork" /> </on> ...</state>
In event listener StartExternalWork you can kick off what needs to be done externally. In that event
listener you can also obtain the exact execution id with execution.getId(). It's that executionId that you'll
need to provide with the signal later on when the external work is done:
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
23 de 75 08/09/2010 14:51
executionService.signalExecutionById(executionId);
There is an alternatively (less preferrable) way to obtain the executionId when the execution arrives in thestate activity. It's only possible to obtain the execution id this way if you know after which jBPM API call the
execution will have entered the state activity:
// assume that we know that after the next call// the process instance will arrive in state external work
ProcessInstance processInstance = executionService.startProcessInstanceById(processDefinitionId);// or ProcessInstance processInstance = // executionService.signalProcessInstanceById(executionId);
Execution execution = processInstance.findActiveExecutionIn("external work");String executionId = execution.getId();
Do note that the above solution couples the application logic (too) closely by using knowledge about theactual process structure.
5.7. TaskService
The primary purpose of the TaskService is to provide access to task lists. The code sample will show how to
get the task list for the user with id johndoe.
List<Task> taskList = taskService.findPersonalTasks("johndoe");
Typically tasks are associated with a form and displayed in some user interface. The form needs to be able to
read and write data related to the task.
// read task variablesSet<String> variableNames = taskService.getVariableNames(taskId);variables = taskService.getVariables(taskId, variableNames);
// write task variablesvariables = new HashMap<String, Object>();variables.put("category", "small");variables.put("lires", 923874893);taskService.setVariables(taskId, variables);
The taskService is also used to complete tasks
taskService.completeTask(taskId);taskService.completeTask(taskId, variables);taskService.completeTask(taskId, outcome);taskService.completeTask(taskId, outcome, variables);
The API allows to provide a map of variables that will be added as process variables before the task iscompleted. It is also possible to provide an 'outcome', that will be used to determine which outgoing
transition will be chosen. The logic is as follows:
If a task has one outgoing transition without a name then:
taskService.getOutcomes() returns a collection that includes one null value
taskService.completeTask(taskId) will take that outgoing transition
taskService.completeTask(taskId, null) will take that outgoing transition
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
24 de 75 08/09/2010 14:51
taskService.completeTask(taskId, "anyvalue") will result in an exception
If a task has one outgoing transition with a name then:
taskService.getOutcomes() returns a collection that includes only the name of the transition
taskService.completeTask(taskId) will take the single outgoing transition
taskService.completeTask(taskId, null) will will result in an exception (as there is no transition without aname)
taskService.completeTask(taskId, "anyvalue") will result in an exception
taskService.completeTask(taskId, "myName") will take the transition with the given name
If a task has multiple outgoing transitions. One transition has no a name and the other transition
have a name:
taskService.getOutcomes() returns a collection that includes a null value and the names of the other
transitions
taskService.completeTask(taskId) will take the transition without a name
taskService.completeTask(taskId, null) will take the transition without a name
taskService.completeTask(taskId, "anyvalue") will result in an exception
taskService.completeTask(taskId, "myName") will take the 'myName' transition
If a task has multiple outgoing transitions and all of them are uniquely named, then:
taskService.getOutcomes() returns a collection that includes all the names of all the transitions
taskService.completeTask(taskId) will result in an exception, since there is no transition without a name
taskService.completeTask(taskId, null) will result in an exception, since there is no unnamed transition
taskService.completeTask(taskId, "anyvalue") will result in an exception
taskService.completeTask(taskId, "myName") will take the 'myName' transition
Tasks can also be offered to a set of candidates. Candidates can be users or groups. Users can take tasks for
which they are a candidate. Taking a task means that this user will be set as the assignee. After that, otherusers will be blocked from taking the task.
People should not work on a task unless they are assigned to that task. The user interface should displayforms and allow users to complete tasks if they are assigned to it. For unassigned tasks for which the user is
a candidate, the only action that should be exposed is 'take'.
More on tasks in Section 6.2.6, “task”
5.8. HistoryService
During runtime execution of process instances, events are generated. And from those events, history
information on both running and completed process executions are collected in the history tables. TheHistoryService provides access to that information.
Querying for all process instances for a specific process definition can be done like this:
List<HistoryProcessInstance> historyProcessInstances = historyService .createHistoryProcessInstanceQuery() .processDefinitionId("ICL-1") .orderAsc(HistoryProcessInstanceQuery.PROPERTY_STARTTIME) .list();
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
25 de 75 08/09/2010 14:51
Also individual activity executions are stored in the history information as HistoryActivityInstances.
List<HistoryActivityInstance> histActInsts = historyService .createHistoryActivityInstanceQuery() .processDefinitionId("ICL-1") .activityName("a") .list();
Convenience methods avgDurationPerActivity and choiceDistribution are also available. See javadocs
for more information on those methods.
Sometimes there is a need to get complete list of nodes executed for a given process instance. Followingquery can be used to get list of all nodes executed:
List<HistoryActivityInstance> histActInsts = historyService .createHistoryActivityInstanceQuery() .processInstanceId("ICL.12345") .list();
Above query is a bit different then querying by execution id. Sometimes execution id is different than process
instance id, for instance when an activity has a timer then execution id will get additional suffix, which makesthat node excluded from a result list while querying by execution id.
5.9. ManagementService
The management service is mostly used to manage the jobs. See javadocs for more information. Thisfunctionality is also exposed through the jBPM web console.
5.10. Query API
Starting from jBPM 4.0, a new API has been introuced with a query system that covers most of the queries
you can think of. Developers who need to write company-specific queries can of course still rely onHibernate. But for most use cases, the query API will be more then suffice. Queries can be written in aunified way on all major jBPM concepts: Process Instances, Tasks, Deployments, Historical processes, etc.
For example:
List<ProcessInstance> results = executionService.createProcessInstanceQuery() .processDefinitionId("my_process_definition") .notSuspended() .page(0, 50) .list();
This example returns all the process instances of the given process definition which are not suspended. The
result is also paged, and the first page of 50 results is given.
Querying tasks is done in completely the same way:
List<Task> myTasks = taskService.createTaskQuery() .processInstanceId(piId) .assignee("John") .page(100, 120) .orderDesc(TaskQuery.PROPERTY_DUEDATE) .list();
This query will give all the tasks for a given process instance assigned to John, paged of course, in a
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
26 de 75 08/09/2010 14:51
descending order based on the duedate.
Every service has operations of creating such unified queries (eg. querying jobs through theManagementService, querying completed process instances through the HistoryService. Do check the
Javadoc of the services to learn everything about the query API.
Chapter 6. jPDL
6.1. process
6.2. Control flow activities6.2.1. start
6.2.2. state
6.2.3. decision
6.2.4. concurrency
6.2.5. end
6.2.6. task
6.2.7. sub-process
6.2.8. custom
6.3. Automatic activities6.3.1. java
6.3.2. script
6.3.3. hql
6.3.4. sql
6.3.5. mail
6.4. Common activity contents6.5. Events
6.5.1. Event listener example
6.5.2. Event propagation6.6. Asynchronous continuations
6.6.1. Async activity6.6.2. Async fork
6.7. User code
6.7.1. User code configuration6.7.2. User code classloading
This chapter will explain the jPDL file format for describing process definitions. jPDL is the prominent processlanguage of jBPM. The goal of jPDL is to be as concise and developer-friendly as possible, while offering
every feature you'd expect from a BPM process language.
The jPDL schema file contains more attributes and elements then this documentation. This part of the
documentation explains the stable and supported part of jPDL. Experimental/not supported jPDL features canbe found in the developers guide.
An example jPDL process file looks like this:
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
27 de 75 08/09/2010 14:51
<?xml version="1.0" encoding="UTF-8"?>
<process name="Purchase order" xmlns="http://jbpm.org/4.4/jpdl">
<start> <transition to="Verify supplier" /> </start>
<state name="Verify supplier"> <transition name="Supplier ok" to="Check supplier data" /> <transition name="Supplier not ok" to="Error" /> </state>
<decision name="Check supplier data"> <transition name="nok" to="Error" /> <transition name="ok" to="Completed" /> </decision>
<end name="Completed" />
<end name="Error" />
</process>
6.1. process
The top level element representing one process definition.
Table 6.1. process attributes:
Attribute Type Default Required? Description
name any text required
name or label of the process used
to display to the process name inuser interactions.
keyalpha numeric
characters andunderscores
if omitted, the key willbe generated based on
the name by replacingall non-alpha-numericcharacters with
underscores
optional
identification to distinct differentprocess definitions. Multipleversions of a process with the same
key can be deployed. Thekey:name combination must
remain exactly the same for alldeployed versions.
version integer
one higher then highest
version number startingwith 1 if no other process
is deployed with thesame name/key.
optional version number of this process
Table 6.2. process elements:
Element Multiplicity Description
description 0..1 description text
activities 1..*a list of any activity type can be placed here. At least one start activity
must be present.
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
28 de 75 08/09/2010 14:51
6.2. Control flow activities
6.2.1. start
Indicates where an execution for this process starts. Typically there is exactly one start activity in a process.
A process has to have at least one start activity. A start activity must have exactly one outgoing transitionand that transition is taken when a process execution starts.
Known limitation: for now, a process can not have more then one start.
Table 6.3. start attributes:
Attribute Type Default Required? Description
nameanytext
optionalname of the activity. Since a start activity cannot haveincoming transitions, the name is optional.
Table 6.4. start elements:
Element Multiplicity Description
transition 1 the outgoing transition
6.2.2. state
A wait state. Process execution will wait until an external trigger is provided through the API. Apart from thecommon activity content, state doesn't have any extra attributes or elements.
6.2.2.1. state sequence
Let's look at an example which shows states connected with transitions as a sequence
Figure 6.1. A sequence of states
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
29 de 75 08/09/2010 14:51
<process name="StateSequence" xmlns="http://jbpm.org/4.4/jpdl">
<start> <transition to="a" /> </start>
<state name="a"> <transition to="b" /> </state>
<state name="b"> <transition to="c" /> </state>
<state name="c" />
</process>
After you start an execution like this:
ProcessInstance processInstance = executionService.startProcessInstanceByKey("StateSequence");
the created process instance will be positioned in state a. Providing an external trigger can be done with the
signalExecution methods.
Execution executionInA = processInstance.findActiveExecutionIn("a");assertNotNull(executionInA);
processInstance = executionService.signalExecutionById(executionInA.getId());Execution executionInB = processInstance.findActiveExecutionIn("b");assertNotNull(executionInB);
processInstance = executionService.signalExecutionById(executionInB.getId());Execution executionInC = processInstance.findActiveExecutionIn("c");assertNotNull(executionInC);
6.2.2.2. state choice
In this second example with states, we'll show how you can use a state can be used to feed in an external
choice of the path to take.
Figure 6.2. A choice between state
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
30 de 75 08/09/2010 14:51
<process name="StateChoice" xmlns="http://jbpm.org/4.4/jpdl">
<start> <transition to="wait for response" /> </start>
<state name="wait for response"> <transition name="accept" to="submit document" /> <transition name="reject" to="try again" /> </state>
<state name="submit document" />
<state name="try again" />
</process>
Let's start a new process instance for this process definition:
ProcessInstance processInstance = executionService .startProcessInstanceByKey("StateChoice");
Now, the execution has arrived in the wait for response. The execution will wait there until an external
trigger is given. In case a state has multiple outgoing transitions, the signalName given in the external
trigger will be matched against the name of the outgoing transition to take. So when we provide signalNameaccept like this:
String executionId = processInstance .findActiveExecutionIn("wait for response") .getId();
processInstance = executionService.signalExecutionById(executionId, "accept");
assertTrue(processInstance.isActive("submit document"));
Then the execution will continue over the outgoing transition named accept. Analogue, when signalName
reject is given in the signalExecutionXxx methods, the execution will continue over the outgoing transition
named reject.
6.2.3. decision
Takes one path of many alternatives. Also known as a decision. A decision activity has multiple outgoingtransitions and when an execution arrives in a decision activity, an automatic evaluation will decide whichoutgoing transition is taken.
A decision activity should be configured in one of the three following ways:
6.2.3.1. Decision conditions
A decision with conditions on the transitions evaluates the condition in each transition. The first transition for
which the nested condition expression resolves to true or which does not have a condition is taken.
Table 6.5. decision.transition.condition attributes:
Attribute Type Default Required? Description
expr expression requiredscript that will beevaluated in the
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
31 de 75 08/09/2010 14:51
Attribute Type Default Required? Description
specified expressionlanguage.
langexpressionlanguage
the default-expression-language
taken from the script-manager
configuration
optional
the language in which
expr is to be
evaluated.
Example:
Figure 6.3. The decision conditions example process
<process name="DecisionConditions" >
<start> <transition to="evaluate document" /> </start>
<decision name="evaluate document"> <transition to="submit document"> <condition expr="#{content=="good"}" /> </transition> <transition to="try again"> <condition expr="#{content=="not so good"}" /> </transition> <transition to="give up" /> </decision>
<state name="submit document" />
<state name="try again" />
<state name="give up" />
</process>
After starting a process instance with good content
Map<String, Object> variables = new HashMap<String, Object>();variables.put("content", "good");ProcessInstance processInstance = executionService.startProcessInstanceByKey("DecisionConditions", variables);
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
32 de 75 08/09/2010 14:51
The activity submit document will be active
assertTrue(processInstance.isActive("submit document"));
See the example unit test for more scenarios.
6.2.3.2. Decision expression
A decision expression evaluates to a String representing the name of an outgoing transition.
Table 6.6. decision attributes:
Attribute Type Default Required? Description
expr expression required
script that will beevaluated in thespecified expression
language.
langexpression
language
the default-expression-language
taken from the script-manager
configuration
optional
the language in whichexpr is to be
evaluated.
Example:
The decision expression example process
Figure 6.4. The decision expression example process
<process name="DecisionExpression" xmlns="http://jbpm.org/4.4/jpdl">
<start > <transition to="evaluate document"/> </start>
<decision name="evaluate document" expr="#{content}" > <transition name="good" to="submit document" /> <transition name="bad" to="try again" /> <transition name="ugly" to="give up" /> </decision>
<state name="submit document" /> <state name="try again" /> <state name="give up" />
</process>
When you start an new process instance with good content like this
Map<String, Object> variables = new HashMap<String, Object>();variables.put("content", "good");ProcessInstance processInstance = executionService.startProcessInstanceByKey("DecisionExpression", variables);
then the new execution will go to activity submit document.
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
33 de 75 08/09/2010 14:51
See the example unit test for the other scenarios.
6.2.3.3. Decision handler
A decision handler is a java class that implements the DecisionHandler interface. The decision handler will
be responsible for selecting the name of the outgoing transition.
public interface DecisionHandler { String decide(OpenExecution execution);}
The handler is specified as a sub element of the decision. The configuration attributes and content of adecision handler element can be found in Section 6.7, “User code”.
Here's an example process of a decision using a DecisionHandler:
The decision handler example process
Figure 6.5. The decision handler example process
<process name="DecisionHandler">
<start> <transition to="evaluate document" /> </start>
<decision name="evaluate document"> <handler class="org.jbpm.examples.decision.handler.ContentEvaluation" /> <transition name="good" to="submit document" /> <transition name="bad" to="try again" /> <transition name="ugly" to="give up" /> </decision>
<state name="submit document" />
<state name="try again" />
<state name="give up" />
</process>
The ContentEvaluation class looks like this
public class ContentEvaluation implements DecisionHandler {
public String decide(OpenExecution execution) { String content = (String) execution.getVariable("content"); if (content.equals("you're great")) { return "good"; } if (content.equals("you gotta improve")) { return "bad"; } return "ugly"; }}
Now, when we start a process instance and supply value you're great for variable content, then the
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
34 de 75 08/09/2010 14:51
ContentEvaluation will return String good and the process instance will arrive in activity Submit document.
6.2.4. concurrency
Concurrent paths of executions can be modeled with the fork and join activities. The next table describes
the join attributes; fork has no specific attributes.
Table 6.7. join attributes:
Attribute Type Default Required? Description
multiplicity integer or expressionnbr ofincoming
transitions
optional
The number of executions that shouldarrive in this join before the joinactivates and push an execution out
the single outgoing transition of thejoin.
lockmode
{none, read,upgrade,upgrade_nowait,
write}
upgrade optional
the hibernate lock mode applied on
the parent execution to prevent that2 concurrent transactions see each
other as not yet arrived at the join,causing a process deadlock.
6.2.4.1. Parallel split with fork
The fork activity allows a single path of execution to be split into two or more branches which can execute
activities concurrently.
Figure 6.6. Parallel split example process
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
35 de 75 08/09/2010 14:51
<process name="ConcurrencyGraphBased" xmlns="http://jbpm.org/4.4/jpdl">
<start> <transition to="fork"/> </start>
<fork name="fork"> <transition to="send invoice" /> <transition to="load truck"/> <transition to="print shipping documents" /> </fork>
<state name="send invoice" > <transition to="final join" /> </state>
<state name="load truck" > <transition to="shipping join" /> </state>
<state name="print shipping documents"> <transition to="shipping join" /> </state>
<join name="shipping join" > <transition to="drive truck to destination" /> </join>
<state name="drive truck to destination" > <transition to="final join" /> </state>
<join name="final join" > <transition to="end"/> </join>
<end name="end" />
</process>
6.2.5. end
Ends the execution.
6.2.5.1. end process instance
By default, an end activity will end the complete process instance. In case multiple concurrent executions arestill active within the same process instance, all of them will be ended.
Figure 6.7. The end event
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
36 de 75 08/09/2010 14:51
<process name="EndProcessInstance" xmlns="http://jbpm.org/4.4/jpdl">
<start> <transition to="end" /> </start>
<end name="end" />
</process>
When a new process instance is created, it immediately ends.
6.2.5.2. end execution
Only the execution that arrives in the end activity will be ended and other concurrent executions should beleft active. To get this behaviour, set attribute ends="execution"
Table 6.8. end execution attributes:
Attribute Type Default Required? Description
ends {processinstance|execution} processinstance optional
specifies if the whole process
instance should be ended or justthe path of execution that
arrives in the end activity.
6.2.5.3. end multiple
A process can have multiple end events. This can be handy to indicate different outcomes of a process
instance. For example
Figure 6.8. Multiple end events
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
37 de 75 08/09/2010 14:51
<process name="EndMultiple" xmlns="http://;jbpm.org/4/jpdl">
<start> <transition to="get return code" /> </start>
<state name="get return code"> <transition name="200" to="ok"/> <transition name="400" to="bad request"/> <transition name="500" to="internal server error"/> </state>
<end name="ok"/> <end name="bad request"/> <end name="internal server error"/>
</process>
Now if we would start an execution and signal it to move out of the get return code wait state with the
following code, the execution would end with the bad request end event.
ProcessInstance processInstance = executionService.startProcessInstanceByKey("EndMultiple");String pid = processInstance.getId();processInstance = executionService.signalExecutionById(pid, "400");
Likewise, using the value 200 or 500 would cause the execution to end with the ok or with the
internal server error end events respectively.
6.2.5.4. end state
An execution can also end with different states. It is another way to specify the outcome of a process. It is
indicated by the state attribute of the end event or by the end-cancel and end-error shortcut notations.
Table 6.9. end execution attributes:
Attribute Type Default Required? Description
state String optional the state assigned to the execution.
Take for example the following process.
Figure 6.9. Different end states
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
38 de 75 08/09/2010 14:51
<process name="EndState" xmlns="http://jbpm.org/4.4/jpdl">
<start> <transition to="get return code"/> </start>
<state name="get return code"> <transition name="200" to="ok"/> <transition name="400" to="bad request" /> <transition name="500" to="internal server error"/> </state>
<end name="ok" state="completed"/> <end-cancel name="bad request"/> <end-error name="internal server error"/>
</process>
This time, if we would start an execution and signal it to move out of the get return code wait state with
the following code, the execution would end with the cancel state.
Similarly, using the value 200 or 500 would cause the execution to end with the completed or with the error
states respectively.
6.2.6. task
Creates a task for a person in the task component.
6.2.6.1. task assignee
A simple task that will be assigned to a specific user
Table 6.10. task attributes:
Attribute Type Default Required? Description
assignee expression optionaluserId referring to the person that is responsible for
completing this task.
Figure 6.10. The task assignee example process
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
39 de 75 08/09/2010 14:51
<process name="TaskAssignee">
<start> <transition to="review" /> </start>
<task name="review" assignee="#{order.owner}">
<transition to="wait" /> </task>
<state name="wait" />
</process>
This process shows 2 aspects of task assignment. First, that the attribute assignee is used to indicate the
user that is responsible for completing the task. The assignee is a String property of a task and refers to a
user.
Secondly, this attribute is by default evaluated as an expression. In this case the task is assigned to#{order.owner}. Which means that first an object is searched for with name order. One of the places where
this object is looked up is the process variables associated to the task. Then the getOwner() getter will be
used to get the userId that references the user that is responsible for completing this task.
Here's the Order class used in our example:
public class Order implements Serializable {
String owner;
public Order(String owner) { this.owner = owner; }
public String getOwner() { return owner; }
public void setOwner(String owner) { this.owner = owner; }}
Next a new process instance is created with an order as a process variable.
Map<String, Object> variables = new HashMap<String, Object>();variables.put("order", new Order("johndoe"));ProcessInstance processInstance = executionService .startProcessInstanceByKey("TaskAssignee", variables);
Then the task list for johndoe can be obtained like this.
List<Task> taskList = taskService.findPersonalTasks("johndoe");
Note that it is also possible to put plain text like assignee="johndoe". In that case the task will be assigned
to johndoe.
6.2.6.2. task candidates
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
40 de 75 08/09/2010 14:51
A task that will be offered to a group of users. One of the users should then take the task in order tocomplete it.
Table 6.11. task attributes:
Attribute Type Default Required? Description
candidate-groups expression optionalresolves to a comma separated list of groupIds.All the people in the groups will be candidates
for this task.
candidate-users expression optionalresolves to a comma separated list of userIds.
All the users will be candidates for this task.
Figure 6.11. The task candidates example process
Here's an example process using task candidates:
<process name="TaskCandidates">
<start> <transition to="review" /> </start>
<task name="review" candidate-groups="sales-dept">
<transition to="wait" /> </task>
<state name="wait"/>
</process>
After starting, a task will be created. The task will not show up in anyone's personal task list. Following tasklists will be empty.
taskService.getPersonalTasks("johndoe");taskService.getPersonalTasks("joesmoe");
But the task will show up in the group task list of all members of the sales-dept group.
The in our example, the sales-dept has two members: johndoe and joesmoe
identityService.createGroup("sales-dept");
identityService.createUser("johndoe", "johndoe", "John", "Doe");identityService.createMembership("johndoe", "sales-dept");
identityService.createUser("joesmoe", "joesmoe", "Joe", "Smoe");identityService.createMembership("joesmoe", "sales-dept");
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
41 de 75 08/09/2010 14:51
So after the process is created, the task will appear in both the group tasks for users johndoe and joesmoe
taskService.findGroupTasks("johndoe");taskService.findGroupTasks("joesmoe");
Candidates must take a task before they can work on it. This will prevent that two candides start working onthe same task. The user interface must only offer the action 'Take' for the tasks in the group task list.
taskService.takeTask(task.getDbid(), "johndoe");
When a user takes a task, the assignee of that task will be set to the given user. The task will disappear fromall the candidate's group task list and it will appear in the user's assigned tasks.
Users are only allowed to work on tasks in their personal task list. This should be enforced by the userinterface.
Similarly, the attribute candidate-users can be used that resolves to a comma separated list of userIds.
The candidate-users attribute can be used in combination with other assignment options.
6.2.6.3. task assignment handler
An AssignmentHandler can be used to calculate the assignee and the candidates for a task
programmatically.
public interface AssignmentHandler extends Serializable {
/** sets the actorId and candidates for the given assignable. */ void assign(Assignable assignable, OpenExecution execution) throws Exception;}
Assignable is a common interface for Tasks and Swimlanes. So AssignmentHandlers can be used for tasks
as well as swimlanes (see later).
assignment-handler is a sub element of the task element. It specifies a user code object. So the attributes
and elements of assignment-handler are documented in Section 6.7, “User code”
Let's look at the task assignment example process.
Figure 6.12. The task assignment handler example process
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
42 de 75 08/09/2010 14:51
<process name="TaskAssignmentHandler" xmlns="http://jbpm.org/4.4/jpdl">
<start g="20,20,48,48"> <transition to="review" /> </start>
<task name="review" g="96,16,127,52"> <assignment-handler class="org.jbpm.examples.task.assignmenthandler.AssignTask"> <field name="assignee"> <string value="johndoe" /> </field> </assignment-handler> <transition to="wait" /> </task>
<state name="wait" g="255,16,88,52" />
</process>
The referenced class AssignTask looks like this:
public class AssignTask implements AssignmentHandler {
String assignee;
public void assign(Assignable assignable, OpenExecution execution) { assignable.setAssignee(assignee); }}
Please note that potentially, AssignmentHandler implementations can use the process variables and any
other Java API to access resources like your application database to calculate the assignee and candidateusers and groups.
Starting a new process instance of the TaskAssignmentHandler process will immediately bring the new
execution to the task activity. A new review task is created and at that point, the AssignTask assignment
handler is called. That will set johndoe as the assignee. So John Doe will find the task in his personal task
list.
6.2.6.4. task swimlanes
Multiple tasks in a process should be assigned to the same user or candidates. Multiple tasks in a process canbe associated to a single swimlane. The process instance will remember the candidates and user that
performed the first task in the swimlane. And subsequent tasks in the same swimlane will be assigned tothose user and candidates.
A swimlane can also be considered as a process role. In some cases, this might boil down to authorizationroles in the identity component. But bare in mind that it is not always the same thing.
Table 6.12. task attributes:
Attribute Type Default Required? Description
swimlane swimlane (string) optional refers to a swimlane that is declared in the process
Swimlanes can be declared inside a process element:
Table 6.13. swimlane attributes:
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
43 de 75 08/09/2010 14:51
Attribute Type Default Required? Description
nameswimlane
(string) required
Name for this swimlane. This is the name thatwill be referenced by task swimlane
attributes.
assignee expression optionaluserId referring to the person that is
responsible for completing this task.
candidate-groups expression optionalresolves to a comma separated list ofgroupIds. All the people in the groups will be
candidates for this the tasks in this swimlane.
candidate-users expression optionalresolves to a comma separated list of userIds.All the users will be candidates for the tasks in
this swimlane.
Figure 6.13. The task swimlane example process
The task swimlane example has the following process file :
<process name="TaskSwimlane" xmlns="http://jbpm.org/4.4/jpdl">
<swimlane name="sales representative" candidate-groups="sales-dept" />
<start> <transition to="enter order data" /> </start>
<task name="enter order data" swimlane="sales representative">
<transition to="calculate quote"/> </task>
<task name="calculate quote" swimlane="sales representative"> </task>
</process>
In this example we create the following information in the identity component:
identityService.createGroup("sales-dept");
identityService.createUser("johndoe", "johndoe", "John", "Doe");identityService.createMembership("johndoe", "sales-dept");
After starting a new process instance, user johndoe will be a candidate for task enter order data. Again
like in the previous task candidates example, John Doe can now take this task like this:
taskService.takeTask(taskDbid, "johndoe");
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
44 de 75 08/09/2010 14:51
Taking the task will make Litjohndoe the assignee for the task. And since this task is coupled to the
swimlane sales representative, assignee johndoe will also be propagated as the assignee in the
swimlane.
Next, John Doe can complete the task like this:
taskService.completeTask(taskDbid);
Completing the task will bring the process execution to the next task, which is calculate quote. Also this
task is linked to the swimlane. Therefore, the task will be assigned to johndoe. Also the candidate users and
candidate groups of the initial assignment will be copied from the swimlane to the task. This is relevant incase user johndoe would release the task and offer it back to the other candidates.
6.2.6.5. task variables
Tasks can read and update process variables. Later tasks will have the option to declare task-local process
variables. Task variables are an important part of the task forms. Task forms typically show data that comesfrom the task and the process instance. Then input from the user is translated in setting task variables.
Getting task variables can be done like this:
List<Task> taskList = taskService.findPersonalTasks("johndoe");
Task task = taskList.get(0);long taskDbid = task.getDbid();
Set<String> variableNames = taskService.getVariableNames(taskDbid);
Map<String, Object> variables = taskService.getVariables(taskDbid, variableNames);
And setting task variables can be done like this:
variables = new HashMap<String, Object>();variables.put("category", "small");variables.put("lires", 923874893);
taskService.setVariables(taskDbid, variables);
6.2.6.6. e-mail support in tasks
It is possible to provide assignees with notifications when a task is added to their list, as well as reminders atspecific intervals. Every email message is produced from a template. Templates may be specified inline or inthe process-engine-context section of the configuration file.
Table 6.14. task elements
Element Multiplicity Description
notification 0..1
Sends a notification message when a task is assigned. If no template is
referenced or supplied inline, mail support falls back on the template namedtask-notification.
reminder 0..1Sends a reminder message at specific intervals. If no template is referenced orsupplied inline, mail support falls back on the template named task-reminder.
Table 6.15. notification attributes:
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
45 de 75 08/09/2010 14:51
Attribute Type Default Required? Description
continue{sync | async |
exclusive}sync optional
Specifies if an asynchronous continuation should beintroduced right before sending this notification
email.
Table 6.16. reminder attributes:
Attribute Type Default Required? Description
duedateduration (plain string orcontaining expression)
requiredDelay before a reminder email should besend.
repeatduration (plain string or
containing expression) optional
Delay after a subsequent reminder email
should be send
continue{sync | async |
exclusive}sync optional
Specifies if an asynchronous continuation
should be introduced right before sendingthis notification email.
Here is a basic example that accepts the default templates.
<task name="review" assignee="#{order.owner}" <notification/> <reminder duedate="2 days" repeat="1 day"/></task>
6.2.7. sub-process
Creates a sub process instance and waits till it is completed. When the sub process instance completes, then
the execution in the sub-process will continue.
Table 6.17. sub-process attributes:
Attribute Type Default Required? Description
sub-process-idstring or
expression
either this or
sub-process-key isrequired
Identifies the sub process by the id.This means that a specific version of a
process definition is referenced. Subprocess id can be specified as simpletext or EL expression.
sub-process-keystring orexpression
either this orsub-process-key is
required
Identifies the sub process by the key.This means that the latest version of
the process definition with the givenkey is referenced. The latest version ofthe process is looked up each time the
activity executes. Sub process key canbe specified as simple text or EL
expression.
outcome expression
required whentransitions haveoutcome-value's
specified
Expression that is evaluated when thesub process instance ends. The value is
then used for outcome transitionmapping. Add outcome-value
elements to the outgoing transitions of
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
46 de 75 08/09/2010 14:51
Attribute Type Default Required? Description
this sub-process activity.
Table 6.18. sub-process elements:
Element Multiplicity Description
parameter-in 0..*Declares a variable that is passed to the sub process instance when it iscreated.
parameter-out 0..*Declares a variable that will be set in the super process execution whenthe sub process ends.
Table 6.19. parameter-in attributes:
Attribute Type Default Required? Description
subvar string requiredThe name of the sub process variable in whichthe value is set.
var string exactly one of {'var','expr'} is required tospecify the value
The name of the variable in the super processexecution context.
expr string exactly one of {'var','expr'} is required to
specify the value
An expression that will be resolved in the superprocess execution context. The resulting value
will be set in the sub process variable.
lang string juel optionalThe scripting language in which the expressionshould be resolved.
Table 6.20. parameter-out attributes:
Attribute Type Default Required? Description
var string requiredThe name of the variable in the super process
execution context in which the value will be set.
subvar string exactly one of {'subvar','expr'} is required to
specify the value
The name of the sub process variable from
which the value will be taken.
expr string exactly one of {'subvar','expr'} is required to
specify the value
An expression that will be resolved in the subprocess execution context. The resulting value
will be set in the super process variable.
lang string juel optionalThe scripting language in which the expression
should be resolved.
Table 6.21. Extra transition elements in case of outcome variable mappings:
Element Multiplicity Description
outcome-value 0..1If the outcome matches the value, this transition is taken after the
sub-process ended. The value is specified with one child element.
6.2.7.1. sub-process variables
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
47 de 75 08/09/2010 14:51
The SubProcessVariables example scenario will show the basic workings of the sub-process activity, how tofeed information in the sub process when it starts and how to extract information out of the subprocess whenit ends.
The parent process involves a document that needs to be reviewed.
Figure 6.14. The subprocess document example process
<process name="SubProcessDocument" xmlns="http://jbpm.org/4.4/jpdl">
<start> <transition to="review" /> </start>
<sub-process name="review" sub-process-key="SubProcessReview">
<parameter-in var="document" subvar="document" /> <parameter-out var="reviewResult" subvar="result" />
<transition to="wait" /> </sub-process>
<state name="wait"/>
</process>
The review process is a reusable process for all kinds of reviews.
Figure 6.15. The subprocess review example process
<process name="SubProcessReview" xmlns="http://jbpm.org/4.4/jpdl">
<start> <transition to="get approval"/> </start>
<task name="get approval" assignee="johndoe">
<transition to="end"/> </task>
<end name="end" />
</process>
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
48 de 75 08/09/2010 14:51
The document process is started with a document variable:
Map<String, Object> variables = new HashMap<String, Object>();variables.put("document", "This document describes how we can make more money...");
ProcessInstance processInstance = executionService .startProcessInstanceByKey("SubProcessDocument", variables);
Then the parent process execution will arrive in the sub process activity. A sub process instance is created
and linked with the super process execution. When the SubProcessReview process instance starts, it arrives
in the task. A task will be created for johndoe.
List<Task> taskList = taskService.findPersonalTasks("johndoe");Task task = taskList.get(0);
We can see that the document has been passed from the super process instance to the sub process instance:
String document = (String) taskService.getVariable(task.getDbid(), "document");assertEquals("This document describes how we can make more money...", document);
Then we set a variable on the task. This is typically done through a form. But here we'll show how it is doneprogrammatically.
Map<String, Object> variables = new HashMap<String, Object>();variables.put("result", "accept");taskService.setVariables(task.getDbid(), variables);
Completing this task, will cause the sub process instance to end.
taskService.completeTask(task.getDbid());
When the sub process ends, the super process execution will get signalled(=notified). First the result
variable from the sub process instance will be copied into the reviewResult variable in the super process
execution. Then the super process execution will continue and leave the review activity.
6.2.7.2. sub-process outcome value
In the SubProcessOutcomeValueTest example, the value of a sub process variable is used to select the
outgoing transition of the sub-process activity.
Figure 6.16. The subprocess document example process
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
49 de 75 08/09/2010 14:51
<process name="SubProcessDocument">
<start> <transition to="review" /> </start>
<sub-process name="review" sub-process-key="SubProcessReview" outcome="#{result}">
<transition name="ok" to="next step" /> <transition name="nok" to="update" /> <transition name="reject" to="close" /> </sub-process>
<state name="next step" /> <state name="update" /> <state name="close" />
</process>
The SubProcessReview is the same as above in the subprocess variables example:
Figure 6.17. The subprocess review example process for outcome value
<process name="SubProcessReview" xmlns="http://jbpm.org/4.4/jpdl">
<start> <transition to="get approval"/> </start>
<task name="get approval" assignee="johndoe">
<transition to="end"/> </task>
<end name="end" />
</process>
A new document process instance is started like usual:
ProcessInstance processInstance = executionService .startProcessInstanceByKey("SubProcessDocument");
Then task is fetched from johndoe's task list
List<Task> taskList = taskService.findPersonalTasks("johndoe");Task task = taskList.get(0);
Then the result variable is set and the task is completed.
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
50 de 75 08/09/2010 14:51
Map<String, Object> variables = new HashMap<String, Object>();variables.put("result", "ok");taskService.setVariables(task.getId(), variables);taskService.completeTask(task.getDbid());
In this scenario, the ok transition is taken in the parent process out of the sub-process review activity. The
example test case also shows other scenarios.
6.2.7.3. sub-process outcome activity
A process can have many end activities. In the SubProcessOutcomeActivityTest example, the resulting
end activity is used to select the outgoing transition of the sub-process activity.
Figure 6.18. The subprocess document example process for outcome activity
<process name="SubProcessDocument">
<start> <transition to="review" /> </start>
<sub-process name="review" sub-process-key="SubProcessReview">
<transition name="ok" to="next step" /> <transition name="nok" to="update" /> <transition name="reject" to="close" /> </sub-process>
<state name="next step" /> <state name="update" /> <state name="close" />
</process>
The SubProcessReview now has multiple end activities:
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
51 de 75 08/09/2010 14:51
Figure 6.19. The subprocess review example process for outcome activity
<process name="SubProcessReview" xmlns="http://jbpm.org/4.4/jpdl">
<start> <transition to="get approval"/> </start>
<task name="get approval" assignee="johndoe">
<transition name="ok" to="ok"/> <transition name="nok" to="nok"/> <transition name="reject" to="reject"/> </task>
<end name="ok" /> <end name="nok" /> <end name="reject" />
</process>
A new document process instance is started like usual:
ProcessInstance processInstance = executionService .startProcessInstanceByKey("SubProcessDocument");
Then task is fetched from johndoe's task list
List<Task> taskList = taskService.findPersonalTasks("johndoe");Task task = taskList.get(0);
Then the task is completed with outcome ok.
taskService.completeTask(task.getDbid(), "ok");
This will cause the sub process to end in end activity ok. The super process execution will then take outgoing
transition ok to next step.
The example test case also shows the other scenarios.
6.2.8. custom
Invokes user code that implements custom behaviour of an activity.
A custom activity refers to user code. See Section 6.7, “User code” for more details on the specific attributesand elements. Let's look at the example:
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
52 de 75 08/09/2010 14:51
<process name="Custom" xmlns="http://jbpm.org/4.4/jpdl">
<start > <transition to="print dots" /> </start>
<custom name="print dots" class="org.jbpm.examples.custom.PrintDots">
<transition to="end" /> </custom>
<end name="end" />
</process>
The custom activity behaviour class PrintDots shows that it's possible to control the flow when
implementing custom activity behaviours. In this case the PrintDots acitivity implementation will after
printing dots wait in the activity until a signal is given.
public class PrintDots implements ExternalActivityBehaviour {
private static final long serialVersionUID = 1L;
public void execute(ActivityExecution execution) { String executionId = execution.getId();
String dots = ...;
System.out.println(dots);
execution.waitForSignal(); }
public void signal(ActivityExecution execution, String signalName, Map<String, ?> parameters) { execution.take(signalName); }}
6.3. Automatic activities
6.3.1. java
The Java task. A process execution will execute the method of the class that is configured in this activity.
Table 6.22. java attributes:
Attribute Type Default Required? Description
class classname
either 'class' or
'expr' has to bespecified
The fully qualified classname. See Section 6.7.2,“User code classloading” for classloading
information. The user code object will be lazyinitialized and cached as part of the processdefinition.
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
53 de 75 08/09/2010 14:51
Attribute Type Default Required? Description
expr expression either 'expr' or'class' has to be
specified
An expression that returns the target object on
which the method should be invoked.
method methodname required The name of the method to invoke
var variablename optionalThe name of the variable in which the return
value should be stored.
Table 6.23. java elements:
Element Multiplicity Description
field 0..*describes a configuration value to inject in a memberfield before the method isinvoked.
arg 0..* method parameters
Consider the following example.
Figure 6.20. A java task
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
54 de 75 08/09/2010 14:51
<process name="Java" xmlns="http://jbpm.org/4.4/jpdl">
<start > <transition to="greet" /> </start>
<java name="greet" class="org.jbpm.examples.java.JohnDoe" method="hello" var="answer" >
<field name="state"><string value="fine"/></field> <arg><string value="Hi, how are you?"/></arg>
<transition to="shake hand" /> </java>
<java name="shake hand" expr="#{hand}" method="shake" var="hand" >
<arg><object expr="#{joesmoe.handshakes.force}"/></arg> <arg><object expr="#{joesmoe.handshakes.duration}"/></arg>
<transition to="wait" /> </java>
<state name="wait" />
</process>
Classes involved:
public class JohnDoe {
String state; Session session;
public String hello(String msg) { if ( (msg.indexOf("how are you?")!=-1) && (session.isOpen()) ) { return "I'm "+state+", thank you."; } return null; }}
public class JoeSmoe implements Serializable {
static Map<String, Integer> handshakes = new HashMap<String, Integer>(); { handshakes.put("force", 5); handshakes.put("duration", 12); }
public Map<String, Integer> getHandshakes() { return handshakes; }}
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
55 de 75 08/09/2010 14:51
public class Hand implements Serializable {
private boolean isShaken;
public Hand shake(Integer force, Integer duration) { if (force>3 && duration>7) { isShaken = true; }
return this; }
public boolean isShaken() { return isShaken; }}
The first java activity greet specifies that during its execution an instance of the class
org.jbpm.examples.java.JohnDoe will be instantiated and the method hello of this class will be invoked
on the resulting object. The variable named answer will contain the result of the invocation.
The class above reveals that it contains two fields named state and session and that the method hello
accepts one argument. During the execution the values specified in the field and arg configuration
elements will be used. The expected result of creating a process instance is that the process variable answer
contains the string I'm fine, thank you..
The second java activity is named shake hand. It will resolve expression #{hand} and capture the resulting
object as the target object. On that object, the method shake will be invoked. The two arguments will be
calculated by resolving the respective expressions #{joesmoe.handshakes.force} and
#{joesmoe.handshakes.duration}. The resulting object is a mofied version of the hand and var="hand"
will cause the modified hand to overwrite the old hand variable value.
6.3.2. script
A script activity evaluates a script. Scripts can be specified in any language for which there is a JSR-223compliant scripting engine. Configuration of scripting engines is explained below.
There are 2 ways of specifying a script:
6.3.2.1. script expression
The script is provided with the expr attribute. This is for short expressions that are easier expressed in an
attribute then in a text element. If no lang is specified, the default-expression-language is used.
Table 6.24. script expression attributes:
Attribute Type Default Required? Description
expr text requiredthe expression text to
evaluate.
langscripting language nameas defined in Chapter 8,
Scripting
the default expressionlanguage as defined in
Chapter 8, Scripting
optionalthe language in which the
expression is specified.
var variablename optionalname of the variable in
which the return value
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
56 de 75 08/09/2010 14:51
Attribute Type Default Required? Description
should be stored.
In the next example, we'll see how a script activity with an expression and how the result is stored in a
variable.
Figure 6.21. The script.expression example process
<process name="ScriptExpression" xmlns="http://jbpm.org/4.4/jpdl">
<start> <transition to="invoke script" /> </start>
<script name="invoke script" expr="Send packet to #{person.address}" var="text">
<transition to="wait" /> </script>
<state name="wait"/>
</process>
This example uses a Person class that looks like this.
public class Person implements Serializable {
String address;
public Person(String address) { this.address = address; }
public String getAddress() { return address; }
public void setAddress(String address) { this.address = address; }}
When starting a process instance for this process, we supply a person with a given address property as
variable person.
Map<String, Object> variables = new HashMap<String, Object>();variables.put("person", new Person("Honolulu"));
executionService.startProcessInstanceByKey("ScriptText", variables);
After the execution of the script activity, variable text will contain 'Send packet to Honolulu'.
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
57 de 75 08/09/2010 14:51
6.3.2.2. script text
The second way of specifying a script is with a text element. This is convenient when the script text spans
multiple lines.
Table 6.25. script text attributes:
Attribute Type Default Required? Description
langscripting language name
as defined in Chapter 8,Scripting
the default scripting
language as defined inChapter 8, Scripting
optionalthe language in which the
script is specified.
var variablename optional
name of the variable in
which the return valueshould be stored.
Table 6.26. script text elements:
Element Multiplicity Description
text 1 contains the script text
For example
Figure 6.22. The script.text example process
<process name="ScriptText" xmlns="http://jbpm.org/4.4/jpdl">
<start> <transition to="invoke script" /> </start>
<script name="invoke script" var="text"> <text> Send packet to #{person.address} </text> <transition to="wait" /> </script>
<state name="wait"/>
</process>
Execution of this process is exactly the same as with the script expression above.
6.3.3. hql
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
58 de 75 08/09/2010 14:51
With the hql activity, a HQL query can be performed on the database and the result is stored in a process
variable.
Table 6.27. hql attributes:
Attribute Type Default Required? Description
var variablename required the name of the variable in which the result is stored.
unique {true, false} false optional
a value of true means that the result from the
hibernate query should be obtained with methoduniqueResult(). The default is false and in that case
the list() method will be used to get the result.
Table 6.28. hql elements:
Element Multiplicity Description
query 1 The HQL query.
parameter 0..* The query parameters
For example:
Figure 6.23. The hql example process
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
59 de 75 08/09/2010 14:51
<process name="Hql" xmlns="http://jbpm.org/4.4/jpdl">
<start> <transition to="get process names" /> </start>
<hql name="get process names" var="activities with o"> <query> select activity.name from org.jbpm.pvm.internal.model.ActivityImpl as activity where activity.name like :activityName </query> <parameters> <string name="activityName" value="%o%" /> </parameters> <transition to="count activities" /> </hql>
<hql name="count activities" var="activities" unique="true"> <query> select count(*) from org.jbpm.pvm.internal.model.ActivityImpl </query> <transition to="wait" /> </hql>
<state name="wait"/>
</process>
6.3.4. sql
The sql activity is exactly the same as the hql activity, with the only difference that
session.createSQLQuery(...) is used.
6.3.5. mail
Through the mail activity, process authors are able to specify the content of an email message to be sent to
multiple recipients at once. Every email message is produced from a template. Templates may be specifiedinline or in the process-engine-context section of the configuration file.
Table 6.29. mail attributes
Attribute Type Default Required? Description
template string no
Reference to a mail-template element in the configuration
file. If absent, the template must be specified inline using thechild elements.
Table 6.30. mail elements
Element Multiplicity Description
from 0..1 list of sender(s)
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
60 de 75 08/09/2010 14:51
Element Multiplicity Description
to 1 list of primary recipients
cc 0..1 list of carbon copy recipients
bcc 0..1 list of blind carbon copy recipients
subject 1 text content of this element becomes the message subject
text 0..1 text content of this element becomes the message text content
html 0..1 text content of this element becomes the message HTML content
attachments 0..1 each attachment is configured in a separate subelement
Table 6.31. attachment attributes
Attribute Type Default Required? Description
name string no, unless expression
is present
File name associated with this attachment. Ifabsent, data sources that encapsulate files such
as resource, file and url provide a reasonable
fallback value.
description string noDescriptive information associated with this
attachment.
expression string
one of expression,
file, url or resource
must be present
Expression that evaluates to a representation ofthe attachment data in the form of a Java object.
Useful to extract content from process variables.
file string Path to the attachment data in the file system.
The denoted file must exist.
url string Location of the attachment data in the worldwideweb. The pointed resource must exist.
resource string Name of the resource containing the attachmentdata in the class path. The denoted resourcemust exist.
mime-type string no, unless expression
is present
MIME type of the object returned by the
expression.
Example usage:
<process name="InlineMail" xmlns="http://jbpm.org/4.4/jpdl"> <start> <transition to="send birthday reminder note" /> </start> <mail name="send birthday reminder note"> <to addresses="[email protected]" /> <subject>Reminder: ${person} celebrates his birthday!</subject> <text>Do not forget: ${date} is the birthday of ${person} </text> <attachments> <attachment resource="org/example/birthday_card.png"/> <attachment name="picture.jpg" expression="${picture}" mime-type="image/jpeg"/> </attachments> <transition to="end" /> </mail> <state name="end"/></process>
6.4. Common activity contents
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
61 de 75 08/09/2010 14:51
Unless specified otherwise above, all activities also include this content model:
Table 6.32. Common activity attributes:
Attribute Type Default Required? Description
name any text required name of the activity
Table 6.33. Common activity elements:
Element Multiplicity Description
transition 0..* the outgoing transitions
6.5. Events
Events specify points in a process on which a list of event listeners can be registered. When an executionpasses that point in the process, the event listeners are notified. The events and listeners are not shown in
the graphical view of the process, which makes them very interesting for implementing technical details. Anevent is fired by an element in the process definition like e.g. the process definition, an activity or a
transition.
The EventListener interface looks like this:
public interface EventListener extends Serializable {
void notify(EventListenerExecution execution) throws Exception;
}
All automatic activities can be used as event listeners as well.
To associate a list of event listeners with a process or an activity, use the on element to group the event
listeners and specifiy the event. on can be nested as a subelement of process or any activity.
To associate a list of event listeners with a transition take event, just include the event listeners directly in
the transition element.
Table 6.34. on attributes:
Attribute Type Default Required? Description
event {start | end} required name name of the event
Table 6.35. on elements:
Element Multiplicity Description
event-listener 0..* An event listener implementation object.
any automatic activity 0..*
Table 6.36. event listener attributes:
event-listener is user code so it can be configured like described in Section 6.7, “User code”.
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
62 de 75 08/09/2010 14:51
Any automatic activities (including event-listener) that are placed on events can specify following additional
attributes:
Attribute Type Default Required? Description
propagation{enabled |disabled | true |
false | on | off}
disabled optionalindicates if the event listener should also be
invoked for propagating events.
continue{sync | async |exclusive}
sync optional
indicates if the execution should be continued
asynchronously right before the event listeneris executed. @see also Section 6.6,“Asynchronous continuations”
6.5.1. Event listener example
Let's look at an example process with event listeners:
Figure 6.24. The event listener example process
<process name="EventListener" xmlns="http://jbpm.org/4.4/jpdl">
<on event="start"> <event-listener class="org.jbpm.examples.eventlistener.LogListener"> <field name="msg"><string value="start on process definition"/></field> </event-listener> </on>
<start> <transition to="wait"/> </start>
<state name="wait"> <on event="start"> <event-listener class="org.jbpm.examples.eventlistener.LogListener"> <field name="msg"><string value="start on activity wait"/></field> </event-listener> </on> <on event="end"> <event-listener class="org.jbpm.examples.eventlistener.LogListener"> <field name="msg"><string value="end on activity wait"/></field> </event-listener> </on> <transition to="park"> <event-listener class="org.jbpm.examples.eventlistener.LogListener"> <field name="msg"><string value="take transition"/></field> </event-listener> </transition> </state>
<state name="park"/>
</process>
LogListener will maintain a list of logs as a process variable:
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
63 de 75 08/09/2010 14:51
public class LogListener implements EventListener {
// value gets injected from process definition String msg;
public void notify(EventListenerExecution execution) { List<String> logs = (List<String>) execution.getVariable("logs"); if (logs==null) { logs = new ArrayList<String>(); execution.setVariable("logs", logs); }
logs.add(msg);
execution.setVariable("logs", logs); }}
Next, we start a new process instance.
ProcessInstance processInstance = executionService.startProcessInstanceByKey("EventListener");
Then the process instance executes up to the wait activity. So we provide a signal and that will cause it toexecute till the end.
Execution execution = processInstance.findActiveExecutionIn("wait");executionService.signalExecutionById(execution.getId());
The list of log messages will now look like this:
[start on process definition, start on activity wait, end on activity wait, take transition]
6.5.2. Event propagation
Events are propagated from activities and transitions to outer activities and eventually to the processdefinition.
By default, event listeners are only invoked for events that are fired on the elements on which the eventlisteners are subscribed. But by specifying propagation="enabled", the event listener will also be invoked
for all events that are fired on contained elements.
6.6. Asynchronous continuations
Each invocation of ExecutionService.startProcessInstanceById(...) or
ExecutionService.signalProcessInstanceById(...) will cause the process to be executed in the thread
it was called from (=client). In other words, those methods will only return after the process execution has
arrived in a wait state.
This default behaviour has a couple of advantages: user application transactions can be easily propagated to
jBPM to that jBPM's DB updates are done in the user's transaction context. Secondly, it's possible for a clientto get an exception in case something goes wrong during execution of the process. Usually, the automatic
work that has to be done as part of the process inbetween two wait states is relatively small. Even if multipleautomatic activities are executed inbetween 2 wait states. So in most situations, it's good to do all that work
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
64 de 75 08/09/2010 14:51
in a single transaction. This explains that the default behaviour of jPDL is to perform all work of the process
synchronously in the thread of client.
For those cases where you don't want the call to jBPM to be blocking until all the automatic work is done,
jPDL allows for very fine grained control over transaction boundaries. On various places in the process,asynchronous continuations can be introduced. Asynchronous continuations cause the transaction to commit
and the jBPM method invocation will return. jBPM will then start a new transaction in a new thread andcontinue the rest of the automatic process work asynchronously. jBPM uses asynchronous messaginginternally to accomplish this.
Upon an asynchronous continuation, an asynchronous message will be sent as part of the currently ongoing
transaction. And then the originally invoked method like e.g. startProcessInstanceById(...) or
signalProcessInstanceById(...) will return. When the asynchronous message is committed and then
processed, it will start a new transaction and resume execution where it left off.
Table 6.37. Attribute of any activity, transition or on:
Attribute Type Default Required? Description
continue{sync | async |
exclusive}sync optional
indicates if an asynchronous continuation should be
performed before the element is executed.
sync (default) keep executing the element as part of the ongoing transaction.
async introduces an asynchronous continuation (aka safe point). The ongoing transaction is committedand the element is executed in a new transaction. Transactional asynchronous messaging is used by the
jBPM implementation to achieve this.
exclusive introduces a asynchronous continuation (aka safe point). The ongoing transaction is committed
and the element is executed in a new transaction. Transactional asynchronous messaging is used by thejBPM implementation to achieve this. Exclusive messages will not be processed concurrently. jBPM will
make sure that exclusive jobs for the same process instance are not executed concurrently, even if yourjBPM configuration has multiple asynchronous message processors (like the JobExecutor) running ondifferent systems. This can be used to prevent optimistic locking failures in case multiple, potentially
conflicting jobs are scheduled in the same transaction.
Let's look at a couple of examples.
6.6.1. Async activity
Figure 6.25. The async activity example process
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
65 de 75 08/09/2010 14:51
<process name="AsyncActivity" xmlns="http://jbpm.org/4.4/jpdl">
<start> <transition to="generate pdf"/> </start>
<java name="generate pdf" continue="async" class="org.jbpm.examples.async.activity.Application" method="generatePdf" > <transition to="calculate primes"/> </java>
<java name="calculate primes" continue="async" class="org.jbpm.examples.async.activity.Application" method="calculatePrimes"> <transition to="end"/> </java>
<end name="end"/>
</process>
public class Application {
public void generatePdf() { // assume long automatic calculations here }
public void calculatePrimes() { // assume long automatic calculations here }}
ProcessInstance processInstance = executionService.startProcessInstanceByKey("AsyncActivity");String processInstanceId = processInstance.getId();
Without the asynchronous continuations, this would be an all automatic process and the process would
execute all the way up to the end in method startProcessInstanceByKey
But with continue="async" the execution only goes untill it is about to execute activity generate pdf. Then
an asynchronous continuation message is send and the startProcessInstanceByKey method returns.
In a normal configuration, the job executor will automatically pick up the message and execute it. But for
testing scenarios and for these examples we want to control when messages are executed so the jobexecutor is not configured. Therefore we have to execute the jobs manually like this:
Job job = managementService.createJobQuery() .processInstanceId(processInstanceId) .uniqueResult();managementService.executeJob(job.getDbid());
That will bring the process until it's about to execute activity calculate primes and again an asynchronous
message is send.
Then the message can be looked up again and when that message is executed, that transaction will run theexecution till the end.
6.6.2. Async fork
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
66 de 75 08/09/2010 14:51
Figure 6.26. The async fork example process
<process name="AsyncFork" xmlns="http://jbpm.org/4.4/jpdl">
<start > <transition to="fork"/> </start>
<fork > <on event="end" continue="exclusive" /> <transition /> <transition /> </fork>
<java class="org.jbpm.examples.async.fork.Application" > <transition /> </java>
<java class="org.jbpm.examples.async.fork.Application" > <transition /> </java>
<join > <transition to="end"/> </join>
<end />
</process>
public class Application {
public void shipGoods() { // assume automatic calculations here }
public void sendBill() { // assume automatic calculations here }}
By placing the asynchronous continuation on the end event of the fork
(<on event="end" continue="exclusive" />), each forked execution that takes a transition out of the
fork will be continued asynchronously.
Value exclusive was selected to serialize the executions of the 2 asynchonous continuation jobs resulting
from the fork. The respective transactions that will execute activities ship goods and send bill will both
arrive at the join. At the join, both transactions will synchronize on the same execution (read: update the
same execution row in the DB), resulting in a potential optimistic locking failure.
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
67 de 75 08/09/2010 14:51
ProcessInstance processInstance = executionService.startProcessInstanceByKey("AsyncFork");String processInstanceId = processInstance.getId();
List<Job> jobs = managementService.createJobQuery() .processInstanceId(processInstanceId) .list();
assertEquals(2, jobs.size());
Job job = jobs.get(0);
// here we simulate execution of the job,// which is normally done by the job executormanagementService.executeJob(job.getDbid());
job = jobs.get(1);
// here we simulate execution of the job,// which is normally done by the job executormanagementService.executeJob(job.getDbid());
Date endTime = historyService .createHistoryProcessInstanceQuery() .processInstanceId(processInstance.getId()) .uniqueResult() .getEndTime();
assertNotNull(endTime);
6.7. User code
Various elements in the jPDL process language refer to a an object on which an interface method will beinvoked. This section describes the common attributes and elements for the instantiation and configuration of
such user code objects.
custom
event-listener
assignment-handler in task
handler in decision
condition in transition
6.7.1. User code configuration
Table 6.38. attributes:
Attribute Type Default Required? Description
class classname one of{class|expr} is
required
The fully qualified classname. Instantiation is doneonly once and the user object is cached as part of
the process definition.
expr expression
one of
{class|expr} isrequired
Expression for which the resulting value will betaken as the target object. Expressions will be
evaluated for every usage. In other words, theresulting value of the evaluation will not be cached.
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
68 de 75 08/09/2010 14:51
Table 6.39. user code configuration elements:
Element Multiplicity Description
field 0..*describes a configuration value to be injected directly in a memberfield beforethis user class is used.
property 0..*describes a configuration value to injected through a setter method before thisuser object is used.
Table 6.40. field and property attributes:
Attribute Type Default Required? Description
name string required the name of the field or property.
Table 6.41. field and property contained element:
field and property elements have exactly one child element that represents the value that will be injected.
Element Multiplicity Description
string 0..1 a java.lang.String
int 0..1 a java.lang.Integer
long 0..1 a java.lang.Long
float 0..1 a java.lang.Float
double 0..1 a java.lang.Double
true 0..1 Boolean.TRUE
false 0..1 Boolean.FALSE
object 0..1 a object that will be instantiated with reflection
Table 6.42. Attribute for basic type string, int, long, floatand double:
Attribute Type Default Required? Description
value text required text value that will be parsed to the respective type
6.7.2. User code classloading
Process definitions are cached. By default, all user code objects are cached as part of those process
definitions. For all objects that are referenced by a class name, will be instantiated during parsing time.Which implies that the objects aren't allowed to store non-stateless data (ie which can change). This istypically OK since those objects are in practice almost always immutable. If you do need to use 'dynamic'
data in your user code, you can always fall back to process variables (or Environment.get(xxx) calls).
Objects that are referenced by an expression are calculated dynamically.
The devguide also explains an unsupported attribute to prevent that user objects are cached.
Chapter 7. Variables
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
69 de 75 08/09/2010 14:51
7.1. Variable scoping7.2. Variable types7.3. Updating serialized process variables
7.4. Declared variables7.5. Variables history
Process variables can be accessed from outside the process with methods from the ExecutionService:
ProcessInstance startProcessInstanceById(String processDefinitionId, Map<String, Object> variables);
ProcessInstance startProcessInstanceById(String processDefinitionId, Map<String, Object> variables, String pro
ProcessInstance startProcessInstanceByKey(String processDefinitionKey, Map<String, ?> variables);
ProcessInstance startProcessInstanceByKey(String processDefinitionKey, Map<String, ?> variables, String proces
void setVariable(String executionId, String name, Object value);
void setVariables(String executionId, Map<String, ?> variables);
Object getVariable(String executionId, String variableName);
Set<String> getVariableNames(String executionId);
Map<String, Object> getVariables(String executionId, Set<String> variableNames);
And from inside the process with methods from Execution interfaces passed to user code likeActivityExecution and EventListenerExecution:
Object getVariable(String key);
void setVariables(Map<String, ?> variables);
boolean hasVariable(String key);
boolean removeVariable(String key);
void removeVariables();
boolean hasVariables();
Set<String> getVariableKeys();
Map<String, Object> getVariables();
void createVariable(String key, Object value);
void createVariable(String key, Object value, String typeName);
jBPM doesn't have a mechanism for detecting changes automatically to variable values. So if you get e.g. aserializable collection from the process variables and add an element, then you need to set the changed
variable value explicitely for the changes to be saved to the DB.
7.1. Variable scoping
By default variables are created in the top level process instance scope. This means they are visible andaccessible in all the paths of execution of the whole process instance. Process variables are created
dynamically. Meaning that a variable is created the first time it is set through one of these methods.
Each execution is a variable scope. Variables declared in a nested execution level will 'see' their own
variables and variables declared in parent executions according to the normal scoping rules. With thecreateVariable methods in the execution interfaces ActivityExecution and EventListenerExecution,
execution-local variables can be created.
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
70 de 75 08/09/2010 14:51
In one of the future releases, we might add variable declaration in the jPDL process language.
7.2. Variable types
jBPM supports following Java types as process variables:
java.lang.String
java.lang.Long
java.lang.Double
java.util.Date
java.lang.Boolean
java.lang.Character
java.lang.Byte
java.lang.Short
java.lang.Integer
java.lang.Float
byte[] (byte array)
char[] (char array)
hibernate entity with a long id
hibernate entity with a string id
serializable
For persistence of these variable, the type of the variable is checked in the order of this list. The first matchwill determine how the variable is stored.
7.3. Updating serialized process variables
(Since jBPM 4.3)
In customs, event-handlers and other user code, you can retrieve process variables. In case a process
variable is stored as a serialized object, you can just make updates to your deserialized objects without theneed for an explicit save. jBPM will manage deserialized process variables and update them automatically if
you change. For example (@see examples package org.jbpm.examples.serializedobject), look at this pieceof user code inside a custom's activity behaviour:
public class UpdateSerializedVariables implements ActivityBehaviour {
public void execute(ActivityExecution execution) { Set<String> messages = (Set<String>) execution.getVariable("messages"); messages.clear(); messages.add("i"); messages.add("was"); messages.add("updated"); }}
When the transaction commits in which this usercode was called, the updated messages set will be updatedin the database automatically.
When reading process variables that are stored in serialized format from the DB jBPM will monitor that
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
71 de 75 08/09/2010 14:51
deserialized object. Right before the commit of the transaction, jBPM will serialize and update the variable
automatically if that is necessary. jBPM will ignore updates to the deserialized object if another object wasset as the value in that scope (which even can be of another type). jBPM will also skip updating of the
variable if the deserialized object has not been changed. The check to see if the object has changed is basedon comparing the byte arrays from serializing the object again and comparing that with the byte array thatwas originally loaded from the db.
7.4. Declared variables
(Since jBPM 4.4)
Variables can be declared directly in process definition (JPDL). These variables will be created at processinstance startup. There can be more than one variable definition.
There are several possible ways for declaring variable:
declare String variable initialized with static text
<variable name="declaredVar" type="string" init-expr="testing declared variable"/>
declare custom variable initialized with EL
<variable name="declaredVar" type="long" init-expr="#{anotherVar}"/>
declare custom variable initialized with serializable class
<variable name="declaredVar" type="serializable" > <object class="org.jbpm.examples.variable.declared.HistoryVariable" /></variable>
As shown above variable values can be assigned in two ways: using attribute init-expr or by nesting init
descriptor (element object) within variable tags.
Note: Only one of value assignment can be used for a variable declaration.
Table 7.1. Attribute for variable element:
Attribute Type Default Required? Description
name text required name of the variable
type text requiredtype of the variable, must refer to types definedin jbpm.variable.types.xml
init-exprtext (EL
expression) optional
value for the variable, this attribute or nested
element must be given
init-expr-type text UEL optional defines language for expression evaluation
history boolean false optional
indicates wheater variable should be stored inhistory or not - default false, for moreinformation about history see Section 7.5,
“Variables history”
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
72 de 75 08/09/2010 14:51
Table 7.2. Nested element for variable:
Element Multiplicity Description
object 1Value for the variable as custom object, either this element or init-expr
attribute must be specified
7.5. Variables history
(Since jBPM 4.4)
Variables can be marked to be persisted as history records. This means that once process instance is ended
and its runtime information is removed, history details are preserved.
History can be enabled for variable in two ways:
via public API ExecutionService:
void createVariable(String executionId, String name, Object value, boolean historyEnabled);
void createVariables(String executionId, Map<String, ?> variables, boolean historyEnabled);
on variable declaration
<variable name="declaredVar" type="string" init-expr="testing declared variable" his
Currently all variables are persisted in history as String values. Variable (regardless of its type) will be
converted to a string value using toString() method. In case of custom objects they should override
toString() method to provide string representation of the variable that will be available as history record.
This will provide an easy way for enabling convienient search capabilities based on variable values.
Access to history variables is given via HistoryService methods:
Object getVariable(String processInstnceId, String name);
Map<String, Object> getVariables(String processInstnceId, Set<String> variableNames);
Set<String> getVariableNames(String processInstnceId);
Chapter 8. Scripting
Only jUEL is configured as the scripting language. jUEL is an implementation of the Unified Expression
Language. For detailed description of how to use UEL, please refer to the JEE 5 Tutorial, section UnifiedExpression Language
To configure other scripting languages then jUEL, please refer to the developer's guide (non supported).
Chapter 9. Configuration
9.1. Business calendar
9.2. Console9.3. Email
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
73 de 75 08/09/2010 14:51
9.1. Business calendar
To customize the business calendar configuration, remove the default business calendar configuration import
and replace it with the custom values.
<jbpm-configuration>
<import resource="jbpm.businesscalendar.cfg.xml" /> ...
<process-engine-context> <business-calendar> <monday hours="9:00-18:00"/> <tuesday hours="9:00-18:00"/> <wednesday hours="9:00-18:00"/> <thursday hours="9:00-18:00"/> <friday hours="9:00-18:00"/> <holiday period="01/02/2009 - 31/10/2009"/> </business-calendar> </process-engine-context>
</jbpm-configuration>
9.2. Console
By default the server host and port of the console web app are respectively localhost and 8080. It is not
hard to imagine situations where it is needed to change those defaults. Hence they are made configurable.To customize, change the values of the default configuration (e.g. in the file "jbpm.console.cfg.xml") andreplace them with the values you want.
<jbpm-configuration>
<process-engine-context> <string name="jbpm.console.server.host" value="myNewHost"> <string name="jbpm.console.server.port" value="9191"> </process-engine-context>
</jbpm-configuration>
9.3. Email
The default configuration looks for a jbpm.mail.properties classpath resource containing JavaMail
properties. To send mail through a server other than local host, set the mail.smtp.host property in the mail
properties file.
mail.smtp.host=localhostmail.smtp.port=25mail.from=noreply@jbpm.org
If the SMTP server requires authentication, the application can supply a custom authenticator in theconfiguration file.
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
74 de 75 08/09/2010 14:51
<mail-session> <mail-server> <session-properties resource="jbpm.mail.properties" /> <authenticator class='BasicAuthenticator'> <field name='userName'><string value='aguizar'/></field> <field name='password'><string value='wontsay'/></field> </authenticator> </mail-server></mail-session>
In Java EE environments it is often the case that a mail session is already configured and bound to JNDI. Toemploy such a session, specify its JNDI name in the configuration file.
<mail-session> <mail-server session-jndi='java:comp/env/mail/smtp' /></mail-session>
Important
If present, the session JNDI name has precedence over the session properties and theauthenticator. The combined absence of session-properties and session-jndi constitutes an
error.
Refer to the Developer Guide for advanced, yet unsupported, email settings.
jBPM User Guide http://docs.jboss.com/jbpm/v4/userguide/html_single/#thedistribution
75 de 75 08/09/2010 14:51