Author: tom.baeyens(a)jboss.com
Date: 2009-06-02 07:30:44 -0400 (Tue, 02 Jun 2009)
New Revision: 4972
Added:
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch03-GraphicalProcessDesigner.xml
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch04-DeployingBusinessArchives.xml
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch05-Services.xml
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch06-Jpdl.xml
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch07-Variables.xml
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch08-Scripting.xml
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch09-Identity.xml
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch10-JBossIntegration.xml
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch11-Emails.xml
Removed:
jbpm4/trunk/modules/examples/scripts/
jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/esb/
jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/activity/EsbActivity.java
jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/activity/EsbBinding.java
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch03-Gpd.xml
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch04-Services.xml
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch05-Jpdl.xml
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch06-Variables.xml
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch07-Scripting.xml
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch08-Identity.xml
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch09-JBossIntegration.xml
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch10-Emails.xml
Modified:
jbpm4/trunk/modules/api/src/main/resources/jpdl-4.0.xsd
jbpm4/trunk/modules/distro/src/main/files/examples/build.xml
jbpm4/trunk/modules/examples/jbpm4-examples.iml
jbpm4/trunk/modules/examples/pom.xml
jbpm4/trunk/modules/jpdl/pom.xml
jbpm4/trunk/modules/jpdl/src/main/resources/jbpm.jpdl.activities.xml
jbpm4/trunk/modules/jpdl/src/main/resources/jbpm.jpdl.eventlisteners.xml
jbpm4/trunk/modules/jpdl/src/main/resources/jbpm.jpdl.hbm.xml
jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/ant/JbpmDeployTask.java
jbpm4/trunk/modules/userguide/src/main/docbook/en/master.xml
Log:
JBPM-2282 JBPM-2228 remove esb activity and document business archive deployment
Modified: jbpm4/trunk/modules/api/src/main/resources/jpdl-4.0.xsd
===================================================================
--- jbpm4/trunk/modules/api/src/main/resources/jpdl-4.0.xsd 2009-06-02 10:19:40 UTC (rev
4971)
+++ jbpm4/trunk/modules/api/src/main/resources/jpdl-4.0.xsd 2009-06-02 11:30:44 UTC (rev
4972)
@@ -325,23 +325,6 @@
</complexType>
</element>
- <!-- ~~~ ESB ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
- <element name="esb">
- <annotation><documentation>Invokes a service over the ESB.
- </documentation></annotation>
- <complexType>
- <complexContent>
- <extension base="tns:esbType">
- <sequence>
- <element ref="tns:on" minOccurs="0"
maxOccurs="unbounded"/>
- <element ref="tns:transition" minOccurs="0"
maxOccurs="unbounded" />
- </sequence>
- <attributeGroup ref="tns:activityAttributes" />
- </extension>
- </complexContent>
- </complexType>
- </element>
-
<!-- ~~~ TASK ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<element name="task">
<annotation><documentation>Creates a task in the task component.
@@ -573,38 +556,6 @@
</attribute>
</complexType>
- <complexType name="esbType">
- <sequence>
- <element name="part" minOccurs="0"
maxOccurs="unbounded">
- <annotation><documentation>The content of this expression element
- is the script text that will be evaluated. This is mutually
- exclusive with the expression
attribute.</documentation></annotation>
- <complexType>
- <choice minOccurs="0">
- <group ref="tns:wireObjectGroup" />
- </choice>
- <attribute name="name" type="string">
- <annotation><documentation>The name of the message body part.
- </documentation></annotation>
- </attribute>
- <attribute name="expr" type="string">
- <annotation><documentation>The script text that will be evaluated
and
- used and the object in this message body part.
- </documentation></annotation>
- </attribute>
- </complexType>
- </element>
- </sequence>
- <attribute name="category" type="string">
- <annotation><documentation>The category of the service in the esb.
- </documentation></annotation>
- </attribute>
- <attribute name="service" type="string">
- <annotation><documentation>The name of the service in the esb.
- </documentation></annotation>
- </attribute>
- </complexType>
-
<attributeGroup name="activityAttributes">
<attribute name="name" type="string">
<annotation><documentation>The id of this activity. The name should be
unique
@@ -764,7 +715,6 @@
<element name="sql" type="tns:qlType" />
<element name="java" type="tns:javaType" />
<element name="script" type="tns:scriptType" />
- <element name="esb" type="tns:esbType" />
</choice>
</group>
Modified: jbpm4/trunk/modules/distro/src/main/files/examples/build.xml
===================================================================
--- jbpm4/trunk/modules/distro/src/main/files/examples/build.xml 2009-06-02 10:19:40 UTC
(rev 4971)
+++ jbpm4/trunk/modules/distro/src/main/files/examples/build.xml 2009-06-02 11:30:44 UTC
(rev 4972)
@@ -53,7 +53,6 @@
<exclude name="org/jbpm/examples/task/candidates/process.jpdl.xml"
/>
<exclude
name="org/jbpm/examples/concurrency/graphbased/process.jpdl.xml" />
<exclude name="org/jbpm/examples/timer/repeat/process.jpdl.xml"
/>
- <exclude name="org/jbpm/examples/esb/process.jpdl.xml" />
<exclude name="org/jbpm/examples/script/text/process.jpdl.xml"
/>
<exclude name="org/jbpm/examples/decision/handler/process.jpdl.xml"
/>
<exclude name="org/jbpm/examples/mail/template/process.jpdl.xml"
/>
Modified: jbpm4/trunk/modules/examples/jbpm4-examples.iml
===================================================================
--- jbpm4/trunk/modules/examples/jbpm4-examples.iml 2009-06-02 10:19:40 UTC (rev 4971)
+++ jbpm4/trunk/modules/examples/jbpm4-examples.iml 2009-06-02 11:30:44 UTC (rev 4972)
@@ -33,15 +33,6 @@
</library>
</orderEntry>
<orderEntry type="module-library" exported="">
- <library name="M2 Dep:
org.jbpm.jbpm4.dependencies.esb:jbossesb-rosetta:jar:4.4.0.GA:compile">
- <CLASSES>
- <root
url="jar://$MODULE_DIR$/../../../../../../../.m2/repository/org/jbpm/jbpm4/dependencies/esb/jbossesb-rosetta/4.4.0.GA/jbossesb-rosetta-4.4.0.GA.jar!/"
/>
- </CLASSES>
- <JAVADOC />
- <SOURCES />
- </library>
- </orderEntry>
- <orderEntry type="module-library" exported="">
<library name="M2 Dep: stax:stax-api:jar:1.0.1:compile">
<CLASSES>
<root
url="jar://$MODULE_DIR$/../../../../../../../.m2/repository/stax/stax-api/1.0.1/stax-api-1.0.1.jar!/"
/>
@@ -268,15 +259,6 @@
</library>
</orderEntry>
<orderEntry type="module-library" exported="">
- <library name="M2 Dep:
org.jbpm.jbpm4.dependencies.esb:test-util:jar:4.4.0.GA:compile">
- <CLASSES>
- <root
url="jar://$MODULE_DIR$/../../../../../../../.m2/repository/org/jbpm/jbpm4/dependencies/esb/test-util/4.4.0.GA/test-util-4.4.0.GA.jar!/"
/>
- </CLASSES>
- <JAVADOC />
- <SOURCES />
- </library>
- </orderEntry>
- <orderEntry type="module-library" exported="">
<library name="M2 Dep:
org.subethamail:subethasmtp-smtp:jar:1.2:compile">
<CLASSES>
<root
url="jar://$MODULE_DIR$/../../../../../../../.m2/repository/org/subethamail/subethasmtp-smtp/1.2/subethasmtp-smtp-1.2.jar!/"
/>
Modified: jbpm4/trunk/modules/examples/pom.xml
===================================================================
--- jbpm4/trunk/modules/examples/pom.xml 2009-06-02 10:19:40 UTC (rev 4971)
+++ jbpm4/trunk/modules/examples/pom.xml 2009-06-02 11:30:44 UTC (rev 4972)
@@ -63,14 +63,6 @@
</dependency>
<dependency>
- <groupId>org.jbpm.jbpm4.dependencies.esb</groupId>
- <artifactId>jbossesb-rosetta</artifactId>
- </dependency>
- <dependency>
- <groupId>org.jbpm.jbpm4.dependencies.esb</groupId>
- <artifactId>test-util</artifactId>
- </dependency>
- <dependency>
<groupId>org.subethamail</groupId>
<artifactId>subethasmtp-wiser</artifactId>
</dependency>
@@ -213,7 +205,6 @@
<exclude>org/jbpm/examples/task/swimlane/TaskSwimlaneTest.java</exclude>
<exclude>org/jbpm/examples/concurrency/graphbased/ConcurrencyGraphBasedTest.java</exclude>
<exclude>org/jbpm/examples/task/candidates/TaskCandidatesTest.java</exclude>
- <exclude>org/jbpm/examples/esb/EsbTest.java</exclude>
<exclude>org/jbpm/examples/mail/template/TemplateMailTest.java</exclude>
<exclude>org/jbpm/examples/mail/inline/InlineMailTest.java</exclude>
<exclude>org/jbpm/examples/eventlistener/EventListenerTest.java</exclude>
Modified: jbpm4/trunk/modules/jpdl/pom.xml
===================================================================
--- jbpm4/trunk/modules/jpdl/pom.xml 2009-06-02 10:19:40 UTC (rev 4971)
+++ jbpm4/trunk/modules/jpdl/pom.xml 2009-06-02 11:30:44 UTC (rev 4972)
@@ -48,21 +48,6 @@
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
- <dependency>
- <groupId>org.jbpm.jbpm4.dependencies.esb</groupId>
- <artifactId>jbossesb-rosetta</artifactId>
- <exclusions>
- <exclusion>
- <groupId>stax</groupId>
- <artifactId>stax-api</artifactId>
- </exclusion>
- <exclusion>
- <groupId>stax</groupId>
- <artifactId>stax</artifactId>
- </exclusion>
- </exclusions>
- <scope>provided</scope>
- </dependency>
</dependencies>
<!-- Plugins -->
Deleted:
jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/activity/EsbActivity.java
===================================================================
---
jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/activity/EsbActivity.java 2009-06-02
10:19:40 UTC (rev 4971)
+++
jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/activity/EsbActivity.java 2009-06-02
11:30:44 UTC (rev 4972)
@@ -1,81 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2005, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
- */
-package org.jbpm.jpdl.internal.activity;
-
-import org.jboss.soa.esb.client.ServiceInvoker;
-import org.jboss.soa.esb.message.Body;
-import org.jboss.soa.esb.message.Message;
-import org.jboss.soa.esb.message.format.MessageFactory;
-import org.jbpm.api.model.OpenExecution;
-import org.jbpm.internal.log.Log;
-import org.jbpm.pvm.internal.model.ExpressionEvaluator;
-import org.jbpm.pvm.internal.wire.Descriptor;
-import org.jbpm.pvm.internal.wire.WireContext;
-import org.jbpm.pvm.internal.wire.descriptor.ListDescriptor;
-
-
-/**
- * @author Tom Baeyens
- */
-public class EsbActivity extends JpdlAutomaticActivity {
-
- private static final long serialVersionUID = 1L;
-
- private static Log log = Log.getLog(EsbActivity.class.getName());
-
- protected String category = null;
- protected String service = null;
- protected ListDescriptor partsListDescriptor = null;
-
- public void perform(OpenExecution execution) throws Exception {
- Message message = MessageFactory.getInstance().getMessage();
- Body body = message.getBody();
-
- if (partsListDescriptor!=null) {
- WireContext wireContext = new WireContext();
- for (Descriptor descriptor: partsListDescriptor.getValueDescriptors()) {
- String name = descriptor.getName();
-
- Object object = wireContext.create(descriptor, true);
- if (object instanceof ExpressionEvaluator) {
- ExpressionEvaluator expressionEvaluator = (ExpressionEvaluator) object;
- object = expressionEvaluator.evaluateExpression(execution);
- }
- body.add(name, object);
- }
- }
-
- ServiceInvoker invoker = new ServiceInvoker(category, service);
- log.debug("sending "+message.getBody()+" to service
"+service+" in category "+category+" over the esb");
- invoker.deliverAsync(message);
- }
-
- public void setCategory(String category) {
- this.category = category;
- }
- public void setService(String service) {
- this.service = service;
- }
- public void setPartsListDescriptor(ListDescriptor partsListDescriptor) {
- this.partsListDescriptor = partsListDescriptor;
- }
-}
Deleted:
jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/activity/EsbBinding.java
===================================================================
---
jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/activity/EsbBinding.java 2009-06-02
10:19:40 UTC (rev 4971)
+++
jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/activity/EsbBinding.java 2009-06-02
11:30:44 UTC (rev 4972)
@@ -1,95 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2005, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
- */
-package org.jbpm.jpdl.internal.activity;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.jbpm.pvm.internal.util.XmlUtil;
-import org.jbpm.pvm.internal.wire.Descriptor;
-import org.jbpm.pvm.internal.wire.descriptor.AbstractDescriptor;
-import org.jbpm.pvm.internal.wire.descriptor.ExpressionEvaluatorDescriptor;
-import org.jbpm.pvm.internal.wire.descriptor.ListDescriptor;
-import org.jbpm.pvm.internal.wire.xml.WireParser;
-import org.jbpm.pvm.internal.xml.Parse;
-import org.jbpm.pvm.internal.xml.Parser;
-import org.w3c.dom.Element;
-
-
-/**
- * @author Tom Baeyens
- */
-public class EsbBinding extends JpdlBinding {
-
- public static final String TAG = "esb";
- private static final WireParser wireParser = WireParser.getInstance();
-
- public EsbBinding() {
- super(TAG);
- }
-
- public Object parse(Element element, Parse parse, Parser parser) {
- EsbActivity esbActivity = new EsbActivity();
-
- String category = XmlUtil.attribute(element, "category", true, parse);
- esbActivity.setCategory(category);
-
- String service = XmlUtil.attribute(element, "service", true, parse);
- esbActivity.setService(service);
-
- List<Descriptor> partDescriptors = new ArrayList<Descriptor>();
- List<Element> partElements = XmlUtil.elements(element, "part");
- for (Element partElement: partElements) {
- String name = XmlUtil.attribute(partElement, "name", true, parse);
- AbstractDescriptor partDescriptor = getPartDescriptor(partElement, parse);
- partDescriptor.setName(name);
- partDescriptors.add(partDescriptor);
- }
- ListDescriptor partsListDescriptor = new ListDescriptor();
- if (!partDescriptors.isEmpty()) {
- partsListDescriptor.setValueDescriptors(partDescriptors);
- }
- esbActivity.setPartsListDescriptor(partsListDescriptor);
-
- return esbActivity;
- }
-
- public AbstractDescriptor getPartDescriptor(Element partElement, Parse parse) {
- String expression = XmlUtil.attribute(partElement, "expr");
- Element descriptorElement = XmlUtil.element(partElement);
-
- if ( ( (expression==null) && (descriptorElement==null) )
- ||
- ( (expression!=null) && (descriptorElement!=null) )
- ) {
- parse.addProblem("in <"+TAG+"...> an expr or exactly one child
element is expected");
- }
-
- if (expression!=null) {
- return new ExpressionEvaluatorDescriptor(expression, null);
- }
-
- AbstractDescriptor descriptor = (AbstractDescriptor)
wireParser.parseElement(descriptorElement, parse, WireParser.CATEGORY_DESCRIPTOR);
- return descriptor;
- }
-
-}
Modified: jbpm4/trunk/modules/jpdl/src/main/resources/jbpm.jpdl.activities.xml
===================================================================
--- jbpm4/trunk/modules/jpdl/src/main/resources/jbpm.jpdl.activities.xml 2009-06-02
10:19:40 UTC (rev 4971)
+++ jbpm4/trunk/modules/jpdl/src/main/resources/jbpm.jpdl.activities.xml 2009-06-02
11:30:44 UTC (rev 4972)
@@ -11,7 +11,6 @@
<activity binding="org.jbpm.jpdl.internal.activity.SqlBinding" />
<activity binding="org.jbpm.jpdl.internal.activity.JavaBinding" />
<activity binding="org.jbpm.jpdl.internal.activity.ScriptBinding" />
- <activity binding="org.jbpm.jpdl.internal.activity.EsbBinding" />
<activity binding="org.jbpm.jpdl.internal.activity.TaskBinding" />
<activity binding="org.jbpm.jpdl.internal.activity.SubProcessBinding"
/>
<activity binding="org.jbpm.jpdl.internal.activity.MailBinding" />
Modified: jbpm4/trunk/modules/jpdl/src/main/resources/jbpm.jpdl.eventlisteners.xml
===================================================================
--- jbpm4/trunk/modules/jpdl/src/main/resources/jbpm.jpdl.eventlisteners.xml 2009-06-02
10:19:40 UTC (rev 4971)
+++ jbpm4/trunk/modules/jpdl/src/main/resources/jbpm.jpdl.eventlisteners.xml 2009-06-02
11:30:44 UTC (rev 4972)
@@ -1,7 +1,6 @@
<eventlisteners>
<eventlistener
binding="org.jbpm.jpdl.internal.activity.EventListenerBinding" />
<eventlistener binding="org.jbpm.jpdl.internal.activity.JavaBinding"
/>
- <eventlistener binding="org.jbpm.jpdl.internal.activity.EsbBinding" />
<eventlistener binding="org.jbpm.jpdl.internal.activity.HqlBinding" />
<eventlistener binding="org.jbpm.jpdl.internal.activity.SqlBinding" />
<eventlistener binding="org.jbpm.jpdl.internal.activity.ScriptBinding"
/>
Modified: jbpm4/trunk/modules/jpdl/src/main/resources/jbpm.jpdl.hbm.xml
===================================================================
--- jbpm4/trunk/modules/jpdl/src/main/resources/jbpm.jpdl.hbm.xml 2009-06-02 10:19:40 UTC
(rev 4971)
+++ jbpm4/trunk/modules/jpdl/src/main/resources/jbpm.jpdl.hbm.xml 2009-06-02 11:30:44 UTC
(rev 4972)
@@ -3,27 +3,6 @@
<hibernate-mapping default-access="field">
- <!-- subclass name="org.jbpm.jpdl.internal.model.JpdlProcessDefinition"
- extends="org.jbpm.pvm.internal.model.ProcessDefinitionImpl"
- discriminator-value="jpdl">
- <map name="swimlaneDefinitions"
- cascade="all-delete-orphan">
- <key foreign-key="FK_SWLDEF_PROCESS">
- <column name="PROCESS_SWL_"
index="IDX_SWLDEF_PROCESS"/>
- </key>
- <map-key type="string" column="NAME_" />
- <one-to-many class="org.jbpm.pvm.internal.task.SwimlaneDefinitionImpl"
/>
- </map>
- <map name="taskDefinitions"
- cascade="all-delete-orphan">
- <key foreign-key="FK_TSKDEF_PROCESS">
- <column name="PROCESS_" index="IDX_TSKDEF_PROCESS"/>
- </key>
- <map-key type="string" column="NAME_" />
- <one-to-many class="org.jbpm.pvm.internal.task.TaskDefinitionImpl"
/>
- </map>
- </subclass -->
-
<subclass name="org.jbpm.jpdl.internal.model.JpdlExecution"
extends="org.jbpm.pvm.internal.model.ExecutionImpl"
discriminator-value="jpdl">
@@ -38,86 +17,4 @@
</map>
</subclass>
- <!-- class name="org.jbpm.jpdl.internal.activity.JpdlActivity"
table="JBPM4_JPDL_ACTIVITY" abstract="true"
discriminator-value="X">
- <id name="dbid" column="DBID_">
- <generator class="native" />
- </id>
- <discriminator column="CLASS_" />
- <subclass name="org.jbpm.jpdl.internal.activity.StartActivity"
discriminator-value="start" />
- <subclass
name="org.jbpm.jpdl.internal.activity.DecisionConditionActivity"
discriminator-value="excl-cond" />
- <subclass
name="org.jbpm.jpdl.internal.activity.DecisionExpressionActivity"
discriminator-value="excl-expr">
- <property name="expr" column="TEXT_" />
- <property name="lang" column="TEXT2_" />
- </subclass>
- <subclass name="org.jbpm.jpdl.internal.activity.DecisionHandlerActivity"
discriminator-value="excl-handler">
- <property name="decisionHandlerName" column="TEXT_" />
- <many-to-one name="decisionHandlerDescriptor"
- column="EXCLDESCR_"
- cascade="all"
-
class="org.jbpm.pvm.internal.wire.descriptor.AbstractDescriptor"
- foreign-key="FK_ACT_EXCLDESCR"
- index="IDX_ACT_EXCLDESCR" />
- </subclass>
- <subclass name="org.jbpm.jpdl.internal.activity.StateActivity"
discriminator-value="state" />
- <subclass name="org.jbpm.jpdl.internal.activity.EndActivity"
discriminator-value="end">
- <property name="endProcessInstance" column="ENDPI_" />
- <property name="state" column="TEXT_" />
- </subclass>
- <subclass name="org.jbpm.jpdl.internal.activity.ForkActivity"
discriminator-value="fork" />
- <subclass name="org.jbpm.jpdl.internal.activity.JoinActivity"
discriminator-value="join" />
- <subclass name="org.jbpm.jpdl.internal.activity.HqlActivity"
discriminator-value="hql">
- <property name="query" column="TEXT_" />
- <property name="resultVariableName" column="TEXT2_" />
- <property name="isResultUnique" column="ISUNIQ_" />
- <many-to-one name="parametersDescriptor"
- column="PARAMDESCR_"
- cascade="all"
-
class="org.jbpm.pvm.internal.wire.descriptor.ListDescriptor"
- foreign-key="FK_ACT_PARAMDESCR"
- index="IDX_ACT_PARAMDESCR" />
-
- <subclass name="org.jbpm.jpdl.internal.activity.SqlActivity"
discriminator-value="sql" />
- </subclass>
- <subclass name="org.jbpm.jpdl.internal.activity.JavaActivity"
discriminator-value="java">
- <property name="methodName" column="TEXT_" />
- <property name="variableName" column="TEXT2_" />
- <many-to-one name="descriptor"
- column="JAVADESCR_"
- cascade="all"
-
class="org.jbpm.pvm.internal.wire.descriptor.AbstractDescriptor"
- foreign-key="FK_ACT_JAVADESCR"
- index="IDX_ACT_JAVADESCR" />
- <many-to-one name="invokeOperation"
- column="INVOPER_"
- cascade="all"
-
class="org.jbpm.pvm.internal.wire.operation.InvokeOperation"
- foreign-key="FK_ACT_INVKOPER"
- index="IDX_ACT_INVKOPER" />
- </subclass>
- <subclass name="org.jbpm.jpdl.internal.activity.ScriptActivity"
discriminator-value="script">
- <property name="script" column="TEXT_" />
- <property name="language" column="TEXT2_" />
- <property name="variableName" column="TEXT3_" />
- </subclass>
- <subclass name="org.jbpm.jpdl.internal.activity.EsbActivity"
discriminator-value="esb">
- <property name="service" column="TEXT_" />
- <property name="category" column="TEXT2_" />
- <many-to-one name="partsListDescriptor"
- column="PARTSDESCR_"
- cascade="all"
- class="org.jbpm.pvm.internal.wire.descriptor.ListDescriptor"
- foreign-key="FK_ACT_PARTSDESCR"
- index="IDX_ACT_PARTSDESCR" />
- </subclass>
- <subclass name="org.jbpm.jpdl.internal.activity.TaskActivity"
discriminator-value="task">
- <many-to-one name="taskDefinition"
- column="TASKDEF_"
- cascade="all"
- class="org.jbpm.pvm.internal.task.TaskDefinitionImpl"
- foreign-key="FK_ACT_TASKDEF"
- index="IDX_ACT_TASKDEF" />
- </subclass>
- </class>
- -->
-
</hibernate-mapping>
\ No newline at end of file
Modified:
jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/ant/JbpmDeployTask.java
===================================================================
---
jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/ant/JbpmDeployTask.java 2009-06-02
10:19:40 UTC (rev 4971)
+++
jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/ant/JbpmDeployTask.java 2009-06-02
11:30:44 UTC (rev 4972)
@@ -83,7 +83,7 @@
}
}
- private void deployFile(ProcessEngine processEngine, File processFile) {
+ protected void deployFile(ProcessEngine processEngine, File processFile) {
RepositoryService repositoryService = processEngine.getRepositoryService();
Deployment deployment = repositoryService.createDeployment();
deployment.setName(processFile.getName());
Modified: jbpm4/trunk/modules/userguide/src/main/docbook/en/master.xml
===================================================================
--- jbpm4/trunk/modules/userguide/src/main/docbook/en/master.xml 2009-06-02 10:19:40 UTC
(rev 4971)
+++ jbpm4/trunk/modules/userguide/src/main/docbook/en/master.xml 2009-06-02 11:30:44 UTC
(rev 4972)
@@ -3,14 +3,15 @@
<!DOCTYPE book [
<!ENTITY ch01-Introduction SYSTEM
"modules/ch01-Introduction.xml">
<!ENTITY ch02-Installation SYSTEM
"modules/ch02-Installation.xml">
- <!ENTITY ch03-Gpd SYSTEM "modules/ch03-Gpd.xml">
- <!ENTITY ch04-Services SYSTEM "modules/ch04-Services.xml">
- <!ENTITY ch05-Jpdl SYSTEM "modules/ch05-Jpdl.xml">
- <!ENTITY ch06-Variables SYSTEM "modules/ch06-Variables.xml">
- <!ENTITY ch07-Scripting SYSTEM "modules/ch07-Scripting.xml">
- <!ENTITY ch08-Identity SYSTEM "modules/ch08-Identity.xml">
- <!ENTITY ch09-JBossIntegration SYSTEM
"modules/ch09-JBossIntegration.xml">
- <!ENTITY ch10-Emails SYSTEM "modules/ch10-Emails.xml">
+ <!ENTITY ch03-GraphicalProcessDesigner SYSTEM
"modules/ch03-GraphicalProcessDesigner.xml">
+ <!ENTITY ch04-DeployingBusinessArchives SYSTEM
"modules/ch04-DeployingBusinessArchives.xml">
+ <!ENTITY ch05-Services SYSTEM "modules/ch05-Services.xml">
+ <!ENTITY ch06-Jpdl SYSTEM "modules/ch06-Jpdl.xml">
+ <!ENTITY ch07-Variables SYSTEM "modules/ch07-Variables.xml">
+ <!ENTITY ch08-Scripting SYSTEM "modules/ch08-Scripting.xml">
+ <!ENTITY ch09-Identity SYSTEM "modules/ch09-Identity.xml">
+ <!ENTITY ch10-JBossIntegration SYSTEM
"modules/ch10-JBossIntegration.xml">
+ <!ENTITY ch11-Emails SYSTEM "modules/ch11-Emails.xml">
]>
<book lang="en">
@@ -23,13 +24,14 @@
&ch01-Introduction;
&ch02-Installation;
- &ch03-Gpd;
- &ch04-Services;
- &ch05-Jpdl;
- &ch06-Variables;
- &ch07-Scripting;
- &ch08-Identity;
- &ch09-JBossIntegration;
- &ch10-Emails;
+ &ch03-GraphicalProcessDesigner;
+ &ch04-DeployingBusinessArchives;
+ &ch05-Services;
+ &ch06-Jpdl;
+ &ch07-Variables;
+ &ch08-Scripting;
+ &ch09-Identity;
+ &ch10-JBossIntegration;
+ &ch11-Emails;
</book>
\ No newline at end of file
Deleted: jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch03-Gpd.xml
===================================================================
--- jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch03-Gpd.xml 2009-06-02
10:19:40 UTC (rev 4971)
+++ jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch03-Gpd.xml 2009-06-02
11:30:44 UTC (rev 4972)
@@ -1,44 +0,0 @@
-<chapter id="gpd">
- <title>GPD</title>
-
- <para>This chapter will explain how to work with the Graphical Process Designer.
- After installing the GPD and setting up the examples, you'll see that the
- jPDL process files will get a special icon. Double clicking such a file
- in the package view will open up the jPDL process in the GPD.
- </para>
- <figure id="gpd">
- <title>The GPD</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/gpd.png"/></imageobject></mediaobject>
- </figure>
-
- <section id="creatingnewprocessfile">
- <title>Creating a new process file</title>
- <para>CRTL+N will open up the wizard selector.
- </para>
- <figure id="gpd.new.process.wizard">
- <title>Select wizard dialog</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/gpd.new.process.wizard.png"/></imageobject></mediaobject>
- </figure>
- <para>Select jBPM --> jPDL 4 File. Click 'Next >'. Then the
- 'New jPDL 4 File' wizard opens.
- </para>
- <figure id="gpd.new.process.file">
- <title>Create a new process dialog</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/gpd.new.process.file.png"/></imageobject></mediaobject>
- </figure>
- <para>Select the parent directory, enter a file name and click
'Finish'. Voila,
- you've created your first jPDL process file.
- </para>
- </section>
-
- <section id="editingtheprocesssource">
- <title>Editing the process source</title>
- <para>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.</para>
- <figure id="gpd.source.tab">
- <title>Editing jPDL using the source view</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/gpd.xml.view.png"/></imageobject></mediaobject>
- </figure>
- </section>
-
-</chapter>
Copied:
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch03-GraphicalProcessDesigner.xml
(from rev 4967, jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch03-Gpd.xml)
===================================================================
---
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch03-GraphicalProcessDesigner.xml
(rev 0)
+++
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch03-GraphicalProcessDesigner.xml 2009-06-02
11:30:44 UTC (rev 4972)
@@ -0,0 +1,44 @@
+<chapter id="graphicalprocessdesigner">
+ <title>Graphical Process Designer (GPD)</title>
+
+ <para>This chapter will explain how to work with the Graphical Process Designer.
+ After installing the GPD and setting up the examples, you'll see that the
+ jPDL process files will get a special icon. Double clicking such a file
+ in the package view will open up the jPDL process in the GPD.
+ </para>
+ <figure id="gpd">
+ <title>The GPD</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/gpd.png"/></imageobject></mediaobject>
+ </figure>
+
+ <section id="creatingnewprocessfile">
+ <title>Creating a new process file</title>
+ <para>CRTL+N will open up the wizard selector.
+ </para>
+ <figure id="gpd.new.process.wizard">
+ <title>Select wizard dialog</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/gpd.new.process.wizard.png"/></imageobject></mediaobject>
+ </figure>
+ <para>Select jBPM --> jPDL 4 File. Click 'Next >'. Then the
+ 'New jPDL 4 File' wizard opens.
+ </para>
+ <figure id="gpd.new.process.file">
+ <title>Create a new process dialog</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/gpd.new.process.file.png"/></imageobject></mediaobject>
+ </figure>
+ <para>Select the parent directory, enter a file name and click
'Finish'. Voila,
+ you've created your first jPDL process file.
+ </para>
+ </section>
+
+ <section id="editingtheprocesssource">
+ <title>Editing the process source</title>
+ <para>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.</para>
+ <figure id="gpd.source.tab">
+ <title>Editing jPDL using the source view</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/gpd.xml.view.png"/></imageobject></mediaobject>
+ </figure>
+ </section>
+
+</chapter>
Property changes on:
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch03-GraphicalProcessDesigner.xml
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:mergeinfo
+
Name: svn:eol-style
+ LF
Added:
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch04-DeployingBusinessArchives.xml
===================================================================
---
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch04-DeployingBusinessArchives.xml
(rev 0)
+++
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch04-DeployingBusinessArchives.xml 2009-06-02
11:30:44 UTC (rev 4972)
@@ -0,0 +1,149 @@
+<chapter id="deployingbusinessarchives">
+ <title>Deploying business archives</title>
+
+ <para>A business archive is a collection of files
+ assembled in a jar formatted file. The files in
+ a business archive can be jPDL process files, forms,
+ process image and other process resources.
+ </para>
+
+ <section id="deployingprocessfilesandprocessresources">
+ <title>Deploying process files and process resources</title>
+
+ <para>Process files and process resources have to be
+ deployed in the process repository which is stored in
+ the database.
+ </para>
+
+ <para>There is a jBPM ant task to deploy business archives
+ (<literal>org.jbpm.pvm.internal.ant.JbpmDeployTask</literal>)
+ The <literal>JbpmDeployTask</literal> 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 can
+ deploy processes.
+ </para>
+
+ <para>An example of creating and deploying a business
+ archive can be found in the 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.
+ </para>
+
+ <programlisting><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></programlisting>
+
+ <para>The JDBC driver jar(s) for your database should also be included
+ in the path. MySql, Postgresql and hsqldb 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.
+ </para>
+
+ <para>When a business archive is deployed, jBPM scans for all the files
+ with the <literal>.jpdl.xml</literal> 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
+ <literal>InputStream getResourceAsStream(long deploymentDbid, String
resourceName);</literal>
+ in class <literal>RepositoryService</literal>
+ </para>
+
+ <para>For creating a business archives, the <literal>jar</literal>
task
+ can be used.
+ </para>
+
+ <programlisting><jar
destfile="${jbpm.home}/examples/target/examples.bar">
+ <fileset dir="${jbpm.home}/examples/src">
+ <include name="**/*.jpdl.xml" />
+ ...
+ </fileset>
+ </jar></programlisting>
+
+ <para>Before the jbpm-deploy task can be used it need to be declared like
this:</para>
+
+ <programlisting><taskdef name="jbpm-deploy"
+ classname="org.jbpm.pvm.internal.ant.JbpmDeployTask"
+ classpathref="jbpm.libs.incl.dependencies"
/></programlisting>
+
+ <para>Then the ant task can be used like this</para>
+
+ <programlisting>
+ <jbpm-deploy file="${jbpm.home}/examples/target/examples.bar"
/></programlisting>
+
+ <table><title><literal>jbpm-deploy</literal>
attributes:</title>
+ <tgroup cols="5" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Attribute</entry>
+ <entry>Type</entry>
+ <entry>Default</entry>
+ <entry>Required?</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>file</literal></entry>
+ <entry>file</entry>
+ <entry></entry>
+ <entry>optional</entry>
+ <entry>A file to be deployed. Files ending with
<literal>.xml</literal> will be deployed
+ as process files. Files ending with <literal>ar</literal> like
.bar or .jar
+ will be deployed as business archives.
+ </entry>
+ </row>
+ <row>
+ <entry><literal>cfg</literal></entry>
+ <entry>file</entry>
+ <entry>jbpm.cfg.xml</entry>
+ <entry>optional</entry>
+ <entry>Points to the jbpm configuration file that has to be on the
classpath in which
+ the <literal>jbpm-deploy</literal> task was defined.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table><title><literal>jbpm-deploy</literal>
elements:</title>
+ <tgroup cols="3" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Element</entry>
+ <entry>Multiplicity</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>fileset</literal></entry>
+ <entry>0..*</entry>
+ <entry>files to be deployed expressed as a plain ant fileset.
+ Files ending with <literal>.xml</literal> will be deployed
+ as process files. Files ending with <literal>ar</literal> like
.bar or .jar
+ will be deployed as business archives.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ </section>
+
+ <section id="deployingclasses">
+ <title>Deploying classes</title>
+ <para>jBPM 4 does not yet have a process classloading mechanism as in jBPM 3.
+ </para>
+ <para>All the classes that are referred to
+ in your process files, either directly or indirectly, need to be made available
+ on the classpath of your jBPM installation.
+ </para>
+ <para>In case of the examples, an examples.jar file is created with
+ all the classes and it is put in the <literal>lib</literal> directory of
the JBoss
+ server configuration.</para>
+ </section>
+
+</chapter>
Property changes on:
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch04-DeployingBusinessArchives.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Deleted: jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch04-Services.xml
===================================================================
--- jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch04-Services.xml 2009-06-02
10:19:40 UTC (rev 4971)
+++ jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch04-Services.xml 2009-06-02
11:30:44 UTC (rev 4972)
@@ -1,395 +0,0 @@
-<chapter id="services">
- <title>Services</title>
-
- <section id="processdefinitionprocessinstanceandexecutions">
- <title>Process definition, process instance and executions</title>
- <para>A process definition is description of the steps in a procedure.
- For example, an insurance company could have a <literal>loan</literal>
- process definition that describes the steps of how the company deals
- with loan requests.
- </para>
- <figure id="loan.process.definition.example">
- <title>The loan process definition example</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/loan.process.definition.png"/></imageobject></mediaobject>
- </figure>
- <para>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 process definition.
- </para>
- <para>A process instance contains all the runtime state. The
- most prominent property is the pointer that keeps track of the current activity.
- </para>
- <figure id="loan.process.instance.example">
- <title>The loan process instance example</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/loan.process.instance.png"/></imageobject></mediaobject>
- </figure>
- <para>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:
- </para>
- <figure id="loan.executions.example">
- <title>The loan executions example</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/loan.executions.png"/></imageobject></mediaobject>
- </figure>
- <para>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.
- </para>
- <para>The motivation to work with a tree structure like this is that
- this conceptually remains simple in the case where 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 both <literal>ProcessInstance</literal>s
and
- <literal>Execution</literal>s.
- </para>
- </section>
-
- <section id="processengine">
- <title>ProcessEngine</title>
- <para>Interacting with jBPM occurs through services.
- The service interfaces can be obtained from the
<literal>ProcessEngine</literal>
- which is build from a <literal>Configuration</literal>.
- </para>
- <para>A <literal>ProcessEngine</literal> is thread safe and can be
stored in a
- static member field or even better in JNDI or some other central location.
- One <literal>ProcessEngine</literal> object can be used by all requests
and
- threads in an application. Here's how you can obtain a
<literal>ProcessEngine</literal>
- </para>
-
- <para>The code snippets in this section and the next section about process
- deployments are taken from example
- <literal>org.jbpm.examples.services.ServicesTest</literal>
- </para>
-
- <programlisting>ProcessEngine processEngine = new Configuration()
- .buildProcessEngine();</programlisting>
-
- <para>The previous code snippet shows how to build a
<literal>ProcessEngine</literal>
- from the default configuration file <literal>jbpm.cfg.xml</literal> which
is
- expected in the root of the classpath. If you want to specify another
- resource location, use the <literal>setResource</literal> method like
this:
- </para>
-
- <programlisting>ProcessEngine processEngine = new Configuration()
- .setResource("my-own-configuration-file.xml")
- .buildProcessEngine();</programlisting>
-
- <para>There are other <literal>setXxxx</literal> methods that allow
to specify
- the configuration content as an <literal>InputStream</literal>, an
- <literal>xmlString</literal>, <literal>InputSource</literal>,
- <literal>URL</literal> or <literal>File</literal>.
- </para>
-
- <para>From a <literal>ProcessEngine</literal> the following
services
- can be obtained:
- </para>
-
- <programlisting><emphasis
role="bold">RepositoryService</emphasis> repositoryService =
processEngine.getRepositoryService();
-<emphasis role="bold">ExecutionService</emphasis> executionService
= processEngine.getExecutionService();
-<emphasis role="bold">TaskService</emphasis> taskService =
processEngine.getTaskService();
-<emphasis role="bold">HistoryService</emphasis> historyService =
processEngine.getHistoryService();
-<emphasis role="bold">ManagementService</emphasis>
managementService = processEngine.getManagementService();</programlisting>
-
- <para>Process engine objects defined in the configuration can also be retrieved
by
- type (<literal>processEngine.get(Class<T>)</literal>)
- or by name (<literal>processEngine.get(String)</literal>)</para>
-
- </section>
-
- <section id="deployingaprocess">
- <title>Deploying a process</title>
- <para>The <literal>RepositoryService</literal> groups all methods
to manage
- the repository of deployments. In this first example, we'll deploy one process
- resource from the classpath with the
<literal>RepositoryService</literal>:
- </para>
- <programlisting>long deploymentDbid = repositoryService.createDeployment()
- .addResourceFromClasspath("org/jbpm/examples/services/Order.jpdl.xml")
- .deploy();</programlisting>
- <para>Analogue to the <literal>addResourceFromClasspath</literal>
method above,
- the source of the processes definitions XML can be picked up from a file, url,
string,
- input stream or zip input stream.
- </para>
- <para>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
- <literal>.jpdl.xml</literal>. Other resource types are task forms and
java classes.
- </para>
- <para>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 <literal>.jpdl.xml</literal>
- extension automatically.
- </para>
- <para>During deployment, an <literal>id</literal> is assigned to
the process
- definitions. The <literal>id</literal> will have format
- <literal>{key}-{version}</literal> with a dash between key and version
- </para>
- <para>If <literal>key</literal> 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.
- </para>
- <para>The same <literal>name</literal> can only be associated to
one
- <literal>key</literal> and vice verca.
- </para>
- <para>If <literal>version</literal> is not provided, a
<literal>version</literal>
- 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 <literal>version</literal> will be
one higher
- then the highest <literal>version</literal> number of deployed process
definitions
- with the same <literal>key</literal>. If no process definitions with a
similar
- <literal>key</literal> have been deployed, version number 1 is assigned.
- </para>
- <para>In this first example, we'll supply a name and nothing
else.</para>
- <programlisting><process name="Insurance
claim">
-...
-</process></programlisting>
- <para>Let's assume that this is the first time that this process gets
deployed.
- Then it will get the following properties:
- </para>
- <table><title>Process properties without key</title>
- <tgroup cols="3" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Property</entry>
- <entry>Value</entry>
- <entry>Source</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>name</literal></entry>
- <entry>Insurance claim</entry>
- <entry>process xml</entry>
- </row>
- <row>
- <entry><literal>key</literal></entry>
- <entry>Insurance_claim</entry>
- <entry>generated</entry>
- </row>
- <row>
- <entry><literal>version</literal></entry>
- <entry>1</entry>
- <entry>generated</entry>
- </row>
- <row>
- <entry><literal>id</literal></entry>
- <entry>Insurance_claim:1</entry>
- <entry>generated</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>And as a second example, we'll show how you can get shorter ids by
- specifying a process key:</para>
- <programlisting><process name="Insurance claim"
key="ICL">
-...
-</process></programlisting>
- <para>Then the process definition properties look like this:</para>
- <table><title>Process properties with key</title>
- <tgroup cols="2" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Property</entry>
- <entry>Value</entry>
- <entry>Source</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>name</literal></entry>
- <entry>Insurance claim</entry>
- <entry>process xml</entry>
- </row>
- <row>
- <entry><literal>key</literal></entry>
- <entry>ICL</entry>
- <entry>process xml</entry>
- </row>
- <row>
- <entry><literal>version</literal></entry>
- <entry>1</entry>
- <entry>generated</entry>
- </row>
- <row>
- <entry><literal>id</literal></entry>
- <entry>ICL:1</entry>
- <entry>generated</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </section>
-
- <section id="undeployingdeployments">
- <title>Undeploying deployments</title>
- <para>TODO</para>
- </section>
-
- <section id="deletingadeployment">
- <title>Deleting a deployment</title>
- <para>Deleting a deployment will remove it from the DB.</para>
-
<programlisting>repositoryService.deleteDeployment(deploymentDbid);</programlisting>
- <para>That method will throw an exception when there are still active
- process executions for process definitions in that deployment.
- </para>
- <para>If you want to cascade deletion of a deployment to all
- the process instances of all the process definitions, use
- <literal>deleteDeploymentCascade</literal>.
- </para>
- </section>
-
- <section id="startinganewprocessinstance">
- <title>Starting a new process instance</title>
-
- <section id="inlatest">
- <title>In latest</title>
- <para>Simplest and most common way to start a new process instance for a
process
- definition is like this:
- </para>
-
<programlisting>executionService.startProcessInstanceByKey("ICL");</programlisting>
- <para>In this case, the service method will first look up the latest version
of
- the processes with key <literal>ICL</literal>. Then a new
- process instance is started in that latest process definition.
- </para>
- <para>When a new version of the insurance claim process
- is deployed, all invocations of
<literal>startProcessInstanceByKey</literal>
- will automatically switch to the newly deployed version.
- </para>
- </section>
-
- <section id="specificprocessversion">
- <title>Specific process version</title>
- <para>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:
- </para>
-
<programlisting>executionService.startProcessInstanceById("ICL-1");</programlisting>
- </section>
-
- <section id="withakey">
- <title>With a key</title>
- <para>A new process instance can optionally be given a key. A key is
- a user defined reference to the execution. A 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.
- </para>
- <programlisting>executionService.startProcessInstanceByKey("ICL",
"CL92837");</programlisting>
- <para>The key is used to create the id of the process instance.
- The format used is <literal>{process-key}.{execution-id}</literal>.
- With a dot between process-key and execution-id.
- So execution created in the previous code snippet will have id
- <literal>ICL.CL92837</literal>.
- </para>
- <para>If no user defined key is provided, the DB primary key is taken
- as the key. In that case, the id can be retrieved like this:
- <programlisting>Execution execution =
executionService.startProcessInstanceByKey("ICL");
-String executionId = execution.getId();</programlisting>
- </para>
- <para>We recommend the use of a user defined keys. Typically in your
application
- code, you'll have the key available. 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.
- </para>
- </section>
-
- <section id="withvariables">
- <title>With variables</title>
- <para>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 process instance.
- </para>
- <programlisting>Map<String,Object> variables = new
HashMap<String,Object>();
-variables.put("customer", "John Doe");
-variables.put("type", "Accident");
-variables.put("amount", new Float(763.74));
-
-executionService.startProcessInstanceByKey("ICL",
variables);</programlisting>
- </section>
- </section>
-
- <section id="singallingawaitingexecution">
- <title>Signalling a waiting execution</title>
- <para>A process definition describes what must be done in terms of activities.
- Each activity in a process is either to be performed by the process
- system or by an external participant. When an activity is to be performed
- by an external participant, then the execution must wait until the
- external participant notifies the process system that the activity is
- completed. So an execution is either executing or waiting on an external
- participant. Typically, you'll see that the processes are mostly
- waiting for external participations. Especially humans tend to be slow :-)
- The time consumed by the process system between two wait states is
- typically very small.
- </para>
- <para>A <literal>state</literal> is the basic activity that
represents
- something has to be done by an external participant and the execution
- must wait until a signal (aka external trigger) is given.
- </para>
- <para>When an execution is in a wait state, it can be given an external trigger
- with one of the signal methods. The recommended way to reference an execution
- is by using the process definition and execution key. In the next code snippet,
- <literal>ICL</literal> refers to the process definition key and
<literal>82436</literal>
- refers to the execution key.
- </para>
- <programlisting>executionService.signalExecutionByKey("ICL",
"82436");</programlisting>
- <para>Alternatively, the execution that must be signaled can be referenced
- by a unique execution id. In the next snippet,
<literal>ICL.82436</literal>
- refers to the executionId.</para>
-
<programlisting>executionService.signalExecutionById("ICL.82436");</programlisting>
- <para>Optionally some data can be passed along with a signal: a
<literal>signalName</literal>
- and <literal>parameters</literal>. How the signalName gets used depends
on
- the execution's current activity. The parameters get stored as process
variables.
- </para>
- <programlisting>Map<String,Object> parameters = new
HashMap<String,Object>();
-parameters.put("quality", "a+");
-parameters.put("target", "profit");
-
-executionService.signalExecutionById("ICL/82436", "Accept",
parameters);</programlisting>
- </section>
-
- <section id="taskservice">
- <title>TaskService</title>
- <para>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 <literal>johndoe</literal>.
- </para>
- <programlisting>List<Task> taskList =
taskService.findPersonalTasks("johndoe");</programlisting>
- <para>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.
- </para>
- <programlisting>long taskDbid = task.getDbid();
-
-Set<String> variableNames = taskService.getVariableNames(taskDbid);
-variables = taskService.getVariables(taskDbid, variableNames);
-
-variables = new HashMap<String, Object>();
-variables.put("category", "small");
-variables.put("lires", 923874893);
-taskService.setVariables(taskDbid, variables);</programlisting>
- <para>and complete tasks</para>
- <programlisting>taskService.completeTask(taskDbid);</programlisting>
- <para>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, other users
- will be blocked from taking the task.
- </para>
- <programlisting></programlisting>
- <para>
- People should not work on
- a task unless they are assigned to that task. The user interface should display
- forms 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'. Since taking a task boiles down to setting the
- assignee to the current user, we didn't introduce a separate method for that.
- </para>
- <para>More on tasks in <xref linkend="tasks" /> </para>
- </section>
-
- <section id="historyservice">
- <title>HistoryService</title>
- <para>TODO</para>
- </section>
-
- <section id="managementservice">
- <title>ManagementService</title>
- <para>TODO</para>
- </section>
-
-</chapter>
\ No newline at end of file
Deleted: jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch05-Jpdl.xml
===================================================================
--- jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch05-Jpdl.xml 2009-06-02
10:19:40 UTC (rev 4971)
+++ jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch05-Jpdl.xml 2009-06-02
11:30:44 UTC (rev 4972)
@@ -1,3113 +0,0 @@
-<chapter id="jpdl">
- <title>jPDL</title>
-
- <para>This chapter will explain the jPDL file format for describing
- process definitions. The schemadocs can also serve as a quick reference for this
- information.
- </para>
- <para>An example jPDL process file looks like this:
- </para>
- <programlisting><?xml version="1.0"
encoding="UTF-8"?>
-
-<process name="Purchase order"
xmlns="http://jbpm.org/4.0/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></programlisting>
-
- <section id="process">
- <title><literal>process</literal></title>
- <para>The top level element representing one process definition.
- </para>
- <table><title><literal>process</literal>
attributes:</title>
- <tgroup cols="5" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Attribute</entry>
- <entry>Type</entry>
- <entry>Default</entry>
- <entry>Required?</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>name</literal></entry>
- <entry>any text</entry>
- <entry></entry>
- <entry><emphasis
role="bold">required</emphasis></entry>
- <entry>name or label of the process used to display to the process
- name in user interactions.
- </entry>
- </row>
- <row>
- <entry><literal>key</literal></entry>
- <entry>alpha numeric characters and underscores</entry>
- <entry>if omitted, the key will be generated based on the name by
replacing
- all non-alpha-numeric characters with underscores</entry>
- <entry>optional</entry>
- <entry>identification to distinct different process definitions.
- Multiple versions of a process with the same key can be deployed.
- The key:name combination must remain exactly the same for all
- deployed versions.
- </entry>
- </row>
- <row>
- <entry><literal>version</literal></entry>
- <entry>integer</entry>
- <entry>one higher then highest version number starting with 1 if no
other process
- is deployed with the same name/key.
- </entry>
- <entry>optional</entry>
- <entry>version number of this process</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table><title><literal>process</literal>
elements:</title>
- <tgroup cols="3" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Element</entry>
- <entry>Multiplicity</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>description</literal></entry>
- <entry>0..1</entry>
- <entry>description text</entry>
- </row>
- <row>
- <entry><link
linkend="activities">activities</link></entry>
- <entry>1..*</entry>
- <entry>a list of any activity type can be placed here. At least
- one <literal>start</literal> activity must be present.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </section>
-
- <!-- ##################################################################### -->
- <!-- ### CONTROL FLOW ACTIVITIES ### -->
- <!-- ##################################################################### -->
-
- <section id="controlflowactivities">
- <title>Control flow activities</title>
-
- <section id="start">
- <title><literal>start</literal></title>
- <para>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 transition and that
transition
- is taken when a process execution starts.
- </para>
- <para>Known limitation: for now, a process can not have more then
- one <literal>start</literal>.
- </para>
- <table><title><literal>start</literal>
attributes:</title>
- <tgroup cols="5" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Attribute</entry>
- <entry>Type</entry>
- <entry>Default</entry>
- <entry>Required?</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>name</literal></entry>
- <entry>any text</entry>
- <entry></entry>
- <entry>optional</entry>
- <entry>name of the activity. Since a start activity
- cannot have incoming transitions, the name is optional.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <table><title><literal>start</literal>
elements:</title>
- <tgroup cols="3" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Element</entry>
- <entry>Multiplicity</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>transition</literal></entry>
- <entry>1</entry>
- <entry>the outgoing transition</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </section>
-
- <section id="state">
- <title><literal>state</literal></title>
- <para>A wait state. Process execution will wait until an external trigger is
- provided through the API. Apart from the <link
linkend="commonactivitycontent">
- common activity content</link>, <literal>state</literal>
doesn't have any extra
- attributes or elements.
- </para>
- <section id="statesequence">
- <title><literal>state</literal> sequence</title>
- <para>Let's look at an example which shows states connected with
transitions
- as a sequence</para>
- <figure id="process.state.sequence">
- <title>A sequence of states</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/process.state.sequence.png"/></imageobject></mediaobject>
- </figure>
- <programlisting><process name="StateSequence"
xmlns="http://jbpm.org/4.0/jpdl">
-
- <start>
- <transition to="a" />
- </start>
-
- <state name="a">
- <transition to="b" />
- </state>
-
- <state name="b">
- <transition to="c" />
- </state>
-
- <state name="c" />
-
-</process></programlisting>
- <para>After you start an execution like this:</para>
- <programlisting>Execution execution =
executionService.startProcessInstanceByKey("StateSequence");</programlisting>
- <para>the created process instance will be positioned in
- state <literal>a</literal>. Providing an external trigger can
- be done with the <literal>signalExecution</literal>
methods.</para>
- <programlisting>String executionId = execution.getId();
-execution = executionService.signalExecutionById(executionId);</programlisting>
- </section>
- <section id="statechoice">
- <title><literal>state</literal> choice</title>
- <para>In this second example with states, we'll show how you can use a
- <literal>state</literal> can be used to feed in an external choice of
- the path to take.
- </para>
- <figure id="process.state.choice">
- <title>A choice between state</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/process.state.choice.png"/></imageobject></mediaobject>
- </figure>
- <programlisting><process name="StateChoice"
xmlns="http://jbpm.org/4.0/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></programlisting>
- <para>Let's start a new process instance for this process
definition:</para>
- <programlisting>Execution execution =
executionService.startProcessInstanceByKey("StateSequence");</programlisting>
- <para>Now, the execution is arrived in the <literal>wait for
response</literal>.
- The execution will wait there until an external trigger is given. In case
- a <literal>state</literal> 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 signalName <literal>accept</literal>
like this:
- </para>
- <programlisting>executionService.signalExecutionById(executionId,
"accept");</programlisting>
- <para>Then the execution will continue over the outgoing transition named
- <literal>accept</literal>. Analogue, when signalName
<literal>reject</literal>
- is given in the signalExecutionXxx methods, the execution will continue over
- the outgoing transition named reject.
- </para>
- </section>
- </section>
-
- <section id="decision">
- <title><literal>decision</literal></title>
- <para>Takes one path of many alternatives. Also known as a decision. A
decision
- activity has multiple outgoing transitions and when an execution arrives in a
decision
- activity, an automatic evaluation will decide which outgoing transition is taken.
- </para>
- <para>A decision activity should be configured in one of the three following
ways:
- </para>
-
- <section id="decisionconditions">
- <title>Decision conditions</title>
- <para>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.
- </para>
-
<table><title><literal>decision.transition.condition</literal>
attributes:</title>
- <tgroup cols="5" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Attribute</entry>
- <entry>Type</entry>
- <entry>Default</entry>
- <entry>Required?</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>expr</literal></entry>
- <entry>expression</entry>
- <entry></entry>
- <entry><emphasis
role="bold">required</emphasis></entry>
- <entry>script that will be evaluated in the specified
- expression language.
- </entry>
- </row>
- <row>
- <entry><literal>lang</literal></entry>
- <entry>expression language</entry>
- <entry>the
<literal>default-expression-language</literal> taken from the <link
linkend="scripting"><literal>script-manager</literal>
configuration</link></entry>
- <entry>optional</entry>
- <entry>the language in which <literal>expr</literal> is
- to be evaluated.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>Example:
- </para>
- <figure id="process.decision.condition">
- <title>The decision conditions example process</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/process.decision.png"/></imageobject></mediaobject>
- </figure>
- <programlisting><process name="DecisionConditions"
>
-
- <start>
- <transition to="evaluate document" />
- </start>
-
- <decision name="evaluate document">
- <transition to="submit document">
- <emphasis role="bold"><condition
expr="#{content=="good"}" /></emphasis>
- </transition>
- <transition to="try again">
- <emphasis role="bold"><condition
expr="#{content=="not so good"}"
/></emphasis>
- </transition>
- <transition to="give up" />
- </decision>
-
- <state name="submit document" />
-
- <state name="try again" />
-
- <state name="give up" />
-
-</process></programlisting>
- </section>
-
- <section id="decisionexpression">
- <title>Decision expression</title>
- <para>A decision expression evaluates to a String representing the name of
- an outgoing transition.
- </para>
- <table><title><literal>decision</literal>
attributes:</title>
- <tgroup cols="5" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Attribute</entry>
- <entry>Type</entry>
- <entry>Default</entry>
- <entry>Required?</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>expr</literal></entry>
- <entry>expression</entry>
- <entry></entry>
- <entry><emphasis
role="bold">required</emphasis></entry>
- <entry>script that will be evaluated in the specified
- expression language.
- </entry>
- </row>
- <row>
- <entry><literal>lang</literal></entry>
- <entry>expression language</entry>
- <entry>the
<literal>default-expression-language</literal> taken from the <link
linkend="scripting"><literal>script-manager</literal>
configuration</link></entry>
- <entry>optional</entry>
- <entry>the language in which <literal>expr</literal> is
- to be evaluated.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>Example:
- </para>
- <figure id="process.decision.expression">
- <title>The decision expression example process</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/process.decision.png"/></imageobject></mediaobject>
- </figure>
- <programlisting><process name="Poolcar">
- <start>
- <transition to="How far?" />
- </start>
- <decision name="How far?" <emphasis
role="bold">expr="#{distance}"</emphasis>>
- <transition name="far" to="Big car"
/>
- <transition name="nearby" to="Small car"
/>
- </decision>
- <state name="Big car" />
- <state name="Small car" />
-</process></programlisting>
- <para>When you start an new process instance like this
- </para>
- <programlisting>Map<String, Object> variables = new
HashMap<String, Object>();
-variables.put("distance", "far");
-Execution execution =
executionService.startProcessInstanceByKey("Poolcar",
variables);</programlisting>
- <para>then the new execution will go to activity <literal>Big
car</literal>.</para>
- </section>
-
- <section id="decisionhandler">
- <title>Decision handler</title>
- <para>A decision handler is a java class that implements the
- <literal>DecisionHandler</literal> interface. The decision handler
- will be responsible for selecting the name of the outgoing transition.
- </para>
- <programlisting>public interface DecisionHandler {
- String select(OpenExecution execution);
-}</programlisting>
- <para>The handler is specified as a sub element of the
decision</para>
- <table><title><literal>decision.handler</literal>
attributes:</title>
- <tgroup cols="5" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Attribute</entry>
- <entry>Type</entry>
- <entry>Default</entry>
- <entry>Required?</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>class</literal></entry>
- <entry>classname</entry>
- <entry></entry>
- <entry><emphasis
role="bold">required</emphasis></entry>
- <entry>fully qualified classname of the handler implementation
class.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>Here's an example process of a decision using a
DecisionHandler:</para>
- <figure id="process.decision.handler">
- <title>The decision handler example process</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/process.decision.png"/></imageobject></mediaobject>
- </figure>
- <programlisting><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></programlisting>
- <para>The ContentEvaluation class looks like this</para>
- <programlisting>public class ContentEvaluation implements DecisionHandler
{
-
- public String select(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";
- }
-}</programlisting>
- <para>Now, when we start a process instance and supply value
- <literal>you're great</literal> for variable content, then the
- ContentEvaluation will return String <literal>good</literal> and
- the process instance will arrive in activity <literal>Submit
document</literal>.
- </para>
- </section>
-
- </section>
-
- <section id="concurrency">
- <title><literal>concurrency</literal></title>
- <para>With the <literal>fork</literal> and
<literal>join</literal> activities,
- concurrent paths of executions can be modeled.
- </para>
- <table><title><literal>join</literal>
attributes:</title>
- <tgroup cols="5" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Attribute</entry>
- <entry>Type</entry>
- <entry>Default</entry>
- <entry>Required?</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>multiplicity</literal></entry>
- <entry>integer</entry>
- <entry>nbr of incoming transitions</entry>
- <entry>optional</entry>
- <entry>The number of executions that should arrive in this join
- before the join activates and push an execution out the single
- outgoing transition of the join.
- </entry>
- </row>
- <row>
- <entry><literal>lockmode</literal></entry>
- <entry>{none, read, upgrade, upgrade_nowait, write}</entry>
- <entry>upgrade</entry>
- <entry>optional</entry>
- <entry>the hibernate lock mode applied on the parent execution to
- prevent that 2 concurrent transactions see each other as not yet
- arrived at the join, causing a process deadlock.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>For example:</para>
- <figure id="process.concurrency">
- <title>The concurrency example process</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/process.concurrency.png"/></imageobject></mediaobject>
- </figure>
-
- <programlisting><process
name="ConcurrencyGraphBased"
xmlns="http://jbpm.org/4.0/jpdl">
-
- <start>
- <transition to="fork"/>
- </start>
-
- <emphasis role="bold"><fork
name="fork">
- <transition to="send invoice" />
- <transition to="load truck"/>
- <transition to="print shipping documents" />
- </fork></emphasis>
-
- <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>
-
- <emphasis role="bold"><join name="shipping
join" >
- <transition to="drive truck to destination" />
- </join></emphasis>
-
- <state name="drive truck to destination" >
- <transition to="final join" />
- </state>
-
- <emphasis role="bold"><join name="final join"
>
- <transition to="end"/>
- </join></emphasis>
-
- <end name="end" />
-
-</process></programlisting>
- </section>
-
- <!-- ### END ########################################################### -->
-
- <section id="end">
- <title><literal>end</literal></title>
- <para>Ends the execution.
- </para>
- <section id="endprocessinstance">
- <title><literal>end</literal> process instance</title>
- <para>By default, an end activity will end the complete
- process instance. In case multiple concurrent executions
- are still active within the same process instance, all of
- them will be ended.
- </para>
- <figure id="process.end.processinstance">
- <title>The end event</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/process.end.processinstance.png"/></imageobject></mediaobject>
- </figure>
- <programlisting><process name="EndProcessInstance"
xmlns="http://jbpm.org/4.0/jpdl">
-
- <start>
- <transition to="end" />
- </start>
-
- <end name="end" />
-
-</process></programlisting>
- <para>When a new process instance is created, it immediately
ends.</para>
- </section>
- <section id="endexecution">
- <title><literal>end</literal> execution</title>
- <para>Only the execution that arrives in the
- end activity will be ended and other concurrent executions
- should be left active. To get this behaviour, set
- attribute <literal>ends="execution"</literal>
- </para>
- <table><title><literal>end</literal> execution
attributes:</title>
- <tgroup cols="5" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Attribute</entry>
- <entry>Type</entry>
- <entry>Default</entry>
- <entry>Required?</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>ends</literal></entry>
- <entry>{processinstance|execution}</entry>
- <entry>processinstance</entry>
- <entry>optional</entry>
- <entry>specifies if the whole process instance should be ended or
- just the path of execution that arrives in the end activity.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </section>
- <section id="endmultiple">
- <title><literal>end</literal> multiple</title>
- <para>A process can have multiple end events. This can be handy to
indicate
- different outcomes of a process instance. For example
- </para>
- <figure id="process.end.multiple">
- <title>Multiple end events</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/process.end.multiple.png"/></imageobject></mediaobject>
- </figure>
- <programlisting><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>
- </programlisting>
- <para>Now if we would start an execution and signal it to move out of the
<literal>get return code</literal> wait state with the
- following code, the execution would end with the <literal>bad
request</literal> end event.</para>
- <programlisting>Execution execution =
executionService.startProcessInstanceByKey("EndMultiple");
-String executionId = execution.getId();
-execution = executionService.signalExecutionById(executionId, "400");
- </programlisting>
- <para>Likewise, using the value <literal>200</literal> or
<literal>500</literal> would cause the execution
- to end with the <literal>ok</literal> or with the
<literal>internal server error</literal> end events
- respectively.</para>
- </section>
-
- <section id="endstate">
- <title><literal>end</literal> state</title>
- <para>An execution can also end with different states. It is another way to
specify the outcome of a process.
- It is indicated by the <literal>state</literal> attribute of the end
event or by the <literal>end-cancel</literal>
- and <literal>end-error</literal> shortcut notations.
- </para>
-
- <table><title><literal>end</literal> execution
attributes:</title>
- <tgroup cols="5" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Attribute</entry>
- <entry>Type</entry>
- <entry>Default</entry>
- <entry>Required?</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>state</literal></entry>
- <entry>String</entry>
- <entry></entry>
- <entry>optional</entry>
- <entry>the state assigned to the execution.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <para>Take for example the following process.
- </para>
- <figure id="process.end.state">
- <title>Different end states</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/process.end.state.png"/></imageobject></mediaobject>
- </figure>
- <programlisting><process name="EndState"
xmlns="http://jbpm.org/4.0/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>
- </programlisting>
- <para>This time, if we would start an execution and signal it to move out
of the <literal>get return code</literal> wait state with the
- following code, the execution would end with the
<literal>cancel</literal> state.</para>
- <programlisting>Execution execution =
executionService.startProcessInstanceByKey("EndState");
-String executionId = execution.getId();
-execution = executionService.signalExecutionById(executionId, "400");
- </programlisting>
- <para>Similarly as above, using the value
<literal>200</literal> or <literal>500</literal> would cause the
execution
- to end with the <literal>completed</literal> or with the
<literal>error</literal> states
- respectively.</para>
- </section>
- </section>
-
- <!-- ### TASK ########################################################## -->
-
- <section id="task">
- <title><literal>task</literal></title>
-
- <para>Creates a task for a person in the task component.</para>
-
- <!-- ~~~ TASK ASSIGNEE ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
-
- <section id="taskassignee">
- <title><literal>task</literal> assignee</title>
- <para>A simple task that will be assigned to a specific user
- </para>
- <table><title><literal>task</literal>
attributes:</title>
- <tgroup cols="5" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Attribute</entry>
- <entry>Type</entry>
- <entry>Default</entry>
- <entry>Required?</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>assignee</literal></entry>
- <entry>expression</entry>
- <entry></entry>
- <entry>optional</entry>
- <entry>userId referring to the person that is responsible for
- completing this task.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <figure id="process.task.assignee">
- <title>The task assignee example process</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/process.task.png"/></imageobject></mediaobject>
- </figure>
- <programlisting><process
name="TaskAssignee">
-
- <start>
- <transition to="review" />
- </start>
-
- <task name="review"
- <emphasis
role="bold">assignee="#{order.owner}"</emphasis>>
-
- <transition to="wait" />
- </task>
-
- <state name="wait" />
-
-</process></programlisting>
- <para>This process shows 2 aspects of task assignment. First, that the
- attribute <literal>assignee</literal> 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.
- </para>
- <para>Secondly, this attribute is by default evaluated as an expression.
- In this case the task is assigned to
<literal>#{order.owner}</literal>.
- 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 <literal>getOwner()</literal>
getter
- will be used to get the userId that references the user that is
- responsible for completing this task.
- </para>
- <para>Here's the Order class used in our example:</para>
- <programlisting>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;
- }
-}</programlisting>
- <para>Next a new process instance is created with an order as a process
- variable.</para>
- <programlisting>Map<String, Object> variables = new
HashMap<String, Object>();
-variables.put("order", new Order("johndoe"));
-Execution execution = executionService
- .startProcessInstanceByKey("TaskAssignee",
variables);</programlisting>
- <para>Then the task list for <literal>johndoe</literal> can be
obtained like this.</para>
- <programlisting>List<Task> taskList =
taskService.findPersonalTasks("johndoe");</programlisting>
- <para>Note that it is also possible to put plain text like
- <literal>assignee="johndoe"</literal>. In that
case
- the task will be assigned to johndoe.
- </para>
- </section>
-
- <!-- ~~~ TASK CANDIDATES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
-
- <section id="taskcandidates">
- <title><literal>task</literal> candidates</title>
- <para>A task that will be offered to a group of users. One of the users
should then
- take the task in order to complete it.
- </para>
- <table><title><literal>task</literal>
attributes:</title>
- <tgroup cols="5" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Attribute</entry>
- <entry>Type</entry>
- <entry>Default</entry>
- <entry>Required?</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
-
<entry><literal>candidate-groups</literal></entry>
- <entry>expression</entry>
- <entry></entry>
- <entry>optional</entry>
- <entry>resolves to a comma separated list of groupIds.
- All the people in the groups will be candidates for this
- task.</entry>
- </row>
- <row>
-
<entry><literal>candidate-users</literal></entry>
- <entry>expression</entry>
- <entry></entry>
- <entry>optional</entry>
- <entry>resolves to a comma separated list of userIds.
- All the users will be candidates for this task.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <figure id="process.task.candidates">
- <title>The task candidates example process</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/process.task.png"/></imageobject></mediaobject>
- </figure>
- <para>Here's an example process using task candidates:</para>
- <programlisting><process
name="TaskCandidates">
-
- <start>
- <transition to="review" />
- </start>
-
- <task name="review"
- <emphasis
role="bold">candidate-groups="sales-dept"</emphasis>>
-
- <transition to="wait" />
- </task>
-
- <state name="wait"/>
-
-</process>
- </programlisting>
- <para>After starting, a task will be created. The task will not show up in
anyone's
- personal task list. Following task lists will be empty.
- </para>
- <programlisting>taskService.getAssignedTasks("johndoe");
-taskService.getAssignedTasks("joesmoe");</programlisting>
- <para>But the task will show up in the group task list of all members of
the <literal>sales-dept</literal>
- group.
- </para>
- <para>The in our example, the <literal>sales-dept</literal> has
two members: johndoe and joesmoe</para>
-
<programlisting>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"); </programlisting>
- <para>So after the process is created, the task will appear in both the
- group tasks for users johndoe and joesmoe</para>
- <programlisting>taskService.findGroupTasks("johndoe");
-taskService.findGroupTasks("joesmoe");</programlisting>
- <para>Candidates must take a task before they can work on it. This will
prevent
- that two candides start working on the same task. The user interface must only
- offer the action 'Take' for the tasks in the group task list.
- </para>
- <programlisting>taskService.takeTask(task.getDbid(),
"johndoe");</programlisting>
- <para>When a user takes a task, the assignee of that task will be set to
the given
- user. The task will disappear from all the candidate's group task list and
- it will appear in the user's assigned tasks.
- </para>
- <para>Users are only allowed to work on tasks in their personal task list.
This
- should be enforced by the user interface.</para>
- <para>Similarly, the attribute
<literal>candidate-users</literal> can be used that
- resolves to a comma separated list of userIds. The
<literal>candidate-users</literal>
- attribute can be used in combination with other assignment options.
- </para>
- </section>
-
- <!-- ~~~ TASK ASSIGNMENT HANDLER ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
-
- <section id="taskassignmenthandler">
- <title><literal>task</literal> assignment
handler</title>
- <para>An <literal>AssignmentHandler</literal> can be used to
calculate the
- assignee and the candidates for a task programmatically.
- </para>
- <programlisting>public interface <emphasis
role="bold">AssignmentHandler</emphasis> extends Serializable {
-
- /** sets the actorId and candidates for the given assignable. */
- void assign(Assignable assignable, OpenExecution execution) throws Exception;
-}</programlisting>
- <para><literal>Assignable</literal> is a common interface for
Tasks and
- Swimlanes. So AssignmentHandlers can be used for tasks as well as swimlanes
- (see later).
- </para>
- <para><literal>assignment-handler</literal> is a sub element of
the task element.
- It specifies a user code object. So the attributes and elements of
<literal>assignment-handler</literal>
- are documented in <xref linkend="usercode" />
- </para>
- <para>Let's look at the task assignment example process.</para>
- <figure id="process.task.assignmenthandler">
- <title>The task assignment handler example process</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/process.task.png"/></imageobject></mediaobject>
- </figure>
- <programlisting><process
name="TaskAssignmentHandler"
xmlns="http://jbpm.org/4.0/jpdl">
-
- <start g="20,20,48,48">
- <transition to="review" />
- </start>
-
- <task name="review"
g="96,16,127,52">
- <emphasis role="bold"><assignment-handler
class="org.jbpm.examples.task.assignmenthandler.AssignTask">
- <field name="assignee">
- <string value="johndoe" />
- </field>
- </assignment-handler></emphasis>
- <transition to="wait" />
- </task>
-
- <state name="wait" g="255,16,88,52"
/>
-
-</process></programlisting>
- <para>The referenced class <literal>AssignTask</literal> looks
like this: </para>
- <programlisting>public class AssignTask implements AssignmentHandler {
-
- String assignee;
-
- public void assign(Assignable assignable, OpenExecution execution) {
- assignable.setAssignee(assignee);
- }
-}</programlisting>
- <para>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 candidate users and groups.
- </para>
- <para>Starting a new process instance of the
<literal>TaskAssignmentHandler</literal>
- process will immediately bring the new execution to the task activity. A new
- <literal>review</literal> task is created and at that point, the
<literal>AssignTask</literal>
- assignment handler is called. That will set
<literal>johndoe</literal> as
- the assignee. So John Doe will find the task in his personal task list.
- </para>
- </section>
-
- <!-- ~~~ TASK SWIMLANES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
-
- <section id="taskswimlanes">
- <title><literal>task</literal> swimlanes</title>
- <para>Multiple tasks in a process should be assigned to the same
- user or candidates. Multiple tasks in a process can be 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 to those user and candidates.
- </para>
- <para>A swimlane can also be considered as a process role. In some
- cases, this might boil down to authorization roles in the
- identity component. But bare in mind that it is not always the
- same thing.</para>
- <table><title><literal>task</literal>
attributes:</title>
- <tgroup cols="5" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Attribute</entry>
- <entry>Type</entry>
- <entry>Default</entry>
- <entry>Required?</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>swimlane</literal></entry>
- <entry>swimlane (string)</entry>
- <entry></entry>
- <entry>optional</entry>
- <entry>refers to a swimlane that is declared in the
process</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>Swimlanes can be declared inside a process element:</para>
- <table><title><literal>swimlane</literal>
attributes:</title>
- <tgroup cols="5" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Attribute</entry>
- <entry>Type</entry>
- <entry>Default</entry>
- <entry>Required?</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>name</literal></entry>
- <entry>swimlane (string)</entry>
- <entry></entry>
- <entry><emphasis
role="bold">required</emphasis></entry>
- <entry>Name for this swimlane. This is the
- name that will be referenced by task swimlane attributes.
- </entry>
- </row>
- <row>
- <entry><literal>assignee</literal></entry>
- <entry>expression</entry>
- <entry></entry>
- <entry>optional</entry>
- <entry>userId referring to the person that is responsible for
- completing this task.</entry>
- </row>
- <row>
-
<entry><literal>candidate-groups</literal></entry>
- <entry>expression</entry>
- <entry></entry>
- <entry>optional</entry>
- <entry>resolves to a comma separated list of groupIds.
- All the people in the groups will be candidates for this
- the tasks in this swimlane.</entry>
- </row>
- <row>
-
<entry><literal>candidate-users</literal></entry>
- <entry>expression</entry>
- <entry></entry>
- <entry>optional</entry>
- <entry>resolves to a comma separated list of userIds.
- All the users will be candidates for the
- tasks in this swimlane.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <figure id="process.task.swimlane">
- <title>The task swimlane example process</title>
-
- <!-- KOEN: volgende image moet aangepast worden naar
- images/process.task.swimlane.png
- nadat je die hebt toegevoegd aan de images directory -->
-
- <mediaobject><imageobject><imagedata align="center"
fileref="images/process.task.png"/></imageobject></mediaobject>
- </figure>
- <para>The task swimlane example has the following process file
:</para>
- <programlisting><process name="TaskSwimlane"
xmlns="http://jbpm.org/4.0/jpdl">
-
- <emphasis role="bold"><swimlane name="sales
representative"
- candidate-groups="sales-dept" /></emphasis>
-
- <start>
- <transition to="enter order data" />
- </start>
-
- <task name="enter order data"
- <emphasis role="bold">swimlane="sales
representative"</emphasis>>
-
- <transition to="calculate quote"/>
- </task>
-
- <task
- name="calculate quote"
- <emphasis role="bold">swimlane="sales
representative"</emphasis>>
- </task>
-
-</process></programlisting>
- <para>In this example we create the following information in the identity
- component:</para>
-
<programlisting>identityService.createGroup("sales-dept");
-
-identityService.createUser("johndoe", "johndoe",
"John", "Doe");
-identityService.createMembership("johndoe",
"sales-dept");</programlisting>
- <para>After starting a new process instance, user
<literal>johndoe</literal> will
- be a candidate for task <literal>enter order data</literal>. Again
like in the
- previous task candidates example, John Doe can now take this task like this:
- </para>
- <programlisting>taskService.takeTask(taskDbid,
"johndoe");</programlisting>
- <para>Taking the task will make Lit<literal>johndoe</literal>
the assignee for
- the task. And since this task is coupled to the swimlane
- <literal>sales representative</literal>, assignee
<literal>johndoe</literal> will
- also be propagated as the assignee in the swimlane.</para>
- <para>Next, John Doe can complete the task like this:</para>
- <programlisting>taskService.completeTask(taskDbid);</programlisting>
- <para>Completing the task will bring the process execution to the
- next task, which is <literal>calculate quote</literal>. Also
- this task is linked to the swimlane. Therefore, the task will be
- assigned to <literal>johndoe</literal>. Also the candidate users
- and candidate groups of the initial assignment will be copied from
- the swimlane to the task. This is relevant in case user
<literal>johndoe</literal>
- would release the task and offer it back to the other candidates.
- </para>
- </section>
-
- <!-- ~~~ TASK VARIABLES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
-
- <section id="taskvariables">
- <title><literal>task</literal> variables</title>
- <para>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 comes from the task and the process instance. Then
- input from the user is translated in setting task variables.
- </para>
- <para>Getting task variables can be done like this:</para>
- <programlisting>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);</programlisting>
- <para>And setting task variables can be done like this:</para>
- <programlisting>variables = new HashMap<String, Object>();
-variables.put("category", "small");
-variables.put("lires", 923874893);
-
-taskService.setVariables(taskDbid, variables);</programlisting>
- </section>
-
- <!-- ~~~ MAIL SUPPORT IN TASKS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-->
-
- <section id="mailintasks">
- <title>e-mail support in tasks</title>
- <para>It is possible to provide assignees with notifications when a task
- is added to their list, as well as reminders at specific intervals.
- Every email message is produced from a template. Templates may be specified
- inline or in the <literal>process-engine-context</literal> section
of the
- configuration file.</para>
- <table><title><literal>task</literal>
elements</title>
- <tgroup cols="3" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Element</entry>
- <entry>Multiplicity</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>notification</entry>
- <entry>0..1</entry>
- <entry>Sends a notification message when a task is assigned.
- If no template is referenced or supplied inline, mail support
- falls back on the template named
<emphasis>task-notification</emphasis>.
- </entry>
- </row>
- <row>
- <entry>reminder</entry>
- <entry>0..1</entry>
- <entry>Sends a reminder message at specific intervals.
- If no template is referenced or supplied inline, mail support
- falls back on the template named
<emphasis>task-reminder</emphasis>.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>Here is a basic example that accepts the default
templates.</para>
- <programlisting><![CDATA[<task name="review"
- assignee="#{order.owner}"
- <notification/>
- <reminder duedate="2 days" repeat="1 day"/>
-</task>]]></programlisting>
- <para>Refer to the <link linkend="mailsupport">mail
chapter</link> for full details
- on mail support.</para>
- </section>
- </section>
-
- <!-- ### SUB-PROCESS ################################################## -->
-
- <section id="subprocess">
- <title><literal>sub-process</literal></title>
-
- <para>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.
- </para>
-
- <table><title><literal>sub-process</literal>
attributes:</title>
- <tgroup cols="5" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Attribute</entry>
- <entry>Type</entry>
- <entry>Default</entry>
- <entry>Required?</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>sub-process-id</literal></entry>
- <entry>string</entry>
- <entry></entry>
- <entry>either this or sub-process-key is required</entry>
- <entry>Identifies the sub process by the id. This means that a
specific
- version of a process definition is referenced.</entry>
- </row>
- <row>
- <entry><literal>sub-process-key</literal></entry>
- <entry>string</entry>
- <entry></entry>
- <entry>either this or sub-process-key is required</entry>
- <entry>Identifies the sub process by the key. This means that the
latest
- version of the process definition with the given key is referenced. The
latest version
- of the process is looked up each time the activity executes.
- </entry>
- </row>
- <row>
- <entry><literal>outcome</literal></entry>
- <entry>expression</entry>
- <entry></entry>
- <entry>required when transitions have
<literal>outcome-value</literal>'s specified</entry>
- <entry>Expression that is evaluated when the sub process
- instance ends. The value is then used for outcome transition mapping.
- Add <literal>outcome-value</literal> elements to the outgoing
transitions
- of this <literal>sub-process</literal> activity.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table><title><literal>sub-process</literal>
elements:</title>
- <tgroup cols="3" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Element</entry>
- <entry>Multiplicity</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>parameter-in</literal></entry>
- <entry>0..*</entry>
- <entry>Declares a variable that is passed to the sub process instance
- when it is created.
- </entry>
- </row>
- <!--
- <row>
- <entry><literal>swimlane-mapping</literal></entry>
- <entry>0..*</entry>
- <entry>Declares a swimlane that will be propagated to the sub process
- instance when the sub process is created.
- </entry>
- </row>
- -->
- <row>
- <entry><literal>parameter-out</literal></entry>
- <entry>0..*</entry>
- <entry>Declares a variable that will be set in the super process
execution
- when the sub process ends.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table><title><literal>parameter-in</literal>
attributes:</title>
- <tgroup cols="5" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Attribute</entry>
- <entry>Type</entry>
- <entry>Default</entry>
- <entry>Required?</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>subvar</literal></entry>
- <entry>string</entry>
- <entry></entry>
- <entry><emphasis
role="bold">required</emphasis> </entry>
- <entry>The name of the sub process variable in which the value is
set.</entry>
- </row>
- <row>
- <entry><literal>var</literal></entry>
- <entry>string</entry>
- <entry></entry>
- <entry>exactly one of {'var', 'expr'} is required to
specify the value</entry>
- <entry>The name of the variable in the super process execution
context.</entry>
- </row>
- <row>
- <entry><literal>expr</literal></entry>
- <entry>string</entry>
- <entry></entry>
- <entry>exactly one of {'var', 'expr'} is required to
specify the value</entry>
- <entry>An expression that will be resolved in the <emphasis
role="bold">super</emphasis> process execution
- context. The resulting value will be set in the sub process variable.
- </entry>
- </row>
- <row>
- <entry><literal>lang</literal></entry>
- <entry>string</entry>
- <entry>juel</entry>
- <entry>optional</entry>
- <entry>The scripting language in which the expression should be
resolved.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table><title><literal>parameter-out</literal>
attributes:</title>
- <tgroup cols="5" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Attribute</entry>
- <entry>Type</entry>
- <entry>Default</entry>
- <entry>Required?</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>var</literal></entry>
- <entry>string</entry>
- <entry></entry>
- <entry><emphasis
role="bold">required</emphasis></entry>
- <entry>The name of the variable in the super process execution
context
- in which the value will be set.</entry>
- </row>
- <row>
- <entry><literal>subvar</literal></entry>
- <entry>string</entry>
- <entry></entry>
- <entry>exactly one of {'subvar', 'expr'} is required
to specify the value</entry>
- <entry>The name of the sub process variable from which the value
- will be taken.</entry>
- </row>
- <row>
- <entry><literal>expr</literal></entry>
- <entry>string</entry>
- <entry></entry>
- <entry>exactly one of {'subvar', 'expr'} is required
to specify the value</entry>
- <entry>An expression that will be resolved in the <emphasis
role="bold">sub</emphasis> process execution
- context. The resulting value will be set in the super process variable.
- </entry>
- </row>
- <row>
- <entry><literal>lang</literal></entry>
- <entry>string</entry>
- <entry>juel</entry>
- <entry>optional</entry>
- <entry>The scripting language in which the expression should be
resolved.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table><title>Extra <literal>transition</literal> elements
in case of outcome variable mappings:</title>
- <tgroup cols="3" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Element</entry>
- <entry>Multiplicity</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>outcome-value</literal></entry>
- <entry>0..1</entry>
- <entry>If the <literal>outcome</literal> matches the
value, this
- transition is taken after the sub-process ended. The value is specified
with one child
- element.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <!-- ~~~ SUB PROCESS VARIABLES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
- <section id="subprocessvariables">
- <title><literal>sub-process</literal> variables</title>
- <para>The SubProcessVariables example scenario will show the basic workings
of the
- sub-process activity, how to feed information in the sub process when it starts
- and how to extract information out of the subprocess when it ends.
- </para>
- <para>The parent process involves a document that needs to be
reviewed.</para>
- <figure id="process.subprocess.variables.document">
- <title>The subprocess document example process</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/process.task.png"/></imageobject></mediaobject>
- </figure>
- <programlisting><process name="SubProcessDocument"
xmlns="http://jbpm.org/4.0/jpdl">
-
- <start>
- <transition to="review" />
- </start>
-
- <emphasis role="bold"><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></emphasis>
-
- <state name="wait"/>
-
-</process></programlisting>
- <para>The review process is a reusable process for all kinds of
reviews.</para>
- <figure id="process.subprocess.variables.review">
- <title>The subprocess review example process</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/process.subprocess.review.png"/></imageobject></mediaobject>
- </figure>
- <programlisting><process name="SubProcessReview"
xmlns="http://jbpm.org/4.0/jpdl">
-
- <start>
- <transition to="get approval"/>
- </start>
-
- <task name="get approval"
- assignee="johndoe">
-
- <transition to="end"/>
- </task>
-
- <end name="end" />
-
-</process></programlisting>
- <para>The document process is started with a document
variable:</para>
- <programlisting>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);</programlisting>
- <para>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 <literal>SubProcessReview</literal>
process
- instance starts, it arrives in the <literal>task</literal>. A task
will be
- created for <literal>johndoe</literal>.
- </para>
- <programlisting>List<Task> taskList =
taskService.findPersonalTasks("johndoe");
-Task task = taskList.get(0);</programlisting>
- <para>We can see that the document has been passed from the super process
- instance to the sub process instance:
- </para>
- <programlisting>String document = (String)
taskService.getVariable(task.getDbid(), "document");
-assertEquals("This document describes how we can make more money...",
document);</programlisting>
- <para>Then we set a variable on the task. This is typically done through a
form. But
- here we'll show how it is done programmatically.
- </para>
- <programlisting>taskService.setVariable(task.getDbid(),
"result", "accept");</programlisting>
- <para>Completing this task, will cause the sub process instance to end.
- </para>
-
<programlisting>taskService.completeTask(task.getDbid());</programlisting>
- <para>When the sub process ends, the super process execution will get
signalled(=notified).
- First the <literal>result</literal> variable from the sub process
instance
- will be copied into the <literal>reviewResult</literal> variable in
the
- super process execution. Then the super process execution will continue
- and leave the <link>review</link> activity.
- </para>
- </section>
-
- <!-- ~~~ SUB PROCESS OUTCOME VALUE ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
- <section id="subprocessoutcomevalue">
- <title><literal>sub-process</literal> outcome
value</title>
- <para>In the <literal>SubProcessOutcomeValueTest</literal>
example, the value
- of a sub process variable is used to select the outgoing transition
- of the <literal>sub-process</literal> activity.
- </para>
- <figure id="process.subprocess.outcomevalue.document">
- <title>The subprocess document example process</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/process.subprocess.document.png"/></imageobject></mediaobject>
- </figure>
- <programlisting><process
name="SubProcessDocument">
-
- <start>
- <transition to="review" />
- </start>
-
- <sub-process name="review"
- sub-process-key="SubProcessReview"
- <emphasis
role="bold">outcome="#{result}"</emphasis>>
-
- <transition <emphasis
role="bold">name="ok"</emphasis> to="next
step" />
- <transition <emphasis
role="bold">name="nok"</emphasis>
to="update" />
- <transition <emphasis
role="bold">name="reject"</emphasis>
to="close" />
- </sub-process>
-
- <state name="next step" />
- <state name="update" />
- <state name="close" />
-
-</process></programlisting>
- <para>The <literal>SubProcessReview</literal> is the same as
above in the
- <link linkend="subprocessvariables">subprocess variables
example</link>:</para>
- <figure id="process.subprocess.outcomevalue.review">
- <title>The subprocess review example process for outcome
value</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/process.subprocess.review.png"/></imageobject></mediaobject>
- </figure>
- <programlisting><process name="SubProcessReview"
xmlns="http://jbpm.org/4.0/jpdl">
-
- <start>
- <transition to="get approval"/>
- </start>
-
- <task name="get approval"
- assignee="johndoe">
-
- <transition to="end"/>
- </task>
-
- <end name="end" />
-
-</process></programlisting>
- <para>A new document process instance is started like usual:
- </para>
- <programlisting>ProcessInstance processInstance = executionService
-
.startProcessInstanceByKey("SubProcessDocument");</programlisting>
- <para>Then task is fetched from
<literal>johndoe</literal>'s task list</para>
- <programlisting>List<Task> taskList =
taskService.findPersonalTasks("johndoe");
-Task task = taskList.get(0);
- </programlisting>
- <para>Then the <literal>result</literal> variable is set and
- the task is completed.
- </para>
- <programlisting>taskService.setVariable(task.getDbid(),
"result", "ok");
-taskService.completeTask(task.getDbid());
- </programlisting>
- <para>In this scenario, the <literal>ok</literal> transition is
taken in
- the parent process out of the sub-process review activity. The example
- test case also shows other scenarios.
- </para>
- </section>
-
- <!-- ~~~ SUB PROCESS OUTCOME ACTIVITY ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
- <section id="subprocessoutcomeactivity">
- <title><literal>sub-process</literal> outcome
activity</title>
- <para>A process can have many end activities. In the
<literal>SubProcessOutcomeActivityTest</literal>
- example, the resulting end activity is used to select the outgoing transition of
the <literal>sub-process</literal>
- activity.
- </para>
- <figure id="process.subprocess.outcomeactivity.document">
- <title>The subprocess document example process for outcome
activity</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/process.subprocess.document.png"/></imageobject></mediaobject>
- </figure>
- <programlisting><process
name="SubProcessDocument">
-
- <start>
- <transition to="review" />
- </start>
-
- <sub-process name="review"
- sub-process-key="SubProcessReview">
-
- <transition <emphasis
role="bold">name="ok"</emphasis> to="next
step" />
- <transition <emphasis
role="bold">name="nok"</emphasis>
to="update" />
- <transition <emphasis
role="bold">name="reject"</emphasis>
to="close" />
- </sub-process>
-
- <state name="next step" />
- <state name="update" />
- <state name="close" />
-
-</process></programlisting>
- <para>The <literal>SubProcessReview</literal> now has multiple
end activities:</para>
- <figure id="process.subprocess.outcomeactivity.review">
- <title>The subprocess review example process for outcome
activity</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/process.subprocess.outcomeactivity.review.png"/></imageobject></mediaobject>
- </figure>
- <programlisting><process name="SubProcessReview"
xmlns="http://jbpm.org/4.0/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>
-
- <emphasis role="bold"><end name="ok"
/>
- <end name="nok" />
- <end name="reject" /></emphasis>
-
-</process></programlisting>
- <para>A new document process instance is started like usual:
- </para>
- <programlisting>ProcessInstance processInstance = executionService
-
.startProcessInstanceByKey("SubProcessDocument");</programlisting>
- <para>Then task is fetched from
<literal>johndoe</literal>'s task list</para>
- <programlisting>List<Task> taskList =
taskService.findPersonalTasks("johndoe");
-Task task = taskList.get(0);
- </programlisting>
- <para>Then the task is completed with outcome
<literal>ok</literal>.
- </para>
- <programlisting>taskService.completeTask(task.getDbid(),
"ok");
- </programlisting>
- <para>This will cause the sub process to end in end activity
<literal>ok</literal>.
- The super process execution will then take outgoing transition
<literal>ok</literal>
- to <literal>next step</literal>.
- </para>
- <para>The example test case also shows the other scenarios.
- </para>
- </section>
-
- </section>
- </section>
-
- <!-- ##################################################################### -->
- <!-- ### AUTOMATIC ACTIVITIES ### -->
- <!-- ##################################################################### -->
-
- <section id="automaticactivities">
- <title>Automatic activities</title>
-
- <!-- ### JAVA ########################################################## -->
-
- <section id="java">
- <title><literal>java</literal></title>
- <para>The Java task. A process execution will execute the method of the class
that is configured
- in this activity.</para>
- <table><title><literal>java</literal>
attributes:</title>
- <tgroup cols="5" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Attribute</entry>
- <entry>Type</entry>
- <entry>Default</entry>
- <entry>Required?</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>class</literal></entry>
- <entry>classname</entry>
- <entry></entry>
- <entry>either 'class' or 'expr' has to be
specified</entry>
- <entry>The fully qualified classname. The class will be instantiated
- and the object will be disposed after this method invocation.
- </entry>
- </row>
- <row>
- <entry><literal>expr</literal></entry>
- <entry>expression</entry>
- <entry></entry>
- <entry>either 'expr' or 'class' has to be
specified</entry>
- <entry>An expression that returns the target object on which
- the method should be invoked.
- </entry>
- </row>
- <row>
- <entry><literal>method</literal></entry>
- <entry>methodname</entry>
- <entry></entry>
- <entry><emphasis
role="bold">required</emphasis></entry>
- <entry>The name of the method to invoke</entry>
- </row>
- <row>
- <entry><literal>var</literal></entry>
- <entry>variablename</entry>
- <entry></entry>
- <entry>optional</entry>
- <entry>The name of the variable in which the return value
- should be stored.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <table><title><literal>java</literal>
elements:</title>
- <tgroup cols="3" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Element</entry>
- <entry>Multiplicity</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>field</literal></entry>
- <entry>0..*</entry>
- <entry>describes a configuration value to inject in a memberfield
before
- the method is invoked.</entry>
- </row>
- <row>
- <entry><literal>arg</literal></entry>
- <entry>0..*</entry>
- <entry>method parameters</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>Consider the following example.</para>
- <figure id="process.java">
- <title>A java task</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/process.java.png"/></imageobject></mediaobject>
- </figure>
- <programlisting><process name="Java"
xmlns="http://jbpm.org/4.0/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><resolve
expr="#{joesmoe.handshakes.force}"/></arg>
- <arg><resolve
expr="#{joesmoe.handshakes.duration}"/></arg>
-
- <transition to="wait" />
- </java>
-
- <state name="wait" />
-
-</process>
- </programlisting>
- <para>Classes involved:</para>
- <programlisting>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;
- }
-}</programlisting>
- <programlisting>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;
- }
-}</programlisting>
- <programlisting>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;
- }
-}</programlisting>
- <para>The first java activity <literal>greet</literal> specifies
that during its execution an instance of the
- class <literal>org.jbpm.examples.java.JohnDoe</literal> will be
instantiated and the method
- <literal>hello</literal> of this class will be invoked on the resulting
object. The variable named
- <literal>answer</literal> will contain the result of the invocation.
- </para>
- <para>The class above reveals that it contains two fields named
<literal>state</literal> and <literal>session</literal>
- and that the method <literal>hello</literal> accepts one argument.
During the execution the values specified in the
- <literal>field</literal> and <literal>arg</literal>
configuration elements will be used. The expected result of creating
- a process instance is that the process variable
<literal>answer</literal> contains the string
- <literal>I'm fine, thank you.</literal>.
- </para>
- <para>The second java activity is named <literal>shake
hand</literal>. It will resolve
- expression <literal>#{hand}</literal>
- and capture the resulting object as the target object. On that object, the method
- <literal>shake</literal> will be invoked. The two arguments will be
calculated by resolving
- the respective expressions
<literal>#{joesmoe.handshakes.force}</literal> and
- <literal>#{joesmoe.handshakes.duration}</literal>. The resulting
object is a mofied
- version of the hand and <literal>var="hand"</literal>
will cause the modified
- hand to overwrite the old <literal>hand</literal> variable value.
- </para>
- </section>
-
- <!-- ### SCRIPT ######################################################## -->
-
- <section id="script">
- <title><literal>script</literal></title>
- <para>A script activity evaluates a script. Scripts can be specified in any
language for
- which there is <ulink
url="https://scripting.dev.java.net/">a
JSR-223 compliant scripting engine</ulink>.
- Configuration of scripting engines <link linkend="scripting">is
explained below</link>.
- </para>
- <para>There are 2 ways of specifying a script:
- </para>
- <section id="script.expression">
- <title><literal>script</literal> expression</title>
- <para>The script is provided with the <literal>expr</literal>
attribute.
- This is for short expressions that are easier expressed in an attribute
- then in a text element. If no <literal>lang</literal> is specified,
- the default-expression-language is used.
- </para>
- <table><title><literal>script</literal> expression
attributes:</title>
- <tgroup cols="5" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Attribute</entry>
- <entry>Type</entry>
- <entry>Default</entry>
- <entry>Required?</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>expr</literal></entry>
- <entry>text</entry>
- <entry></entry>
- <entry><emphasis
role="bold">required</emphasis></entry>
- <entry>the expression text to evaluate.</entry>
- </row>
- <row>
- <entry><literal>lang</literal></entry>
- <entry>scripting language name as defined in <xref
linkend="scripting"/></entry>
- <entry>the default <emphasis
role="bold">expression</emphasis> language as defined in <xref
linkend="scripting"/></entry>
- <entry>optional</entry>
- <entry>the language in which the expression is
specified.</entry>
- </row>
- <row>
- <entry><literal>var</literal></entry>
- <entry>variablename</entry>
- <entry></entry>
- <entry>optional</entry>
- <entry>name of the variable in which the return value
- should be stored.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>In the next example, we'll see how a script activity with an
expression and
- how the result is stored in a variable.
- </para>
- <figure id="process.script.expression">
- <title>The script.expression example process</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/process.script.png"/></imageobject></mediaobject>
- </figure>
- <programlisting><process name="ScriptExpression"
xmlns="http://jbpm.org/4.0/jpdl">
-
- <start>
- <transition to="invoke script" />
- </start>
-
- <emphasis role="bold"><script name="invoke
script"
- expr="Send packet to #{person.address}"
- var="text"></emphasis>
-
- <transition to="wait" />
- <emphasis role="bold"></script></emphasis>
-
- <state name="wait"/>
-
-</process></programlisting>
- <para>This example uses a <literal>Person</literal> class that
looks like this.
- </para>
- <programlisting>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;
- }
-}</programlisting>
- <para>When starting a process instance for this process, we supply a person
- with a given address property as variable <literal>person</literal>.
- </para>
- <programlisting>Map<String, Object> variables = new
HashMap<String, Object>();
-variables.put("<emphasis role="bold">person</emphasis>",
<emphasis role="bold">new
Person("Honolulu")</emphasis>);
-
-executionService.startProcessInstanceByKey("ScriptText",
variables);</programlisting>
- <para>After the execution of the script activity, variable
<literal>text</literal>
- will contain 'Send packet to Honolulu'.
- </para>
- </section>
-
- <section id="script.text">
- <title><literal>script</literal> text</title>
- <para>The second way of specifying a script is with a
<literal>text</literal> element.
- This is convenient when the script text spans multiple lines.
- </para>
- <table><title><literal>script</literal> text
attributes:</title>
- <tgroup cols="5" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Attribute</entry>
- <entry>Type</entry>
- <entry>Default</entry>
- <entry>Required?</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>lang</literal></entry>
- <entry>scripting language name as defined in <xref
linkend="scripting"/></entry>
- <entry>the default <emphasis
role="bold">scripting</emphasis> language as defined in <xref
linkend="scripting"/></entry>
- <entry>optional</entry>
- <entry>the language in which the script is
specified.</entry>
- </row>
- <row>
- <entry><literal>var</literal></entry>
- <entry>variablename</entry>
- <entry></entry>
- <entry>optional</entry>
- <entry>name of the variable in which the return value
- should be stored.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <table><title><literal>script</literal> text
elements:</title>
- <tgroup cols="3" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Element</entry>
- <entry>Multiplicity</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>text</literal></entry>
- <entry>1</entry>
- <entry>contains the script text</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>For example</para>
- <figure id="process.script.text">
- <title>The script.text example process</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/process.script.png"/></imageobject></mediaobject>
- </figure>
- <programlisting><process name="ScriptText"
xmlns="http://jbpm.org/4.0/jpdl">
-
- <start>
- <transition to="invoke script" />
- </start>
-
- <emphasis role="bold"><script name="invoke
script"
- var="text">
- <text>
- Send packet to #{person.address}
- </text></emphasis>
- <transition to="wait" />
- <emphasis role="bold"></script></emphasis>
-
- <state name="wait"/>
-
-</process></programlisting>
- </section>
- <para>Execution of this process is exactly the same as with the script
expression above.
- </para>
- </section>
-
- <!-- ### ESB ########################################################### -->
-
- <section id="esb">
- <title><literal>esb</literal></title>
- <para>An <literal>esb</literal> activity sends a message to a
service over the ESB.
- The attributes <literal>category</literal> and
<literal>service</literal> identify the
- service in the esb repository. The message is composed with the
- <literal>part</literal> elements.
- </para>
- <table><title><literal>esb</literal>
attributes:</title>
- <tgroup cols="5" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Attribute</entry>
- <entry>Type</entry>
- <entry>Default</entry>
- <entry>Required?</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>category</literal></entry>
- <entry>string</entry>
- <entry></entry>
- <entry><emphasis
role="bold">required</emphasis></entry>
- <entry>the esb category where the service is defined.</entry>
- </row>
- <row>
- <entry><literal>service</literal></entry>
- <entry>string</entry>
- <entry></entry>
- <entry><emphasis
role="bold">required</emphasis></entry>
- <entry>the esb name of the service
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <table><title><literal>esb</literal>
elements:</title>
- <tgroup cols="3" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Element</entry>
- <entry>Multiplicity</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>part</literal></entry>
- <entry>0..*</entry>
- <entry>Parts of the message to be sent.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>For example</para>
- <figure id="process.esb">
- <title>The esb example process</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/process.esb.png"/></imageobject></mediaobject>
- </figure>
- <programlisting><process name="Esb"
xmlns="http://jbpm.org/4.0/jpdl">
-
- <start >
- <transition to="invoke esb service" />
- </start>
-
- <emphasis role="bold"><esb name="invoke esb
service"
- category="orderProcessing"
- service="bookSold">
-
- <part name="bookTitle" expr="#{title}"
/>
- <part name="goal">
- <string value="deliver asap" />
- </part></emphasis>
-
- <transition to="wait" />
- <emphasis role="bold"></esb></emphasis>
-
- <state name="wait" />
-
-</process></programlisting>
- <para>When a new process is started, a message will be sent to the esb
- service <literal>bookSold</literal> in category
<literal>orderProcessing</literal>.
- The message will have 2 parts: one named <literal>bookTitle</literal>
containing
- the title process variable. And one named <literal>goal</literal>
which
- contains the text 'deliver asap'.
- </para>
- </section>
-
- <!-- ### HQL ########################################################### -->
-
- <section id="hql">
- <title><literal>hql</literal></title>
- <para>With the<literal>hql</literal> activity, a HQL query can be
performed
- on the database and the result is stored in a process variable.
- </para>
- <table><title><literal>hql</literal>
attributes:</title>
- <tgroup cols="5" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Attribute</entry>
- <entry>Type</entry>
- <entry>Default</entry>
- <entry>Required?</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>var</literal></entry>
- <entry>variablename</entry>
- <entry></entry>
- <entry><emphasis
role="bold">required</emphasis></entry>
- <entry>the name of the variable in which the result is
stored.</entry>
- </row>
- <row>
- <entry><literal>unique</literal></entry>
- <entry>{true, false}</entry>
- <entry>false</entry>
- <entry>optional</entry>
- <entry>a value of true means that the result from the hibernate
- query should be obtained with method
<literal>uniqueResult()</literal>.
- The default is false and in that case the
<literal>list()</literal>
- method will be used to get the result.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <table><title><literal>hql</literal>
elements:</title>
- <tgroup cols="3" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Element</entry>
- <entry>Multiplicity</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>query</literal></entry>
- <entry>1</entry>
- <entry>The HQL query.</entry>
- </row>
- <row>
- <entry><literal>parameter</literal></entry>
- <entry>0..*</entry>
- <entry>The query parameters</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>For example:</para>
- <figure id="process.hql">
- <title>The hql example process</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/process.hql.png"/></imageobject></mediaobject>
- </figure>
- <programlisting><process name="Hql"
xmlns="http://jbpm.org/4.0/jpdl">
-
- <start>
- <transition to="get process names" />
- </start>
-
- <emphasis role="bold"><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></emphasis>
- <transition to="count activities" />
- <emphasis role="bold"></hql>
-
- <hql name="count activities"
- var="activities"
- unique="true">
- <query>
- select count(*)
- from org.jbpm.pvm.internal.model.ActivityImpl
- </query></emphasis>
- <transition to="wait" />
- <emphasis role="bold"></hql></emphasis>
-
- <state name="wait"/>
-
-</process></programlisting>
- </section>
-
- <!-- ### SQL ########################################################### -->
-
- <section id="sql">
- <title><literal>sql</literal></title>
- <para>The <literal>sql</literal> activity is exactly the same as
the
- <link linkend="hql">hql</link> activity, with the only
difference that
- <literal>session.createSQLQuery(...)</literal> is used.
- </para>
- </section>
-
- <!-- ### Mail ########################################################## -->
-
- <section id="mail">
- <title><literal>mail</literal></title>
- <para>Through the <literal>mail</literal> 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 specified inline or in the
<literal>process-engine-context
- </literal> section of the configuration file.</para>
- <table><title><literal>mail</literal>
attributes</title>
- <tgroup cols="5" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Attribute</entry>
- <entry>Type</entry>
- <entry>Default</entry>
- <entry>Required?</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>template</entry>
- <entry>string</entry>
- <entry></entry>
- <entry>no</entry>
- <entry>Reference to a <literal>mail-template</literal>
element in the
- configuration file. If absent, the template must be specified
- inline using the child elements.</entry>
- </row>
- <row>
- <entry>template</entry>
- <entry>string</entry>
- <entry></entry>
- <entry>no</entry>
- <entry>Reference to a <literal>mail-template</literal>
element in the
- configuration file. If absent, the template must be specified
- inline using the nested elements.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <table><title><literal>mail</literal>
elements</title>
- <tgroup cols="3" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Element</entry>
- <entry>Multiplicity</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>from</entry>
- <entry>0..1</entry>
- <entry>list of sender(s)</entry>
- </row>
- <row>
- <entry>to</entry>
- <entry>1</entry>
- <entry>list of primary recipients</entry>
- </row>
- <row>
- <entry>cc</entry>
- <entry>0..1</entry>
- <entry>list of carbon copy recipients</entry>
- </row>
- <row>
- <entry>bcc</entry>
- <entry>0..1</entry>
- <entry>list of blind carbon copy recipients</entry>
- </row>
- <row>
- <entry>subject</entry>
- <entry>1</entry>
- <entry>text content of this element becomes the message
subject</entry>
- </row>
- <row>
- <entry>text</entry>
- <entry>0..1</entry>
- <entry>text content of this element becomes the message text
content</entry>
- </row>
- <row>
- <entry>html</entry>
- <entry>0..1</entry>
- <entry>text content of this element becomes the message HTML
content</entry>
- </row>
- <row>
- <entry>attachments</entry>
- <entry>0..1</entry>
- <entry>attachments can be specified as URLs, classpath resources or
- local files</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>Refer to the <link linkend="mailsupport">mail
chapter</link> for full details
- on mail support.</para>
- </section>
-
- </section>
-
- <!-- ##################################################################### -->
- <!-- ### COMMON ACTIVITY CONTENTS ### -->
- <!-- ##################################################################### -->
-
- <section id="commonactivitycontents">
- <title>Common activity contents</title>
- <para>Unless specified otherwise above, all activities also include this
- content model:
- </para>
- <table><title>Common activity attributes:</title>
- <tgroup cols="5" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Attribute</entry>
- <entry>Type</entry>
- <entry>Default</entry>
- <entry>Required?</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>name</literal></entry>
- <entry>any text</entry>
- <entry></entry>
- <entry><emphasis
role="bold">required</emphasis></entry>
- <entry>name of the activity</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <table><title>Common activity elements:</title>
- <tgroup cols="3" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Element</entry>
- <entry>Multiplicity</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>transition</literal></entry>
- <entry>0..*</entry>
- <entry>the outgoing transitions</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </section>
-
- <!-- ##################################################################### -->
- <!-- ### EVENTS ### -->
- <!-- ##################################################################### -->
-
- <section id="events">
- <title>Events</title>
- <para>Events specify points in a process on which a list of event listeners can
be registered.
- When an execution passes that point in the process, the event listeners are
notified.
- The events and listeners are not shown in the graphical view of the process. An event
- is fired by an element in the process definition like e.g. the process definition,
- an activity or a transition.
- </para>
- <para>The EventListener interface looks like this:
- </para>
- <programlisting>public interface <emphasis
role="bold">EventListener</emphasis> extends Serializable {
-
- void notify(EventListenerExecution execution) throws Exception;
-
-}</programlisting>
- <para>All <link linkend="automaticactivities">automatic
activities</link> can be used as
- event listeners as well.</para>
- <para>To associate a list of event listeners with a process or an activity, use
- the <literal>on</literal> element to group the event listeners and
specifiy the
- event. <literal>on</literal> can be nested as a subelement of
<literal>process</literal>
- or any activity.
- </para>
- <para>To associate a list of event listeners with a transition
<literal>take</literal>
- event, just include the event listeners directly in the
<literal>transition</literal>
- element.
- </para>
- <table><title><literal>on</literal>
attributes:</title>
- <tgroup cols="5" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Attribute</entry>
- <entry>Type</entry>
- <entry>Default</entry>
- <entry>Required?</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>event</literal></entry>
- <entry>{start | end}</entry>
- <entry></entry>
- <entry><emphasis
role="bold">required</emphasis></entry>
- <entry>name name of the event</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <table><title><literal>on</literal> elements:</title>
- <tgroup cols="3" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Element</entry>
- <entry>Multiplicity</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>event-listener</literal></entry>
- <entry>0..*</entry>
- <entry>An event listener implementation object.</entry>
- </row>
- <row>
- <entry>any automatic activity</entry>
- <entry>0..*</entry>
- <entry></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>Let's look at an example process with event listeners:</para>
- <figure id="process.eventlistener">
- <title>The event listener example process</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/process.eventlistener.png"/></imageobject></mediaobject>
- </figure>
- <programlisting><process name="EventListener"
xmlns="http://jbpm.org/4.0/jpdl">
-
- <emphasis role="bold"><on
event="start">
- <event-listener
class="org.jbpm.examples.eventlistener.LogListener"/>
- </on>
-
- <on event="end">
- <event-listener
class="org.jbpm.examples.eventlistener.LogListener"/>
- </on></emphasis>
-
-
- <start>
- <transition to="wait" name=""/>
- </start>
-
- <state name="wait">
- <emphasis role="bold"><on
event="start">
- <event-listener
class="org.jbpm.examples.eventlistener.LogListener"/>
- </on>
- <on event="end">
- <event-listener
class="org.jbpm.examples.eventlistener.LogListener"/>
- </on></emphasis>
-
- <transition to="end" name="">
- <event-listener
class="org.jbpm.examples.eventlistener.LogListener"/>
- </transition>
- </state>
-
- <end name="end"/>
-
-</process></programlisting>
- <para><literal>LogListener</literal> will maintain a list of logs
in a static member
- field:</para>
- <programlisting>public class <emphasis
role="bold">LogListener</emphasis> implements EventListener {
-
- public static List<String> logs; // initialization done in test method
-
- public void notify(EventListenerExecution execution) {
- logs.add(execution.getEvent()+" on "+execution.getEventSource());
- }
-}</programlisting>
- <para>Next, we start a new process instance.</para>
- <programlisting>Execution execution =
executionService.startProcessInstanceByKey("EventListener");</programlisting>
- <para>Then the process instance executes up to the wait activity. So we
provide a signal
- and that will cause it to execute till the end.</para>
-
<programlisting>executionService.signalExecutionById(execution.getId());</programlisting>
- <para>The list of log messages will now look like this:</para>
- <programlisting>[event(start) on process(EventListener),
- event(start) on activity(wait),
- event(end) on activity(wait),
- event(take) on (wait)-->(end),
- event(end) on process(EventListener)]</programlisting>
- </section>
-
- <section id="asynchronouscontinuations">
- <title>Asynchronous continuations</title>
- <para>Each invocation of
<literal>ExecutionService.startProcessInstanceById(...)</literal>
- or <literal>ExecutionService.signalProcessInstanceById(...)</literal>
will cause
- the process to be executed in the thread of the client. In other words, those
- methods will only return after the process execution has arrived in a wait state.
- </para>
- <para>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 client to 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. E.g. < 1 second, even if multiple automatic activities
- are executed inbetween 2 wait states. So in most situations, it's good to
- do all that work 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.
- </para>
- <para>For those cases where it is needed, jPDL allows for very fine grained
control over
- transaction boundaries. On various places in the process, asynchronous continuations
- can be introduced. Asynchronous continuations are placed on places where logically
- the jBPM engine remains in control for executing a series of automatic steps.
- </para>
- <para>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. <literal>startProcessInstanceById(...)</literal>
- or <literal>signalProcessInstanceById(...)</literal> will return. When
the
- asynchronous message is committed and then processed, it will start a new
transaction
- and resume execution where it left off.
- </para>
- <table><title>Attribute of any activity,
<literal>transition</literal> or
<literal>on</literal>:</title>
- <tgroup cols="5" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Attribute</entry>
- <entry>Type</entry>
- <entry>Default</entry>
- <entry>Required?</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>continue</literal></entry>
- <entry>{sync | async | exclusive}</entry>
- <entry>sync</entry>
- <entry>optional</entry>
- <entry><para>indicates if an asynchronous continuation should be
performed
- before the element is executed.</para>
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <itemizedlist>
- <listitem><emphasis role="bold">sync</emphasis>
(default) keep executing
- the element as part of the ongoing transaction.
- </listitem>
- <listitem><emphasis role="bold">async</emphasis>
introduces an 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 the jBPM
- implementation to achieve this.
- </listitem>
- <listitem><emphasis role="bold">exclusive</emphasis>
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 the jBPM
- implementation to achieve this. Exclusive messages will not be processed
- concurrently. The JobExecutor(s) will serialize all exclusive job
- executions. This can be used to prevent optimistic locking failures in case
- multiple, potentially conflicting jobs are scheduled in the same transaction.
- </listitem>
- </itemizedlist>
- <para>Let's look at a couple of examples.</para>
-
- <section id="asyncactivity">
- <title>Async activity</title>
- <figure id="process.async.activity">
- <title>The async activity example process</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/process.async.activity.png"/></imageobject></mediaobject>
- </figure>
- <programlisting><process name="AsyncActivity"
xmlns="http://jbpm.org/4.0/jpdl">
-
- <start>
- <transition to="generate pdf"/>
- </start>
-
- <java name="generate pdf"
- <emphasis
role="bold">continue="async"</emphasis>
- class="org.jbpm.examples.async.activity.Application"
- method="generatePdf" >
- <transition to="calculate primes"/>
- </java>
-
- <java name="calculate primes"
- <emphasis
role="bold">continue="async"</emphasis>
- class="org.jbpm.examples.async.activity.Application"
- method="calculatePrimes">
- <transition to="end"/>
- </java>
-
- <end name="end"/>
-
-</process></programlisting>
- <programlisting>public class Application {
-
- public void generatePdf() {
- // assume long automatic calculations here
- }
-
- public void calculatePrimes() {
- // assume long automatic calculations here
- }
-}</programlisting>
- <programlisting>ProcessInstance processInstance =
- executionService.startProcessInstanceByKey("AsyncActivity");
-String processInstanceId = processInstance.getId();</programlisting>
- <para>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 <literal>startProcessInstanceByKey</literal>
- </para>
- <para>But with
<literal>continue="async"</literal> the execution only
- goes untill it is about to execute activity <literal>generate
pdf</literal>. Then
- an asynchronous continuation message is send and the
<literal>startProcessInstanceByKey</literal>
- method returns.
- </para>
- <para>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 job executor is not configured.
- Therefor we have to execute the jobs manually like this:
- </para>
- <programlisting>Job job = managementService.createJobQuery()
- .processInstanceId(processInstanceId)
- .uniqueResult();
-managementService.executeJob(job.getDbid());</programlisting>
- <para>That will bring the process until it's about to execute activity
- <literal>calculate primes</literal> and again an asynchronous message
is
- send.
- </para>
- <para>Then the message can be looked up again and when that message
- is executed, that transaction will run the execution till the end.
- </para>
- </section>
-
- <section id="asyncfork">
- <title>Async fork</title>
- <figure id="process.async.fork">
- <title>The async fork example process</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/process.async.fork.png"/></imageobject></mediaobject>
- </figure>
- <programlisting><process name="AsyncFork"
xmlns="http://jbpm.org/4.0/jpdl">
-
- <start >
- <transition to="fork"/>
- </start>
-
- <fork >
- <emphasis role="bold"><on event="end"
continue="exclusive" /></emphasis>
- <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></programlisting>
- <programlisting>public class Application {
-
- public void shipGoods() {
- // assume automatic calculations here
- }
-
- public void sendBill() {
- // assume automatic calculations here
- }
-}</programlisting>
- <para>By placing the asynchronous continuation on the
<literal>end</literal>
- event of the fork (<literal><on event="end"
continue="exclusive" /></literal>),
- each forked execution that takes a transition out of the
- fork will be continued asynchronously.
- </para>
- <para>Value <literal>exclusive</literal> was selected to
serialize the executions of
- the 2 asynchonous continuation jobs resulting from the fork. The respective
transactions
- that will execute activities <literal>ship goods</literal>
- and <literal>send bill</literal> 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.
- </para>
- <programlisting>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 executor
-managementService.executeJob(job.getDbid());
-
-job = jobs.get(1);
-
-// here we simulate execution of the job,
-// which is normally done by the job executor
-managementService.executeJob(job.getDbid());
-
-Date endTime = historyService
- .createHistoryProcessInstanceQuery()
- .processInstanceId(processInstance.getId())
- .uniqueResult()
- .getEndTime();
-
-assertNotNull(endTime);</programlisting>
- </section>
- </section>
-
- <section id="timer">
- <title><literal>timer</literal> </title>
- <para>A timer can be specified in the
<literal>transition</literal>
- element in wait state activities such as <literal>state</literal>s,
- <literal>task</literal>s, <literal>sub-process</literal>es
and
- <literal>group</literal>s.
- When such a timer fires, that transition is taken.
- </para>
- <para>A timer can also be specified in custom events in wait state
- activities such as <literal>state</literal>s,
- <literal>task</literal>s, <literal>sub-process</literal>es
and
- <literal>group</literal>s. The <literal>timer</literal>
element
- should then be the first element in the <literal>on</literal> element
representing
- the event. In that case the event fires upon the duedate of the timer.
- </para>
- <para>Timers are created when the activity is entered. The timer can fire
- when the execution remains in the activity until the
<literal>duedate</literal>.
- When the execution leaves the activity, the timer is cancelled.
- </para>
- <table><title><literal>timer</literal>
attributes:</title>
- <tgroup cols="5" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Attribute</entry>
- <entry>Type</entry>
- <entry>Default</entry>
- <entry>Required?</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>duedate</literal></entry>
- <entry><link linkend="duedateexpressions">duedate
expression</link></entry>
- <entry></entry>
- <entry><emphasis
role="bold">required</emphasis></entry>
- <entry>Specifies when the timer needs to fire. For
- example: <literal>20 minutes</literal> or
- <literal>3 business days</literal>
- </entry>
- </row>
- <row>
- <entry><literal>repeat</literal></entry>
- <entry><link linkend="duedateexpressions">duedate
expression</link></entry>
- <entry></entry>
- <entry>optional</entry>
- <entry>When a timer fires, this attribute specifies when the timer
- needs to fire again. For example: <literal>20 minutes</literal>
or
- <literal>3 business days</literal>
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <section id="duedateexpressions">
- <title>Duedate expressions</title>
- <para>A duedate expression has the following syntax:</para>
- <programlisting>quantity [business] {second | seconds | minute | minutes |
- hour | hours | day | days | week |
- weeks | month | months | year | years}</programlisting>
- <para>where <literal>quantity</literal> is a positive integer.
- </para>
- <para>And adding the optional indication
<literal>business</literal> means
- that only business hours should be taken into account for this duration. Without
- the indication business, the duration will be interpreted as an absolute time
period.
- How to configure business hours is explained in <xref
linkend="businesscalendar"/>
- </para>
- </section>
-
- <section id="businesscalendar">
- <title>Business calendar</title>
- <para>The default configuration will contain a reference to the file
- <literal>jbpm.business.calendar.xml</literal>. That contains a
- configuration of business hours in the following format:
- </para>
- <programlisting><?xml version="1.0"
encoding="UTF-8"?>
-
-<jbpm-configuration
xmlns="http://jbpm.org/xsd/cfg">
-
- <process-engine-context>
-
- <business-calendar>
- <monday hours="9:00-12:00 and 12:30-17:00"/>
- <tuesday hours="9:00-12:00 and 12:30-17:00"/>
- <wednesday hours="9:00-12:00 and 12:30-17:00"/>
- <thursday hours="9:00-12:00 and 12:30-17:00"/>
- <friday hours="9:00-12:00 and 12:30-17:00"/>
- <holiday period="01/07/2008 - 31/08/2008"/>
- </business-calendar>
-
- </process-engine-context>
-
-</jbpm-configuration></programlisting>
- <para>For an example of where the business calendar is used, see
- <xref linkedn="timerbusinesstime" />
- </para>
- </section>
-
- <section id="timertransition">
- <title>Timer transition</title>
- <para>Example TimerTransitionTest shows how to put a timer on a
transition.</para>
- <figure id="process.timer.transition">
- <title>The timer transition example process</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/process.timer.transition.png"/></imageobject></mediaobject>
- </figure>
- <programlisting><process name="TimerTransition"
xmlns="http://jbpm.org/4.0/jpdl">
-
- <start>
- <transition to="guardedWait" />
- </start>
-
- <state name="guardedWait">
- <transition name="go on" to="next step"
/>
- <transition name="timeout"
to="escalation">
- <emphasis role="bold"><timer duedate="10
minutes" /></emphasis>
- </transition>
- </state>
-
- <state name="next step" />
- <state name="escalation" />
-
-</process></programlisting>
- <para>When an process instance for this process is started, it arrives
immediately
- in the <literal>guardedWait</literal> state. At that time, a timer is
created that will fire
- after 10 minutes.
- </para>
- <programlisting>Execution processInstance = executionService
-
.startProcessInstanceByKey("TimerTransition");</programlisting>
- <para>With the following query, we can query for the timers related to the
newly created
- processInstance. We know that there should be exactly one such timer.
- </para>
- <programlisting>Job job = managementService.createJobQuery()
- .timers()
- .processInstanceId(processInstance.getId())
- .uniqueResult();
- </programlisting>
- <para>In a unit test, we won't use the JobExecutor to execute the timer.
Instead,
- we execute timers directly in the thread of the unit test. That way it is easy to
- simulate one scenario though an execution.
- </para>
- <para>So as the next step, we assume that the timer will fire. We simulate
this
- by executing the timer programmatically:
- </para>
-
<programlisting>managementService.executeJob(job.getDbid());</programlisting>
- <para>After that the process instance will have taken the
- <literal>timeout</literal> transition and moved to the escalation
state.
- </para>
- <programlisting>processInstance =
executionService.findExecutionById(processInstance.getId());
-assertEquals("escalation",
processInstance.getActivityName());</programlisting>
- <para>The second scenario in TimerTransitionTest shows that the
- timer is cancelled in case the signal <literal>go on</literal> is given
- before the timer fires. In that case the execution ends up in the
- <literal>next step</literal>.
- </para>
- </section>
-
- <section id="timerevent">
- <title>Timer event</title>
- <para>Example TimerEventTest shows how to put a timer on a custom
event.</para>
- <figure id="process.timer.event">
- <title>The timer event example process</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/process.timer.event.png"/></imageobject></mediaobject>
- </figure>
- <programlisting><process name="TimerEvent"
xmlns="http://jbpm.org/4.0/jpdl">
-
- <start>
- <transition to="guardedWait" />
- </start>
-
- <state name="guardedWait" >
- <emphasis role="bold"><on
event="timeout">
- <timer duedate="10 minutes"/>
- <event-listener
class="org.jbpm.examples.timer.event.Escalate" />
- </on></emphasis>
- <transition name="go on" to="next step"
/>
- </state>
-
- <state name="next step" />
-
-</process></programlisting>
- <para>In this case, if the execution is not signalled within 10 minutes after
the
- activity is started, the event <literal>timeout</literal> is fired
- and the event listener
<literal>org.jbpm.examples.timer.event.Escalate</literal>
- will be notified.
- </para>
- <para>Again, if the <literal>guardedWait</literal> activity is
ended within
- 10 minutes, then the timer is cancelled and the
<literal>Escalate</literal>
- event listener will not be notified.
- </para>
- </section>
-
- <section id="timerbusinesstime">
- <title>Timer business time</title>
- <para>Example TimerBusinessTimeTest shows how business time
works.</para>
- <figure id="process.timer.event">
- <title>The timer businesstime example process</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/process.timer.transition.png"/></imageobject></mediaobject>
- </figure>
- <programlisting><process name="TimerBusinessTime"
xmlns="http://jbpm.org/4.0/jpdl">
-
- <start>
- <transition to="guardedWait" />
- </start>
-
- <state name="guardedWait" >
- <transition name="go on" to="next step"
/>
- <transition name="timeout" to="escalation"
>
- <timer <emphasis role="bold">duedate="9 business
hours"</emphasis> />
- </transition>
- </state>
-
- <state name="next step" />
- <state name="escalation" />
-
-</process></programlisting>
- <para>Suppose that a new <literal>TimerBusinessTime</literal>
process instance is started
- at 11:30am on a tuesday. The default configured business calendar specifies
working hours
- between 9:00-12:00 and 12:30-17:00. So 9 business hours later results in an actual
duedate
- for the timer of wednesday 13:00 (1pm).
- </para>
- <para>Since we do not know when the TimerBusinessTimeTest will be ran, we
only assert
- in the test that the actual duedate of the scheduled timer at least 24 hours
ahead.
- </para>
- </section>
-
- <section id="timerrepeat">
- <title>Timer repeat</title>
- <para>Example TimerRepeatTest shows how to put a timer with a repeat. The
attribute
- <literal>repeat</literal> on a timer will cause the timer to be
rescheduled automatically
- after it is executed.
- </para>
- <figure id="process.timer.repeat">
- <title>The timer repeat example process</title>
- <mediaobject><imageobject><imagedata align="center"
fileref="images/process.timer.event.png"/></imageobject></mediaobject>
- </figure>
- <programlisting><process name="TimerRepeat"
xmlns="http://jbpm.org/4.0/jpdl">
-
- <start>
- <transition to="guardedWait" />
- </start>
-
- <state name="guardedWait">
- <on event="timeout">
- <timer duedate="20 minutes" <emphasis
role="bold">repeat="10 seconds"</emphasis> />
- <event-listener
class="org.jbpm.examples.timer.repeat.Escalate" />
- </on>
- <transition name="go on" to="next
step"/>
- </state>
-
- <state name="next step"/>
-
-</process></programlisting>
- <para>When a new process is started, a timer is created and the duedate
- will be 20 minutes ahead. When the timer fires, a new timer will be created
- with a duedate of 10 seconds ahead. When that timer fires, a new timer will
- be created again 10 seconds ahead. And so on.
- </para>
- <para>New timers will be created each time the timer fires until the
- <literal>guardedWait</literal> state activity is ended with a signal.
- When the <literal>guardedWait</literal> state activity is ended, the
- existing timer will be cancelled.
- </para>
- </section>
- </section>
-
- <section id="usercode">
- <title>User code</title>
- <para>Various elements in the jPDL process language refer to a an
- object on which an interface method will be invoked. See for example
- <xref linkend="taskassignmenthandler" />. This section describes the
- attributes and sub elements of those type of user code objects.
- </para>
- <table><title>attributes:</title>
- <tgroup cols="5" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Attribute</entry>
- <entry>Type</entry>
- <entry>Default</entry>
- <entry>Required?</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>class</literal></entry>
- <entry>classname</entry>
- <entry></entry>
- <entry><emphasis
role="bold">required</emphasis></entry>
- <entry>The fully qualified classname.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <table><title>sub elements:</title>
- <tgroup cols="3" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Element</entry>
- <entry>Multiplicity</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>field</literal></entry>
- <entry>0..*</entry>
- <entry>describes a configuration value to be injected directly in
- a memberfield before this user class is used.</entry>
- </row>
- <row>
- <entry><literal>property</literal></entry>
- <entry>0..*</entry>
- <entry>describes a configuration value to injected through a setter
- method before this user object is used.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <table><title><literal>field</literal>
attributes:</title>
- <tgroup cols="5" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Attribute</entry>
- <entry>Type</entry>
- <entry>Default</entry>
- <entry>Required?</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>name</literal></entry>
- <entry>string</entry>
- <entry></entry>
- <entry><emphasis
role="bold">required</emphasis></entry>
- <entry>the name of the field</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <table><title><literal>field</literal> sub
elements:</title>
- <tgroup cols="3" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>Element</entry>
- <entry>Multiplicity</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>string</literal></entry>
- <entry>0..1</entry>
- <entry>represents a string value</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </section>
-
-</chapter>
Copied: jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch05-Services.xml (from
rev 4967, jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch04-Services.xml)
===================================================================
--- jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch05-Services.xml
(rev 0)
+++ jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch05-Services.xml 2009-06-02
11:30:44 UTC (rev 4972)
@@ -0,0 +1,395 @@
+<chapter id="services">
+ <title>Services</title>
+
+ <section id="processdefinitionprocessinstanceandexecutions">
+ <title>Process definition, process instance and executions</title>
+ <para>A process definition is description of the steps in a procedure.
+ For example, an insurance company could have a <literal>loan</literal>
+ process definition that describes the steps of how the company deals
+ with loan requests.
+ </para>
+ <figure id="loan.process.definition.example">
+ <title>The loan process definition example</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/loan.process.definition.png"/></imageobject></mediaobject>
+ </figure>
+ <para>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 process definition.
+ </para>
+ <para>A process instance contains all the runtime state. The
+ most prominent property is the pointer that keeps track of the current activity.
+ </para>
+ <figure id="loan.process.instance.example">
+ <title>The loan process instance example</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/loan.process.instance.png"/></imageobject></mediaobject>
+ </figure>
+ <para>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:
+ </para>
+ <figure id="loan.executions.example">
+ <title>The loan executions example</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/loan.executions.png"/></imageobject></mediaobject>
+ </figure>
+ <para>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.
+ </para>
+ <para>The motivation to work with a tree structure like this is that
+ this conceptually remains simple in the case where 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 both <literal>ProcessInstance</literal>s
and
+ <literal>Execution</literal>s.
+ </para>
+ </section>
+
+ <section id="processengine">
+ <title>ProcessEngine</title>
+ <para>Interacting with jBPM occurs through services.
+ The service interfaces can be obtained from the
<literal>ProcessEngine</literal>
+ which is build from a <literal>Configuration</literal>.
+ </para>
+ <para>A <literal>ProcessEngine</literal> is thread safe and can be
stored in a
+ static member field or even better in JNDI or some other central location.
+ One <literal>ProcessEngine</literal> object can be used by all requests
and
+ threads in an application. Here's how you can obtain a
<literal>ProcessEngine</literal>
+ </para>
+
+ <para>The code snippets in this section and the next section about process
+ deployments are taken from example
+ <literal>org.jbpm.examples.services.ServicesTest</literal>
+ </para>
+
+ <programlisting>ProcessEngine processEngine = new Configuration()
+ .buildProcessEngine();</programlisting>
+
+ <para>The previous code snippet shows how to build a
<literal>ProcessEngine</literal>
+ from the default configuration file <literal>jbpm.cfg.xml</literal> which
is
+ expected in the root of the classpath. If you want to specify another
+ resource location, use the <literal>setResource</literal> method like
this:
+ </para>
+
+ <programlisting>ProcessEngine processEngine = new Configuration()
+ .setResource("my-own-configuration-file.xml")
+ .buildProcessEngine();</programlisting>
+
+ <para>There are other <literal>setXxxx</literal> methods that allow
to specify
+ the configuration content as an <literal>InputStream</literal>, an
+ <literal>xmlString</literal>, <literal>InputSource</literal>,
+ <literal>URL</literal> or <literal>File</literal>.
+ </para>
+
+ <para>From a <literal>ProcessEngine</literal> the following
services
+ can be obtained:
+ </para>
+
+ <programlisting><emphasis
role="bold">RepositoryService</emphasis> repositoryService =
processEngine.getRepositoryService();
+<emphasis role="bold">ExecutionService</emphasis> executionService
= processEngine.getExecutionService();
+<emphasis role="bold">TaskService</emphasis> taskService =
processEngine.getTaskService();
+<emphasis role="bold">HistoryService</emphasis> historyService =
processEngine.getHistoryService();
+<emphasis role="bold">ManagementService</emphasis>
managementService = processEngine.getManagementService();</programlisting>
+
+ <para>Process engine objects defined in the configuration can also be retrieved
by
+ type (<literal>processEngine.get(Class<T>)</literal>)
+ or by name (<literal>processEngine.get(String)</literal>)</para>
+
+ </section>
+
+ <section id="deployingaprocess">
+ <title>Deploying a process</title>
+ <para>The <literal>RepositoryService</literal> groups all methods
to manage
+ the repository of deployments. In this first example, we'll deploy one process
+ resource from the classpath with the
<literal>RepositoryService</literal>:
+ </para>
+ <programlisting>long deploymentDbid = repositoryService.createDeployment()
+ .addResourceFromClasspath("org/jbpm/examples/services/Order.jpdl.xml")
+ .deploy();</programlisting>
+ <para>Analogue to the <literal>addResourceFromClasspath</literal>
method above,
+ the source of the processes definitions XML can be picked up from a file, url,
string,
+ input stream or zip input stream.
+ </para>
+ <para>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
+ <literal>.jpdl.xml</literal>. Other resource types are task forms and
java classes.
+ </para>
+ <para>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 <literal>.jpdl.xml</literal>
+ extension automatically.
+ </para>
+ <para>During deployment, an <literal>id</literal> is assigned to
the process
+ definitions. The <literal>id</literal> will have format
+ <literal>{key}-{version}</literal> with a dash between key and version
+ </para>
+ <para>If <literal>key</literal> 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.
+ </para>
+ <para>The same <literal>name</literal> can only be associated to
one
+ <literal>key</literal> and vice verca.
+ </para>
+ <para>If <literal>version</literal> is not provided, a
<literal>version</literal>
+ 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 <literal>version</literal> will be
one higher
+ then the highest <literal>version</literal> number of deployed process
definitions
+ with the same <literal>key</literal>. If no process definitions with a
similar
+ <literal>key</literal> have been deployed, version number 1 is assigned.
+ </para>
+ <para>In this first example, we'll supply a name and nothing
else.</para>
+ <programlisting><process name="Insurance
claim">
+...
+</process></programlisting>
+ <para>Let's assume that this is the first time that this process gets
deployed.
+ Then it will get the following properties:
+ </para>
+ <table><title>Process properties without key</title>
+ <tgroup cols="3" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Property</entry>
+ <entry>Value</entry>
+ <entry>Source</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>name</literal></entry>
+ <entry>Insurance claim</entry>
+ <entry>process xml</entry>
+ </row>
+ <row>
+ <entry><literal>key</literal></entry>
+ <entry>Insurance_claim</entry>
+ <entry>generated</entry>
+ </row>
+ <row>
+ <entry><literal>version</literal></entry>
+ <entry>1</entry>
+ <entry>generated</entry>
+ </row>
+ <row>
+ <entry><literal>id</literal></entry>
+ <entry>Insurance_claim:1</entry>
+ <entry>generated</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>And as a second example, we'll show how you can get shorter ids by
+ specifying a process key:</para>
+ <programlisting><process name="Insurance claim"
key="ICL">
+...
+</process></programlisting>
+ <para>Then the process definition properties look like this:</para>
+ <table><title>Process properties with key</title>
+ <tgroup cols="2" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Property</entry>
+ <entry>Value</entry>
+ <entry>Source</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>name</literal></entry>
+ <entry>Insurance claim</entry>
+ <entry>process xml</entry>
+ </row>
+ <row>
+ <entry><literal>key</literal></entry>
+ <entry>ICL</entry>
+ <entry>process xml</entry>
+ </row>
+ <row>
+ <entry><literal>version</literal></entry>
+ <entry>1</entry>
+ <entry>generated</entry>
+ </row>
+ <row>
+ <entry><literal>id</literal></entry>
+ <entry>ICL:1</entry>
+ <entry>generated</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+
+ <section id="undeployingdeployments">
+ <title>Undeploying deployments</title>
+ <para>TODO</para>
+ </section>
+
+ <section id="deletingadeployment">
+ <title>Deleting a deployment</title>
+ <para>Deleting a deployment will remove it from the DB.</para>
+
<programlisting>repositoryService.deleteDeployment(deploymentDbid);</programlisting>
+ <para>That method will throw an exception when there are still active
+ process executions for process definitions in that deployment.
+ </para>
+ <para>If you want to cascade deletion of a deployment to all
+ the process instances of all the process definitions, use
+ <literal>deleteDeploymentCascade</literal>.
+ </para>
+ </section>
+
+ <section id="startinganewprocessinstance">
+ <title>Starting a new process instance</title>
+
+ <section id="inlatest">
+ <title>In latest</title>
+ <para>Simplest and most common way to start a new process instance for a
process
+ definition is like this:
+ </para>
+
<programlisting>executionService.startProcessInstanceByKey("ICL");</programlisting>
+ <para>In this case, the service method will first look up the latest version
of
+ the processes with key <literal>ICL</literal>. Then a new
+ process instance is started in that latest process definition.
+ </para>
+ <para>When a new version of the insurance claim process
+ is deployed, all invocations of
<literal>startProcessInstanceByKey</literal>
+ will automatically switch to the newly deployed version.
+ </para>
+ </section>
+
+ <section id="specificprocessversion">
+ <title>Specific process version</title>
+ <para>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:
+ </para>
+
<programlisting>executionService.startProcessInstanceById("ICL-1");</programlisting>
+ </section>
+
+ <section id="withakey">
+ <title>With a key</title>
+ <para>A new process instance can optionally be given a key. A key is
+ a user defined reference to the execution. A 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.
+ </para>
+ <programlisting>executionService.startProcessInstanceByKey("ICL",
"CL92837");</programlisting>
+ <para>The key is used to create the id of the process instance.
+ The format used is <literal>{process-key}.{execution-id}</literal>.
+ With a dot between process-key and execution-id.
+ So execution created in the previous code snippet will have id
+ <literal>ICL.CL92837</literal>.
+ </para>
+ <para>If no user defined key is provided, the DB primary key is taken
+ as the key. In that case, the id can be retrieved like this:
+ <programlisting>Execution execution =
executionService.startProcessInstanceByKey("ICL");
+String executionId = execution.getId();</programlisting>
+ </para>
+ <para>We recommend the use of a user defined keys. Typically in your
application
+ code, you'll have the key available. 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.
+ </para>
+ </section>
+
+ <section id="withvariables">
+ <title>With variables</title>
+ <para>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 process instance.
+ </para>
+ <programlisting>Map<String,Object> variables = new
HashMap<String,Object>();
+variables.put("customer", "John Doe");
+variables.put("type", "Accident");
+variables.put("amount", new Float(763.74));
+
+executionService.startProcessInstanceByKey("ICL",
variables);</programlisting>
+ </section>
+ </section>
+
+ <section id="singallingawaitingexecution">
+ <title>Signalling a waiting execution</title>
+ <para>A process definition describes what must be done in terms of activities.
+ Each activity in a process is either to be performed by the process
+ system or by an external participant. When an activity is to be performed
+ by an external participant, then the execution must wait until the
+ external participant notifies the process system that the activity is
+ completed. So an execution is either executing or waiting on an external
+ participant. Typically, you'll see that the processes are mostly
+ waiting for external participations. Especially humans tend to be slow :-)
+ The time consumed by the process system between two wait states is
+ typically very small.
+ </para>
+ <para>A <literal>state</literal> is the basic activity that
represents
+ something has to be done by an external participant and the execution
+ must wait until a signal (aka external trigger) is given.
+ </para>
+ <para>When an execution is in a wait state, it can be given an external trigger
+ with one of the signal methods. The recommended way to reference an execution
+ is by using the process definition and execution key. In the next code snippet,
+ <literal>ICL</literal> refers to the process definition key and
<literal>82436</literal>
+ refers to the execution key.
+ </para>
+ <programlisting>executionService.signalExecutionByKey("ICL",
"82436");</programlisting>
+ <para>Alternatively, the execution that must be signaled can be referenced
+ by a unique execution id. In the next snippet,
<literal>ICL.82436</literal>
+ refers to the executionId.</para>
+
<programlisting>executionService.signalExecutionById("ICL.82436");</programlisting>
+ <para>Optionally some data can be passed along with a signal: a
<literal>signalName</literal>
+ and <literal>parameters</literal>. How the signalName gets used depends
on
+ the execution's current activity. The parameters get stored as process
variables.
+ </para>
+ <programlisting>Map<String,Object> parameters = new
HashMap<String,Object>();
+parameters.put("quality", "a+");
+parameters.put("target", "profit");
+
+executionService.signalExecutionById("ICL/82436", "Accept",
parameters);</programlisting>
+ </section>
+
+ <section id="taskservice">
+ <title>TaskService</title>
+ <para>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 <literal>johndoe</literal>.
+ </para>
+ <programlisting>List<Task> taskList =
taskService.findPersonalTasks("johndoe");</programlisting>
+ <para>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.
+ </para>
+ <programlisting>long taskDbid = task.getDbid();
+
+Set<String> variableNames = taskService.getVariableNames(taskDbid);
+variables = taskService.getVariables(taskDbid, variableNames);
+
+variables = new HashMap<String, Object>();
+variables.put("category", "small");
+variables.put("lires", 923874893);
+taskService.setVariables(taskDbid, variables);</programlisting>
+ <para>and complete tasks</para>
+ <programlisting>taskService.completeTask(taskDbid);</programlisting>
+ <para>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, other users
+ will be blocked from taking the task.
+ </para>
+ <programlisting></programlisting>
+ <para>
+ People should not work on
+ a task unless they are assigned to that task. The user interface should display
+ forms 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'. Since taking a task boiles down to setting the
+ assignee to the current user, we didn't introduce a separate method for that.
+ </para>
+ <para>More on tasks in <xref linkend="tasks" /> </para>
+ </section>
+
+ <section id="historyservice">
+ <title>HistoryService</title>
+ <para>TODO</para>
+ </section>
+
+ <section id="managementservice">
+ <title>ManagementService</title>
+ <para>TODO</para>
+ </section>
+
+</chapter>
\ No newline at end of file
Property changes on:
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch05-Services.xml
___________________________________________________________________
Name: svn:mergeinfo
+
Copied: jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch06-Jpdl.xml (from rev
4967, jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch05-Jpdl.xml)
===================================================================
--- jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch06-Jpdl.xml
(rev 0)
+++ jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch06-Jpdl.xml 2009-06-02
11:30:44 UTC (rev 4972)
@@ -0,0 +1,3022 @@
+<chapter id="jpdl">
+ <title>jPDL</title>
+
+ <para>This chapter will explain the jPDL file format for describing
+ process definitions. The schemadocs can also serve as a quick reference for this
+ information.
+ </para>
+ <para>An example jPDL process file looks like this:
+ </para>
+ <programlisting><?xml version="1.0"
encoding="UTF-8"?>
+
+<process name="Purchase order"
xmlns="http://jbpm.org/4.0/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></programlisting>
+
+ <section id="process">
+ <title><literal>process</literal></title>
+ <para>The top level element representing one process definition.
+ </para>
+ <table><title><literal>process</literal>
attributes:</title>
+ <tgroup cols="5" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Attribute</entry>
+ <entry>Type</entry>
+ <entry>Default</entry>
+ <entry>Required?</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>name</literal></entry>
+ <entry>any text</entry>
+ <entry></entry>
+ <entry><emphasis
role="bold">required</emphasis></entry>
+ <entry>name or label of the process used to display to the process
+ name in user interactions.
+ </entry>
+ </row>
+ <row>
+ <entry><literal>key</literal></entry>
+ <entry>alpha numeric characters and underscores</entry>
+ <entry>if omitted, the key will be generated based on the name by
replacing
+ all non-alpha-numeric characters with underscores</entry>
+ <entry>optional</entry>
+ <entry>identification to distinct different process definitions.
+ Multiple versions of a process with the same key can be deployed.
+ The key:name combination must remain exactly the same for all
+ deployed versions.
+ </entry>
+ </row>
+ <row>
+ <entry><literal>version</literal></entry>
+ <entry>integer</entry>
+ <entry>one higher then highest version number starting with 1 if no
other process
+ is deployed with the same name/key.
+ </entry>
+ <entry>optional</entry>
+ <entry>version number of this process</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <table><title><literal>process</literal>
elements:</title>
+ <tgroup cols="3" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Element</entry>
+ <entry>Multiplicity</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>description</literal></entry>
+ <entry>0..1</entry>
+ <entry>description text</entry>
+ </row>
+ <row>
+ <entry><link
linkend="activities">activities</link></entry>
+ <entry>1..*</entry>
+ <entry>a list of any activity type can be placed here. At least
+ one <literal>start</literal> activity must be present.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+
+ <!-- ##################################################################### -->
+ <!-- ### CONTROL FLOW ACTIVITIES ### -->
+ <!-- ##################################################################### -->
+
+ <section id="controlflowactivities">
+ <title>Control flow activities</title>
+
+ <section id="start">
+ <title><literal>start</literal></title>
+ <para>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 transition and that
transition
+ is taken when a process execution starts.
+ </para>
+ <para>Known limitation: for now, a process can not have more then
+ one <literal>start</literal>.
+ </para>
+ <table><title><literal>start</literal>
attributes:</title>
+ <tgroup cols="5" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Attribute</entry>
+ <entry>Type</entry>
+ <entry>Default</entry>
+ <entry>Required?</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>name</literal></entry>
+ <entry>any text</entry>
+ <entry></entry>
+ <entry>optional</entry>
+ <entry>name of the activity. Since a start activity
+ cannot have incoming transitions, the name is optional.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table><title><literal>start</literal>
elements:</title>
+ <tgroup cols="3" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Element</entry>
+ <entry>Multiplicity</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>transition</literal></entry>
+ <entry>1</entry>
+ <entry>the outgoing transition</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+
+ <section id="state">
+ <title><literal>state</literal></title>
+ <para>A wait state. Process execution will wait until an external trigger is
+ provided through the API. Apart from the <link
linkend="commonactivitycontent">
+ common activity content</link>, <literal>state</literal>
doesn't have any extra
+ attributes or elements.
+ </para>
+ <section id="statesequence">
+ <title><literal>state</literal> sequence</title>
+ <para>Let's look at an example which shows states connected with
transitions
+ as a sequence</para>
+ <figure id="process.state.sequence">
+ <title>A sequence of states</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/process.state.sequence.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting><process name="StateSequence"
xmlns="http://jbpm.org/4.0/jpdl">
+
+ <start>
+ <transition to="a" />
+ </start>
+
+ <state name="a">
+ <transition to="b" />
+ </state>
+
+ <state name="b">
+ <transition to="c" />
+ </state>
+
+ <state name="c" />
+
+</process></programlisting>
+ <para>After you start an execution like this:</para>
+ <programlisting>Execution execution =
executionService.startProcessInstanceByKey("StateSequence");</programlisting>
+ <para>the created process instance will be positioned in
+ state <literal>a</literal>. Providing an external trigger can
+ be done with the <literal>signalExecution</literal>
methods.</para>
+ <programlisting>String executionId = execution.getId();
+execution = executionService.signalExecutionById(executionId);</programlisting>
+ </section>
+ <section id="statechoice">
+ <title><literal>state</literal> choice</title>
+ <para>In this second example with states, we'll show how you can use a
+ <literal>state</literal> can be used to feed in an external choice of
+ the path to take.
+ </para>
+ <figure id="process.state.choice">
+ <title>A choice between state</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/process.state.choice.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting><process name="StateChoice"
xmlns="http://jbpm.org/4.0/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></programlisting>
+ <para>Let's start a new process instance for this process
definition:</para>
+ <programlisting>Execution execution =
executionService.startProcessInstanceByKey("StateSequence");</programlisting>
+ <para>Now, the execution is arrived in the <literal>wait for
response</literal>.
+ The execution will wait there until an external trigger is given. In case
+ a <literal>state</literal> 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 signalName <literal>accept</literal>
like this:
+ </para>
+ <programlisting>executionService.signalExecutionById(executionId,
"accept");</programlisting>
+ <para>Then the execution will continue over the outgoing transition named
+ <literal>accept</literal>. Analogue, when signalName
<literal>reject</literal>
+ is given in the signalExecutionXxx methods, the execution will continue over
+ the outgoing transition named reject.
+ </para>
+ </section>
+ </section>
+
+ <section id="decision">
+ <title><literal>decision</literal></title>
+ <para>Takes one path of many alternatives. Also known as a decision. A
decision
+ activity has multiple outgoing transitions and when an execution arrives in a
decision
+ activity, an automatic evaluation will decide which outgoing transition is taken.
+ </para>
+ <para>A decision activity should be configured in one of the three following
ways:
+ </para>
+
+ <section id="decisionconditions">
+ <title>Decision conditions</title>
+ <para>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.
+ </para>
+
<table><title><literal>decision.transition.condition</literal>
attributes:</title>
+ <tgroup cols="5" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Attribute</entry>
+ <entry>Type</entry>
+ <entry>Default</entry>
+ <entry>Required?</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>expr</literal></entry>
+ <entry>expression</entry>
+ <entry></entry>
+ <entry><emphasis
role="bold">required</emphasis></entry>
+ <entry>script that will be evaluated in the specified
+ expression language.
+ </entry>
+ </row>
+ <row>
+ <entry><literal>lang</literal></entry>
+ <entry>expression language</entry>
+ <entry>the
<literal>default-expression-language</literal> taken from the <link
linkend="scripting"><literal>script-manager</literal>
configuration</link></entry>
+ <entry>optional</entry>
+ <entry>the language in which <literal>expr</literal> is
+ to be evaluated.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>Example:
+ </para>
+ <figure id="process.decision.condition">
+ <title>The decision conditions example process</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/process.decision.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting><process name="DecisionConditions"
>
+
+ <start>
+ <transition to="evaluate document" />
+ </start>
+
+ <decision name="evaluate document">
+ <transition to="submit document">
+ <emphasis role="bold"><condition
expr="#{content=="good"}" /></emphasis>
+ </transition>
+ <transition to="try again">
+ <emphasis role="bold"><condition
expr="#{content=="not so good"}"
/></emphasis>
+ </transition>
+ <transition to="give up" />
+ </decision>
+
+ <state name="submit document" />
+
+ <state name="try again" />
+
+ <state name="give up" />
+
+</process></programlisting>
+ </section>
+
+ <section id="decisionexpression">
+ <title>Decision expression</title>
+ <para>A decision expression evaluates to a String representing the name of
+ an outgoing transition.
+ </para>
+ <table><title><literal>decision</literal>
attributes:</title>
+ <tgroup cols="5" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Attribute</entry>
+ <entry>Type</entry>
+ <entry>Default</entry>
+ <entry>Required?</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>expr</literal></entry>
+ <entry>expression</entry>
+ <entry></entry>
+ <entry><emphasis
role="bold">required</emphasis></entry>
+ <entry>script that will be evaluated in the specified
+ expression language.
+ </entry>
+ </row>
+ <row>
+ <entry><literal>lang</literal></entry>
+ <entry>expression language</entry>
+ <entry>the
<literal>default-expression-language</literal> taken from the <link
linkend="scripting"><literal>script-manager</literal>
configuration</link></entry>
+ <entry>optional</entry>
+ <entry>the language in which <literal>expr</literal> is
+ to be evaluated.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>Example:
+ </para>
+ <figure id="process.decision.expression">
+ <title>The decision expression example process</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/process.decision.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting><process name="Poolcar">
+ <start>
+ <transition to="How far?" />
+ </start>
+ <decision name="How far?" <emphasis
role="bold">expr="#{distance}"</emphasis>>
+ <transition name="far" to="Big car"
/>
+ <transition name="nearby" to="Small car"
/>
+ </decision>
+ <state name="Big car" />
+ <state name="Small car" />
+</process></programlisting>
+ <para>When you start an new process instance like this
+ </para>
+ <programlisting>Map<String, Object> variables = new
HashMap<String, Object>();
+variables.put("distance", "far");
+Execution execution =
executionService.startProcessInstanceByKey("Poolcar",
variables);</programlisting>
+ <para>then the new execution will go to activity <literal>Big
car</literal>.</para>
+ </section>
+
+ <section id="decisionhandler">
+ <title>Decision handler</title>
+ <para>A decision handler is a java class that implements the
+ <literal>DecisionHandler</literal> interface. The decision handler
+ will be responsible for selecting the name of the outgoing transition.
+ </para>
+ <programlisting>public interface DecisionHandler {
+ String select(OpenExecution execution);
+}</programlisting>
+ <para>The handler is specified as a sub element of the
decision</para>
+ <table><title><literal>decision.handler</literal>
attributes:</title>
+ <tgroup cols="5" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Attribute</entry>
+ <entry>Type</entry>
+ <entry>Default</entry>
+ <entry>Required?</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>class</literal></entry>
+ <entry>classname</entry>
+ <entry></entry>
+ <entry><emphasis
role="bold">required</emphasis></entry>
+ <entry>fully qualified classname of the handler implementation
class.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>Here's an example process of a decision using a
DecisionHandler:</para>
+ <figure id="process.decision.handler">
+ <title>The decision handler example process</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/process.decision.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting><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></programlisting>
+ <para>The ContentEvaluation class looks like this</para>
+ <programlisting>public class ContentEvaluation implements DecisionHandler
{
+
+ public String select(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";
+ }
+}</programlisting>
+ <para>Now, when we start a process instance and supply value
+ <literal>you're great</literal> for variable content, then the
+ ContentEvaluation will return String <literal>good</literal> and
+ the process instance will arrive in activity <literal>Submit
document</literal>.
+ </para>
+ </section>
+
+ </section>
+
+ <section id="concurrency">
+ <title><literal>concurrency</literal></title>
+ <para>With the <literal>fork</literal> and
<literal>join</literal> activities,
+ concurrent paths of executions can be modeled.
+ </para>
+ <table><title><literal>join</literal>
attributes:</title>
+ <tgroup cols="5" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Attribute</entry>
+ <entry>Type</entry>
+ <entry>Default</entry>
+ <entry>Required?</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>multiplicity</literal></entry>
+ <entry>integer</entry>
+ <entry>nbr of incoming transitions</entry>
+ <entry>optional</entry>
+ <entry>The number of executions that should arrive in this join
+ before the join activates and push an execution out the single
+ outgoing transition of the join.
+ </entry>
+ </row>
+ <row>
+ <entry><literal>lockmode</literal></entry>
+ <entry>{none, read, upgrade, upgrade_nowait, write}</entry>
+ <entry>upgrade</entry>
+ <entry>optional</entry>
+ <entry>the hibernate lock mode applied on the parent execution to
+ prevent that 2 concurrent transactions see each other as not yet
+ arrived at the join, causing a process deadlock.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>For example:</para>
+ <figure id="process.concurrency">
+ <title>The concurrency example process</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/process.concurrency.png"/></imageobject></mediaobject>
+ </figure>
+
+ <programlisting><process
name="ConcurrencyGraphBased"
xmlns="http://jbpm.org/4.0/jpdl">
+
+ <start>
+ <transition to="fork"/>
+ </start>
+
+ <emphasis role="bold"><fork
name="fork">
+ <transition to="send invoice" />
+ <transition to="load truck"/>
+ <transition to="print shipping documents" />
+ </fork></emphasis>
+
+ <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>
+
+ <emphasis role="bold"><join name="shipping
join" >
+ <transition to="drive truck to destination" />
+ </join></emphasis>
+
+ <state name="drive truck to destination" >
+ <transition to="final join" />
+ </state>
+
+ <emphasis role="bold"><join name="final join"
>
+ <transition to="end"/>
+ </join></emphasis>
+
+ <end name="end" />
+
+</process></programlisting>
+ </section>
+
+ <!-- ### END ########################################################### -->
+
+ <section id="end">
+ <title><literal>end</literal></title>
+ <para>Ends the execution.
+ </para>
+ <section id="endprocessinstance">
+ <title><literal>end</literal> process instance</title>
+ <para>By default, an end activity will end the complete
+ process instance. In case multiple concurrent executions
+ are still active within the same process instance, all of
+ them will be ended.
+ </para>
+ <figure id="process.end.processinstance">
+ <title>The end event</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/process.end.processinstance.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting><process name="EndProcessInstance"
xmlns="http://jbpm.org/4.0/jpdl">
+
+ <start>
+ <transition to="end" />
+ </start>
+
+ <end name="end" />
+
+</process></programlisting>
+ <para>When a new process instance is created, it immediately
ends.</para>
+ </section>
+ <section id="endexecution">
+ <title><literal>end</literal> execution</title>
+ <para>Only the execution that arrives in the
+ end activity will be ended and other concurrent executions
+ should be left active. To get this behaviour, set
+ attribute <literal>ends="execution"</literal>
+ </para>
+ <table><title><literal>end</literal> execution
attributes:</title>
+ <tgroup cols="5" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Attribute</entry>
+ <entry>Type</entry>
+ <entry>Default</entry>
+ <entry>Required?</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>ends</literal></entry>
+ <entry>{processinstance|execution}</entry>
+ <entry>processinstance</entry>
+ <entry>optional</entry>
+ <entry>specifies if the whole process instance should be ended or
+ just the path of execution that arrives in the end activity.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="endmultiple">
+ <title><literal>end</literal> multiple</title>
+ <para>A process can have multiple end events. This can be handy to
indicate
+ different outcomes of a process instance. For example
+ </para>
+ <figure id="process.end.multiple">
+ <title>Multiple end events</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/process.end.multiple.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting><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>
+ </programlisting>
+ <para>Now if we would start an execution and signal it to move out of the
<literal>get return code</literal> wait state with the
+ following code, the execution would end with the <literal>bad
request</literal> end event.</para>
+ <programlisting>Execution execution =
executionService.startProcessInstanceByKey("EndMultiple");
+String executionId = execution.getId();
+execution = executionService.signalExecutionById(executionId, "400");
+ </programlisting>
+ <para>Likewise, using the value <literal>200</literal> or
<literal>500</literal> would cause the execution
+ to end with the <literal>ok</literal> or with the
<literal>internal server error</literal> end events
+ respectively.</para>
+ </section>
+
+ <section id="endstate">
+ <title><literal>end</literal> state</title>
+ <para>An execution can also end with different states. It is another way to
specify the outcome of a process.
+ It is indicated by the <literal>state</literal> attribute of the end
event or by the <literal>end-cancel</literal>
+ and <literal>end-error</literal> shortcut notations.
+ </para>
+
+ <table><title><literal>end</literal> execution
attributes:</title>
+ <tgroup cols="5" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Attribute</entry>
+ <entry>Type</entry>
+ <entry>Default</entry>
+ <entry>Required?</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>state</literal></entry>
+ <entry>String</entry>
+ <entry></entry>
+ <entry>optional</entry>
+ <entry>the state assigned to the execution.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>Take for example the following process.
+ </para>
+ <figure id="process.end.state">
+ <title>Different end states</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/process.end.state.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting><process name="EndState"
xmlns="http://jbpm.org/4.0/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>
+ </programlisting>
+ <para>This time, if we would start an execution and signal it to move out
of the <literal>get return code</literal> wait state with the
+ following code, the execution would end with the
<literal>cancel</literal> state.</para>
+ <programlisting>Execution execution =
executionService.startProcessInstanceByKey("EndState");
+String executionId = execution.getId();
+execution = executionService.signalExecutionById(executionId, "400");
+ </programlisting>
+ <para>Similarly as above, using the value
<literal>200</literal> or <literal>500</literal> would cause the
execution
+ to end with the <literal>completed</literal> or with the
<literal>error</literal> states
+ respectively.</para>
+ </section>
+ </section>
+
+ <!-- ### TASK ########################################################## -->
+
+ <section id="task">
+ <title><literal>task</literal></title>
+
+ <para>Creates a task for a person in the task component.</para>
+
+ <!-- ~~~ TASK ASSIGNEE ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
+
+ <section id="taskassignee">
+ <title><literal>task</literal> assignee</title>
+ <para>A simple task that will be assigned to a specific user
+ </para>
+ <table><title><literal>task</literal>
attributes:</title>
+ <tgroup cols="5" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Attribute</entry>
+ <entry>Type</entry>
+ <entry>Default</entry>
+ <entry>Required?</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>assignee</literal></entry>
+ <entry>expression</entry>
+ <entry></entry>
+ <entry>optional</entry>
+ <entry>userId referring to the person that is responsible for
+ completing this task.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <figure id="process.task.assignee">
+ <title>The task assignee example process</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/process.task.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting><process
name="TaskAssignee">
+
+ <start>
+ <transition to="review" />
+ </start>
+
+ <task name="review"
+ <emphasis
role="bold">assignee="#{order.owner}"</emphasis>>
+
+ <transition to="wait" />
+ </task>
+
+ <state name="wait" />
+
+</process></programlisting>
+ <para>This process shows 2 aspects of task assignment. First, that the
+ attribute <literal>assignee</literal> 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.
+ </para>
+ <para>Secondly, this attribute is by default evaluated as an expression.
+ In this case the task is assigned to
<literal>#{order.owner}</literal>.
+ 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 <literal>getOwner()</literal>
getter
+ will be used to get the userId that references the user that is
+ responsible for completing this task.
+ </para>
+ <para>Here's the Order class used in our example:</para>
+ <programlisting>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;
+ }
+}</programlisting>
+ <para>Next a new process instance is created with an order as a process
+ variable.</para>
+ <programlisting>Map<String, Object> variables = new
HashMap<String, Object>();
+variables.put("order", new Order("johndoe"));
+Execution execution = executionService
+ .startProcessInstanceByKey("TaskAssignee",
variables);</programlisting>
+ <para>Then the task list for <literal>johndoe</literal> can be
obtained like this.</para>
+ <programlisting>List<Task> taskList =
taskService.findPersonalTasks("johndoe");</programlisting>
+ <para>Note that it is also possible to put plain text like
+ <literal>assignee="johndoe"</literal>. In that
case
+ the task will be assigned to johndoe.
+ </para>
+ </section>
+
+ <!-- ~~~ TASK CANDIDATES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
+
+ <section id="taskcandidates">
+ <title><literal>task</literal> candidates</title>
+ <para>A task that will be offered to a group of users. One of the users
should then
+ take the task in order to complete it.
+ </para>
+ <table><title><literal>task</literal>
attributes:</title>
+ <tgroup cols="5" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Attribute</entry>
+ <entry>Type</entry>
+ <entry>Default</entry>
+ <entry>Required?</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+
<entry><literal>candidate-groups</literal></entry>
+ <entry>expression</entry>
+ <entry></entry>
+ <entry>optional</entry>
+ <entry>resolves to a comma separated list of groupIds.
+ All the people in the groups will be candidates for this
+ task.</entry>
+ </row>
+ <row>
+
<entry><literal>candidate-users</literal></entry>
+ <entry>expression</entry>
+ <entry></entry>
+ <entry>optional</entry>
+ <entry>resolves to a comma separated list of userIds.
+ All the users will be candidates for this task.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <figure id="process.task.candidates">
+ <title>The task candidates example process</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/process.task.png"/></imageobject></mediaobject>
+ </figure>
+ <para>Here's an example process using task candidates:</para>
+ <programlisting><process
name="TaskCandidates">
+
+ <start>
+ <transition to="review" />
+ </start>
+
+ <task name="review"
+ <emphasis
role="bold">candidate-groups="sales-dept"</emphasis>>
+
+ <transition to="wait" />
+ </task>
+
+ <state name="wait"/>
+
+</process>
+ </programlisting>
+ <para>After starting, a task will be created. The task will not show up in
anyone's
+ personal task list. Following task lists will be empty.
+ </para>
+ <programlisting>taskService.getAssignedTasks("johndoe");
+taskService.getAssignedTasks("joesmoe");</programlisting>
+ <para>But the task will show up in the group task list of all members of
the <literal>sales-dept</literal>
+ group.
+ </para>
+ <para>The in our example, the <literal>sales-dept</literal> has
two members: johndoe and joesmoe</para>
+
<programlisting>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"); </programlisting>
+ <para>So after the process is created, the task will appear in both the
+ group tasks for users johndoe and joesmoe</para>
+ <programlisting>taskService.findGroupTasks("johndoe");
+taskService.findGroupTasks("joesmoe");</programlisting>
+ <para>Candidates must take a task before they can work on it. This will
prevent
+ that two candides start working on the same task. The user interface must only
+ offer the action 'Take' for the tasks in the group task list.
+ </para>
+ <programlisting>taskService.takeTask(task.getDbid(),
"johndoe");</programlisting>
+ <para>When a user takes a task, the assignee of that task will be set to
the given
+ user. The task will disappear from all the candidate's group task list and
+ it will appear in the user's assigned tasks.
+ </para>
+ <para>Users are only allowed to work on tasks in their personal task list.
This
+ should be enforced by the user interface.</para>
+ <para>Similarly, the attribute
<literal>candidate-users</literal> can be used that
+ resolves to a comma separated list of userIds. The
<literal>candidate-users</literal>
+ attribute can be used in combination with other assignment options.
+ </para>
+ </section>
+
+ <!-- ~~~ TASK ASSIGNMENT HANDLER ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
+
+ <section id="taskassignmenthandler">
+ <title><literal>task</literal> assignment
handler</title>
+ <para>An <literal>AssignmentHandler</literal> can be used to
calculate the
+ assignee and the candidates for a task programmatically.
+ </para>
+ <programlisting>public interface <emphasis
role="bold">AssignmentHandler</emphasis> extends Serializable {
+
+ /** sets the actorId and candidates for the given assignable. */
+ void assign(Assignable assignable, OpenExecution execution) throws Exception;
+}</programlisting>
+ <para><literal>Assignable</literal> is a common interface for
Tasks and
+ Swimlanes. So AssignmentHandlers can be used for tasks as well as swimlanes
+ (see later).
+ </para>
+ <para><literal>assignment-handler</literal> is a sub element of
the task element.
+ It specifies a user code object. So the attributes and elements of
<literal>assignment-handler</literal>
+ are documented in <xref linkend="usercode" />
+ </para>
+ <para>Let's look at the task assignment example process.</para>
+ <figure id="process.task.assignmenthandler">
+ <title>The task assignment handler example process</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/process.task.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting><process
name="TaskAssignmentHandler"
xmlns="http://jbpm.org/4.0/jpdl">
+
+ <start g="20,20,48,48">
+ <transition to="review" />
+ </start>
+
+ <task name="review"
g="96,16,127,52">
+ <emphasis role="bold"><assignment-handler
class="org.jbpm.examples.task.assignmenthandler.AssignTask">
+ <field name="assignee">
+ <string value="johndoe" />
+ </field>
+ </assignment-handler></emphasis>
+ <transition to="wait" />
+ </task>
+
+ <state name="wait" g="255,16,88,52"
/>
+
+</process></programlisting>
+ <para>The referenced class <literal>AssignTask</literal> looks
like this: </para>
+ <programlisting>public class AssignTask implements AssignmentHandler {
+
+ String assignee;
+
+ public void assign(Assignable assignable, OpenExecution execution) {
+ assignable.setAssignee(assignee);
+ }
+}</programlisting>
+ <para>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 candidate users and groups.
+ </para>
+ <para>Starting a new process instance of the
<literal>TaskAssignmentHandler</literal>
+ process will immediately bring the new execution to the task activity. A new
+ <literal>review</literal> task is created and at that point, the
<literal>AssignTask</literal>
+ assignment handler is called. That will set
<literal>johndoe</literal> as
+ the assignee. So John Doe will find the task in his personal task list.
+ </para>
+ </section>
+
+ <!-- ~~~ TASK SWIMLANES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
+
+ <section id="taskswimlanes">
+ <title><literal>task</literal> swimlanes</title>
+ <para>Multiple tasks in a process should be assigned to the same
+ user or candidates. Multiple tasks in a process can be 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 to those user and candidates.
+ </para>
+ <para>A swimlane can also be considered as a process role. In some
+ cases, this might boil down to authorization roles in the
+ identity component. But bare in mind that it is not always the
+ same thing.</para>
+ <table><title><literal>task</literal>
attributes:</title>
+ <tgroup cols="5" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Attribute</entry>
+ <entry>Type</entry>
+ <entry>Default</entry>
+ <entry>Required?</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>swimlane</literal></entry>
+ <entry>swimlane (string)</entry>
+ <entry></entry>
+ <entry>optional</entry>
+ <entry>refers to a swimlane that is declared in the
process</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>Swimlanes can be declared inside a process element:</para>
+ <table><title><literal>swimlane</literal>
attributes:</title>
+ <tgroup cols="5" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Attribute</entry>
+ <entry>Type</entry>
+ <entry>Default</entry>
+ <entry>Required?</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>name</literal></entry>
+ <entry>swimlane (string)</entry>
+ <entry></entry>
+ <entry><emphasis
role="bold">required</emphasis></entry>
+ <entry>Name for this swimlane. This is the
+ name that will be referenced by task swimlane attributes.
+ </entry>
+ </row>
+ <row>
+ <entry><literal>assignee</literal></entry>
+ <entry>expression</entry>
+ <entry></entry>
+ <entry>optional</entry>
+ <entry>userId referring to the person that is responsible for
+ completing this task.</entry>
+ </row>
+ <row>
+
<entry><literal>candidate-groups</literal></entry>
+ <entry>expression</entry>
+ <entry></entry>
+ <entry>optional</entry>
+ <entry>resolves to a comma separated list of groupIds.
+ All the people in the groups will be candidates for this
+ the tasks in this swimlane.</entry>
+ </row>
+ <row>
+
<entry><literal>candidate-users</literal></entry>
+ <entry>expression</entry>
+ <entry></entry>
+ <entry>optional</entry>
+ <entry>resolves to a comma separated list of userIds.
+ All the users will be candidates for the
+ tasks in this swimlane.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <figure id="process.task.swimlane">
+ <title>The task swimlane example process</title>
+
+ <!-- KOEN: volgende image moet aangepast worden naar
+ images/process.task.swimlane.png
+ nadat je die hebt toegevoegd aan de images directory -->
+
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/process.task.png"/></imageobject></mediaobject>
+ </figure>
+ <para>The task swimlane example has the following process file
:</para>
+ <programlisting><process name="TaskSwimlane"
xmlns="http://jbpm.org/4.0/jpdl">
+
+ <emphasis role="bold"><swimlane name="sales
representative"
+ candidate-groups="sales-dept" /></emphasis>
+
+ <start>
+ <transition to="enter order data" />
+ </start>
+
+ <task name="enter order data"
+ <emphasis role="bold">swimlane="sales
representative"</emphasis>>
+
+ <transition to="calculate quote"/>
+ </task>
+
+ <task
+ name="calculate quote"
+ <emphasis role="bold">swimlane="sales
representative"</emphasis>>
+ </task>
+
+</process></programlisting>
+ <para>In this example we create the following information in the identity
+ component:</para>
+
<programlisting>identityService.createGroup("sales-dept");
+
+identityService.createUser("johndoe", "johndoe",
"John", "Doe");
+identityService.createMembership("johndoe",
"sales-dept");</programlisting>
+ <para>After starting a new process instance, user
<literal>johndoe</literal> will
+ be a candidate for task <literal>enter order data</literal>. Again
like in the
+ previous task candidates example, John Doe can now take this task like this:
+ </para>
+ <programlisting>taskService.takeTask(taskDbid,
"johndoe");</programlisting>
+ <para>Taking the task will make Lit<literal>johndoe</literal>
the assignee for
+ the task. And since this task is coupled to the swimlane
+ <literal>sales representative</literal>, assignee
<literal>johndoe</literal> will
+ also be propagated as the assignee in the swimlane.</para>
+ <para>Next, John Doe can complete the task like this:</para>
+ <programlisting>taskService.completeTask(taskDbid);</programlisting>
+ <para>Completing the task will bring the process execution to the
+ next task, which is <literal>calculate quote</literal>. Also
+ this task is linked to the swimlane. Therefore, the task will be
+ assigned to <literal>johndoe</literal>. Also the candidate users
+ and candidate groups of the initial assignment will be copied from
+ the swimlane to the task. This is relevant in case user
<literal>johndoe</literal>
+ would release the task and offer it back to the other candidates.
+ </para>
+ </section>
+
+ <!-- ~~~ TASK VARIABLES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
+
+ <section id="taskvariables">
+ <title><literal>task</literal> variables</title>
+ <para>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 comes from the task and the process instance. Then
+ input from the user is translated in setting task variables.
+ </para>
+ <para>Getting task variables can be done like this:</para>
+ <programlisting>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);</programlisting>
+ <para>And setting task variables can be done like this:</para>
+ <programlisting>variables = new HashMap<String, Object>();
+variables.put("category", "small");
+variables.put("lires", 923874893);
+
+taskService.setVariables(taskDbid, variables);</programlisting>
+ </section>
+
+ <!-- ~~~ MAIL SUPPORT IN TASKS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-->
+
+ <section id="mailintasks">
+ <title>e-mail support in tasks</title>
+ <para>It is possible to provide assignees with notifications when a task
+ is added to their list, as well as reminders at specific intervals.
+ Every email message is produced from a template. Templates may be specified
+ inline or in the <literal>process-engine-context</literal> section
of the
+ configuration file.</para>
+ <table><title><literal>task</literal>
elements</title>
+ <tgroup cols="3" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Element</entry>
+ <entry>Multiplicity</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>notification</entry>
+ <entry>0..1</entry>
+ <entry>Sends a notification message when a task is assigned.
+ If no template is referenced or supplied inline, mail support
+ falls back on the template named
<emphasis>task-notification</emphasis>.
+ </entry>
+ </row>
+ <row>
+ <entry>reminder</entry>
+ <entry>0..1</entry>
+ <entry>Sends a reminder message at specific intervals.
+ If no template is referenced or supplied inline, mail support
+ falls back on the template named
<emphasis>task-reminder</emphasis>.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>Here is a basic example that accepts the default
templates.</para>
+ <programlisting><![CDATA[<task name="review"
+ assignee="#{order.owner}"
+ <notification/>
+ <reminder duedate="2 days" repeat="1 day"/>
+</task>]]></programlisting>
+ <para>Refer to the <link linkend="mailsupport">mail
chapter</link> for full details
+ on mail support.</para>
+ </section>
+ </section>
+
+ <!-- ### SUB-PROCESS ################################################## -->
+
+ <section id="subprocess">
+ <title><literal>sub-process</literal></title>
+
+ <para>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.
+ </para>
+
+ <table><title><literal>sub-process</literal>
attributes:</title>
+ <tgroup cols="5" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Attribute</entry>
+ <entry>Type</entry>
+ <entry>Default</entry>
+ <entry>Required?</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>sub-process-id</literal></entry>
+ <entry>string</entry>
+ <entry></entry>
+ <entry>either this or sub-process-key is required</entry>
+ <entry>Identifies the sub process by the id. This means that a
specific
+ version of a process definition is referenced.</entry>
+ </row>
+ <row>
+ <entry><literal>sub-process-key</literal></entry>
+ <entry>string</entry>
+ <entry></entry>
+ <entry>either this or sub-process-key is required</entry>
+ <entry>Identifies the sub process by the key. This means that the
latest
+ version of the process definition with the given key is referenced. The
latest version
+ of the process is looked up each time the activity executes.
+ </entry>
+ </row>
+ <row>
+ <entry><literal>outcome</literal></entry>
+ <entry>expression</entry>
+ <entry></entry>
+ <entry>required when transitions have
<literal>outcome-value</literal>'s specified</entry>
+ <entry>Expression that is evaluated when the sub process
+ instance ends. The value is then used for outcome transition mapping.
+ Add <literal>outcome-value</literal> elements to the outgoing
transitions
+ of this <literal>sub-process</literal> activity.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <table><title><literal>sub-process</literal>
elements:</title>
+ <tgroup cols="3" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Element</entry>
+ <entry>Multiplicity</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>parameter-in</literal></entry>
+ <entry>0..*</entry>
+ <entry>Declares a variable that is passed to the sub process instance
+ when it is created.
+ </entry>
+ </row>
+ <!--
+ <row>
+ <entry><literal>swimlane-mapping</literal></entry>
+ <entry>0..*</entry>
+ <entry>Declares a swimlane that will be propagated to the sub process
+ instance when the sub process is created.
+ </entry>
+ </row>
+ -->
+ <row>
+ <entry><literal>parameter-out</literal></entry>
+ <entry>0..*</entry>
+ <entry>Declares a variable that will be set in the super process
execution
+ when the sub process ends.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <table><title><literal>parameter-in</literal>
attributes:</title>
+ <tgroup cols="5" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Attribute</entry>
+ <entry>Type</entry>
+ <entry>Default</entry>
+ <entry>Required?</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>subvar</literal></entry>
+ <entry>string</entry>
+ <entry></entry>
+ <entry><emphasis
role="bold">required</emphasis> </entry>
+ <entry>The name of the sub process variable in which the value is
set.</entry>
+ </row>
+ <row>
+ <entry><literal>var</literal></entry>
+ <entry>string</entry>
+ <entry></entry>
+ <entry>exactly one of {'var', 'expr'} is required to
specify the value</entry>
+ <entry>The name of the variable in the super process execution
context.</entry>
+ </row>
+ <row>
+ <entry><literal>expr</literal></entry>
+ <entry>string</entry>
+ <entry></entry>
+ <entry>exactly one of {'var', 'expr'} is required to
specify the value</entry>
+ <entry>An expression that will be resolved in the <emphasis
role="bold">super</emphasis> process execution
+ context. The resulting value will be set in the sub process variable.
+ </entry>
+ </row>
+ <row>
+ <entry><literal>lang</literal></entry>
+ <entry>string</entry>
+ <entry>juel</entry>
+ <entry>optional</entry>
+ <entry>The scripting language in which the expression should be
resolved.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <table><title><literal>parameter-out</literal>
attributes:</title>
+ <tgroup cols="5" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Attribute</entry>
+ <entry>Type</entry>
+ <entry>Default</entry>
+ <entry>Required?</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>var</literal></entry>
+ <entry>string</entry>
+ <entry></entry>
+ <entry><emphasis
role="bold">required</emphasis></entry>
+ <entry>The name of the variable in the super process execution
context
+ in which the value will be set.</entry>
+ </row>
+ <row>
+ <entry><literal>subvar</literal></entry>
+ <entry>string</entry>
+ <entry></entry>
+ <entry>exactly one of {'subvar', 'expr'} is required
to specify the value</entry>
+ <entry>The name of the sub process variable from which the value
+ will be taken.</entry>
+ </row>
+ <row>
+ <entry><literal>expr</literal></entry>
+ <entry>string</entry>
+ <entry></entry>
+ <entry>exactly one of {'subvar', 'expr'} is required
to specify the value</entry>
+ <entry>An expression that will be resolved in the <emphasis
role="bold">sub</emphasis> process execution
+ context. The resulting value will be set in the super process variable.
+ </entry>
+ </row>
+ <row>
+ <entry><literal>lang</literal></entry>
+ <entry>string</entry>
+ <entry>juel</entry>
+ <entry>optional</entry>
+ <entry>The scripting language in which the expression should be
resolved.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <table><title>Extra <literal>transition</literal> elements
in case of outcome variable mappings:</title>
+ <tgroup cols="3" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Element</entry>
+ <entry>Multiplicity</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>outcome-value</literal></entry>
+ <entry>0..1</entry>
+ <entry>If the <literal>outcome</literal> matches the
value, this
+ transition is taken after the sub-process ended. The value is specified
with one child
+ element.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <!-- ~~~ SUB PROCESS VARIABLES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
+ <section id="subprocessvariables">
+ <title><literal>sub-process</literal> variables</title>
+ <para>The SubProcessVariables example scenario will show the basic workings
of the
+ sub-process activity, how to feed information in the sub process when it starts
+ and how to extract information out of the subprocess when it ends.
+ </para>
+ <para>The parent process involves a document that needs to be
reviewed.</para>
+ <figure id="process.subprocess.variables.document">
+ <title>The subprocess document example process</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/process.task.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting><process name="SubProcessDocument"
xmlns="http://jbpm.org/4.0/jpdl">
+
+ <start>
+ <transition to="review" />
+ </start>
+
+ <emphasis role="bold"><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></emphasis>
+
+ <state name="wait"/>
+
+</process></programlisting>
+ <para>The review process is a reusable process for all kinds of
reviews.</para>
+ <figure id="process.subprocess.variables.review">
+ <title>The subprocess review example process</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/process.subprocess.review.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting><process name="SubProcessReview"
xmlns="http://jbpm.org/4.0/jpdl">
+
+ <start>
+ <transition to="get approval"/>
+ </start>
+
+ <task name="get approval"
+ assignee="johndoe">
+
+ <transition to="end"/>
+ </task>
+
+ <end name="end" />
+
+</process></programlisting>
+ <para>The document process is started with a document
variable:</para>
+ <programlisting>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);</programlisting>
+ <para>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 <literal>SubProcessReview</literal>
process
+ instance starts, it arrives in the <literal>task</literal>. A task
will be
+ created for <literal>johndoe</literal>.
+ </para>
+ <programlisting>List<Task> taskList =
taskService.findPersonalTasks("johndoe");
+Task task = taskList.get(0);</programlisting>
+ <para>We can see that the document has been passed from the super process
+ instance to the sub process instance:
+ </para>
+ <programlisting>String document = (String)
taskService.getVariable(task.getDbid(), "document");
+assertEquals("This document describes how we can make more money...",
document);</programlisting>
+ <para>Then we set a variable on the task. This is typically done through a
form. But
+ here we'll show how it is done programmatically.
+ </para>
+ <programlisting>taskService.setVariable(task.getDbid(),
"result", "accept");</programlisting>
+ <para>Completing this task, will cause the sub process instance to end.
+ </para>
+
<programlisting>taskService.completeTask(task.getDbid());</programlisting>
+ <para>When the sub process ends, the super process execution will get
signalled(=notified).
+ First the <literal>result</literal> variable from the sub process
instance
+ will be copied into the <literal>reviewResult</literal> variable in
the
+ super process execution. Then the super process execution will continue
+ and leave the <link>review</link> activity.
+ </para>
+ </section>
+
+ <!-- ~~~ SUB PROCESS OUTCOME VALUE ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
+ <section id="subprocessoutcomevalue">
+ <title><literal>sub-process</literal> outcome
value</title>
+ <para>In the <literal>SubProcessOutcomeValueTest</literal>
example, the value
+ of a sub process variable is used to select the outgoing transition
+ of the <literal>sub-process</literal> activity.
+ </para>
+ <figure id="process.subprocess.outcomevalue.document">
+ <title>The subprocess document example process</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/process.subprocess.document.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting><process
name="SubProcessDocument">
+
+ <start>
+ <transition to="review" />
+ </start>
+
+ <sub-process name="review"
+ sub-process-key="SubProcessReview"
+ <emphasis
role="bold">outcome="#{result}"</emphasis>>
+
+ <transition <emphasis
role="bold">name="ok"</emphasis> to="next
step" />
+ <transition <emphasis
role="bold">name="nok"</emphasis>
to="update" />
+ <transition <emphasis
role="bold">name="reject"</emphasis>
to="close" />
+ </sub-process>
+
+ <state name="next step" />
+ <state name="update" />
+ <state name="close" />
+
+</process></programlisting>
+ <para>The <literal>SubProcessReview</literal> is the same as
above in the
+ <link linkend="subprocessvariables">subprocess variables
example</link>:</para>
+ <figure id="process.subprocess.outcomevalue.review">
+ <title>The subprocess review example process for outcome
value</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/process.subprocess.review.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting><process name="SubProcessReview"
xmlns="http://jbpm.org/4.0/jpdl">
+
+ <start>
+ <transition to="get approval"/>
+ </start>
+
+ <task name="get approval"
+ assignee="johndoe">
+
+ <transition to="end"/>
+ </task>
+
+ <end name="end" />
+
+</process></programlisting>
+ <para>A new document process instance is started like usual:
+ </para>
+ <programlisting>ProcessInstance processInstance = executionService
+
.startProcessInstanceByKey("SubProcessDocument");</programlisting>
+ <para>Then task is fetched from
<literal>johndoe</literal>'s task list</para>
+ <programlisting>List<Task> taskList =
taskService.findPersonalTasks("johndoe");
+Task task = taskList.get(0);
+ </programlisting>
+ <para>Then the <literal>result</literal> variable is set and
+ the task is completed.
+ </para>
+ <programlisting>taskService.setVariable(task.getDbid(),
"result", "ok");
+taskService.completeTask(task.getDbid());
+ </programlisting>
+ <para>In this scenario, the <literal>ok</literal> transition is
taken in
+ the parent process out of the sub-process review activity. The example
+ test case also shows other scenarios.
+ </para>
+ </section>
+
+ <!-- ~~~ SUB PROCESS OUTCOME ACTIVITY ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
+ <section id="subprocessoutcomeactivity">
+ <title><literal>sub-process</literal> outcome
activity</title>
+ <para>A process can have many end activities. In the
<literal>SubProcessOutcomeActivityTest</literal>
+ example, the resulting end activity is used to select the outgoing transition of
the <literal>sub-process</literal>
+ activity.
+ </para>
+ <figure id="process.subprocess.outcomeactivity.document">
+ <title>The subprocess document example process for outcome
activity</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/process.subprocess.document.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting><process
name="SubProcessDocument">
+
+ <start>
+ <transition to="review" />
+ </start>
+
+ <sub-process name="review"
+ sub-process-key="SubProcessReview">
+
+ <transition <emphasis
role="bold">name="ok"</emphasis> to="next
step" />
+ <transition <emphasis
role="bold">name="nok"</emphasis>
to="update" />
+ <transition <emphasis
role="bold">name="reject"</emphasis>
to="close" />
+ </sub-process>
+
+ <state name="next step" />
+ <state name="update" />
+ <state name="close" />
+
+</process></programlisting>
+ <para>The <literal>SubProcessReview</literal> now has multiple
end activities:</para>
+ <figure id="process.subprocess.outcomeactivity.review">
+ <title>The subprocess review example process for outcome
activity</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/process.subprocess.outcomeactivity.review.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting><process name="SubProcessReview"
xmlns="http://jbpm.org/4.0/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>
+
+ <emphasis role="bold"><end name="ok"
/>
+ <end name="nok" />
+ <end name="reject" /></emphasis>
+
+</process></programlisting>
+ <para>A new document process instance is started like usual:
+ </para>
+ <programlisting>ProcessInstance processInstance = executionService
+
.startProcessInstanceByKey("SubProcessDocument");</programlisting>
+ <para>Then task is fetched from
<literal>johndoe</literal>'s task list</para>
+ <programlisting>List<Task> taskList =
taskService.findPersonalTasks("johndoe");
+Task task = taskList.get(0);
+ </programlisting>
+ <para>Then the task is completed with outcome
<literal>ok</literal>.
+ </para>
+ <programlisting>taskService.completeTask(task.getDbid(),
"ok");
+ </programlisting>
+ <para>This will cause the sub process to end in end activity
<literal>ok</literal>.
+ The super process execution will then take outgoing transition
<literal>ok</literal>
+ to <literal>next step</literal>.
+ </para>
+ <para>The example test case also shows the other scenarios.
+ </para>
+ </section>
+
+ </section>
+ </section>
+
+ <!-- ##################################################################### -->
+ <!-- ### AUTOMATIC ACTIVITIES ### -->
+ <!-- ##################################################################### -->
+
+ <section id="automaticactivities">
+ <title>Automatic activities</title>
+
+ <!-- ### JAVA ########################################################## -->
+
+ <section id="java">
+ <title><literal>java</literal></title>
+ <para>The Java task. A process execution will execute the method of the class
that is configured
+ in this activity.</para>
+ <table><title><literal>java</literal>
attributes:</title>
+ <tgroup cols="5" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Attribute</entry>
+ <entry>Type</entry>
+ <entry>Default</entry>
+ <entry>Required?</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>class</literal></entry>
+ <entry>classname</entry>
+ <entry></entry>
+ <entry>either 'class' or 'expr' has to be
specified</entry>
+ <entry>The fully qualified classname. The class will be instantiated
+ and the object will be disposed after this method invocation.
+ </entry>
+ </row>
+ <row>
+ <entry><literal>expr</literal></entry>
+ <entry>expression</entry>
+ <entry></entry>
+ <entry>either 'expr' or 'class' has to be
specified</entry>
+ <entry>An expression that returns the target object on which
+ the method should be invoked.
+ </entry>
+ </row>
+ <row>
+ <entry><literal>method</literal></entry>
+ <entry>methodname</entry>
+ <entry></entry>
+ <entry><emphasis
role="bold">required</emphasis></entry>
+ <entry>The name of the method to invoke</entry>
+ </row>
+ <row>
+ <entry><literal>var</literal></entry>
+ <entry>variablename</entry>
+ <entry></entry>
+ <entry>optional</entry>
+ <entry>The name of the variable in which the return value
+ should be stored.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table><title><literal>java</literal>
elements:</title>
+ <tgroup cols="3" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Element</entry>
+ <entry>Multiplicity</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>field</literal></entry>
+ <entry>0..*</entry>
+ <entry>describes a configuration value to inject in a memberfield
before
+ the method is invoked.</entry>
+ </row>
+ <row>
+ <entry><literal>arg</literal></entry>
+ <entry>0..*</entry>
+ <entry>method parameters</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>Consider the following example.</para>
+ <figure id="process.java">
+ <title>A java task</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/process.java.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting><process name="Java"
xmlns="http://jbpm.org/4.0/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><resolve
expr="#{joesmoe.handshakes.force}"/></arg>
+ <arg><resolve
expr="#{joesmoe.handshakes.duration}"/></arg>
+
+ <transition to="wait" />
+ </java>
+
+ <state name="wait" />
+
+</process>
+ </programlisting>
+ <para>Classes involved:</para>
+ <programlisting>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;
+ }
+}</programlisting>
+ <programlisting>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;
+ }
+}</programlisting>
+ <programlisting>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;
+ }
+}</programlisting>
+ <para>The first java activity <literal>greet</literal> specifies
that during its execution an instance of the
+ class <literal>org.jbpm.examples.java.JohnDoe</literal> will be
instantiated and the method
+ <literal>hello</literal> of this class will be invoked on the resulting
object. The variable named
+ <literal>answer</literal> will contain the result of the invocation.
+ </para>
+ <para>The class above reveals that it contains two fields named
<literal>state</literal> and <literal>session</literal>
+ and that the method <literal>hello</literal> accepts one argument.
During the execution the values specified in the
+ <literal>field</literal> and <literal>arg</literal>
configuration elements will be used. The expected result of creating
+ a process instance is that the process variable
<literal>answer</literal> contains the string
+ <literal>I'm fine, thank you.</literal>.
+ </para>
+ <para>The second java activity is named <literal>shake
hand</literal>. It will resolve
+ expression <literal>#{hand}</literal>
+ and capture the resulting object as the target object. On that object, the method
+ <literal>shake</literal> will be invoked. The two arguments will be
calculated by resolving
+ the respective expressions
<literal>#{joesmoe.handshakes.force}</literal> and
+ <literal>#{joesmoe.handshakes.duration}</literal>. The resulting
object is a mofied
+ version of the hand and <literal>var="hand"</literal>
will cause the modified
+ hand to overwrite the old <literal>hand</literal> variable value.
+ </para>
+ </section>
+
+ <!-- ### SCRIPT ######################################################## -->
+
+ <section id="script">
+ <title><literal>script</literal></title>
+ <para>A script activity evaluates a script. Scripts can be specified in any
language for
+ which there is <ulink
url="https://scripting.dev.java.net/">a
JSR-223 compliant scripting engine</ulink>.
+ Configuration of scripting engines <link linkend="scripting">is
explained below</link>.
+ </para>
+ <para>There are 2 ways of specifying a script:
+ </para>
+ <section id="script.expression">
+ <title><literal>script</literal> expression</title>
+ <para>The script is provided with the <literal>expr</literal>
attribute.
+ This is for short expressions that are easier expressed in an attribute
+ then in a text element. If no <literal>lang</literal> is specified,
+ the default-expression-language is used.
+ </para>
+ <table><title><literal>script</literal> expression
attributes:</title>
+ <tgroup cols="5" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Attribute</entry>
+ <entry>Type</entry>
+ <entry>Default</entry>
+ <entry>Required?</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>expr</literal></entry>
+ <entry>text</entry>
+ <entry></entry>
+ <entry><emphasis
role="bold">required</emphasis></entry>
+ <entry>the expression text to evaluate.</entry>
+ </row>
+ <row>
+ <entry><literal>lang</literal></entry>
+ <entry>scripting language name as defined in <xref
linkend="scripting"/></entry>
+ <entry>the default <emphasis
role="bold">expression</emphasis> language as defined in <xref
linkend="scripting"/></entry>
+ <entry>optional</entry>
+ <entry>the language in which the expression is
specified.</entry>
+ </row>
+ <row>
+ <entry><literal>var</literal></entry>
+ <entry>variablename</entry>
+ <entry></entry>
+ <entry>optional</entry>
+ <entry>name of the variable in which the return value
+ should be stored.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>In the next example, we'll see how a script activity with an
expression and
+ how the result is stored in a variable.
+ </para>
+ <figure id="process.script.expression">
+ <title>The script.expression example process</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/process.script.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting><process name="ScriptExpression"
xmlns="http://jbpm.org/4.0/jpdl">
+
+ <start>
+ <transition to="invoke script" />
+ </start>
+
+ <emphasis role="bold"><script name="invoke
script"
+ expr="Send packet to #{person.address}"
+ var="text"></emphasis>
+
+ <transition to="wait" />
+ <emphasis role="bold"></script></emphasis>
+
+ <state name="wait"/>
+
+</process></programlisting>
+ <para>This example uses a <literal>Person</literal> class that
looks like this.
+ </para>
+ <programlisting>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;
+ }
+}</programlisting>
+ <para>When starting a process instance for this process, we supply a person
+ with a given address property as variable <literal>person</literal>.
+ </para>
+ <programlisting>Map<String, Object> variables = new
HashMap<String, Object>();
+variables.put("<emphasis role="bold">person</emphasis>",
<emphasis role="bold">new
Person("Honolulu")</emphasis>);
+
+executionService.startProcessInstanceByKey("ScriptText",
variables);</programlisting>
+ <para>After the execution of the script activity, variable
<literal>text</literal>
+ will contain 'Send packet to Honolulu'.
+ </para>
+ </section>
+
+ <section id="script.text">
+ <title><literal>script</literal> text</title>
+ <para>The second way of specifying a script is with a
<literal>text</literal> element.
+ This is convenient when the script text spans multiple lines.
+ </para>
+ <table><title><literal>script</literal> text
attributes:</title>
+ <tgroup cols="5" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Attribute</entry>
+ <entry>Type</entry>
+ <entry>Default</entry>
+ <entry>Required?</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>lang</literal></entry>
+ <entry>scripting language name as defined in <xref
linkend="scripting"/></entry>
+ <entry>the default <emphasis
role="bold">scripting</emphasis> language as defined in <xref
linkend="scripting"/></entry>
+ <entry>optional</entry>
+ <entry>the language in which the script is
specified.</entry>
+ </row>
+ <row>
+ <entry><literal>var</literal></entry>
+ <entry>variablename</entry>
+ <entry></entry>
+ <entry>optional</entry>
+ <entry>name of the variable in which the return value
+ should be stored.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table><title><literal>script</literal> text
elements:</title>
+ <tgroup cols="3" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Element</entry>
+ <entry>Multiplicity</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>text</literal></entry>
+ <entry>1</entry>
+ <entry>contains the script text</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>For example</para>
+ <figure id="process.script.text">
+ <title>The script.text example process</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/process.script.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting><process name="ScriptText"
xmlns="http://jbpm.org/4.0/jpdl">
+
+ <start>
+ <transition to="invoke script" />
+ </start>
+
+ <emphasis role="bold"><script name="invoke
script"
+ var="text">
+ <text>
+ Send packet to #{person.address}
+ </text></emphasis>
+ <transition to="wait" />
+ <emphasis role="bold"></script></emphasis>
+
+ <state name="wait"/>
+
+</process></programlisting>
+ </section>
+ <para>Execution of this process is exactly the same as with the script
expression above.
+ </para>
+ </section>
+
+ <!-- ### HQL ########################################################### -->
+
+ <section id="hql">
+ <title><literal>hql</literal></title>
+ <para>With the<literal>hql</literal> activity, a HQL query can be
performed
+ on the database and the result is stored in a process variable.
+ </para>
+ <table><title><literal>hql</literal>
attributes:</title>
+ <tgroup cols="5" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Attribute</entry>
+ <entry>Type</entry>
+ <entry>Default</entry>
+ <entry>Required?</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>var</literal></entry>
+ <entry>variablename</entry>
+ <entry></entry>
+ <entry><emphasis
role="bold">required</emphasis></entry>
+ <entry>the name of the variable in which the result is
stored.</entry>
+ </row>
+ <row>
+ <entry><literal>unique</literal></entry>
+ <entry>{true, false}</entry>
+ <entry>false</entry>
+ <entry>optional</entry>
+ <entry>a value of true means that the result from the hibernate
+ query should be obtained with method
<literal>uniqueResult()</literal>.
+ The default is false and in that case the
<literal>list()</literal>
+ method will be used to get the result.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table><title><literal>hql</literal>
elements:</title>
+ <tgroup cols="3" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Element</entry>
+ <entry>Multiplicity</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>query</literal></entry>
+ <entry>1</entry>
+ <entry>The HQL query.</entry>
+ </row>
+ <row>
+ <entry><literal>parameter</literal></entry>
+ <entry>0..*</entry>
+ <entry>The query parameters</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>For example:</para>
+ <figure id="process.hql">
+ <title>The hql example process</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/process.hql.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting><process name="Hql"
xmlns="http://jbpm.org/4.0/jpdl">
+
+ <start>
+ <transition to="get process names" />
+ </start>
+
+ <emphasis role="bold"><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></emphasis>
+ <transition to="count activities" />
+ <emphasis role="bold"></hql>
+
+ <hql name="count activities"
+ var="activities"
+ unique="true">
+ <query>
+ select count(*)
+ from org.jbpm.pvm.internal.model.ActivityImpl
+ </query></emphasis>
+ <transition to="wait" />
+ <emphasis role="bold"></hql></emphasis>
+
+ <state name="wait"/>
+
+</process></programlisting>
+ </section>
+
+ <!-- ### SQL ########################################################### -->
+
+ <section id="sql">
+ <title><literal>sql</literal></title>
+ <para>The <literal>sql</literal> activity is exactly the same as
the
+ <link linkend="hql">hql</link> activity, with the only
difference that
+ <literal>session.createSQLQuery(...)</literal> is used.
+ </para>
+ </section>
+
+ <!-- ### Mail ########################################################## -->
+
+ <section id="mail">
+ <title><literal>mail</literal></title>
+ <para>Through the <literal>mail</literal> 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 specified inline or in the
<literal>process-engine-context
+ </literal> section of the configuration file.</para>
+ <table><title><literal>mail</literal>
attributes</title>
+ <tgroup cols="5" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Attribute</entry>
+ <entry>Type</entry>
+ <entry>Default</entry>
+ <entry>Required?</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>template</entry>
+ <entry>string</entry>
+ <entry></entry>
+ <entry>no</entry>
+ <entry>Reference to a <literal>mail-template</literal>
element in the
+ configuration file. If absent, the template must be specified
+ inline using the child elements.</entry>
+ </row>
+ <row>
+ <entry>template</entry>
+ <entry>string</entry>
+ <entry></entry>
+ <entry>no</entry>
+ <entry>Reference to a <literal>mail-template</literal>
element in the
+ configuration file. If absent, the template must be specified
+ inline using the nested elements.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table><title><literal>mail</literal>
elements</title>
+ <tgroup cols="3" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Element</entry>
+ <entry>Multiplicity</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>from</entry>
+ <entry>0..1</entry>
+ <entry>list of sender(s)</entry>
+ </row>
+ <row>
+ <entry>to</entry>
+ <entry>1</entry>
+ <entry>list of primary recipients</entry>
+ </row>
+ <row>
+ <entry>cc</entry>
+ <entry>0..1</entry>
+ <entry>list of carbon copy recipients</entry>
+ </row>
+ <row>
+ <entry>bcc</entry>
+ <entry>0..1</entry>
+ <entry>list of blind carbon copy recipients</entry>
+ </row>
+ <row>
+ <entry>subject</entry>
+ <entry>1</entry>
+ <entry>text content of this element becomes the message
subject</entry>
+ </row>
+ <row>
+ <entry>text</entry>
+ <entry>0..1</entry>
+ <entry>text content of this element becomes the message text
content</entry>
+ </row>
+ <row>
+ <entry>html</entry>
+ <entry>0..1</entry>
+ <entry>text content of this element becomes the message HTML
content</entry>
+ </row>
+ <row>
+ <entry>attachments</entry>
+ <entry>0..1</entry>
+ <entry>attachments can be specified as URLs, classpath resources or
+ local files</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>Refer to the <link linkend="mailsupport">mail
chapter</link> for full details
+ on mail support.</para>
+ </section>
+
+ </section>
+
+ <!-- ##################################################################### -->
+ <!-- ### COMMON ACTIVITY CONTENTS ### -->
+ <!-- ##################################################################### -->
+
+ <section id="commonactivitycontents">
+ <title>Common activity contents</title>
+ <para>Unless specified otherwise above, all activities also include this
+ content model:
+ </para>
+ <table><title>Common activity attributes:</title>
+ <tgroup cols="5" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Attribute</entry>
+ <entry>Type</entry>
+ <entry>Default</entry>
+ <entry>Required?</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>name</literal></entry>
+ <entry>any text</entry>
+ <entry></entry>
+ <entry><emphasis
role="bold">required</emphasis></entry>
+ <entry>name of the activity</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table><title>Common activity elements:</title>
+ <tgroup cols="3" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Element</entry>
+ <entry>Multiplicity</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>transition</literal></entry>
+ <entry>0..*</entry>
+ <entry>the outgoing transitions</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+
+ <!-- ##################################################################### -->
+ <!-- ### EVENTS ### -->
+ <!-- ##################################################################### -->
+
+ <section id="events">
+ <title>Events</title>
+ <para>Events specify points in a process on which a list of event listeners can
be registered.
+ When an execution passes that point in the process, the event listeners are
notified.
+ The events and listeners are not shown in the graphical view of the process. An event
+ is fired by an element in the process definition like e.g. the process definition,
+ an activity or a transition.
+ </para>
+ <para>The EventListener interface looks like this:
+ </para>
+ <programlisting>public interface <emphasis
role="bold">EventListener</emphasis> extends Serializable {
+
+ void notify(EventListenerExecution execution) throws Exception;
+
+}</programlisting>
+ <para>All <link linkend="automaticactivities">automatic
activities</link> can be used as
+ event listeners as well.</para>
+ <para>To associate a list of event listeners with a process or an activity, use
+ the <literal>on</literal> element to group the event listeners and
specifiy the
+ event. <literal>on</literal> can be nested as a subelement of
<literal>process</literal>
+ or any activity.
+ </para>
+ <para>To associate a list of event listeners with a transition
<literal>take</literal>
+ event, just include the event listeners directly in the
<literal>transition</literal>
+ element.
+ </para>
+ <table><title><literal>on</literal>
attributes:</title>
+ <tgroup cols="5" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Attribute</entry>
+ <entry>Type</entry>
+ <entry>Default</entry>
+ <entry>Required?</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>event</literal></entry>
+ <entry>{start | end}</entry>
+ <entry></entry>
+ <entry><emphasis
role="bold">required</emphasis></entry>
+ <entry>name name of the event</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table><title><literal>on</literal> elements:</title>
+ <tgroup cols="3" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Element</entry>
+ <entry>Multiplicity</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>event-listener</literal></entry>
+ <entry>0..*</entry>
+ <entry>An event listener implementation object.</entry>
+ </row>
+ <row>
+ <entry>any automatic activity</entry>
+ <entry>0..*</entry>
+ <entry></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>Let's look at an example process with event listeners:</para>
+ <figure id="process.eventlistener">
+ <title>The event listener example process</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/process.eventlistener.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting><process name="EventListener"
xmlns="http://jbpm.org/4.0/jpdl">
+
+ <emphasis role="bold"><on
event="start">
+ <event-listener
class="org.jbpm.examples.eventlistener.LogListener"/>
+ </on>
+
+ <on event="end">
+ <event-listener
class="org.jbpm.examples.eventlistener.LogListener"/>
+ </on></emphasis>
+
+
+ <start>
+ <transition to="wait" name=""/>
+ </start>
+
+ <state name="wait">
+ <emphasis role="bold"><on
event="start">
+ <event-listener
class="org.jbpm.examples.eventlistener.LogListener"/>
+ </on>
+ <on event="end">
+ <event-listener
class="org.jbpm.examples.eventlistener.LogListener"/>
+ </on></emphasis>
+
+ <transition to="end" name="">
+ <event-listener
class="org.jbpm.examples.eventlistener.LogListener"/>
+ </transition>
+ </state>
+
+ <end name="end"/>
+
+</process></programlisting>
+ <para><literal>LogListener</literal> will maintain a list of logs
in a static member
+ field:</para>
+ <programlisting>public class <emphasis
role="bold">LogListener</emphasis> implements EventListener {
+
+ public static List<String> logs; // initialization done in test method
+
+ public void notify(EventListenerExecution execution) {
+ logs.add(execution.getEvent()+" on "+execution.getEventSource());
+ }
+}</programlisting>
+ <para>Next, we start a new process instance.</para>
+ <programlisting>Execution execution =
executionService.startProcessInstanceByKey("EventListener");</programlisting>
+ <para>Then the process instance executes up to the wait activity. So we
provide a signal
+ and that will cause it to execute till the end.</para>
+
<programlisting>executionService.signalExecutionById(execution.getId());</programlisting>
+ <para>The list of log messages will now look like this:</para>
+ <programlisting>[event(start) on process(EventListener),
+ event(start) on activity(wait),
+ event(end) on activity(wait),
+ event(take) on (wait)-->(end),
+ event(end) on process(EventListener)]</programlisting>
+ </section>
+
+ <section id="asynchronouscontinuations">
+ <title>Asynchronous continuations</title>
+ <para>Each invocation of
<literal>ExecutionService.startProcessInstanceById(...)</literal>
+ or <literal>ExecutionService.signalProcessInstanceById(...)</literal>
will cause
+ the process to be executed in the thread of the client. In other words, those
+ methods will only return after the process execution has arrived in a wait state.
+ </para>
+ <para>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 client to 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. E.g. < 1 second, even if multiple automatic activities
+ are executed inbetween 2 wait states. So in most situations, it's good to
+ do all that work 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.
+ </para>
+ <para>For those cases where it is needed, jPDL allows for very fine grained
control over
+ transaction boundaries. On various places in the process, asynchronous continuations
+ can be introduced. Asynchronous continuations are placed on places where logically
+ the jBPM engine remains in control for executing a series of automatic steps.
+ </para>
+ <para>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. <literal>startProcessInstanceById(...)</literal>
+ or <literal>signalProcessInstanceById(...)</literal> will return. When
the
+ asynchronous message is committed and then processed, it will start a new
transaction
+ and resume execution where it left off.
+ </para>
+ <table><title>Attribute of any activity,
<literal>transition</literal> or
<literal>on</literal>:</title>
+ <tgroup cols="5" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Attribute</entry>
+ <entry>Type</entry>
+ <entry>Default</entry>
+ <entry>Required?</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>continue</literal></entry>
+ <entry>{sync | async | exclusive}</entry>
+ <entry>sync</entry>
+ <entry>optional</entry>
+ <entry><para>indicates if an asynchronous continuation should be
performed
+ before the element is executed.</para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <itemizedlist>
+ <listitem><emphasis role="bold">sync</emphasis>
(default) keep executing
+ the element as part of the ongoing transaction.
+ </listitem>
+ <listitem><emphasis role="bold">async</emphasis>
introduces an 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 the jBPM
+ implementation to achieve this.
+ </listitem>
+ <listitem><emphasis role="bold">exclusive</emphasis>
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 the jBPM
+ implementation to achieve this. Exclusive messages will not be processed
+ concurrently. The JobExecutor(s) will serialize all exclusive job
+ executions. This can be used to prevent optimistic locking failures in case
+ multiple, potentially conflicting jobs are scheduled in the same transaction.
+ </listitem>
+ </itemizedlist>
+ <para>Let's look at a couple of examples.</para>
+
+ <section id="asyncactivity">
+ <title>Async activity</title>
+ <figure id="process.async.activity">
+ <title>The async activity example process</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/process.async.activity.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting><process name="AsyncActivity"
xmlns="http://jbpm.org/4.0/jpdl">
+
+ <start>
+ <transition to="generate pdf"/>
+ </start>
+
+ <java name="generate pdf"
+ <emphasis
role="bold">continue="async"</emphasis>
+ class="org.jbpm.examples.async.activity.Application"
+ method="generatePdf" >
+ <transition to="calculate primes"/>
+ </java>
+
+ <java name="calculate primes"
+ <emphasis
role="bold">continue="async"</emphasis>
+ class="org.jbpm.examples.async.activity.Application"
+ method="calculatePrimes">
+ <transition to="end"/>
+ </java>
+
+ <end name="end"/>
+
+</process></programlisting>
+ <programlisting>public class Application {
+
+ public void generatePdf() {
+ // assume long automatic calculations here
+ }
+
+ public void calculatePrimes() {
+ // assume long automatic calculations here
+ }
+}</programlisting>
+ <programlisting>ProcessInstance processInstance =
+ executionService.startProcessInstanceByKey("AsyncActivity");
+String processInstanceId = processInstance.getId();</programlisting>
+ <para>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 <literal>startProcessInstanceByKey</literal>
+ </para>
+ <para>But with
<literal>continue="async"</literal> the execution only
+ goes untill it is about to execute activity <literal>generate
pdf</literal>. Then
+ an asynchronous continuation message is send and the
<literal>startProcessInstanceByKey</literal>
+ method returns.
+ </para>
+ <para>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 job executor is not configured.
+ Therefor we have to execute the jobs manually like this:
+ </para>
+ <programlisting>Job job = managementService.createJobQuery()
+ .processInstanceId(processInstanceId)
+ .uniqueResult();
+managementService.executeJob(job.getDbid());</programlisting>
+ <para>That will bring the process until it's about to execute activity
+ <literal>calculate primes</literal> and again an asynchronous message
is
+ send.
+ </para>
+ <para>Then the message can be looked up again and when that message
+ is executed, that transaction will run the execution till the end.
+ </para>
+ </section>
+
+ <section id="asyncfork">
+ <title>Async fork</title>
+ <figure id="process.async.fork">
+ <title>The async fork example process</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/process.async.fork.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting><process name="AsyncFork"
xmlns="http://jbpm.org/4.0/jpdl">
+
+ <start >
+ <transition to="fork"/>
+ </start>
+
+ <fork >
+ <emphasis role="bold"><on event="end"
continue="exclusive" /></emphasis>
+ <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></programlisting>
+ <programlisting>public class Application {
+
+ public void shipGoods() {
+ // assume automatic calculations here
+ }
+
+ public void sendBill() {
+ // assume automatic calculations here
+ }
+}</programlisting>
+ <para>By placing the asynchronous continuation on the
<literal>end</literal>
+ event of the fork (<literal><on event="end"
continue="exclusive" /></literal>),
+ each forked execution that takes a transition out of the
+ fork will be continued asynchronously.
+ </para>
+ <para>Value <literal>exclusive</literal> was selected to
serialize the executions of
+ the 2 asynchonous continuation jobs resulting from the fork. The respective
transactions
+ that will execute activities <literal>ship goods</literal>
+ and <literal>send bill</literal> 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.
+ </para>
+ <programlisting>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 executor
+managementService.executeJob(job.getDbid());
+
+job = jobs.get(1);
+
+// here we simulate execution of the job,
+// which is normally done by the job executor
+managementService.executeJob(job.getDbid());
+
+Date endTime = historyService
+ .createHistoryProcessInstanceQuery()
+ .processInstanceId(processInstance.getId())
+ .uniqueResult()
+ .getEndTime();
+
+assertNotNull(endTime);</programlisting>
+ </section>
+ </section>
+
+ <section id="timer">
+ <title><literal>timer</literal> </title>
+ <para>A timer can be specified in the
<literal>transition</literal>
+ element in wait state activities such as <literal>state</literal>s,
+ <literal>task</literal>s, <literal>sub-process</literal>es
and
+ <literal>group</literal>s.
+ When such a timer fires, that transition is taken.
+ </para>
+ <para>A timer can also be specified in custom events in wait state
+ activities such as <literal>state</literal>s,
+ <literal>task</literal>s, <literal>sub-process</literal>es
and
+ <literal>group</literal>s. The <literal>timer</literal>
element
+ should then be the first element in the <literal>on</literal> element
representing
+ the event. In that case the event fires upon the duedate of the timer.
+ </para>
+ <para>Timers are created when the activity is entered. The timer can fire
+ when the execution remains in the activity until the
<literal>duedate</literal>.
+ When the execution leaves the activity, the timer is cancelled.
+ </para>
+ <table><title><literal>timer</literal>
attributes:</title>
+ <tgroup cols="5" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Attribute</entry>
+ <entry>Type</entry>
+ <entry>Default</entry>
+ <entry>Required?</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>duedate</literal></entry>
+ <entry><link linkend="duedateexpressions">duedate
expression</link></entry>
+ <entry></entry>
+ <entry><emphasis
role="bold">required</emphasis></entry>
+ <entry>Specifies when the timer needs to fire. For
+ example: <literal>20 minutes</literal> or
+ <literal>3 business days</literal>
+ </entry>
+ </row>
+ <row>
+ <entry><literal>repeat</literal></entry>
+ <entry><link linkend="duedateexpressions">duedate
expression</link></entry>
+ <entry></entry>
+ <entry>optional</entry>
+ <entry>When a timer fires, this attribute specifies when the timer
+ needs to fire again. For example: <literal>20 minutes</literal>
or
+ <literal>3 business days</literal>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <section id="duedateexpressions">
+ <title>Duedate expressions</title>
+ <para>A duedate expression has the following syntax:</para>
+ <programlisting>quantity [business] {second | seconds | minute | minutes |
+ hour | hours | day | days | week |
+ weeks | month | months | year | years}</programlisting>
+ <para>where <literal>quantity</literal> is a positive integer.
+ </para>
+ <para>And adding the optional indication
<literal>business</literal> means
+ that only business hours should be taken into account for this duration. Without
+ the indication business, the duration will be interpreted as an absolute time
period.
+ How to configure business hours is explained in <xref
linkend="businesscalendar"/>
+ </para>
+ </section>
+
+ <section id="businesscalendar">
+ <title>Business calendar</title>
+ <para>The default configuration will contain a reference to the file
+ <literal>jbpm.business.calendar.xml</literal>. That contains a
+ configuration of business hours in the following format:
+ </para>
+ <programlisting><?xml version="1.0"
encoding="UTF-8"?>
+
+<jbpm-configuration
xmlns="http://jbpm.org/xsd/cfg">
+
+ <process-engine-context>
+
+ <business-calendar>
+ <monday hours="9:00-12:00 and 12:30-17:00"/>
+ <tuesday hours="9:00-12:00 and 12:30-17:00"/>
+ <wednesday hours="9:00-12:00 and 12:30-17:00"/>
+ <thursday hours="9:00-12:00 and 12:30-17:00"/>
+ <friday hours="9:00-12:00 and 12:30-17:00"/>
+ <holiday period="01/07/2008 - 31/08/2008"/>
+ </business-calendar>
+
+ </process-engine-context>
+
+</jbpm-configuration></programlisting>
+ <para>For an example of where the business calendar is used, see
+ <xref linkedn="timerbusinesstime" />
+ </para>
+ </section>
+
+ <section id="timertransition">
+ <title>Timer transition</title>
+ <para>Example TimerTransitionTest shows how to put a timer on a
transition.</para>
+ <figure id="process.timer.transition">
+ <title>The timer transition example process</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/process.timer.transition.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting><process name="TimerTransition"
xmlns="http://jbpm.org/4.0/jpdl">
+
+ <start>
+ <transition to="guardedWait" />
+ </start>
+
+ <state name="guardedWait">
+ <transition name="go on" to="next step"
/>
+ <transition name="timeout"
to="escalation">
+ <emphasis role="bold"><timer duedate="10
minutes" /></emphasis>
+ </transition>
+ </state>
+
+ <state name="next step" />
+ <state name="escalation" />
+
+</process></programlisting>
+ <para>When an process instance for this process is started, it arrives
immediately
+ in the <literal>guardedWait</literal> state. At that time, a timer is
created that will fire
+ after 10 minutes.
+ </para>
+ <programlisting>Execution processInstance = executionService
+
.startProcessInstanceByKey("TimerTransition");</programlisting>
+ <para>With the following query, we can query for the timers related to the
newly created
+ processInstance. We know that there should be exactly one such timer.
+ </para>
+ <programlisting>Job job = managementService.createJobQuery()
+ .timers()
+ .processInstanceId(processInstance.getId())
+ .uniqueResult();
+ </programlisting>
+ <para>In a unit test, we won't use the JobExecutor to execute the timer.
Instead,
+ we execute timers directly in the thread of the unit test. That way it is easy to
+ simulate one scenario though an execution.
+ </para>
+ <para>So as the next step, we assume that the timer will fire. We simulate
this
+ by executing the timer programmatically:
+ </para>
+
<programlisting>managementService.executeJob(job.getDbid());</programlisting>
+ <para>After that the process instance will have taken the
+ <literal>timeout</literal> transition and moved to the escalation
state.
+ </para>
+ <programlisting>processInstance =
executionService.findExecutionById(processInstance.getId());
+assertEquals("escalation",
processInstance.getActivityName());</programlisting>
+ <para>The second scenario in TimerTransitionTest shows that the
+ timer is cancelled in case the signal <literal>go on</literal> is given
+ before the timer fires. In that case the execution ends up in the
+ <literal>next step</literal>.
+ </para>
+ </section>
+
+ <section id="timerevent">
+ <title>Timer event</title>
+ <para>Example TimerEventTest shows how to put a timer on a custom
event.</para>
+ <figure id="process.timer.event">
+ <title>The timer event example process</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/process.timer.event.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting><process name="TimerEvent"
xmlns="http://jbpm.org/4.0/jpdl">
+
+ <start>
+ <transition to="guardedWait" />
+ </start>
+
+ <state name="guardedWait" >
+ <emphasis role="bold"><on
event="timeout">
+ <timer duedate="10 minutes"/>
+ <event-listener
class="org.jbpm.examples.timer.event.Escalate" />
+ </on></emphasis>
+ <transition name="go on" to="next step"
/>
+ </state>
+
+ <state name="next step" />
+
+</process></programlisting>
+ <para>In this case, if the execution is not signalled within 10 minutes after
the
+ activity is started, the event <literal>timeout</literal> is fired
+ and the event listener
<literal>org.jbpm.examples.timer.event.Escalate</literal>
+ will be notified.
+ </para>
+ <para>Again, if the <literal>guardedWait</literal> activity is
ended within
+ 10 minutes, then the timer is cancelled and the
<literal>Escalate</literal>
+ event listener will not be notified.
+ </para>
+ </section>
+
+ <section id="timerbusinesstime">
+ <title>Timer business time</title>
+ <para>Example TimerBusinessTimeTest shows how business time
works.</para>
+ <figure id="process.timer.event">
+ <title>The timer businesstime example process</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/process.timer.transition.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting><process name="TimerBusinessTime"
xmlns="http://jbpm.org/4.0/jpdl">
+
+ <start>
+ <transition to="guardedWait" />
+ </start>
+
+ <state name="guardedWait" >
+ <transition name="go on" to="next step"
/>
+ <transition name="timeout" to="escalation"
>
+ <timer <emphasis role="bold">duedate="9 business
hours"</emphasis> />
+ </transition>
+ </state>
+
+ <state name="next step" />
+ <state name="escalation" />
+
+</process></programlisting>
+ <para>Suppose that a new <literal>TimerBusinessTime</literal>
process instance is started
+ at 11:30am on a tuesday. The default configured business calendar specifies
working hours
+ between 9:00-12:00 and 12:30-17:00. So 9 business hours later results in an actual
duedate
+ for the timer of wednesday 13:00 (1pm).
+ </para>
+ <para>Since we do not know when the TimerBusinessTimeTest will be ran, we
only assert
+ in the test that the actual duedate of the scheduled timer at least 24 hours
ahead.
+ </para>
+ </section>
+
+ <section id="timerrepeat">
+ <title>Timer repeat</title>
+ <para>Example TimerRepeatTest shows how to put a timer with a repeat. The
attribute
+ <literal>repeat</literal> on a timer will cause the timer to be
rescheduled automatically
+ after it is executed.
+ </para>
+ <figure id="process.timer.repeat">
+ <title>The timer repeat example process</title>
+ <mediaobject><imageobject><imagedata align="center"
fileref="images/process.timer.event.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting><process name="TimerRepeat"
xmlns="http://jbpm.org/4.0/jpdl">
+
+ <start>
+ <transition to="guardedWait" />
+ </start>
+
+ <state name="guardedWait">
+ <on event="timeout">
+ <timer duedate="20 minutes" <emphasis
role="bold">repeat="10 seconds"</emphasis> />
+ <event-listener
class="org.jbpm.examples.timer.repeat.Escalate" />
+ </on>
+ <transition name="go on" to="next
step"/>
+ </state>
+
+ <state name="next step"/>
+
+</process></programlisting>
+ <para>When a new process is started, a timer is created and the duedate
+ will be 20 minutes ahead. When the timer fires, a new timer will be created
+ with a duedate of 10 seconds ahead. When that timer fires, a new timer will
+ be created again 10 seconds ahead. And so on.
+ </para>
+ <para>New timers will be created each time the timer fires until the
+ <literal>guardedWait</literal> state activity is ended with a signal.
+ When the <literal>guardedWait</literal> state activity is ended, the
+ existing timer will be cancelled.
+ </para>
+ </section>
+ </section>
+
+ <section id="usercode">
+ <title>User code</title>
+ <para>Various elements in the jPDL process language refer to a an
+ object on which an interface method will be invoked. See for example
+ <xref linkend="taskassignmenthandler" />. This section describes the
+ attributes and sub elements of those type of user code objects.
+ </para>
+ <table><title>attributes:</title>
+ <tgroup cols="5" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Attribute</entry>
+ <entry>Type</entry>
+ <entry>Default</entry>
+ <entry>Required?</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>class</literal></entry>
+ <entry>classname</entry>
+ <entry></entry>
+ <entry><emphasis
role="bold">required</emphasis></entry>
+ <entry>The fully qualified classname.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table><title>sub elements:</title>
+ <tgroup cols="3" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Element</entry>
+ <entry>Multiplicity</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>field</literal></entry>
+ <entry>0..*</entry>
+ <entry>describes a configuration value to be injected directly in
+ a memberfield before this user class is used.</entry>
+ </row>
+ <row>
+ <entry><literal>property</literal></entry>
+ <entry>0..*</entry>
+ <entry>describes a configuration value to injected through a setter
+ method before this user object is used.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table><title><literal>field</literal>
attributes:</title>
+ <tgroup cols="5" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Attribute</entry>
+ <entry>Type</entry>
+ <entry>Default</entry>
+ <entry>Required?</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>name</literal></entry>
+ <entry>string</entry>
+ <entry></entry>
+ <entry><emphasis
role="bold">required</emphasis></entry>
+ <entry>the name of the field</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table><title><literal>field</literal> sub
elements:</title>
+ <tgroup cols="3" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Element</entry>
+ <entry>Multiplicity</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>string</literal></entry>
+ <entry>0..1</entry>
+ <entry>represents a string value</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+
+</chapter>
Property changes on:
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch06-Jpdl.xml
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:mergeinfo
+
Name: svn:eol-style
+ LF
Deleted: jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch06-Variables.xml
===================================================================
---
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch06-Variables.xml 2009-06-02
10:19:40 UTC (rev 4971)
+++
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch06-Variables.xml 2009-06-02
11:30:44 UTC (rev 4972)
@@ -1,7 +0,0 @@
-<chapter id="variables">
- <title>Variables</title>
-
- <para>TODO
- </para>
-
-</chapter>
Deleted: jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch07-Scripting.xml
===================================================================
---
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch07-Scripting.xml 2009-06-02
10:19:40 UTC (rev 4971)
+++
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch07-Scripting.xml 2009-06-02
11:30:44 UTC (rev 4972)
@@ -1,18 +0,0 @@
-<chapter id="scripting">
- <title>Scripting</title>
-
- <para>Scripting in jBPM is based on JSR 223: Scripting for the JavaTM Platform.
- Scripting engines can be configured like this:
- </para>
- <programlisting><script-manager
default-expression-language="juel"
- default-script-language="juel"
- read-contexts="execution, environment,
process-engine"
- write-context="">
- <script-language name="juel"
factory="com.sun.script.juel.JuelScriptEngineFactory" />
-</script-manager></programlisting>
- <para>A jPDL process definition can contain scripts and expressions. All
- of the configured scripting engines can be used in each situation. But
- scripts and expressions each have their own default.
- </para>
-
-</chapter>
Copied: jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch07-Variables.xml (from
rev 4967, jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch06-Variables.xml)
===================================================================
--- jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch07-Variables.xml
(rev 0)
+++
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch07-Variables.xml 2009-06-02
11:30:44 UTC (rev 4972)
@@ -0,0 +1,7 @@
+<chapter id="variables">
+ <title>Variables</title>
+
+ <para>TODO
+ </para>
+
+</chapter>
Property changes on:
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch07-Variables.xml
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Deleted: jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch08-Identity.xml
===================================================================
--- jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch08-Identity.xml 2009-06-02
10:19:40 UTC (rev 4971)
+++ jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch08-Identity.xml 2009-06-02
11:30:44 UTC (rev 4972)
@@ -1,38 +0,0 @@
-<chapter id="identity">
- <title>Identity</title>
-
- <para>The default jBPM identity component is based on
- <ulink
url="http://www.jboss.org/community/docs/DOC-13258">JBoss
IDM</ulink>.
- Configuration is like this:
- </para>
-
- <programlisting><jbpm-configuration
xmlns="http://jbpm.org/xsd/cfg">
-
- <emphasis
role="bold"><process-engine-context></emphasis>
- ...
- <identity-service />
- ...
- </process-engine-context>
-
- <transaction-context>
- ...
- <emphasis role="bold"><identity-session
realm="realm://jbpm-identity" /></emphasis>
- </transaction-context>
-
-</jbpm-configuration></programlisting>
-
- <para>To replace the identity component, keep the identity-service declaration,
- implement org.jbpm.session.IdentitySession and configure your identity session in
- the transaction context like this:
- </para>
-
- <programlisting><jbpm-configuration
xmlns="http://jbpm.org/xsd/cfg">
- ...
- <transaction-context>
- ...
- <object class="your.package.YourIdentitySession" />
- </transaction-context>
-
-</jbpm-configuration></programlisting>
-
-</chapter>
Copied: jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch08-Scripting.xml (from
rev 4967, jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch07-Scripting.xml)
===================================================================
--- jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch08-Scripting.xml
(rev 0)
+++
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch08-Scripting.xml 2009-06-02
11:30:44 UTC (rev 4972)
@@ -0,0 +1,18 @@
+<chapter id="scripting">
+ <title>Scripting</title>
+
+ <para>Scripting in jBPM is based on JSR 223: Scripting for the JavaTM Platform.
+ Scripting engines can be configured like this:
+ </para>
+ <programlisting><script-manager
default-expression-language="juel"
+ default-script-language="juel"
+ read-contexts="execution, environment,
process-engine"
+ write-context="">
+ <script-language name="juel"
factory="com.sun.script.juel.JuelScriptEngineFactory" />
+</script-manager></programlisting>
+ <para>A jPDL process definition can contain scripts and expressions. All
+ of the configured scripting engines can be used in each situation. But
+ scripts and expressions each have their own default.
+ </para>
+
+</chapter>
Property changes on:
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch08-Scripting.xml
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:mergeinfo
+
Name: svn:eol-style
+ LF
Copied: jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch09-Identity.xml (from
rev 4967, jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch08-Identity.xml)
===================================================================
--- jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch09-Identity.xml
(rev 0)
+++ jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch09-Identity.xml 2009-06-02
11:30:44 UTC (rev 4972)
@@ -0,0 +1,38 @@
+<chapter id="identity">
+ <title>Identity</title>
+
+ <para>The default jBPM identity component is based on
+ <ulink
url="http://www.jboss.org/community/docs/DOC-13258">JBoss
IDM</ulink>.
+ Configuration is like this:
+ </para>
+
+ <programlisting><jbpm-configuration
xmlns="http://jbpm.org/xsd/cfg">
+
+ <emphasis
role="bold"><process-engine-context></emphasis>
+ ...
+ <identity-service />
+ ...
+ </process-engine-context>
+
+ <transaction-context>
+ ...
+ <emphasis role="bold"><identity-session
realm="realm://jbpm-identity" /></emphasis>
+ </transaction-context>
+
+</jbpm-configuration></programlisting>
+
+ <para>To replace the identity component, keep the identity-service declaration,
+ implement org.jbpm.session.IdentitySession and configure your identity session in
+ the transaction context like this:
+ </para>
+
+ <programlisting><jbpm-configuration
xmlns="http://jbpm.org/xsd/cfg">
+ ...
+ <transaction-context>
+ ...
+ <object class="your.package.YourIdentitySession" />
+ </transaction-context>
+
+</jbpm-configuration></programlisting>
+
+</chapter>
Property changes on:
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch09-Identity.xml
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Deleted:
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch09-JBossIntegration.xml
===================================================================
---
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch09-JBossIntegration.xml 2009-06-02
10:19:40 UTC (rev 4971)
+++
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch09-JBossIntegration.xml 2009-06-02
11:30:44 UTC (rev 4972)
@@ -1,140 +0,0 @@
-<chapter id="identity">
- <title>JBoss Integration</title>
-
- <para>
- jBPM provides integration with JBoss 4.2.x and JBoss 5.0.0.GA.
- As part of the <link
linkend="runningtheinstaller">installation</link>, the ProcessEngine
and a deployer for jBPM archives
- will be installed as a JBoss service.
- </para>
-
- <para>
- After a successful installation you should see that the ProcessEngine
- has been started and bound to JNDI:
- </para>
-
- <programlisting>
- [...]
- 14:12:09,301 INFO [JBPMService] jBPM 4 - Integration JBoss 4
- 14:12:09,301 INFO [JBPMService] 4.0.0.Beta1
- 14:12:09,301 INFO [JBPMService] ProcessEngine bound to: java:/ProcessEngine
- </programlisting>
-
- <section>
- <title>Packaging process archives</title>
- <para>
- When jBPM is deployed on a JBoss instance, process deployments are treated like
- any other deployment artifact (i.e. *.war, *.ear) and processed by the
JBPMDeployer.
- In order to deploy a process archive simply create a *.jpdl archive (zip file) that
contains
- the process definition (*.jpdl.xml) and all required resources to execute the
process (i.e. classes, property files):
- </para>
- <programlisting>
- Bonanova:Desktop hbraun$ jar -tf OrderProcess.jpdl
-
- META-INF/MANIFEST.MF
- OrderProcess.jpdl.xml
- org/mycompany/order/*.class
- </programlisting>
- </section>
-
- <section>
- <title>Deploying processes archives to a JBoss instance</title>
- <para>
- In order to deploy a process archive simply copy it to
$JBOSS_HOME/server/<config>/deploy:
- </para>
-
- <programlisting>
- (1) cp OrderProcess.jpdl $JBOSS_HOME/server/default/deploy
-
- (2) less $JBOSS_HOME/server/default/log
- [...]
- 2009-04-08 14:12:21,947 INFO [org.jbpm.integration.jboss4.JBPMDeployer]
- Deploy file:/Users/hbraun/dev/prj/jboss/tags/JBoss_4_2_2_GA
- /build/output/jboss-4.2.2.GA/server/default/deploy/OrderProcess.jpdl
- </programlisting>
-
- <para>
- In order to remove a process simply remove the process archive from the deploy
directory.
- </para>
- </section>
-
- <section>
- <title>Process deployments and versioning</title>
- <para>
- TBD: A prelimenary explanation cn be found <ulink
url="http://relative-order.blogspot.com/2009/03/rfc-process-deployme...
- </para>
- </section>
-
- <section>
- <title>ProcessEngine and J2EE/JEE programming models</title>
- <para>
- As described above the ProcessEngine will be installed as JBoss service and bound
to JNDI.
- This means that any EE component (i.e. servlet, ejb) can access it doing a JNDI
lookup:
- </para>
-
- <programlisting>
- private ProcessEngine processEngine;
- [...]
-
- try
- {
- InitialContext ctx = new InitialContext();
- this.processEngine = (ProcessEngine)ctx.lookup("java:/ProcessEngine");
- }
- catch (Exception e)
- {
- throw new RuntimeException("Failed to lookup process engine");
- }
- </programlisting>
-
- <para>
- Once you obtained an instance of the ProcessEngine you can invoke on it
- as described in <link linkend="services">chapter
services</link>
- </para>
-
- <programlisting>
- UserTransaction tx = (UserTransaction)ctx.lookup("UserTransaction");
(1)
- Environment env = ((EnvironmentFactory)processEngine).openEnvironment();
-
- try
- {
-
- ExecutionService execService = (ExecutionService)
- this.processEngine.get(ExecutionService.class);
-
- // begin transaction
- tx.begin();
-
- // invoke on process engine
- executionService.signalExecutionById("ICL.82436");
-
- // commit transaction
- tx.commit();
-
- }
- catch (Exception e)
- {
- if(tx!=null)
- {
- try
- {
- tx.rollback();
- }
- catch (SystemException e1) {}
- }
-
- throw new RuntimeException("...", e);
-
- }
- finally
- {
- env.close();
- }
- </programlisting>
-
- <para>
- (1) Wrapping the call in a UserTransaction is not necessary if the invocation comes
a
- CMT component, i.e. an EJB.
- </para>
- </section>
-
-</chapter>
Deleted: jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch10-Emails.xml
===================================================================
--- jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch10-Emails.xml 2009-06-02
10:19:40 UTC (rev 4971)
+++ jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch10-Emails.xml 2009-06-02
11:30:44 UTC (rev 4972)
@@ -1,196 +0,0 @@
-<chapter id="mailsupport">
- <title>Mail Support</title>
- <para>jBPM 4 takes advantage of the JavaMail API to make high-level email
- services available to business process authors.</para>
-
- <section id="mailproducers">
- <title>Producers</title>
- <para>Producers are responsible for creating email messages within jBPM. All
mail producers
- implement the
<literal>org.jbpm.pvm.internal.email.spi.MailProducer</literal> interface.
- A default mail producer is available out of the box to address typical email
needs.</para>
-
- <section id="defaultmailproducer">
- <title>Default Producer</title>
- <para>The default mail producer is capable of creating email messages with
text,
- HTML and attachments from a template. Templates can be provided inline or
- in the process-engine-context section of the jBPM configuration. Templates
- may contain expressions which are evaluated through the script manager. Refer to
- <link linkend="scripting">Scripting</link> for
details.</para>
- <para>The following listing presents a mail activity with an inline
template.</para>
- <programlisting><![CDATA[<mail name="rectify"
language="juel"> (1)
- <from addresses='winston@minitrue' /> (2)
- <to addresses='julia@minitrue, obrien@miniluv'/> (3)
- <cc users='bigbrother'/>
- <bcc groups='thinkpol, innerparty'/>
- <subject>Part ${part} Chapter ${chapter}</subject> (4)
- <text>times ${date} reporting bb dayorder doubleplusungood (5)
- refs ${unpersons} rewrite fullwise upsub antefiling</text>
-
<html><table><tr><td>times</td><td>${date}</td>
(6)
- <td>reporting bb dayorder doubleplusungood
- refs ${unpersons} rewrite fullwise upsub antefiling</td>
- </tr></table></html>
- <attachments> (7)
- <attachment
url='http://www.george-orwell.org/1984/3.html'/>
- <attachment resource='org/example/pic.jpg'/>
- <attachment file='${user.home}/.face'/>
- </attachments>
-</mail>]]></programlisting>
- <orderedlist>
- <listitem><para>Expressions within the template are written in the
scripting language
- indicated here. If not specified, the default expression language will be
assumed.
- </para></listitem>
- <listitem><para>List of message senders. Senders are either identified
directly by
- their email addresses or appointed by means of the identity
model.</para></listitem>
- <listitem><para>Lists of message recipients, categorized as follows:
<emphasis>To</emphasis>
- (primary), <emphasis>CC</emphasis> (carbon copy) and
<emphasis>BCC</emphasis> (blind
- carbon copy). Like senders, recipients are directly identified by their email
addresses
- or appointed by means of the identity model.</para></listitem>
- <listitem><para>Character data contained in element
<literal>subject</literal>
- are used as the message subject.</para></listitem>
- <listitem><para>Character data contained in element
<literal>text</literal>
- are used as the plain text content of the message.</para></listitem>
- <listitem><para>Nodes contained in element
<literal>html</literal>
- are used as the HTML content of the message.</para></listitem>
- <listitem><para>Attachments can be specified as absolute URLs,
- classpath resources or local files.</para></listitem>
- </orderedlist>
- <para>Note that every section of the template is amenable to expression
evaluation.</para>
- </section>
- <para>For complex emails or custom generation of attachments, see: <link
- linkend="customemails">Extension Points: Custom
Emails</link>.</para>
- </section>
-
- <section id="mailtemplates">
- <title>Templates</title>
- <para>Mail templates are available to externalize commonly used messages from
process definitions.
- Templates are placed in the process-engine-context section of your configuration
file. All elements
- available to inline templates, as described in the <link
linkend="defaultmailproducer">previous
- section</link> are available to external templates. Consider the fragment
below.</para>
- <programlisting><![CDATA[<jbpm-configuration>
-<process-engine-context>
- <mail-template name="rectify-template">
- <!-- same elements as inline template -->
- </mail-template>
-</process-engine-context>
-</jbpm-configuration>]]></programlisting>
- <para>Each template must have an unique name. Mail activities may reference the
template
- through the <literal>template</literal> attribute, as
follows.</para>
- <programlisting><![CDATA[<mail name="rectify"
template="rectify-template />]]></programlisting>
- </section>
-
- <section id="mailservers">
- <title>Servers</title>
- <para>Mail servers are declared in the configuration file. The
<literal>mail-server</literal>
- element describes an SMTP mail server capable of sending email messages.
- Because jBPM uses JavaMail to send mail, all properties supported by JavaMail are
also
- exposed to jBPM. Within the <literal>session-properties</literal>
child element,
- the SMTP properties must be provided as shown in the example below.</para>
- <para>See the Sun JavaMail API for more information on supported properties:
- <ulink
url="http://java.sun.com/products/javamail/javadocs/com/sun/mail/smt...
- Sun SMTP Properties</ulink>.</para>
- <programlisting><![CDATA[<jbpm-configuration>
-<transaction-context>
- <mail-session>
- <mail-server>
- <session-properties>
- <property name="mail.smtp.host" value="localhost" />
- <property name="mail.smtp.port" value="2525" />
- <property name="mail.from" value="noreply(a)jbpm.org" />
- </session-properties>
- </mail-server>
- </mail-session>
-</transaction-context>
-</jbpm-configuration>]]></programlisting>
- <para>If the "From" attribute is not present in an outgoing message,
the value of the
- <literal>mail.from</literal> property will be used
instead.</para>
-
- <section id="multiplemailservers">
- <title>Multiple Servers</title>
- <para>Multiple SMTP server support has been added to jBPM 4 to accommodate a
wider
- variety of organizational server structures. For example, this is useful for
companies
- that have both internal and external SMTP servers.</para>
- <para>To setup multiple SMTP mail servers, declare multiple mail servers
within the
- configuration file, as described below. The tag
<literal>address-filter</literal> exists
- to define which domains are serviced by each mail server. The address filter
consists
- of regular expressions that determine whether an address will be processed by a
given
- server.</para>
- <para>See the Sun Pattern API for more information on supported regular
expressions:
- <ulink
url="http://java.sun.com/j2se/1.5.0/docs/api/java/util/regex/Pattern...
- Sun Regex Patterns</ulink>.</para>
- <programlisting><![CDATA[<jbpm-configuration>
-<transaction-context>
- <mail-session>
- <mail-server>
- <address-filter>
- <include>.+(a)jbpm.org</include>
- </address-filter>
- <session-properties>
- <property name="mail.smtp.host" value="int.smtp.jbpm.org"
/>
- <property name="mail.from" value="noreply(a)jbpm.org" />
- </session-properties>
- </mail-server>
- <mail-server>
- <address-filter>
- <exclude>.+(a)jbpm.org</exclude>
- </address-filter>
- <session-properties>
- <property name="mail.smtp.host" value="ext.smtp.jbpm.org"
/>
- <property name="mail.from" value="noreply(a)jbpm.org" />
- </session-properties>
- </mail-server>
- </mail-session>
-</transaction-context>
-</jbpm-configuration>]]></programlisting>
- <para>Address filters follow the logic below to accept an
address.</para>
- <itemizedlist>
- <listitem><para>Address is accepted if it is
<emphasis>included</emphasis> and
- <emphasis>not excluded</emphasis>.</para></listitem>
- <listitem><para>Absence of includes implies the address is
- <emphasis>included</emphasis>.</para></listitem>
- <listitem><para>Absence of excludes implies the address is
- <emphasis>not excluded</emphasis>.</para></listitem>
- </itemizedlist>
- </section>
- </section>
-
- <section id="extensibility">
- <title>Extension Points</title>
-
- <section id="customproducers">
- <title>Custom Producers</title>
- <para>jBPM 4 allows the creation of your own Mail Producers to address an
organization's
- specific email needs. To do so, users must implement the
- <literal>org.jbpm.pvm.internal.email.spi.MailProducer</literal>
interface. The method
- <literal>produce</literal> will return one or more
<literal>Message</literal> objects,
- which will be sent through the
<literal>MailSession</literal>.</para>
-
- <section id="custom attachments">
- <title>Example: Custom Attachments</title>
- <para>Generation of custom attachments at runtime can be easily implemented
in jBPM 4.
- By extending the default mail producer, or implementing your own with the
- <literal>MailProducer</literal> interface, attachments can be
generated and
- added to email messages at runtime.</para>
- <para>The following is an example of how to extend
<literal>MailProducerImpl</literal>
- to add an extra attachment to every outgoing mail.</para>
- <programlisting><![CDATA[public class CustomMailProducer extends
MailProducerImpl {
-
- protected void addAttachments(Execution execution, Multipart multipart) {
- // have default mail producer create attachments from template
- super.addAttachments(execution, multipart);
-
- // create a body part to carry the content
- BodyPart attachmentPart = new MimeBodyPart();
-
- // set content provided by an arbitrary data handler
- attachmentPart.setDataHandler(...);
-
- // attach content
- multipart.addBodyPart(attachmentPart);
- }
-}]]></programlisting>
- </section>
- </section>
-
- </section>
-
-</chapter>
\ No newline at end of file
Copied:
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch10-JBossIntegration.xml (from
rev 4967,
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch09-JBossIntegration.xml)
===================================================================
--- jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch10-JBossIntegration.xml
(rev 0)
+++
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch10-JBossIntegration.xml 2009-06-02
11:30:44 UTC (rev 4972)
@@ -0,0 +1,140 @@
+<chapter id="identity">
+ <title>JBoss Integration</title>
+
+ <para>
+ jBPM provides integration with JBoss 4.2.x and JBoss 5.0.0.GA.
+ As part of the <link
linkend="runningtheinstaller">installation</link>, the ProcessEngine
and a deployer for jBPM archives
+ will be installed as a JBoss service.
+ </para>
+
+ <para>
+ After a successful installation you should see that the ProcessEngine
+ has been started and bound to JNDI:
+ </para>
+
+ <programlisting>
+ [...]
+ 14:12:09,301 INFO [JBPMService] jBPM 4 - Integration JBoss 4
+ 14:12:09,301 INFO [JBPMService] 4.0.0.Beta1
+ 14:12:09,301 INFO [JBPMService] ProcessEngine bound to: java:/ProcessEngine
+ </programlisting>
+
+ <section>
+ <title>Packaging process archives</title>
+ <para>
+ When jBPM is deployed on a JBoss instance, process deployments are treated like
+ any other deployment artifact (i.e. *.war, *.ear) and processed by the
JBPMDeployer.
+ In order to deploy a process archive simply create a *.jpdl archive (zip file) that
contains
+ the process definition (*.jpdl.xml) and all required resources to execute the
process (i.e. classes, property files):
+ </para>
+ <programlisting>
+ Bonanova:Desktop hbraun$ jar -tf OrderProcess.jpdl
+
+ META-INF/MANIFEST.MF
+ OrderProcess.jpdl.xml
+ org/mycompany/order/*.class
+ </programlisting>
+ </section>
+
+ <section>
+ <title>Deploying processes archives to a JBoss instance</title>
+ <para>
+ In order to deploy a process archive simply copy it to
$JBOSS_HOME/server/<config>/deploy:
+ </para>
+
+ <programlisting>
+ (1) cp OrderProcess.jpdl $JBOSS_HOME/server/default/deploy
+
+ (2) less $JBOSS_HOME/server/default/log
+ [...]
+ 2009-04-08 14:12:21,947 INFO [org.jbpm.integration.jboss4.JBPMDeployer]
+ Deploy file:/Users/hbraun/dev/prj/jboss/tags/JBoss_4_2_2_GA
+ /build/output/jboss-4.2.2.GA/server/default/deploy/OrderProcess.jpdl
+ </programlisting>
+
+ <para>
+ In order to remove a process simply remove the process archive from the deploy
directory.
+ </para>
+ </section>
+
+ <section>
+ <title>Process deployments and versioning</title>
+ <para>
+ TBD: A prelimenary explanation cn be found <ulink
url="http://relative-order.blogspot.com/2009/03/rfc-process-deployme...
+ </para>
+ </section>
+
+ <section>
+ <title>ProcessEngine and J2EE/JEE programming models</title>
+ <para>
+ As described above the ProcessEngine will be installed as JBoss service and bound
to JNDI.
+ This means that any EE component (i.e. servlet, ejb) can access it doing a JNDI
lookup:
+ </para>
+
+ <programlisting>
+ private ProcessEngine processEngine;
+ [...]
+
+ try
+ {
+ InitialContext ctx = new InitialContext();
+ this.processEngine = (ProcessEngine)ctx.lookup("java:/ProcessEngine");
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("Failed to lookup process engine");
+ }
+ </programlisting>
+
+ <para>
+ Once you obtained an instance of the ProcessEngine you can invoke on it
+ as described in <link linkend="services">chapter
services</link>
+ </para>
+
+ <programlisting>
+ UserTransaction tx = (UserTransaction)ctx.lookup("UserTransaction");
(1)
+ Environment env = ((EnvironmentFactory)processEngine).openEnvironment();
+
+ try
+ {
+
+ ExecutionService execService = (ExecutionService)
+ this.processEngine.get(ExecutionService.class);
+
+ // begin transaction
+ tx.begin();
+
+ // invoke on process engine
+ executionService.signalExecutionById("ICL.82436");
+
+ // commit transaction
+ tx.commit();
+
+ }
+ catch (Exception e)
+ {
+ if(tx!=null)
+ {
+ try
+ {
+ tx.rollback();
+ }
+ catch (SystemException e1) {}
+ }
+
+ throw new RuntimeException("...", e);
+
+ }
+ finally
+ {
+ env.close();
+ }
+ </programlisting>
+
+ <para>
+ (1) Wrapping the call in a UserTransaction is not necessary if the invocation comes
a
+ CMT component, i.e. an EJB.
+ </para>
+ </section>
+
+</chapter>
Copied: jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch11-Emails.xml (from
rev 4967, jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch10-Emails.xml)
===================================================================
--- jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch11-Emails.xml
(rev 0)
+++ jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch11-Emails.xml 2009-06-02
11:30:44 UTC (rev 4972)
@@ -0,0 +1,196 @@
+<chapter id="mailsupport">
+ <title>Mail Support</title>
+ <para>jBPM 4 takes advantage of the JavaMail API to make high-level email
+ services available to business process authors.</para>
+
+ <section id="mailproducers">
+ <title>Producers</title>
+ <para>Producers are responsible for creating email messages within jBPM. All
mail producers
+ implement the
<literal>org.jbpm.pvm.internal.email.spi.MailProducer</literal> interface.
+ A default mail producer is available out of the box to address typical email
needs.</para>
+
+ <section id="defaultmailproducer">
+ <title>Default Producer</title>
+ <para>The default mail producer is capable of creating email messages with
text,
+ HTML and attachments from a template. Templates can be provided inline or
+ in the process-engine-context section of the jBPM configuration. Templates
+ may contain expressions which are evaluated through the script manager. Refer to
+ <link linkend="scripting">Scripting</link> for
details.</para>
+ <para>The following listing presents a mail activity with an inline
template.</para>
+ <programlisting><![CDATA[<mail name="rectify"
language="juel"> (1)
+ <from addresses='winston@minitrue' /> (2)
+ <to addresses='julia@minitrue, obrien@miniluv'/> (3)
+ <cc users='bigbrother'/>
+ <bcc groups='thinkpol, innerparty'/>
+ <subject>Part ${part} Chapter ${chapter}</subject> (4)
+ <text>times ${date} reporting bb dayorder doubleplusungood (5)
+ refs ${unpersons} rewrite fullwise upsub antefiling</text>
+
<html><table><tr><td>times</td><td>${date}</td>
(6)
+ <td>reporting bb dayorder doubleplusungood
+ refs ${unpersons} rewrite fullwise upsub antefiling</td>
+ </tr></table></html>
+ <attachments> (7)
+ <attachment
url='http://www.george-orwell.org/1984/3.html'/>
+ <attachment resource='org/example/pic.jpg'/>
+ <attachment file='${user.home}/.face'/>
+ </attachments>
+</mail>]]></programlisting>
+ <orderedlist>
+ <listitem><para>Expressions within the template are written in the
scripting language
+ indicated here. If not specified, the default expression language will be
assumed.
+ </para></listitem>
+ <listitem><para>List of message senders. Senders are either identified
directly by
+ their email addresses or appointed by means of the identity
model.</para></listitem>
+ <listitem><para>Lists of message recipients, categorized as follows:
<emphasis>To</emphasis>
+ (primary), <emphasis>CC</emphasis> (carbon copy) and
<emphasis>BCC</emphasis> (blind
+ carbon copy). Like senders, recipients are directly identified by their email
addresses
+ or appointed by means of the identity model.</para></listitem>
+ <listitem><para>Character data contained in element
<literal>subject</literal>
+ are used as the message subject.</para></listitem>
+ <listitem><para>Character data contained in element
<literal>text</literal>
+ are used as the plain text content of the message.</para></listitem>
+ <listitem><para>Nodes contained in element
<literal>html</literal>
+ are used as the HTML content of the message.</para></listitem>
+ <listitem><para>Attachments can be specified as absolute URLs,
+ classpath resources or local files.</para></listitem>
+ </orderedlist>
+ <para>Note that every section of the template is amenable to expression
evaluation.</para>
+ </section>
+ <para>For complex emails or custom generation of attachments, see: <link
+ linkend="customemails">Extension Points: Custom
Emails</link>.</para>
+ </section>
+
+ <section id="mailtemplates">
+ <title>Templates</title>
+ <para>Mail templates are available to externalize commonly used messages from
process definitions.
+ Templates are placed in the process-engine-context section of your configuration
file. All elements
+ available to inline templates, as described in the <link
linkend="defaultmailproducer">previous
+ section</link> are available to external templates. Consider the fragment
below.</para>
+ <programlisting><![CDATA[<jbpm-configuration>
+<process-engine-context>
+ <mail-template name="rectify-template">
+ <!-- same elements as inline template -->
+ </mail-template>
+</process-engine-context>
+</jbpm-configuration>]]></programlisting>
+ <para>Each template must have an unique name. Mail activities may reference the
template
+ through the <literal>template</literal> attribute, as
follows.</para>
+ <programlisting><![CDATA[<mail name="rectify"
template="rectify-template />]]></programlisting>
+ </section>
+
+ <section id="mailservers">
+ <title>Servers</title>
+ <para>Mail servers are declared in the configuration file. The
<literal>mail-server</literal>
+ element describes an SMTP mail server capable of sending email messages.
+ Because jBPM uses JavaMail to send mail, all properties supported by JavaMail are
also
+ exposed to jBPM. Within the <literal>session-properties</literal>
child element,
+ the SMTP properties must be provided as shown in the example below.</para>
+ <para>See the Sun JavaMail API for more information on supported properties:
+ <ulink
url="http://java.sun.com/products/javamail/javadocs/com/sun/mail/smt...
+ Sun SMTP Properties</ulink>.</para>
+ <programlisting><![CDATA[<jbpm-configuration>
+<transaction-context>
+ <mail-session>
+ <mail-server>
+ <session-properties>
+ <property name="mail.smtp.host" value="localhost" />
+ <property name="mail.smtp.port" value="2525" />
+ <property name="mail.from" value="noreply(a)jbpm.org" />
+ </session-properties>
+ </mail-server>
+ </mail-session>
+</transaction-context>
+</jbpm-configuration>]]></programlisting>
+ <para>If the "From" attribute is not present in an outgoing message,
the value of the
+ <literal>mail.from</literal> property will be used
instead.</para>
+
+ <section id="multiplemailservers">
+ <title>Multiple Servers</title>
+ <para>Multiple SMTP server support has been added to jBPM 4 to accommodate a
wider
+ variety of organizational server structures. For example, this is useful for
companies
+ that have both internal and external SMTP servers.</para>
+ <para>To setup multiple SMTP mail servers, declare multiple mail servers
within the
+ configuration file, as described below. The tag
<literal>address-filter</literal> exists
+ to define which domains are serviced by each mail server. The address filter
consists
+ of regular expressions that determine whether an address will be processed by a
given
+ server.</para>
+ <para>See the Sun Pattern API for more information on supported regular
expressions:
+ <ulink
url="http://java.sun.com/j2se/1.5.0/docs/api/java/util/regex/Pattern...
+ Sun Regex Patterns</ulink>.</para>
+ <programlisting><![CDATA[<jbpm-configuration>
+<transaction-context>
+ <mail-session>
+ <mail-server>
+ <address-filter>
+ <include>.+(a)jbpm.org</include>
+ </address-filter>
+ <session-properties>
+ <property name="mail.smtp.host" value="int.smtp.jbpm.org"
/>
+ <property name="mail.from" value="noreply(a)jbpm.org" />
+ </session-properties>
+ </mail-server>
+ <mail-server>
+ <address-filter>
+ <exclude>.+(a)jbpm.org</exclude>
+ </address-filter>
+ <session-properties>
+ <property name="mail.smtp.host" value="ext.smtp.jbpm.org"
/>
+ <property name="mail.from" value="noreply(a)jbpm.org" />
+ </session-properties>
+ </mail-server>
+ </mail-session>
+</transaction-context>
+</jbpm-configuration>]]></programlisting>
+ <para>Address filters follow the logic below to accept an
address.</para>
+ <itemizedlist>
+ <listitem><para>Address is accepted if it is
<emphasis>included</emphasis> and
+ <emphasis>not excluded</emphasis>.</para></listitem>
+ <listitem><para>Absence of includes implies the address is
+ <emphasis>included</emphasis>.</para></listitem>
+ <listitem><para>Absence of excludes implies the address is
+ <emphasis>not excluded</emphasis>.</para></listitem>
+ </itemizedlist>
+ </section>
+ </section>
+
+ <section id="extensibility">
+ <title>Extension Points</title>
+
+ <section id="customproducers">
+ <title>Custom Producers</title>
+ <para>jBPM 4 allows the creation of your own Mail Producers to address an
organization's
+ specific email needs. To do so, users must implement the
+ <literal>org.jbpm.pvm.internal.email.spi.MailProducer</literal>
interface. The method
+ <literal>produce</literal> will return one or more
<literal>Message</literal> objects,
+ which will be sent through the
<literal>MailSession</literal>.</para>
+
+ <section id="custom attachments">
+ <title>Example: Custom Attachments</title>
+ <para>Generation of custom attachments at runtime can be easily implemented
in jBPM 4.
+ By extending the default mail producer, or implementing your own with the
+ <literal>MailProducer</literal> interface, attachments can be
generated and
+ added to email messages at runtime.</para>
+ <para>The following is an example of how to extend
<literal>MailProducerImpl</literal>
+ to add an extra attachment to every outgoing mail.</para>
+ <programlisting><![CDATA[public class CustomMailProducer extends
MailProducerImpl {
+
+ protected void addAttachments(Execution execution, Multipart multipart) {
+ // have default mail producer create attachments from template
+ super.addAttachments(execution, multipart);
+
+ // create a body part to carry the content
+ BodyPart attachmentPart = new MimeBodyPart();
+
+ // set content provided by an arbitrary data handler
+ attachmentPart.setDataHandler(...);
+
+ // attach content
+ multipart.addBodyPart(attachmentPart);
+ }
+}]]></programlisting>
+ </section>
+ </section>
+
+ </section>
+
+</chapter>
\ No newline at end of file