[jbpm-commits] JBoss JBPM SVN: r5960 - in jbpm4/trunk/modules/devguide/src/main/docbook/en: modules and 1 other directory.
do-not-reply at jboss.org
do-not-reply at jboss.org
Tue Dec 15 10:51:10 EST 2009
Author: jbarrez
Date: 2009-12-15 10:51:09 -0500 (Tue, 15 Dec 2009)
New Revision: 5960
Added:
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch03-Bpmn2.xml
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch04-MigrationFromJbpm3.xml
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch05-ProcessVirtualMachine.xml
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch06-Architecture.xml
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch07-ImplementingBasicActivities.xml
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch08-ProcessAnatomy.xml
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch09-ImplementingAdvancedActivities.xml
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch10-Configuration.xml
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch11-Persistence.xml
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch12-JobExecutor.xml
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch13-AdvancedEmail.xml
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch14-SoftwareLogging.xml
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch15-History.xml
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch16-JBossIntegration.xml
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch17-SpringIntegration.xml
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch18-Signavio.xml
Removed:
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch03-MigrationFromJbpm3.xml
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch04-ProcessVirtualMachine.xml
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch05-Architecture.xml
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch06-ImplementingBasicActivities.xml
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch07-ProcessAnatomy.xml
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch08-ImplementingAdvancedActivities.xml
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch09-Configuration.xml
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch10-Persistence.xml
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch11-JobExecutor.xml
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch12-AdvancedEmail.xml
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch13-SoftwareLogging.xml
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch14-History.xml
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch15-JBossIntegration.xml
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch16-SpringIntegration.xml
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch17-Signavio.xml
Modified:
jbpm4/trunk/modules/devguide/src/main/docbook/en/master.xml
Log:
Added first section of BPMN2.0 documentation to dev guide
Modified: jbpm4/trunk/modules/devguide/src/main/docbook/en/master.xml
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/master.xml 2009-12-15 10:55:41 UTC (rev 5959)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/master.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -3,21 +3,22 @@
<!DOCTYPE book [
<!ENTITY ch01-Introduction SYSTEM "modules/ch01-Introduction.xml">
<!ENTITY ch02-Incubation SYSTEM "modules/ch02-Incubation.xml">
- <!ENTITY ch03-MigrationFromJbpm3 SYSTEM "modules/ch03-MigrationFromJbpm3.xml">
- <!ENTITY ch04-ProcessVirtualMachine SYSTEM "modules/ch04-ProcessVirtualMachine.xml">
- <!ENTITY ch05-Architecture SYSTEM "modules/ch05-Architecture.xml">
- <!ENTITY ch06-ImplementingBasicActivities SYSTEM "modules/ch06-ImplementingBasicActivities.xml">
- <!ENTITY ch07-ProcessAnatomy SYSTEM "modules/ch07-ProcessAnatomy.xml">
- <!ENTITY ch08-ImplementingAdvancedActivities SYSTEM "modules/ch08-ImplementingAdvancedActivities.xml">
- <!ENTITY ch09-Configuration SYSTEM "modules/ch09-Configuration.xml">
- <!ENTITY ch10-Persistence SYSTEM "modules/ch10-Persistence.xml">
- <!ENTITY ch11-JobExecutor SYSTEM "modules/ch11-JobExecutor.xml">
- <!ENTITY ch12-AdvancedEmail SYSTEM "modules/ch12-AdvancedEmail.xml">
- <!ENTITY ch13-SoftwareLogging SYSTEM "modules/ch13-SoftwareLogging.xml">
- <!ENTITY ch14-History SYSTEM "modules/ch14-History.xml">
- <!ENTITY ch15-JBossIntegration SYSTEM "modules/ch15-JBossIntegration.xml">
- <!ENTITY ch16-SpringIntegration SYSTEM "modules/ch16-SpringIntegration.xml">
- <!ENTITY ch17-Signavio SYSTEM "modules/ch17-Signavio.xml">
+ <!ENTITY ch03-Bpmn2 SYSTEM "modules/ch03-Bpmn2.xml">
+ <!ENTITY ch04-MigrationFromJbpm3 SYSTEM "modules/ch04-MigrationFromJbpm3.xml">
+ <!ENTITY ch05-ProcessVirtualMachine SYSTEM "modules/ch05-ProcessVirtualMachine.xml">
+ <!ENTITY ch06-Architecture SYSTEM "modules/ch06-Architecture.xml">
+ <!ENTITY ch07-ImplementingBasicActivities SYSTEM "modules/ch07-ImplementingBasicActivities.xml">
+ <!ENTITY ch08-ProcessAnatomy SYSTEM "modules/ch08-ProcessAnatomy.xml">
+ <!ENTITY ch09-ImplementingAdvancedActivities SYSTEM "modules/ch09-ImplementingAdvancedActivities.xml">
+ <!ENTITY ch10-Configuration SYSTEM "modules/ch10-Configuration.xml">
+ <!ENTITY ch11-Persistence SYSTEM "modules/ch11-Persistence.xml">
+ <!ENTITY ch12-JobExecutor SYSTEM "modules/ch12-JobExecutor.xml">
+ <!ENTITY ch13-AdvancedEmail SYSTEM "modules/ch13-AdvancedEmail.xml">
+ <!ENTITY ch14-SoftwareLogging SYSTEM "modules/ch14-SoftwareLogging.xml">
+ <!ENTITY ch15-History SYSTEM "modules/ch15-History.xml">
+ <!ENTITY ch16-JBossIntegration SYSTEM "modules/ch16-JBossIntegration.xml">
+ <!ENTITY ch17-SpringIntegration SYSTEM "modules/ch17-SpringIntegration.xml">
+ <!ENTITY ch18-Signavio SYSTEM "modules/ch18-Signavio.xml">
]>
<book lang="en">
@@ -30,20 +31,21 @@
&ch01-Introduction;
&ch02-Incubation;
- &ch03-MigrationFromJbpm3;
- &ch04-ProcessVirtualMachine;
- &ch05-Architecture;
- &ch06-ImplementingBasicActivities;
- &ch07-ProcessAnatomy;
- &ch08-ImplementingAdvancedActivities;
- &ch09-Configuration;
- &ch10-Persistence;
- &ch11-JobExecutor;
- &ch12-AdvancedEmail;
- &ch13-SoftwareLogging;
- &ch14-History;
- &ch15-JBossIntegration;
- &ch16-SpringIntegration;
- &ch17-Signavio;
+ &ch03-Bpmn2;
+ &ch04-MigrationFromJbpm3;
+ &ch05-ProcessVirtualMachine;
+ &ch06-Architecture;
+ &ch07-ImplementingBasicActivities;
+ &ch08-ProcessAnatomy;
+ &ch09-ImplementingAdvancedActivities;
+ &ch10-Configuration;
+ &ch11-Persistence;
+ &ch12-JobExecutor;
+ &ch13-AdvancedEmail;
+ &ch14-SoftwareLogging;
+ &ch15-History;
+ &ch16-JBossIntegration;
+ &ch17-SpringIntegration;
+ &ch18-Signavio;
</book>
\ No newline at end of file
Added: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch03-Bpmn2.xml
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch03-Bpmn2.xml (rev 0)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch03-Bpmn2.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<chapter id="bpmn2">
+
+ <title>BPMN 2.0</title>
+
+ <section id="whatIsBpmn">
+
+ <title>What is BPMN 2.0?</title>
+
+ <para>
+ The Business Process Modeling Notation (BPMN) is a standard for a
+ graphical notation of business processes models. The standard is
+ maitained by the Object Management Group (OMG)
+ </para>
+ <para>
+ Basically, the BPMN spec defines how a task must look like, which constructs can
+ be connected to each other, etc. in a meaning that cannot be
+ misinterpreted.
+ </para>
+ <para>
+ Earlier versions of the standard (<= version 1.2) are limited to the modeling
+ only, aiming at a common understanding between all stakeholders
+ involved in documenting, discussing and implementing business
+ processes. The BPMN standard has proven itself, as many modeling tools
+ on the market today use the symbols and constructs specified in the
+ BPMN standard. In fact, the current JPDL designer also uses BPMN
+ symbols.
+ </para>
+ <para>
+ Version 2.0 of the BPMN specification, which is currently in beta phase and is
+ scheduled to be finalized in June 2010, allows to add precise technical
+ details to the shapes and symbols available in BPMN and at the same
+ time specify what the execution semantics of BPMN 'elements' are. By
+ using an XML language to specify the executable semantics of a business
+ process, the BPMN specification has evolved into a language for
+ business processes that can be executed on any BPMN2 compliant process
+ engine - while still having the powerful graphical notations.
+ </para>
+
+ </section>
+
+ <section id="historyAndGodl">
+
+ <title>History and goal</title>
+
+ <para>
+ The jBPM BPMN2 implementation was started in close collaboration with the
+ community in augustus 2009 after releasing jBPM 4.0.
+ Later, it was decided that the first release (ie documented/QA'd) to
+ incorporate parts of the BPMN2 spec would be jBPM 4.3.
+ </para>
+ <para>
+ The goal of this effort is to build a native BPMN2 runtime engine (or
+ better said implementing 'BPMN2 exectuable') leveraging the Process
+ Virtual Machine (PVM).
+ </para>
+ <para>
+ Do note that the primary focus of this release is native executability,
+ not the graphical notation - but we recognize its importance for
+ further releases.
+ </para>
+
+ </section>
+
+ <section id="jpdlVsBpmn2" >
+
+ <title>JPDL vs BPMN 2.0</title>
+
+ <para>
+ One of the first questions that might, rightfully, come to mind is why
+ BPMN2 is being implemented while there is jPDL. Both are languages that
+ have as goal to define executable business processes. From a high-level
+ technical point of view, both languages are equivalent. The main
+ distinction is that BPMN2 is as vendor-neutral as you can have with
+ standards, while JPDL has always been tied to jBPM (although some might
+ argue that a vendor lock-in for an open-source process language such as
+ JPDL is less a lock-in than with closed-source products).
+ </para>
+ <para>
+ Within jBPM, both language implementations are built on top of the jBPM
+ Process Virtual Machine (PVM). This means that both languages share a
+ common foundation (persistence, transactions, configuration, but also
+ basic process constructs, etc.). As a result, optimizations to the core
+ of jBPM often benefits both languages. Leveraging the PVM, the BPMN2
+ implementation is built upon a foundation that has already proven
+ itself in the past and has a large end-user community.
+ </para>
+ <para>
+ When evaluating the languages and comparing them which each other however,
+ following points must be taken into consideration:
+ <itemizedlist>
+ <listitem>BPMN2 is based on a standard accepted by the BPM industry.</listitem>
+ <listitem>BPMN2 is implementation-unaware. The downside of this is that
+ integrating with Java technology will always be easier with JPDL. So,
+ from a Java developer's perspective JPDL is simpler and feels more
+ natural (some of the 'layers' of BPEL/WSDL are in BPMN as well)</listitem>
+ <listitem>A focus of JPDL is XML readability. BPMN2 processes will still be
+ readable to a certain level, but tooling or a more detailed knowledge
+ of the spec will definitely be required to achieve the same level of
+ productivity.</listitem>
+ <listitem>Java developers who are super-fast in JPDL since they know the JPDL
+ language by heart, will find the use of tools sometimes bothersome and
+ the language itself overly complicated.</listitem>
+ <listitem>BPMN2 contains a large set of constructs described in the
+ specification. However, the "binding" of interfaces to code is left
+ open in the spec (comparable with XPDL), even is WDSL is considered the
+ default. This means that a process portability can be lost when porting
+ the process to an engine that doesn't support the same binding
+ mechanism. Calling Java classes for example is already going to be such
+ a jBPM specific binding.</listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ It is natural to the political level of BPMN2 specification process to go
+ rather slow. JPDL on the other hand will be able to incorporate changes
+ faster, integrate with new technologies when they are released and
+ evolve generally at a quicker pace compared to BPMN2.
+
+ Of course, since both are built on top of the same PVM, it is only
+ logical that additions to JPDL can be ported to BPMN2 as an extension
+ without much hassle.
+ </para>
+
+ </section>
+
+ <section id="gettingStartedWithBpmn2" >
+
+ <title>Getting started with BPMN 2.0</title>
+
+ <para>
+
+ </para>
+
+ </section>
+
+ <section id="Bpmn2Constructs" >
+
+ <title>Bpmn 2.0 constructs</title>
+
+ <para>
+ The BPMN2 specification defines a very rich language for modeling and
+ executing business processes. However, this also means that it is quite
+ hard to get an overview of what's possible with BPMN2. To simplify this
+ situation, we've decided to categorize the BPMN2 constructs into three
+ 'levels'. The separation itself is primarily based on the book 'BPMN
+ method & Style' by Bruce Silver (<ulink url="http://www.bpmnstyle.com/">http://www.bpmnstyle.com/</ulink>), the
+ training material of Dr. Jim Arlow
+ (<ulink url="http://www.slideshare.net/jimarlow/introductiontobpmn005">http://www.slideshare.net/jimarlow/introductiontobpmn005</ulink>),
+ 'How much BPMN do you need'
+ (<ulink url="http://www.bpm-research.com/2008/03/03/how-much-bpmn-do-you-need/">http://www.bpm-research.com/2008/03/03/how-much-bpmn-do-you-need/</ulink>),
+ and also our own experience.
+ </para>
+ <para>
+ We define three categories of BPMN2 constructs:
+ <itemizedlist>
+ <listitem><emphasis role="bold">Basic</emphasis>: constructs in this category are
+ straight-forward and easy to grasp. Constructs in this category can be used to
+ model simple business processes.</listitem>
+ <listitem><emphasis role="bold">Advanced</emphasis>: contains more powerful or
+ expressive constructs, but this comes with higher modeling and execution semantics
+ learning curve. 80% of the business processes are implementable with constructs from this
+ and the previous category.</listitem>
+ <listitem><emphasis role="bold">Complex</emphasis>: constructs in this category are
+ used in specific and/or rare cases, or their semantics are difficult to understand.</listitem>
+ </itemizedlist>
+ </para>
+
+ </section>
+
+</chapter>
Deleted: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch03-MigrationFromJbpm3.xml
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch03-MigrationFromJbpm3.xml 2009-12-15 10:55:41 UTC (rev 5959)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch03-MigrationFromJbpm3.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -1,237 +0,0 @@
-<chapter id="migrationfromjbpm3">
- <title>Migration from jBPM 3</title>
-
- <section>
- <title>Goals of jBPM 4</title>
- <para>In building jBPM 4, we have pursued 2 major goals:</para>
- <itemizedlist>
- <listitem><emphasis role="bold">Improve supportability:</emphasis> In jBPM 3 we relied only on community
- feedback for improving stability and portability. In jBPM 4 we have added
- a clear indication of which environments and configurations that we support.
- Those environments will be backed with continuous integration in the JBoss QA
- Labs. The build now supports all these environments and configurations so that
- it is easier for us to reproduce and investigate problems if they pop up.
- This coverage will also guarantee longer lifespan of jBPM 4.
- </listitem>
- <listitem><emphasis role="bold">Lowering the treshold and increasing adoption to the next level:</emphasis>
- In jBPM 4 we created a clear differentiation between the common, basic usage on the
- one hand and the advanced usage on the other hand. So it will be easier to
- get started and harder (but still possible) to leverage the bleeding edge stuff
- on which developers can burn their fingers.
- </listitem>
- </itemizedlist>
- </section>
-
- <section>
- <title>Known limitations</title>
- <para>As part of creating a clear separation between basic and advanced usage, the API
- has been completely revisited. Basic usage is covered with the public API. The same API
- is available in all the supported environments. Package names in jBPM 4 are strictly
- separated from package names in jBPM 3.
- </para>
- <para>Instead of providing a full DB migration, we opted for a strategy to
- allow for jBPM 3 and jBPM 4 instances to run concurrently next to each
- other. The table prefix is changed from <literal>JBPM_</literal> to <literal>JBPM4_</literal>.
- There is no migration tool to convert jBPM 3 runtime database contents
- to jBPM 4. We're not sure if we'll be able to build such a tool in one of the
- next version. One of the main reasons is that any QA for a data migration of the
- DB contents would be impossible for the project team to achieve.
- </para>
- <para>Furthermore, there are some features that are not yet available
- on jBPM 4. They are ordered from likely to unlikely to get implemented in
- jBPM 4.
- </para>
- <itemizedlist>
- <listitem>User provided transasctional resources such as JDBC connections
- or hibernate connections</listitem>
- <listitem>Exception handlers</listitem>
- <listitem>Transient variables</listitem>
- <listitem>Identity expression to calculate the assignee of a task</listitem>
- <listitem>Task form variable-to-parameter conversions</listitem>
- </itemizedlist>
- </section>
-
- <section id="processconversiontool">
- <title>Process conversion tool</title>
- <para>In many cases, a lot of work has been put in the design of JPDL3 process
- definitions. To avoid a complete manual translation of these processes to the
- JPDL4 format, the jBPM distribution contains a subdirectory called
- <emphasis role="bold">migration</emphasis>, which contains a command-line
- tool for converting JPDL3 process definition files to JPDL process XML files.
- </para>
-
- <para>Translated processes might not be executable any more. The jBPM 4
- features might still be missing or the translation itself might not yet
- be implemented. But the tedious work of reformatting will be handled
- by the tool. It will also indicate the parts that it can't translate.
- </para>
-
- <para>
- The tool itself uses only dom4j to do the translation between
- the two formats and should be easy extensible (the source code is also in
- the same directory). The design of the tool is deliberately kept very simple
- (ie most of the logic can be found in the <emphasis role="bold">Jpdl3Converter</emphasis> class).
- Note that this tool is experimental and tested only a small set of JPDL3
- process files.
- </para>
-
- <section>
- <title>Overview</title>
- <para>
- The jPDL Conversion tool takes a jpdl3 process file as input, and
- converts it to a jpdl4 process file.
- </para>
- <para>
- Syntax:
- <programlisting>java org.jbpm.jpdl.internal.convert.JpdlConverterTool -v -o <outputfile> <processfile></programlisting>
- </para>
- </section>
-
- <section>
- <title>Arguments</title>
- <itemizedlist>
- <listitem>
- <emphasis role="bold">-v (verbose):</emphasis> The tool will print the detail
- messages while converting the process file. When this argument is used,
- it will also print the error stacktrace if exceptions are thrown.
- </listitem>
- <listitem>
- <emphasis role="bold">-o (output)</emphasis> Specifies the output file name.
- By default, the tool will generate a file name ending in 'converted.jpdl.xml'
- using as a base file name the name derived from the input process file.
- The output-filename can be an absolute file name path or a relative file name path.
- </listitem>
- </itemizedlist>
- </section>
-
- <section>
- <title>Usage examples</title>
- <programlisting>
-java -jar jpdl-migration-XX.jar simple.jpdl.xml
-java -jar jpdl-migration-XX.jar -v simple.jpdl.xml
-java -jar jpdl-migration-XX.jar -o /home/scott/simple.converted.xml simple.jpdl.xml
- </programlisting>
- </section>
-
- <section>
- <title>Advanced</title>
- <para>
- The conversion tool can easily be integrated with regular Java code
- (or with Maven or Ant). The following code example shows how to call the
- internal api to convert the process file:
- <programlisting>
-URL url = new URL("simple.jpdl");
-Jpdl3Converter jpdlConverter = new Jpdl3Converter(url);
-Document jpdl4Doc = jpdlConverter.readAndConvert();
-
-for (Problem problem : jpdlConverter.problems) {
- //do something to handle the problem
-}
-
-Writer fileWriter = new FileWriter(outputFile);
-OutputFormat format = OutputFormat.createPrettyPrint();
-XMLWriter writer = new XMLWriter( fileWriter, format );
-writer.write(jpdl4Doc);
-writer.close();</programlisting>
- </para>
- </section>
- </section>
-
- <section>
- <title>Translations and changes</title>
- <para>This section gives an indication of the most important renamings and changes that
- were applied in jBPM4
- </para>
-
- <table><title>General name changes</title>
- <tgroup cols="2" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>jBPM 3</entry>
- <entry>jBPM 4</entry>
- <entry>Remarks</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>Node</entry>
- <entry>Activity</entry>
- </row>
- <row>
- <entry>Token</entry>
- <entry>Execution</entry>
- <entry>The root execution is now the same object as the
- process instance. (In jBPM 3, the ProcessInstance had
- a pointer to the root token). Also, unlike in jBPM 3, executions in jBPM 4 might
- get inactivated, create a child execution and let the child execution continue, even
- when logically this represents only one single path of execution. This happens in
- scope activities (or composite activities) that have timers or variables declared.
- </entry>
- </row>
- <row>
- <entry>Action</entry>
- <entry>Event listener</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table><title>jPDL XML changes</title>
- <tgroup cols="2" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>jBPM 3</entry>
- <entry>jBPM 4</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>process-definition</entry>
- <entry>process</entry>
- </row>
- <row>
- <entry>event type="..."</entry>
- <entry>on event="..."</entry>
- </row>
- <row>
- <entry>action</entry>
- <entry>event-listener</entry>
- </row>
- <row>
- <entry>node</entry>
- <entry>custom</entry>
- </row>
- <row>
- <entry>process-state</entry>
- <entry>sub-process</entry>
- </row>
- <row>
- <entry>super-state</entry>
- <entry>group (still in incubation)</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table><title>Default changes</title>
- <tgroup cols="2" rowsep="1" colsep="1">
- <thead>
- <row>
- <entry>jBPM 3</entry>
- <entry>jBPM 4</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>by default, propagated events trigger actions in outer process elements</entry>
- <entry>by default, propagated events <emphasis role="bold">do not</emphasis>
- invoke event-listeners in outer elements, but only in the element on which the
- event listener is subscribed.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- </section>
-
-</chapter>
Copied: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch04-MigrationFromJbpm3.xml (from rev 5958, jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch03-MigrationFromJbpm3.xml)
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch04-MigrationFromJbpm3.xml (rev 0)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch04-MigrationFromJbpm3.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -0,0 +1,237 @@
+<chapter id="migrationfromjbpm3">
+ <title>Migration from jBPM 3</title>
+
+ <section>
+ <title>Goals of jBPM 4</title>
+ <para>In building jBPM 4, we have pursued 2 major goals:</para>
+ <itemizedlist>
+ <listitem><emphasis role="bold">Improve supportability:</emphasis> In jBPM 3 we relied only on community
+ feedback for improving stability and portability. In jBPM 4 we have added
+ a clear indication of which environments and configurations that we support.
+ Those environments will be backed with continuous integration in the JBoss QA
+ Labs. The build now supports all these environments and configurations so that
+ it is easier for us to reproduce and investigate problems if they pop up.
+ This coverage will also guarantee longer lifespan of jBPM 4.
+ </listitem>
+ <listitem><emphasis role="bold">Lowering the treshold and increasing adoption to the next level:</emphasis>
+ In jBPM 4 we created a clear differentiation between the common, basic usage on the
+ one hand and the advanced usage on the other hand. So it will be easier to
+ get started and harder (but still possible) to leverage the bleeding edge stuff
+ on which developers can burn their fingers.
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Known limitations</title>
+ <para>As part of creating a clear separation between basic and advanced usage, the API
+ has been completely revisited. Basic usage is covered with the public API. The same API
+ is available in all the supported environments. Package names in jBPM 4 are strictly
+ separated from package names in jBPM 3.
+ </para>
+ <para>Instead of providing a full DB migration, we opted for a strategy to
+ allow for jBPM 3 and jBPM 4 instances to run concurrently next to each
+ other. The table prefix is changed from <literal>JBPM_</literal> to <literal>JBPM4_</literal>.
+ There is no migration tool to convert jBPM 3 runtime database contents
+ to jBPM 4. We're not sure if we'll be able to build such a tool in one of the
+ next version. One of the main reasons is that any QA for a data migration of the
+ DB contents would be impossible for the project team to achieve.
+ </para>
+ <para>Furthermore, there are some features that are not yet available
+ on jBPM 4. They are ordered from likely to unlikely to get implemented in
+ jBPM 4.
+ </para>
+ <itemizedlist>
+ <listitem>User provided transasctional resources such as JDBC connections
+ or hibernate connections</listitem>
+ <listitem>Exception handlers</listitem>
+ <listitem>Transient variables</listitem>
+ <listitem>Identity expression to calculate the assignee of a task</listitem>
+ <listitem>Task form variable-to-parameter conversions</listitem>
+ </itemizedlist>
+ </section>
+
+ <section id="processconversiontool">
+ <title>Process conversion tool</title>
+ <para>In many cases, a lot of work has been put in the design of JPDL3 process
+ definitions. To avoid a complete manual translation of these processes to the
+ JPDL4 format, the jBPM distribution contains a subdirectory called
+ <emphasis role="bold">migration</emphasis>, which contains a command-line
+ tool for converting JPDL3 process definition files to JPDL process XML files.
+ </para>
+
+ <para>Translated processes might not be executable any more. The jBPM 4
+ features might still be missing or the translation itself might not yet
+ be implemented. But the tedious work of reformatting will be handled
+ by the tool. It will also indicate the parts that it can't translate.
+ </para>
+
+ <para>
+ The tool itself uses only dom4j to do the translation between
+ the two formats and should be easy extensible (the source code is also in
+ the same directory). The design of the tool is deliberately kept very simple
+ (ie most of the logic can be found in the <emphasis role="bold">Jpdl3Converter</emphasis> class).
+ Note that this tool is experimental and tested only a small set of JPDL3
+ process files.
+ </para>
+
+ <section>
+ <title>Overview</title>
+ <para>
+ The jPDL Conversion tool takes a jpdl3 process file as input, and
+ converts it to a jpdl4 process file.
+ </para>
+ <para>
+ Syntax:
+ <programlisting>java org.jbpm.jpdl.internal.convert.JpdlConverterTool -v -o <outputfile> <processfile></programlisting>
+ </para>
+ </section>
+
+ <section>
+ <title>Arguments</title>
+ <itemizedlist>
+ <listitem>
+ <emphasis role="bold">-v (verbose):</emphasis> The tool will print the detail
+ messages while converting the process file. When this argument is used,
+ it will also print the error stacktrace if exceptions are thrown.
+ </listitem>
+ <listitem>
+ <emphasis role="bold">-o (output)</emphasis> Specifies the output file name.
+ By default, the tool will generate a file name ending in 'converted.jpdl.xml'
+ using as a base file name the name derived from the input process file.
+ The output-filename can be an absolute file name path or a relative file name path.
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>Usage examples</title>
+ <programlisting>
+java -jar jpdl-migration-XX.jar simple.jpdl.xml
+java -jar jpdl-migration-XX.jar -v simple.jpdl.xml
+java -jar jpdl-migration-XX.jar -o /home/scott/simple.converted.xml simple.jpdl.xml
+ </programlisting>
+ </section>
+
+ <section>
+ <title>Advanced</title>
+ <para>
+ The conversion tool can easily be integrated with regular Java code
+ (or with Maven or Ant). The following code example shows how to call the
+ internal api to convert the process file:
+ <programlisting>
+URL url = new URL("simple.jpdl");
+Jpdl3Converter jpdlConverter = new Jpdl3Converter(url);
+Document jpdl4Doc = jpdlConverter.readAndConvert();
+
+for (Problem problem : jpdlConverter.problems) {
+ //do something to handle the problem
+}
+
+Writer fileWriter = new FileWriter(outputFile);
+OutputFormat format = OutputFormat.createPrettyPrint();
+XMLWriter writer = new XMLWriter( fileWriter, format );
+writer.write(jpdl4Doc);
+writer.close();</programlisting>
+ </para>
+ </section>
+ </section>
+
+ <section>
+ <title>Translations and changes</title>
+ <para>This section gives an indication of the most important renamings and changes that
+ were applied in jBPM4
+ </para>
+
+ <table><title>General name changes</title>
+ <tgroup cols="2" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>jBPM 3</entry>
+ <entry>jBPM 4</entry>
+ <entry>Remarks</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>Node</entry>
+ <entry>Activity</entry>
+ </row>
+ <row>
+ <entry>Token</entry>
+ <entry>Execution</entry>
+ <entry>The root execution is now the same object as the
+ process instance. (In jBPM 3, the ProcessInstance had
+ a pointer to the root token). Also, unlike in jBPM 3, executions in jBPM 4 might
+ get inactivated, create a child execution and let the child execution continue, even
+ when logically this represents only one single path of execution. This happens in
+ scope activities (or composite activities) that have timers or variables declared.
+ </entry>
+ </row>
+ <row>
+ <entry>Action</entry>
+ <entry>Event listener</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <table><title>jPDL XML changes</title>
+ <tgroup cols="2" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>jBPM 3</entry>
+ <entry>jBPM 4</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>process-definition</entry>
+ <entry>process</entry>
+ </row>
+ <row>
+ <entry>event type="..."</entry>
+ <entry>on event="..."</entry>
+ </row>
+ <row>
+ <entry>action</entry>
+ <entry>event-listener</entry>
+ </row>
+ <row>
+ <entry>node</entry>
+ <entry>custom</entry>
+ </row>
+ <row>
+ <entry>process-state</entry>
+ <entry>sub-process</entry>
+ </row>
+ <row>
+ <entry>super-state</entry>
+ <entry>group (still in incubation)</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <table><title>Default changes</title>
+ <tgroup cols="2" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>jBPM 3</entry>
+ <entry>jBPM 4</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>by default, propagated events trigger actions in outer process elements</entry>
+ <entry>by default, propagated events <emphasis role="bold">do not</emphasis>
+ invoke event-listeners in outer elements, but only in the element on which the
+ event listener is subscribed.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ </section>
+
+</chapter>
Deleted: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch04-ProcessVirtualMachine.xml
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch04-ProcessVirtualMachine.xml 2009-12-15 10:55:41 UTC (rev 5959)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch04-ProcessVirtualMachine.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -1,50 +0,0 @@
-<chapter id="processvirtualmachine">
- <title>The Process Virtual Machine</title>
- <para>To accomodate multiple process languages and activity pluggability, jBPM is based on
- the Process Virtual Machine. In essence, the Process Virtual Machine is a framework specifying
- executable graphs. A process definition represents an execution flow
- and has a structure that be represented graphically as a diagram.
- </para>
- <para>The Process Virtual Machine separates the structure from a process definition from
- the activity behaviours. The Process Virtual Machine takes the execution of a process from
- one activity to the next and delegates the behaviour of the activities to pluggable Java classes.
- There is an API (<literal>ActivityBehaviour</literal>) that serves as the interface between
- the Process Virtual Machine and the activity behaviour code. Languages like jPDL are
- merely a set of ActivityBehaviour implementations and a parser.
- </para>
- <figure id="example.process.graph">
- <title>Example process definition</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/process.loan.png"/></imageobject></mediaobject>
- </figure>
- <para>Typically, process definitions are static. A process definition is composed of
- activities and transitions. The runtime behaviour of a activity is encapsulated in a so called
- Activity and it's decoupled from the process graph structure.
- </para>
- <figure id="class.diagram.process.definition">
- <title>Process structure class diagram</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/class.diagram.process.definition.png"/></imageobject></mediaobject>
- </figure>
- <para>The Process Virtual
- Machine doesn't contain any such activity implementations. It only provides the
- execution environment and an activity API to write <literal>ActivityBehaviour</literal>
- implementations as Java components. Activities can also be wait states. This means
- that the activity control flow goes outside the process system. For example a human task
- or invoking an service asynchronously. While the execution is waiting, the runtime state
- of that execution can be persisted in a DB.
- </para>
- <para>Many executions can be started for one process definition. An execution is a pointer
- that keeps track of the current activity.
- </para>
- <figure id="example.execution">
- <title>Example execution</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/loan.execution.png"/></imageobject></mediaobject>
- </figure>
- <para>To represent concurrent paths of execution, there is
- a hierarchical parent-child relation between so that one process instance can cope with concurrent
- paths of execution.
- </para>
- <figure id="class.diagram.process.execution">
- <title>Execution class diagram</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/class.diagram.process.execution.png"/></imageobject></mediaobject>
- </figure>
-</chapter>
Deleted: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch05-Architecture.xml
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch05-Architecture.xml 2009-12-15 10:55:41 UTC (rev 5959)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch05-Architecture.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -1,260 +0,0 @@
-<chapter id="architecture">
- <title>Architecture</title>
-
- <section id="apis">
- <title>APIs</title>
- <para>The Process Virtual Machine has 4 integrated API's that together
- offer a complete coverage of working with processes in the different execution modes.
- Each of the APIs has a specific purpose that fits within the following overall
- architecture.
- </para>
- <figure id="apis">
- <title>The 4 API's of the Process Virtual Machine</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/apis.png"/></imageobject></mediaobject>
- </figure>
- <para>The services interfaces should be used from application code that wants to interact
- with the Process Virtual Machine which runs in transactional persistent mode, backed by a
- database. This is the most typical way how users interact with the PVM as a workflow engine.
- </para>
- <para>To execute processes without persistence, the client API can be used to work with process
- and execution objects directly. The client API expose the methods of the core model objects.
- </para>
- <para>The activity API is used to implement the runtime behaviour of activities. So a activity
- type is in fact a component with at the core an implementation of the <literal>ActivityBehaviour</literal>
- interface. ActivityBehaviour implementations can control the flow of execution.
- </para>
- <para>The event listener API serves to write pieces of Java code that should be executed upon
- process events. It's very similar to the activity API with that exception that event listeners
- are not able to control the flow of execution.
- </para>
- </section>
-
- <section>
- <title>Activity API</title>
- <para>The activity API allows to implement the runtime activity behaviour in Java.
- </para>
- <programlisting>public interface ActivityBehaviour extends Serializable {
- void execute(ActivityExecution execution) throws Exception;
-}</programlisting>
- <para>An activity is the behaviour of the activity to which it is associated.
- The provided execution is the execution that arrives in the activity.
- The interface <literal>ActivityExecution</literal> exposes special
- methods to control the execution flow.
- </para>
- <programlisting>public interface ActivityExecution extends OpenExecution {
-
- void waitForSignal();
- void take(String transitionName);
- void execute(String activityName);
-
- ...
-
-}</programlisting>
- </section>
-
- <section>
- <title>Event listener API</title>
- <para>The event listener API allows for listeners to be developed in Java code
- and that are invoked on specific process events like entering a activity or leaving
- a activity. It is very similar to the activity API, but the difference is
- that the propagation of the execution flow cannot be controlled. E.g. when an execution
- is taking a transition, a listener to that event can be notified, but since the
- transition is already being taking, the execution flow cannot be changed
- by the event listeners.
- </para>
- <programlisting>public interface EventListener extends Serializable {
-
- void notify(EventListenerExecution execution) throws Exception;
-
-}</programlisting>
- </section>
-
- <section>
- <title>Client API</title>
- <para>The client API is the interface that exposes the methods for
- managing executions on the plain process definition and execution objects directly.
- </para>
- <para>At a minimal, the client API and the activity API are needed to create
- some a process definition with activities and execute it.
- </para>
- </section>
-
- <section>
- <title>Environment</title>
- <para>In the persistent execution mode, the first purpose of the environment is
- to enable processes to be executed in different transactional environments like
- standard Java, enterprise Java, SEAM and Spring.
- </para>
- <para>The PVM code itself will only use transactional resources through self-defined
- interfaces. For example, the PVM itself has interfaces for some methods on the hibernate
- session, a async messaging session and a timer session.
- </para>
- <para>The environment allows to configure the actual implementations, lazy
- initialization of the services on a request-basis and caching the service
- objects for the duration of the transaction.
- </para>
- <para>An environment factory is static and one environment factory can serve
- all the threads in an application.
- </para>
- <programlisting>EnvironmentFactory environmentFactory = new PvmEnvironmentFactory("environment.cfg.xml");</programlisting>
- <para>Environment blocks can surround persistent process operations
- like this:
- </para>
- <programlisting>Environment environment = environmentFactory.openEnvironment();
-try {
-
- ... inside the environment block...
-
-} finally {
- environment.close();
-}</programlisting>
- <para>The PVM itself will fetch all it's transactional resources and configurations
- from the environment. It's recommended that <literal>Activity</literal> implementations
- do the same.
- </para>
- <para>The <literal>org.jbpm.pvm.internal.cfg.JbpmConfiguration</literal> acts as Configuration,
- ProcessEngine and EnvironmentFactory.
- </para>
- </section>
-
- <section>
- <title>Commands</title>
- <para>Commands encapsulate operations that are to be executed within an environment
- block. The main purpose for commands is to capture the logic of
- </para>
- <programlisting>public interface Command<T> extends Serializable {
-
- T execute(Environment environment) throws Exception;
-
-}</programlisting>
- <para></para>
- </section>
-
- <section>
- <title>Services</title>
- <para>There are three main services: <literal>RepositoryService</literal>,
- <literal>ExecutionService</literal> and <literal>ManagementService</literal>.
- In general, services are session facades that expose methods for persistent
- usage of the PVM. The next fragments show the essential methods as example
- to illustrate those services.
- </para>
- <para>The <literal>RepositoryService</literal> manages the repository of
- process definitions.
- </para>
- <programlisting>public interface RepositoryService {
-
- Deployment createDeployment();
-
- ProcessDefinitionQuery createProcessDefinitionQuery();
-
- ...
-
-}</programlisting>
- <para>The <literal>ExecutionService</literal> manages the runtime
- executions.</para>
- <programlisting>public interface ExecutionService {
-
- ProcessInstance startProcessInstanceById(String processDefinitionId);
-
- ProcessInstance signalExecutionById(String executionId);
-
- ...
-
-}</programlisting>
- <para>The <literal>ManagementService</literal> groups all management operations
- that are needed to keep the system up and running.
- </para>
- <programlisting>public interface ManagementService {
-
- JobQuery createJobQuery();
-
- void executeJob(long jobDbid);
-
- ...
-
-}</programlisting>
- <para>The implementation of all these methods is encapsulated in
- <literal>Command</literal>s. And the three services all delegate the
- execution of the commands to a <literal>CommandService</literal>:
- </para>
- <programlisting>public interface CommandService {
-
- <T> T execute(Command<T> command);
-
-}</programlisting>
- <para>The <literal>CommandService</literal> is configured in the
- environment. A chain of CommandServices can act as interceptors
- around a command. This is the core mechanism on how persistence and
- transactional support can be offered in a variety of environments.
- </para>
- <para>The default configuration file <literal>jbpm.default.cfg.xml</literal>
- includes following section that configures the services
- </para>
- <programlisting><jbpm-configuration>
-
- <process-engine>
-
- <repository-service />
- <repository-cache />
- <execution-service />
- <history-service />
- <management-service />
- <identity-service />
- <task-service /></programlisting>
- <para>And the file <literal>jbpm.tx.hibernate.cfg.xml</literal> contains the
- following command service configuration:</para>
- <programlisting><jbpm-configuration>
-
- <process-engine-context>
- <command-service>
- <retry-interceptor />
- <environment-interceptor />
- <standard-transaction-interceptor />
- </command-service>
- </process-engine-context>
-
- ...</programlisting>
- <para>The services like e.g. <literal>repository-service</literal>, <literal>execution-service</literal>
- and <literal>management-service</literal> will look up the configured
- <literal>command-service</literal> by type. The <literal>command-service</literal>
- tag corresponds to the default command service that essentially does nothing else
- then just execute the command providing it the current environment.
- </para>
- <para>The configured <literal>command-service</literal> results into the following
- a chain of three interceptors followed by the default command executor.
- </para>
- <figure id="interceptors">
- <title>The CommandService interceptors</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/interceptors.png"/></imageobject></mediaobject>
- </figure>
- <para>The retry interceptor is the first in the chain and that one that will be exposed as the
- <literal>CommandService.class</literal> from the environment. So the retry interceptor
- will be given to the respective services <literal>repository-service</literal>, <literal>execution-service</literal>
- and <literal>management-service</literal>.
- </para>
- <para>The <literal>retry-interceptor</literal> will catch hibernate StaleObjectExceptions
- (indicating optimistic locking failures) and retry to execute the command.
- </para>
- <para>The <literal>environment-interceptor</literal> will put an environment block
- around the execution of the command.
- </para>
- <para>The <literal>standard-transaction-interceptor</literal> will initialize a
- <literal>StandardTransaction</literal>. The hibernate session/transaction will be
- enlisted as a resource with this standard transaction.
- </para>
- <para>Different configurations of this interceptor stack will also enable to
- </para>
- <itemizedlist>
- <listitem>delegate execution to a local ejb command service so that an container
- managed transaction is started.
- </listitem>
- <listitem>delegate to a remote ejb command service so that the command actually
- gets executed on a different JVM.
- </listitem>
- <listitem>package the command as an asynchronous message so that the command gets
- executed asynchronously in a different transaction.
- </listitem>
- </itemizedlist>
- </section>
-
-</chapter>
\ No newline at end of file
Copied: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch05-ProcessVirtualMachine.xml (from rev 5958, jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch04-ProcessVirtualMachine.xml)
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch05-ProcessVirtualMachine.xml (rev 0)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch05-ProcessVirtualMachine.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -0,0 +1,50 @@
+<chapter id="processvirtualmachine">
+ <title>The Process Virtual Machine</title>
+ <para>To accomodate multiple process languages and activity pluggability, jBPM is based on
+ the Process Virtual Machine. In essence, the Process Virtual Machine is a framework specifying
+ executable graphs. A process definition represents an execution flow
+ and has a structure that be represented graphically as a diagram.
+ </para>
+ <para>The Process Virtual Machine separates the structure from a process definition from
+ the activity behaviours. The Process Virtual Machine takes the execution of a process from
+ one activity to the next and delegates the behaviour of the activities to pluggable Java classes.
+ There is an API (<literal>ActivityBehaviour</literal>) that serves as the interface between
+ the Process Virtual Machine and the activity behaviour code. Languages like jPDL are
+ merely a set of ActivityBehaviour implementations and a parser.
+ </para>
+ <figure id="example.process.graph">
+ <title>Example process definition</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/process.loan.png"/></imageobject></mediaobject>
+ </figure>
+ <para>Typically, process definitions are static. A process definition is composed of
+ activities and transitions. The runtime behaviour of a activity is encapsulated in a so called
+ Activity and it's decoupled from the process graph structure.
+ </para>
+ <figure id="class.diagram.process.definition">
+ <title>Process structure class diagram</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/class.diagram.process.definition.png"/></imageobject></mediaobject>
+ </figure>
+ <para>The Process Virtual
+ Machine doesn't contain any such activity implementations. It only provides the
+ execution environment and an activity API to write <literal>ActivityBehaviour</literal>
+ implementations as Java components. Activities can also be wait states. This means
+ that the activity control flow goes outside the process system. For example a human task
+ or invoking an service asynchronously. While the execution is waiting, the runtime state
+ of that execution can be persisted in a DB.
+ </para>
+ <para>Many executions can be started for one process definition. An execution is a pointer
+ that keeps track of the current activity.
+ </para>
+ <figure id="example.execution">
+ <title>Example execution</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/loan.execution.png"/></imageobject></mediaobject>
+ </figure>
+ <para>To represent concurrent paths of execution, there is
+ a hierarchical parent-child relation between so that one process instance can cope with concurrent
+ paths of execution.
+ </para>
+ <figure id="class.diagram.process.execution">
+ <title>Execution class diagram</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/class.diagram.process.execution.png"/></imageobject></mediaobject>
+ </figure>
+</chapter>
Copied: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch06-Architecture.xml (from rev 5958, jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch05-Architecture.xml)
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch06-Architecture.xml (rev 0)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch06-Architecture.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -0,0 +1,260 @@
+<chapter id="architecture">
+ <title>Architecture</title>
+
+ <section id="apis">
+ <title>APIs</title>
+ <para>The Process Virtual Machine has 4 integrated API's that together
+ offer a complete coverage of working with processes in the different execution modes.
+ Each of the APIs has a specific purpose that fits within the following overall
+ architecture.
+ </para>
+ <figure id="apis">
+ <title>The 4 API's of the Process Virtual Machine</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/apis.png"/></imageobject></mediaobject>
+ </figure>
+ <para>The services interfaces should be used from application code that wants to interact
+ with the Process Virtual Machine which runs in transactional persistent mode, backed by a
+ database. This is the most typical way how users interact with the PVM as a workflow engine.
+ </para>
+ <para>To execute processes without persistence, the client API can be used to work with process
+ and execution objects directly. The client API expose the methods of the core model objects.
+ </para>
+ <para>The activity API is used to implement the runtime behaviour of activities. So a activity
+ type is in fact a component with at the core an implementation of the <literal>ActivityBehaviour</literal>
+ interface. ActivityBehaviour implementations can control the flow of execution.
+ </para>
+ <para>The event listener API serves to write pieces of Java code that should be executed upon
+ process events. It's very similar to the activity API with that exception that event listeners
+ are not able to control the flow of execution.
+ </para>
+ </section>
+
+ <section>
+ <title>Activity API</title>
+ <para>The activity API allows to implement the runtime activity behaviour in Java.
+ </para>
+ <programlisting>public interface ActivityBehaviour extends Serializable {
+ void execute(ActivityExecution execution) throws Exception;
+}</programlisting>
+ <para>An activity is the behaviour of the activity to which it is associated.
+ The provided execution is the execution that arrives in the activity.
+ The interface <literal>ActivityExecution</literal> exposes special
+ methods to control the execution flow.
+ </para>
+ <programlisting>public interface ActivityExecution extends OpenExecution {
+
+ void waitForSignal();
+ void take(String transitionName);
+ void execute(String activityName);
+
+ ...
+
+}</programlisting>
+ </section>
+
+ <section>
+ <title>Event listener API</title>
+ <para>The event listener API allows for listeners to be developed in Java code
+ and that are invoked on specific process events like entering a activity or leaving
+ a activity. It is very similar to the activity API, but the difference is
+ that the propagation of the execution flow cannot be controlled. E.g. when an execution
+ is taking a transition, a listener to that event can be notified, but since the
+ transition is already being taking, the execution flow cannot be changed
+ by the event listeners.
+ </para>
+ <programlisting>public interface EventListener extends Serializable {
+
+ void notify(EventListenerExecution execution) throws Exception;
+
+}</programlisting>
+ </section>
+
+ <section>
+ <title>Client API</title>
+ <para>The client API is the interface that exposes the methods for
+ managing executions on the plain process definition and execution objects directly.
+ </para>
+ <para>At a minimal, the client API and the activity API are needed to create
+ some a process definition with activities and execute it.
+ </para>
+ </section>
+
+ <section>
+ <title>Environment</title>
+ <para>In the persistent execution mode, the first purpose of the environment is
+ to enable processes to be executed in different transactional environments like
+ standard Java, enterprise Java, SEAM and Spring.
+ </para>
+ <para>The PVM code itself will only use transactional resources through self-defined
+ interfaces. For example, the PVM itself has interfaces for some methods on the hibernate
+ session, a async messaging session and a timer session.
+ </para>
+ <para>The environment allows to configure the actual implementations, lazy
+ initialization of the services on a request-basis and caching the service
+ objects for the duration of the transaction.
+ </para>
+ <para>An environment factory is static and one environment factory can serve
+ all the threads in an application.
+ </para>
+ <programlisting>EnvironmentFactory environmentFactory = new PvmEnvironmentFactory("environment.cfg.xml");</programlisting>
+ <para>Environment blocks can surround persistent process operations
+ like this:
+ </para>
+ <programlisting>Environment environment = environmentFactory.openEnvironment();
+try {
+
+ ... inside the environment block...
+
+} finally {
+ environment.close();
+}</programlisting>
+ <para>The PVM itself will fetch all it's transactional resources and configurations
+ from the environment. It's recommended that <literal>Activity</literal> implementations
+ do the same.
+ </para>
+ <para>The <literal>org.jbpm.pvm.internal.cfg.JbpmConfiguration</literal> acts as Configuration,
+ ProcessEngine and EnvironmentFactory.
+ </para>
+ </section>
+
+ <section>
+ <title>Commands</title>
+ <para>Commands encapsulate operations that are to be executed within an environment
+ block. The main purpose for commands is to capture the logic of
+ </para>
+ <programlisting>public interface Command<T> extends Serializable {
+
+ T execute(Environment environment) throws Exception;
+
+}</programlisting>
+ <para></para>
+ </section>
+
+ <section>
+ <title>Services</title>
+ <para>There are three main services: <literal>RepositoryService</literal>,
+ <literal>ExecutionService</literal> and <literal>ManagementService</literal>.
+ In general, services are session facades that expose methods for persistent
+ usage of the PVM. The next fragments show the essential methods as example
+ to illustrate those services.
+ </para>
+ <para>The <literal>RepositoryService</literal> manages the repository of
+ process definitions.
+ </para>
+ <programlisting>public interface RepositoryService {
+
+ Deployment createDeployment();
+
+ ProcessDefinitionQuery createProcessDefinitionQuery();
+
+ ...
+
+}</programlisting>
+ <para>The <literal>ExecutionService</literal> manages the runtime
+ executions.</para>
+ <programlisting>public interface ExecutionService {
+
+ ProcessInstance startProcessInstanceById(String processDefinitionId);
+
+ ProcessInstance signalExecutionById(String executionId);
+
+ ...
+
+}</programlisting>
+ <para>The <literal>ManagementService</literal> groups all management operations
+ that are needed to keep the system up and running.
+ </para>
+ <programlisting>public interface ManagementService {
+
+ JobQuery createJobQuery();
+
+ void executeJob(long jobDbid);
+
+ ...
+
+}</programlisting>
+ <para>The implementation of all these methods is encapsulated in
+ <literal>Command</literal>s. And the three services all delegate the
+ execution of the commands to a <literal>CommandService</literal>:
+ </para>
+ <programlisting>public interface CommandService {
+
+ <T> T execute(Command<T> command);
+
+}</programlisting>
+ <para>The <literal>CommandService</literal> is configured in the
+ environment. A chain of CommandServices can act as interceptors
+ around a command. This is the core mechanism on how persistence and
+ transactional support can be offered in a variety of environments.
+ </para>
+ <para>The default configuration file <literal>jbpm.default.cfg.xml</literal>
+ includes following section that configures the services
+ </para>
+ <programlisting><jbpm-configuration>
+
+ <process-engine>
+
+ <repository-service />
+ <repository-cache />
+ <execution-service />
+ <history-service />
+ <management-service />
+ <identity-service />
+ <task-service /></programlisting>
+ <para>And the file <literal>jbpm.tx.hibernate.cfg.xml</literal> contains the
+ following command service configuration:</para>
+ <programlisting><jbpm-configuration>
+
+ <process-engine-context>
+ <command-service>
+ <retry-interceptor />
+ <environment-interceptor />
+ <standard-transaction-interceptor />
+ </command-service>
+ </process-engine-context>
+
+ ...</programlisting>
+ <para>The services like e.g. <literal>repository-service</literal>, <literal>execution-service</literal>
+ and <literal>management-service</literal> will look up the configured
+ <literal>command-service</literal> by type. The <literal>command-service</literal>
+ tag corresponds to the default command service that essentially does nothing else
+ then just execute the command providing it the current environment.
+ </para>
+ <para>The configured <literal>command-service</literal> results into the following
+ a chain of three interceptors followed by the default command executor.
+ </para>
+ <figure id="interceptors">
+ <title>The CommandService interceptors</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/interceptors.png"/></imageobject></mediaobject>
+ </figure>
+ <para>The retry interceptor is the first in the chain and that one that will be exposed as the
+ <literal>CommandService.class</literal> from the environment. So the retry interceptor
+ will be given to the respective services <literal>repository-service</literal>, <literal>execution-service</literal>
+ and <literal>management-service</literal>.
+ </para>
+ <para>The <literal>retry-interceptor</literal> will catch hibernate StaleObjectExceptions
+ (indicating optimistic locking failures) and retry to execute the command.
+ </para>
+ <para>The <literal>environment-interceptor</literal> will put an environment block
+ around the execution of the command.
+ </para>
+ <para>The <literal>standard-transaction-interceptor</literal> will initialize a
+ <literal>StandardTransaction</literal>. The hibernate session/transaction will be
+ enlisted as a resource with this standard transaction.
+ </para>
+ <para>Different configurations of this interceptor stack will also enable to
+ </para>
+ <itemizedlist>
+ <listitem>delegate execution to a local ejb command service so that an container
+ managed transaction is started.
+ </listitem>
+ <listitem>delegate to a remote ejb command service so that the command actually
+ gets executed on a different JVM.
+ </listitem>
+ <listitem>package the command as an asynchronous message so that the command gets
+ executed asynchronously in a different transaction.
+ </listitem>
+ </itemizedlist>
+ </section>
+
+</chapter>
\ No newline at end of file
Deleted: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch06-ImplementingBasicActivities.xml
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch06-ImplementingBasicActivities.xml 2009-12-15 10:55:41 UTC (rev 5959)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch06-ImplementingBasicActivities.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -1,486 +0,0 @@
-<chapter id="implementingbasicactivities">
- <title>Implementing basic activities</title>
-
- <para>This chapter explains the basics of process definitions, the features offered by
- the Process Virtual Machine and how activity implementations can be build. At the same
- time the client API is shown to execute processes with those activity implementations.
- </para>
-
- <!-- ### Activity ####################################################### -->
- <section id="activity">
- <title>ActivityBehaviour</title>
- <para>The PVM library doesn't have a fixed set of process constructs.
- Instead, runtime behaviour of a activity is delegated to an <literal>ActivityBehaviour</literal>.
- In other words, <literal>ActivityBehaviour</literal> is an interface to implement the runtime
- behaviour of process constructs in plain Java.
- </para>
- <programlisting>public <emphasis role="bold">interface ActivityBehaviour</emphasis> extends Serializable {
-
- void <emphasis role="bold">execute</emphasis>(ActivityExecution execution) throws Exception;
-
-}</programlisting>
- <para>When an activity behaviour is called, it is in full control of the further
- propagation of the execution. In other words, an activity behaviour can decide what the execution
- should do next. For example, it can take a transition with
- <literal>execution.take(Transition)</literal> or go into a wait state with
- <literal>execution.waitForSignal()</literal>. In case the activity behaviour does not invoke
- any of the above execution propagation methods, the execution will
- <link linkend="implicitproceedbehaviour">proceed in a default way</link>.
- </para>
- </section>
-
- <!-- ### ActivityBehaviour example ############################################### -->
- <section id="activitybehaviourexample">
- <title>ActivityBehaviour example</title>
- <para>We'll start with a very original hello world example. A Display
- activity will print a message to the console:
- </para>
- <programlisting>public <emphasis role="bold">class Display</emphasis> implements <emphasis role="bold">ActivityBehaviour</emphasis> {
-
- String message;
-
- public Display(String message) {
- this.message = message;
- }
-
- public void execute(ActivityExecution execution) {
- <emphasis role="bold">System.out.println(message);</emphasis>
- }
-}</programlisting>
- <para>Let' build our first process definition with this activity:</para>
- <figure id="activity.example">
- <title>Display example process</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/process.ab.png"/></imageobject></mediaobject>
- </figure>
- <programlisting>TODO add ProcessBuilder example code</programlisting>
- <para>Now we can execute this process as follows:</para>
- <programlisting>Execution execution = processDefinition.startExecution();</programlisting>
- <para>The invocation of <literal>startExecution</literal> will print hello world to the console:</para>
- <programlisting>hello
-world</programlisting>
- <para>One thing already worth noticing is that activities can be configured
- with properties. In the Display example, you can see that the message property
- is configured differently in the two usages. With configuration properties
- it becomes possible to write reusable activities. They can then be configured
- differently each time they are used in a process. That is an essential part of
- how process languages can be build on top of the Process Virtual Machine.
- </para>
- <para>The other part that needs explanation is that this activity
- implementation does not contain any instructions for the propagation of the
- execution. When a new process instance is started, the execution is positioned
- in the initial activity and that activity is executed. The method
- <literal>Display.execute</literal> makes use of what is called implicit propagation
- of execution. Concretely this means that the activity itself does not
- invoke any of the methods on the execution to propagate it. In that case
- implicit propagation kicks in. Implicit propagation will take the first
- transition if there is one. If not, it will end the execution. This explains
- why both activities <literal>a</literal> and <literal>b</literal> are executed and that
- the execution stops after activity <literal>b</literal> is executed.
- </para>
- <para>More details about the implicit proceed behaviour can be found
- in <xref linkend="implicitproceedbehaviour" /></para>
- </section>
-
- <!-- ### ExternalActivityBehaviour ############################################### -->
- <section id="externalactivitybehaviour">
- <title>ExternalActivityBehaviour</title>
- <para>External activities are activities for which the responsibility for proceeding
- the execution is transferred externally, meaning outside the process system. This
- means that for the system that is executing the process, it's a wait state. The
- execution will wait until an external trigger is given.
- </para>
- <para>For dealing with external triggers, <literal>ExternalActivityBehaviour</literal>
- adds one method to the <literal>ActivityBehaviour</literal>:</para>
- <programlisting>public <emphasis role="bold">interface ExternalActivity</emphasis> extends <emphasis role="bold">Activity</emphasis> {
-
- void <emphasis role="bold">signal</emphasis>(Execution execution,
- String signal,
- Map<String, Object> parameters) throws Exception;
-
-}</programlisting>
- <para>Just like with plain activities, when an execution arrives in a activity, the
- <literal>execute</literal>-method of the external activity behaviour is invoked.
- In external activities, the execute method typically does something to
- transfer the responsibility to another system and then enters a wait
- state by invoking <literal>execution.waitForSignal()</literal>. For
- example in the execute method, responsibility could be transferred to a
- person by creating a task entry in a task management system and then
- wait until the person completes the task.
- </para>
- <para>In case a activity behaves as a wait state, then the execution will
- wait in that activity until the execution's <literal>signal</literal> method
- is invoked. The execution will delegate that signal to the ExternalActivityBehaviour
- object associated to the current activity.
- </para>
- <para>So the Activity's <literal>signal</literal>-method is invoked
- when the execution receives an external trigger during the wait state. With the
- signal method, responsibility is transferred back to the process execution. For
- example, when a person completes a task, the task management system calls the
- signal method on the execution.
- </para>
- <para>A signal can optionally have a signal name and a map of parameters. Most
- common way on how activity behaviours interprete the signal and parameters is that
- the signal relates to the outgoing transition that needs to be taken and that the
- parameters are set as variables on the execution. But those are just examples, it
- is up to the activity to use the signal and the parameters as it pleases.
- </para>
- </section>
-
- <!-- ### ExternalActivity example ####################################### -->
- <section id="externalactivityexample">
- <title>ExternalActivity example</title>
- <para>Here's a first example of a simple wait state implementation:
- </para>
- <programlisting>public <emphasis role="bold">class WaitState</emphasis> implements <emphasis role="bold">ExternalActivity</emphasis> {
-
- public void execute(ActivityExecution execution) {
- <emphasis role="bold">execution.waitForSignal();</emphasis>
- }
-
- public void signal(ActivityExecution execution,
- String signalName,
- Map<String, Object> parameters) {
- <emphasis role="bold">execution.take(signalName);</emphasis>
- }
-}</programlisting>
- <para>The <literal>execute</literal>-method calls
- <literal>execution.waitForSignal()</literal>. The invocation of
- <literal>execution.waitForSignal()</literal> will bring the process execution
- into a wait state until an external trigger is given.
- </para>
- <para><literal>signal</literal>-method takes the transition with
- the signal parameter as the transition name. So when an execution receives an
- external trigger, the signal name is interpreted as the name of an outgoing
- transition and the execution will be propagated over that transition.
- </para>
- <para>Here's the same simple process that has a transition from a to b. This
- time, the behaviour of the two activities will be WaitState's.
- </para>
- <figure id="process.diagram">
- <title>The external activity example process</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/process.ab.png"/></imageobject></mediaobject>
- </figure>
- <programlisting>ClientProcessDefinition processDefinition = ProcessFactory.build()
- <emphasis role="bold">.activity("a").initial().behaviour(new WaitState())</emphasis>
- .transition().to("b")
- <emphasis role="bold">.activity("b").behaviour(new WaitState())</emphasis>
-.done();</programlisting>
- <para>Let's start a new process instance for this process definition:</para>
- <programlisting>ClientExecution execution = processDefinition.startProcessInstance();</programlisting>
- <para>Starting this process will execute the <literal>WaitState</literal> activity
- in activity <literal>a</literal>. <literal>WaitState.execute</literal> will invoke
- <literal>ActivityExecution.waitForSignal</literal>. So when the
- <literal>processDefinition.startProcessInstance()</literal> returns, the execution
- will still be positioned in activity a.
- </para>
- <programlisting>assertEquals("a", execution.getActivityName());</programlisting>
- <para>Then we provide the external trigger by calling the <literal>signal</literal>
- method.
- </para>
- <programlisting>execution.signal();</programlisting>
- <para>The <literal>execution.signal()</literal> will delegate to the activity
- of the current activity. So in this case that is the <literal>WaitState</literal>
- activity in activity <literal>a</literal>. The <literal>WaitState.signal</literal>
- will invoke the <literal>ActivityExecution.take(String transitionName)</literal>.
- Since we didn't supply a signalName, the first transition with name <literal>null</literal>
- will be taken. The only transition we specified out of activity <literal>a</literal>
- didn't get a name so that one will be taken. And that transition points to activity
- <literal>b</literal>. When the execution arrives in activity <literal>b</literal>,
- the <literal>WaitState</literal> in activity <literal>b</literal> is executed.
- Similar as we saw above, the execution will wait in activity <literal>b</literal>
- and this time the <literal>signal</literal> method will return, leaving the
- execution positioned in activity <literal>b</literal>.
- </para>
- <programlisting>assertEquals("b", execution.getActivityName());</programlisting>
- </section>
-
- <!-- ### BASIC PROCESS EXECUTION ######################################## -->
- <section id="basicprocessexecution">
- <title>Basic process execution</title>
- <para>In this next example, we'll combine automatic activities and wait states.
- This example builds upon the loan approval process with the <literal>WaitState</literal>
- and <literal>Display</literal> activities that we've just created. Graphically,
- the loan process looks like this:
- </para>
- <figure id="basicprocessexecution.loan.process">
- <title>The loan process</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/process.loan.png"/></imageobject></mediaobject>
- </figure>
- <para>Building process graphs in Java code can be tedious because you have to keep track of all the
- references in local variables. To resolve that, the Process Virtual Machine comes with a
- ProcessFactory. The ProcessFactory is a kind of domain specific language (DSL) that is embedded
- in Java and eases the construction of process graphs. This pattern is also known as
- a <ulink url="http://martinfowler.com/bliki/FluentInterface.html">fluent
- interface</ulink>.
- </para>
- <programlisting>ClientProcessDefinition processDefinition = ProcessFactory.build("loan")
- .activity(<emphasis role="bold">"submit loan request"</emphasis>).initial().behaviour(new Display("loan request submitted"))
- .transition().to("evaluate")
- <emphasis role="bold">.activity("evaluate").behaviour(new WaitState())</emphasis>
- .transition("approve").to("wire money")
- .transition("reject").to("end")
- <emphasis role="bold">.activity("wire money").behaviour(new Display("wire the money"))</emphasis>
- .transition().to("archive")
- <emphasis role="bold">.activity("archive").behaviour(new WaitState())</emphasis>
- .transition().to("end")
- <emphasis role="bold">.activity("end").behaviour(new WaitState())</emphasis>
-.done();</programlisting>
- <para>For more details about the ProcessFactory, see <ulink url="../../api/org/jbpm/pvm/package-summary.html">the
- api docs</ulink>. An alternative for
- the ProcessFactory would be to create an XML language and an XML parser for expressing
- processes. The XML parser can then instantiate the classes of package
- <literal>org.jbpm.pvm.internal.model</literal> directly. That approach is typically taken by
- process languages.
- </para>
- <para>The initial activity <literal>submit loan request</literal> and the activity
- <literal>wire the money</literal> are automatic activities. In this example,
- the <literal>Display</literal> implementation of activity
- <literal>wire the money</literal> uses the Java API's to just print a
- message to the console. But the witty reader can imagine an alternative
- <literal>Activity</literal> implementation that uses the Java API of a payment
- processing library to make a real automatic payment.
- </para>
- <para>A new execution for the process above can be started like this
- </para>
- <programlisting>ClientExecution execution = processDefinition.startProcessInstance();</programlisting>
- <para>When the <literal>startExecution</literal>-method returns, the activity
- <literal>submit loan request</literal> will be executed and the execution will be
- positioned in the activity <literal>evaluate</literal>.
- </para>
- <figure id="execution.loan.evaluate">
- <title>Execution positioned in the 'evaluate' activity</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/execution.loan.evaluate.png"/></imageobject></mediaobject>
- </figure>
- <para>Now, the execution is at an interesting point. There are two transitions out of
- the state <literal>evaluate</literal>. One transition is called <literal>approve</literal>
- and one transition is called <literal>reject</literal>. As we explained above, the WaitState
- implementation will take the transition that corresponds to the signal that is given.
- Let's feed in the 'approve' signal like this:
- </para>
- <programlisting>execution.signal("approve");</programlisting>
- <para>The <literal>approve</literal> signal will cause the execution to take the <literal>approve</literal>
- transition and it will arrive in the activity <literal>wire money</literal>.
- </para>
- <para>In activity <literal>wire money</literal>, the message will be printed to the console.
- Since, the <literal>Display</literal> activity didn't invoke the
- <literal>execution.waitForSignal()</literal>, nor any of the other execution propagation
- methods, the implicit proceed behaviour will just make the execution continue
- over the outgoing transition to activity <literal>archive</literal>, which is again
- a <literal>WaitState</literal>.
- </para>
- <figure id="execution.loan.archive">
- <title>Execution positioned in 'archive' activity</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/execution.loan.archive.png"/></imageobject></mediaobject>
- </figure>
- <para>So only when the <literal>archive</literal> wait state is reached,
- the <literal>signal("approve")</literal> returns.
- </para>
- <para>Another signal like this:</para>
- <programlisting>execution.signal("approve");</programlisting>
- <para>will bring the execution eventually in the end state.</para>
- <figure id="execution.loan.end">
- <title>Execution positioned in the 'end' activity</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/execution.loan.end.png"/></imageobject></mediaobject>
- </figure>
- </section>
-
- <!-- ### EVENTS ######################################################### -->
- <section id="events">
- <title>Events</title>
- <para>Events are points in the process definition to which a list of
- <literal>EventListener</literal>s can be subscribed.
- </para>
- <programlisting>public interface EventListener extends Serializable {
-
- void notify(EventListenerExecution execution) throws Exception;
-
-}</programlisting>
- <para>The motivation for events is to allow for
- developers to add programming logic to a process without changing the process diagram.
- This is a very valuable instrument in facilitating the collaboration between business analysts
- and developers. Business analysts
- are responsible for expressing the requirements. When they use a process graph to document
- those requirements, developers can take this diagram and make it executable. Events can
- be a very handy to insert technical details into a process (like e.g. some database insert)
- in which the business analyst is not interested.
- </para>
- <para>Most common events are fired by the execution automatically:
- </para>
- <para>TODO: explain events in userguide</para>
- <para>Events are identified by the combination of a process element
- and an event name. Users and process languages can also fire events
- programmatically with the fire method on the Execution:
- </para>
- <programlisting>public interface Execution extends Serializable {
- ...
- void fire(String eventName, ProcessElement eventSource);
- ...
-}</programlisting>
-
- <para>A list of <literal>EventListeners</literal> can be associated to an
- event. But event listeners can not influence the control flow of the execution since
- they are merely listeners to an execution which is already in progress. This is different from
- activities that serve as the behaviour for activities. Activity behaviour activities are responsible
- for propagating the execution.
- </para>
- <para>We'll create a <literal>PrintLn</literal> event listener which is
- very similar to the <literal>Display</literal> activity from above.
- </para>
- <programlisting>public class PrintLn implements EventListener {
-
- String message;
-
- public PrintLn(String message) {
- this.message = message;
- }
-
- public void notify(EventListenerExecution execution) throws Exception {
- System.out.println("message");
- }
-}</programlisting>
- <para>Several <literal>PrintLn</literal> listeners will be subscribed to events in
- the process.</para>
- <figure id="action.process">
- <title>The PrintLn listener process</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/process.ab.png"/></imageobject></mediaobject>
- </figure>
- <programlisting>ClientProcessDefinition processDefinition = ProcessFactory.build()
- .activity("a").initial().behaviour(new AutomaticActivity())
- <emphasis role="bold">.event("end")
- .listener(new PrintLn("leaving a"))
- .listener(new PrintLn("second message while leaving a"))</emphasis>
- .transition().to("b")
- <emphasis role="bold">.listener(new PrintLn("taking transition"))</emphasis>
- .activity("b").behaviour(new WaitState())
- .event("start")
- <emphasis role="bold">.listener(new PrintLn("entering b"))</emphasis>
-.done();</programlisting>
- <para>The first event shows how to register multiple listeners to the same
- event. They will be notified in the order as they are specified.
- </para>
- <para>Then, on the transition, there is only one type of event. So in that case,
- the event type must not be specified and the listeners can be added directly on
- the transition.
- </para>
- <para>A listeners will be called each time an execution fires the event to
- which the listener is subscribed. The execution will be provided in the activity
- interface as a parameter and can be used by listeners except for the methods that
- control the propagation of execution.
- </para>
- </section>
-
- <!-- ### EVENT PROPAGATION ############################################## -->
- <section>
- <title>Event propagation</title>
- <para>Events are by default propagated to enclosing process elements. The motivation
- is to allow for listeners on process definitions or composite activities that get executed
- for all events that occur within that process element. For example this feature
- allows to register an event listener on a process definition or a composite activity on
- <literal>end</literal> events. Such action will be executed if that activity is
- left. And if that event listener is registered on a composite activity, it will also be executed
- for all activities that are left within that composite activity.
- </para>
- <para>To show this clearly, we'll create a <literal>DisplaySource</literal> event listener
- that will print the message <literal>leaving</literal> and the source of the event
- to the console.
- </para>
- <programlisting>public class <emphasis role="bold">DisplaySource</emphasis> implements EventListener {
-
- public void execute(EventListenerExecution execution) {
- <emphasis role="bold">System.out.println("leaving "+execution.getEventSource());</emphasis>
- }
-}</programlisting>
- <para>Note that the purpose of event listeners is not to be visible, that's why the event listener
- itself should not be displayed in the diagram. A <literal>DisplaySource</literal> event listener
- will be added as a listener to the event <literal>end</literal> on the composite activity.
- </para>
- <para>The next process shows how the <literal>DisplaySource</literal> event listener is registered
- as a listener to to the 'end' event on the <literal>composite</literal> activity:</para>
- <figure id="process.propagate">
- <title>A process with an invisible event listener on a end event on a composite activity.</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/process.propagate.png"/></imageobject></mediaobject>
- </figure>
- <programlisting>TODO update code snippet</programlisting>
- <para>Next we'll start an execution.</para>
- <programlisting>ClientExecution execution = processDefinition.startProcessInstance();</programlisting>
- <para>After starting a new execution, the execution will be in activity <literal>a</literal> as
- that is the initial activity. No activities have been left so no message is logged. Next a signal
- will be given to the execution, causing it to take the transition from <literal>a</literal>
- to <literal>b</literal>.
- </para>
- <programlisting>execution.signal();</programlisting>
- <para>When the signal method returns, the execution will have taken the transition and
- the <literal>end</literal> event will be fired on activity <literal>a</literal>. That
- event will be propagated to the
- composite activity and to the process definition. Since our <literal>DisplaySource</literal>
- event listener is placed
- on the <literal>composite</literal> activity, it will receive the event and print the following
- message on the console:
- </para>
- <programlisting>leaving activity(a)</programlisting>
- <para>Another</para>
- <programlisting>execution.signal();</programlisting>
- <para>will take the transition from b to c. That will fire two activity-leave events. One on
- activity b and one on activity composite. So the following lines will be appended to the console
- output:</para>
- <programlisting>leaving activity(b)
-leaving activity(composite)</programlisting>
- <para>Event propagation is build on the hierarchical composition structure of the process
- definition. The top level element is always the process definition. The process
- definition contains a list of activities. Each activity can be a leaf activity or it can be a
- composite activity, which means that it contains a list of nested activities. Nested activities
- can be used for e.g. super states or composite activities in nested process languages like BPEL.
- </para>
- <para>So the even model also works similarly for composite activities as it did for the process
- definition above. Suppose that 'Phase one' models
- a super state as in state machines. Then event propagation allows to subscribe to all events
- within that super state. The idea is that the hierarchical composition corresponds to
- diagram representation. If an element 'e' is drawn inside another element 'p', then p
- is the parent of e. A process definition has a set of top level activities. Every activity can have
- a set of nested activities. The parent of a transition is considered as the first common
- parent for it's source and destination.
- </para>
- <para>If an event listener is not interested in propagated events, propagation can be disabled
- with <literal>propagationDisabled()</literal> while building the process with the
- <literal>ProcessFactory</literal>. The next process is the same process
- as above except that propagated events will be disabled on the event listener. The graph diagram
- remains the same.
- </para>
- <figure id="process.propagate.propagation.disabled">
- <title>A process with an event listener to 'end' events with propagation disabled.</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/process.propagate.png"/></imageobject></mediaobject>
- </figure>
- <para>Building the process with the process factory:
- </para>
- <programlisting>TODO update code snippet</programlisting>
- <para>So when the first signal is given for this process, again the <literal>end</literal>
- event will be fired on activity <literal>a</literal>, but now the event listener on the composite
- activity will not be executed cause
- propagated events have been disabled. Disabling propagation is a property on the individual
- event listener and doesn't influence the other listeners. The event will always be fired and
- propagated over the whole parent hierarchy.
- </para>
- <programlisting>ClientExecution execution = processDefinition.startProcessInstance();</programlisting>
- <para>The first signal will take the process from <literal>a</literal> to
- <literal>b</literal>. No messages will be printed to the console.
- </para>
- <programlisting>execution.signal();</programlisting>
- <para>Next, the second signal will take the transition from b to c.
- </para>
- <programlisting>execution.signal()</programlisting>
- <para>Again two <literal>end</literal>
- events are fired just like above on activities <literal>b</literal> and <literal>composite</literal>
- respectively. The first event
- is the <literal>end</literal> event on activity <literal>b</literal>. That will be propagated
- to the <literal>composite</literal> activity. So the event
- listener will not be executed for this event cause it has propagation disabled. But the
- event listener will be executed for the <literal>end</literal> event on the
- <literal>composite</literal> activity. That is not
- propagated, but fired directly on the <literal>composite</literal> activity. So the event
- listener will now be executed
- only once for the composite activity as shown in the following console output:
- </para>
- <programlisting>leaving activity(composite)</programlisting>
- </section>
-
-</chapter>
Copied: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch07-ImplementingBasicActivities.xml (from rev 5958, jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch06-ImplementingBasicActivities.xml)
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch07-ImplementingBasicActivities.xml (rev 0)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch07-ImplementingBasicActivities.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -0,0 +1,486 @@
+<chapter id="implementingbasicactivities">
+ <title>Implementing basic activities</title>
+
+ <para>This chapter explains the basics of process definitions, the features offered by
+ the Process Virtual Machine and how activity implementations can be build. At the same
+ time the client API is shown to execute processes with those activity implementations.
+ </para>
+
+ <!-- ### Activity ####################################################### -->
+ <section id="activity">
+ <title>ActivityBehaviour</title>
+ <para>The PVM library doesn't have a fixed set of process constructs.
+ Instead, runtime behaviour of a activity is delegated to an <literal>ActivityBehaviour</literal>.
+ In other words, <literal>ActivityBehaviour</literal> is an interface to implement the runtime
+ behaviour of process constructs in plain Java.
+ </para>
+ <programlisting>public <emphasis role="bold">interface ActivityBehaviour</emphasis> extends Serializable {
+
+ void <emphasis role="bold">execute</emphasis>(ActivityExecution execution) throws Exception;
+
+}</programlisting>
+ <para>When an activity behaviour is called, it is in full control of the further
+ propagation of the execution. In other words, an activity behaviour can decide what the execution
+ should do next. For example, it can take a transition with
+ <literal>execution.take(Transition)</literal> or go into a wait state with
+ <literal>execution.waitForSignal()</literal>. In case the activity behaviour does not invoke
+ any of the above execution propagation methods, the execution will
+ <link linkend="implicitproceedbehaviour">proceed in a default way</link>.
+ </para>
+ </section>
+
+ <!-- ### ActivityBehaviour example ############################################### -->
+ <section id="activitybehaviourexample">
+ <title>ActivityBehaviour example</title>
+ <para>We'll start with a very original hello world example. A Display
+ activity will print a message to the console:
+ </para>
+ <programlisting>public <emphasis role="bold">class Display</emphasis> implements <emphasis role="bold">ActivityBehaviour</emphasis> {
+
+ String message;
+
+ public Display(String message) {
+ this.message = message;
+ }
+
+ public void execute(ActivityExecution execution) {
+ <emphasis role="bold">System.out.println(message);</emphasis>
+ }
+}</programlisting>
+ <para>Let' build our first process definition with this activity:</para>
+ <figure id="activity.example">
+ <title>Display example process</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/process.ab.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting>TODO add ProcessBuilder example code</programlisting>
+ <para>Now we can execute this process as follows:</para>
+ <programlisting>Execution execution = processDefinition.startExecution();</programlisting>
+ <para>The invocation of <literal>startExecution</literal> will print hello world to the console:</para>
+ <programlisting>hello
+world</programlisting>
+ <para>One thing already worth noticing is that activities can be configured
+ with properties. In the Display example, you can see that the message property
+ is configured differently in the two usages. With configuration properties
+ it becomes possible to write reusable activities. They can then be configured
+ differently each time they are used in a process. That is an essential part of
+ how process languages can be build on top of the Process Virtual Machine.
+ </para>
+ <para>The other part that needs explanation is that this activity
+ implementation does not contain any instructions for the propagation of the
+ execution. When a new process instance is started, the execution is positioned
+ in the initial activity and that activity is executed. The method
+ <literal>Display.execute</literal> makes use of what is called implicit propagation
+ of execution. Concretely this means that the activity itself does not
+ invoke any of the methods on the execution to propagate it. In that case
+ implicit propagation kicks in. Implicit propagation will take the first
+ transition if there is one. If not, it will end the execution. This explains
+ why both activities <literal>a</literal> and <literal>b</literal> are executed and that
+ the execution stops after activity <literal>b</literal> is executed.
+ </para>
+ <para>More details about the implicit proceed behaviour can be found
+ in <xref linkend="implicitproceedbehaviour" /></para>
+ </section>
+
+ <!-- ### ExternalActivityBehaviour ############################################### -->
+ <section id="externalactivitybehaviour">
+ <title>ExternalActivityBehaviour</title>
+ <para>External activities are activities for which the responsibility for proceeding
+ the execution is transferred externally, meaning outside the process system. This
+ means that for the system that is executing the process, it's a wait state. The
+ execution will wait until an external trigger is given.
+ </para>
+ <para>For dealing with external triggers, <literal>ExternalActivityBehaviour</literal>
+ adds one method to the <literal>ActivityBehaviour</literal>:</para>
+ <programlisting>public <emphasis role="bold">interface ExternalActivity</emphasis> extends <emphasis role="bold">Activity</emphasis> {
+
+ void <emphasis role="bold">signal</emphasis>(Execution execution,
+ String signal,
+ Map<String, Object> parameters) throws Exception;
+
+}</programlisting>
+ <para>Just like with plain activities, when an execution arrives in a activity, the
+ <literal>execute</literal>-method of the external activity behaviour is invoked.
+ In external activities, the execute method typically does something to
+ transfer the responsibility to another system and then enters a wait
+ state by invoking <literal>execution.waitForSignal()</literal>. For
+ example in the execute method, responsibility could be transferred to a
+ person by creating a task entry in a task management system and then
+ wait until the person completes the task.
+ </para>
+ <para>In case a activity behaves as a wait state, then the execution will
+ wait in that activity until the execution's <literal>signal</literal> method
+ is invoked. The execution will delegate that signal to the ExternalActivityBehaviour
+ object associated to the current activity.
+ </para>
+ <para>So the Activity's <literal>signal</literal>-method is invoked
+ when the execution receives an external trigger during the wait state. With the
+ signal method, responsibility is transferred back to the process execution. For
+ example, when a person completes a task, the task management system calls the
+ signal method on the execution.
+ </para>
+ <para>A signal can optionally have a signal name and a map of parameters. Most
+ common way on how activity behaviours interprete the signal and parameters is that
+ the signal relates to the outgoing transition that needs to be taken and that the
+ parameters are set as variables on the execution. But those are just examples, it
+ is up to the activity to use the signal and the parameters as it pleases.
+ </para>
+ </section>
+
+ <!-- ### ExternalActivity example ####################################### -->
+ <section id="externalactivityexample">
+ <title>ExternalActivity example</title>
+ <para>Here's a first example of a simple wait state implementation:
+ </para>
+ <programlisting>public <emphasis role="bold">class WaitState</emphasis> implements <emphasis role="bold">ExternalActivity</emphasis> {
+
+ public void execute(ActivityExecution execution) {
+ <emphasis role="bold">execution.waitForSignal();</emphasis>
+ }
+
+ public void signal(ActivityExecution execution,
+ String signalName,
+ Map<String, Object> parameters) {
+ <emphasis role="bold">execution.take(signalName);</emphasis>
+ }
+}</programlisting>
+ <para>The <literal>execute</literal>-method calls
+ <literal>execution.waitForSignal()</literal>. The invocation of
+ <literal>execution.waitForSignal()</literal> will bring the process execution
+ into a wait state until an external trigger is given.
+ </para>
+ <para><literal>signal</literal>-method takes the transition with
+ the signal parameter as the transition name. So when an execution receives an
+ external trigger, the signal name is interpreted as the name of an outgoing
+ transition and the execution will be propagated over that transition.
+ </para>
+ <para>Here's the same simple process that has a transition from a to b. This
+ time, the behaviour of the two activities will be WaitState's.
+ </para>
+ <figure id="process.diagram">
+ <title>The external activity example process</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/process.ab.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting>ClientProcessDefinition processDefinition = ProcessFactory.build()
+ <emphasis role="bold">.activity("a").initial().behaviour(new WaitState())</emphasis>
+ .transition().to("b")
+ <emphasis role="bold">.activity("b").behaviour(new WaitState())</emphasis>
+.done();</programlisting>
+ <para>Let's start a new process instance for this process definition:</para>
+ <programlisting>ClientExecution execution = processDefinition.startProcessInstance();</programlisting>
+ <para>Starting this process will execute the <literal>WaitState</literal> activity
+ in activity <literal>a</literal>. <literal>WaitState.execute</literal> will invoke
+ <literal>ActivityExecution.waitForSignal</literal>. So when the
+ <literal>processDefinition.startProcessInstance()</literal> returns, the execution
+ will still be positioned in activity a.
+ </para>
+ <programlisting>assertEquals("a", execution.getActivityName());</programlisting>
+ <para>Then we provide the external trigger by calling the <literal>signal</literal>
+ method.
+ </para>
+ <programlisting>execution.signal();</programlisting>
+ <para>The <literal>execution.signal()</literal> will delegate to the activity
+ of the current activity. So in this case that is the <literal>WaitState</literal>
+ activity in activity <literal>a</literal>. The <literal>WaitState.signal</literal>
+ will invoke the <literal>ActivityExecution.take(String transitionName)</literal>.
+ Since we didn't supply a signalName, the first transition with name <literal>null</literal>
+ will be taken. The only transition we specified out of activity <literal>a</literal>
+ didn't get a name so that one will be taken. And that transition points to activity
+ <literal>b</literal>. When the execution arrives in activity <literal>b</literal>,
+ the <literal>WaitState</literal> in activity <literal>b</literal> is executed.
+ Similar as we saw above, the execution will wait in activity <literal>b</literal>
+ and this time the <literal>signal</literal> method will return, leaving the
+ execution positioned in activity <literal>b</literal>.
+ </para>
+ <programlisting>assertEquals("b", execution.getActivityName());</programlisting>
+ </section>
+
+ <!-- ### BASIC PROCESS EXECUTION ######################################## -->
+ <section id="basicprocessexecution">
+ <title>Basic process execution</title>
+ <para>In this next example, we'll combine automatic activities and wait states.
+ This example builds upon the loan approval process with the <literal>WaitState</literal>
+ and <literal>Display</literal> activities that we've just created. Graphically,
+ the loan process looks like this:
+ </para>
+ <figure id="basicprocessexecution.loan.process">
+ <title>The loan process</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/process.loan.png"/></imageobject></mediaobject>
+ </figure>
+ <para>Building process graphs in Java code can be tedious because you have to keep track of all the
+ references in local variables. To resolve that, the Process Virtual Machine comes with a
+ ProcessFactory. The ProcessFactory is a kind of domain specific language (DSL) that is embedded
+ in Java and eases the construction of process graphs. This pattern is also known as
+ a <ulink url="http://martinfowler.com/bliki/FluentInterface.html">fluent
+ interface</ulink>.
+ </para>
+ <programlisting>ClientProcessDefinition processDefinition = ProcessFactory.build("loan")
+ .activity(<emphasis role="bold">"submit loan request"</emphasis>).initial().behaviour(new Display("loan request submitted"))
+ .transition().to("evaluate")
+ <emphasis role="bold">.activity("evaluate").behaviour(new WaitState())</emphasis>
+ .transition("approve").to("wire money")
+ .transition("reject").to("end")
+ <emphasis role="bold">.activity("wire money").behaviour(new Display("wire the money"))</emphasis>
+ .transition().to("archive")
+ <emphasis role="bold">.activity("archive").behaviour(new WaitState())</emphasis>
+ .transition().to("end")
+ <emphasis role="bold">.activity("end").behaviour(new WaitState())</emphasis>
+.done();</programlisting>
+ <para>For more details about the ProcessFactory, see <ulink url="../../api/org/jbpm/pvm/package-summary.html">the
+ api docs</ulink>. An alternative for
+ the ProcessFactory would be to create an XML language and an XML parser for expressing
+ processes. The XML parser can then instantiate the classes of package
+ <literal>org.jbpm.pvm.internal.model</literal> directly. That approach is typically taken by
+ process languages.
+ </para>
+ <para>The initial activity <literal>submit loan request</literal> and the activity
+ <literal>wire the money</literal> are automatic activities. In this example,
+ the <literal>Display</literal> implementation of activity
+ <literal>wire the money</literal> uses the Java API's to just print a
+ message to the console. But the witty reader can imagine an alternative
+ <literal>Activity</literal> implementation that uses the Java API of a payment
+ processing library to make a real automatic payment.
+ </para>
+ <para>A new execution for the process above can be started like this
+ </para>
+ <programlisting>ClientExecution execution = processDefinition.startProcessInstance();</programlisting>
+ <para>When the <literal>startExecution</literal>-method returns, the activity
+ <literal>submit loan request</literal> will be executed and the execution will be
+ positioned in the activity <literal>evaluate</literal>.
+ </para>
+ <figure id="execution.loan.evaluate">
+ <title>Execution positioned in the 'evaluate' activity</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/execution.loan.evaluate.png"/></imageobject></mediaobject>
+ </figure>
+ <para>Now, the execution is at an interesting point. There are two transitions out of
+ the state <literal>evaluate</literal>. One transition is called <literal>approve</literal>
+ and one transition is called <literal>reject</literal>. As we explained above, the WaitState
+ implementation will take the transition that corresponds to the signal that is given.
+ Let's feed in the 'approve' signal like this:
+ </para>
+ <programlisting>execution.signal("approve");</programlisting>
+ <para>The <literal>approve</literal> signal will cause the execution to take the <literal>approve</literal>
+ transition and it will arrive in the activity <literal>wire money</literal>.
+ </para>
+ <para>In activity <literal>wire money</literal>, the message will be printed to the console.
+ Since, the <literal>Display</literal> activity didn't invoke the
+ <literal>execution.waitForSignal()</literal>, nor any of the other execution propagation
+ methods, the implicit proceed behaviour will just make the execution continue
+ over the outgoing transition to activity <literal>archive</literal>, which is again
+ a <literal>WaitState</literal>.
+ </para>
+ <figure id="execution.loan.archive">
+ <title>Execution positioned in 'archive' activity</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/execution.loan.archive.png"/></imageobject></mediaobject>
+ </figure>
+ <para>So only when the <literal>archive</literal> wait state is reached,
+ the <literal>signal("approve")</literal> returns.
+ </para>
+ <para>Another signal like this:</para>
+ <programlisting>execution.signal("approve");</programlisting>
+ <para>will bring the execution eventually in the end state.</para>
+ <figure id="execution.loan.end">
+ <title>Execution positioned in the 'end' activity</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/execution.loan.end.png"/></imageobject></mediaobject>
+ </figure>
+ </section>
+
+ <!-- ### EVENTS ######################################################### -->
+ <section id="events">
+ <title>Events</title>
+ <para>Events are points in the process definition to which a list of
+ <literal>EventListener</literal>s can be subscribed.
+ </para>
+ <programlisting>public interface EventListener extends Serializable {
+
+ void notify(EventListenerExecution execution) throws Exception;
+
+}</programlisting>
+ <para>The motivation for events is to allow for
+ developers to add programming logic to a process without changing the process diagram.
+ This is a very valuable instrument in facilitating the collaboration between business analysts
+ and developers. Business analysts
+ are responsible for expressing the requirements. When they use a process graph to document
+ those requirements, developers can take this diagram and make it executable. Events can
+ be a very handy to insert technical details into a process (like e.g. some database insert)
+ in which the business analyst is not interested.
+ </para>
+ <para>Most common events are fired by the execution automatically:
+ </para>
+ <para>TODO: explain events in userguide</para>
+ <para>Events are identified by the combination of a process element
+ and an event name. Users and process languages can also fire events
+ programmatically with the fire method on the Execution:
+ </para>
+ <programlisting>public interface Execution extends Serializable {
+ ...
+ void fire(String eventName, ProcessElement eventSource);
+ ...
+}</programlisting>
+
+ <para>A list of <literal>EventListeners</literal> can be associated to an
+ event. But event listeners can not influence the control flow of the execution since
+ they are merely listeners to an execution which is already in progress. This is different from
+ activities that serve as the behaviour for activities. Activity behaviour activities are responsible
+ for propagating the execution.
+ </para>
+ <para>We'll create a <literal>PrintLn</literal> event listener which is
+ very similar to the <literal>Display</literal> activity from above.
+ </para>
+ <programlisting>public class PrintLn implements EventListener {
+
+ String message;
+
+ public PrintLn(String message) {
+ this.message = message;
+ }
+
+ public void notify(EventListenerExecution execution) throws Exception {
+ System.out.println("message");
+ }
+}</programlisting>
+ <para>Several <literal>PrintLn</literal> listeners will be subscribed to events in
+ the process.</para>
+ <figure id="action.process">
+ <title>The PrintLn listener process</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/process.ab.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting>ClientProcessDefinition processDefinition = ProcessFactory.build()
+ .activity("a").initial().behaviour(new AutomaticActivity())
+ <emphasis role="bold">.event("end")
+ .listener(new PrintLn("leaving a"))
+ .listener(new PrintLn("second message while leaving a"))</emphasis>
+ .transition().to("b")
+ <emphasis role="bold">.listener(new PrintLn("taking transition"))</emphasis>
+ .activity("b").behaviour(new WaitState())
+ .event("start")
+ <emphasis role="bold">.listener(new PrintLn("entering b"))</emphasis>
+.done();</programlisting>
+ <para>The first event shows how to register multiple listeners to the same
+ event. They will be notified in the order as they are specified.
+ </para>
+ <para>Then, on the transition, there is only one type of event. So in that case,
+ the event type must not be specified and the listeners can be added directly on
+ the transition.
+ </para>
+ <para>A listeners will be called each time an execution fires the event to
+ which the listener is subscribed. The execution will be provided in the activity
+ interface as a parameter and can be used by listeners except for the methods that
+ control the propagation of execution.
+ </para>
+ </section>
+
+ <!-- ### EVENT PROPAGATION ############################################## -->
+ <section>
+ <title>Event propagation</title>
+ <para>Events are by default propagated to enclosing process elements. The motivation
+ is to allow for listeners on process definitions or composite activities that get executed
+ for all events that occur within that process element. For example this feature
+ allows to register an event listener on a process definition or a composite activity on
+ <literal>end</literal> events. Such action will be executed if that activity is
+ left. And if that event listener is registered on a composite activity, it will also be executed
+ for all activities that are left within that composite activity.
+ </para>
+ <para>To show this clearly, we'll create a <literal>DisplaySource</literal> event listener
+ that will print the message <literal>leaving</literal> and the source of the event
+ to the console.
+ </para>
+ <programlisting>public class <emphasis role="bold">DisplaySource</emphasis> implements EventListener {
+
+ public void execute(EventListenerExecution execution) {
+ <emphasis role="bold">System.out.println("leaving "+execution.getEventSource());</emphasis>
+ }
+}</programlisting>
+ <para>Note that the purpose of event listeners is not to be visible, that's why the event listener
+ itself should not be displayed in the diagram. A <literal>DisplaySource</literal> event listener
+ will be added as a listener to the event <literal>end</literal> on the composite activity.
+ </para>
+ <para>The next process shows how the <literal>DisplaySource</literal> event listener is registered
+ as a listener to to the 'end' event on the <literal>composite</literal> activity:</para>
+ <figure id="process.propagate">
+ <title>A process with an invisible event listener on a end event on a composite activity.</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/process.propagate.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting>TODO update code snippet</programlisting>
+ <para>Next we'll start an execution.</para>
+ <programlisting>ClientExecution execution = processDefinition.startProcessInstance();</programlisting>
+ <para>After starting a new execution, the execution will be in activity <literal>a</literal> as
+ that is the initial activity. No activities have been left so no message is logged. Next a signal
+ will be given to the execution, causing it to take the transition from <literal>a</literal>
+ to <literal>b</literal>.
+ </para>
+ <programlisting>execution.signal();</programlisting>
+ <para>When the signal method returns, the execution will have taken the transition and
+ the <literal>end</literal> event will be fired on activity <literal>a</literal>. That
+ event will be propagated to the
+ composite activity and to the process definition. Since our <literal>DisplaySource</literal>
+ event listener is placed
+ on the <literal>composite</literal> activity, it will receive the event and print the following
+ message on the console:
+ </para>
+ <programlisting>leaving activity(a)</programlisting>
+ <para>Another</para>
+ <programlisting>execution.signal();</programlisting>
+ <para>will take the transition from b to c. That will fire two activity-leave events. One on
+ activity b and one on activity composite. So the following lines will be appended to the console
+ output:</para>
+ <programlisting>leaving activity(b)
+leaving activity(composite)</programlisting>
+ <para>Event propagation is build on the hierarchical composition structure of the process
+ definition. The top level element is always the process definition. The process
+ definition contains a list of activities. Each activity can be a leaf activity or it can be a
+ composite activity, which means that it contains a list of nested activities. Nested activities
+ can be used for e.g. super states or composite activities in nested process languages like BPEL.
+ </para>
+ <para>So the even model also works similarly for composite activities as it did for the process
+ definition above. Suppose that 'Phase one' models
+ a super state as in state machines. Then event propagation allows to subscribe to all events
+ within that super state. The idea is that the hierarchical composition corresponds to
+ diagram representation. If an element 'e' is drawn inside another element 'p', then p
+ is the parent of e. A process definition has a set of top level activities. Every activity can have
+ a set of nested activities. The parent of a transition is considered as the first common
+ parent for it's source and destination.
+ </para>
+ <para>If an event listener is not interested in propagated events, propagation can be disabled
+ with <literal>propagationDisabled()</literal> while building the process with the
+ <literal>ProcessFactory</literal>. The next process is the same process
+ as above except that propagated events will be disabled on the event listener. The graph diagram
+ remains the same.
+ </para>
+ <figure id="process.propagate.propagation.disabled">
+ <title>A process with an event listener to 'end' events with propagation disabled.</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/process.propagate.png"/></imageobject></mediaobject>
+ </figure>
+ <para>Building the process with the process factory:
+ </para>
+ <programlisting>TODO update code snippet</programlisting>
+ <para>So when the first signal is given for this process, again the <literal>end</literal>
+ event will be fired on activity <literal>a</literal>, but now the event listener on the composite
+ activity will not be executed cause
+ propagated events have been disabled. Disabling propagation is a property on the individual
+ event listener and doesn't influence the other listeners. The event will always be fired and
+ propagated over the whole parent hierarchy.
+ </para>
+ <programlisting>ClientExecution execution = processDefinition.startProcessInstance();</programlisting>
+ <para>The first signal will take the process from <literal>a</literal> to
+ <literal>b</literal>. No messages will be printed to the console.
+ </para>
+ <programlisting>execution.signal();</programlisting>
+ <para>Next, the second signal will take the transition from b to c.
+ </para>
+ <programlisting>execution.signal()</programlisting>
+ <para>Again two <literal>end</literal>
+ events are fired just like above on activities <literal>b</literal> and <literal>composite</literal>
+ respectively. The first event
+ is the <literal>end</literal> event on activity <literal>b</literal>. That will be propagated
+ to the <literal>composite</literal> activity. So the event
+ listener will not be executed for this event cause it has propagation disabled. But the
+ event listener will be executed for the <literal>end</literal> event on the
+ <literal>composite</literal> activity. That is not
+ propagated, but fired directly on the <literal>composite</literal> activity. So the event
+ listener will now be executed
+ only once for the composite activity as shown in the following console output:
+ </para>
+ <programlisting>leaving activity(composite)</programlisting>
+ </section>
+
+</chapter>
Deleted: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch07-ProcessAnatomy.xml
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch07-ProcessAnatomy.xml 2009-12-15 10:55:41 UTC (rev 5959)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch07-ProcessAnatomy.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -1,67 +0,0 @@
-<chapter id="processanatomy">
- <title>Process anatomy</title>
-
- <para>Above we already touched briefly on the two main process constructs:
- Activities, transitions and activity composition. This chapter explores in full
- all the possibilities of the process definition structures.
- </para>
-
- <para>There are basically two forms of process languages: graph based and composite
- process languages. First of all, the process supports both. Even graph based execution
- and activity composition can be used in combination to implement something like UML super states.
- Furthermore, automatic functional activities can be implemented so that they can be
- used with transitions as well as with activity composition.
- </para>
-
- <figure id="process.anatomy">
- <title>UML class diagram of the logical process structure</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/process.anatomy.classes.png"/></imageobject></mediaobject>
- </figure>
-
- <para>By separating the structure of a process from the behaviour of the activities,
- any process model can be formed in the PVM. It's up to the activity implementations
- to use this structure. Activities can also impose restrictions on the diagram
- structures they can support. Typically activities that control process concurrency
- will impose restrictions on the process model structures that they can support.
- Next we'll show a series of example diagram structures that can be formed
- with the PVM process model.
- </para>
-
- <figure id="transition">
- <title>Any two activities can be connected with a transition.</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/transition.png"/></imageobject></mediaobject>
- </figure>
-
- <figure id="self.transition">
- <title>A self transition.</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/self.transition.png"/></imageobject></mediaobject>
- </figure>
- <figure id="composite.activity">
- <title>Composite activity is a list of nested activities.</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/composite.activity.png"/></imageobject></mediaobject>
- </figure>
- <figure id="transition.into.composite">
- <title>Transition to a activity inside a composite.</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/transition.into.composite.png"/></imageobject></mediaobject>
- </figure>
- <figure id="transition.out.of.composite">
- <title>Transition from a activity inside a composite to a activity outside the composite.</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/transition.out.of.composite.png"/></imageobject></mediaobject>
- </figure>
- <figure id="transition.inheritence">
- <title>Transition of composite activities are inherited. The activity inside can take the transition of the composite activity.</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/transition.inheritence.png"/></imageobject></mediaobject>
- </figure>
- <figure id="transition.to.outer">
- <title>Transition from a activity to an outer composite.</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/transition.to.outer.png"/></imageobject></mediaobject>
- </figure>
- <figure id="transition.to.inner">
- <title>Transition from a composite activity to an inner composed activity.</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/transition.to.inner.png"/></imageobject></mediaobject>
- </figure>
- <figure id="initial.in.composite">
- <title>An initial activity inside a composite activity.</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/initial.in.composite.png"/></imageobject></mediaobject>
- </figure>
-</chapter>
\ No newline at end of file
Deleted: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch08-ImplementingAdvancedActivities.xml
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch08-ImplementingAdvancedActivities.xml 2009-12-15 10:55:41 UTC (rev 5959)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch08-ImplementingAdvancedActivities.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -1,398 +0,0 @@
-<chapter id="advancedgraphexecution">
- <title>Advanced graph execution</title>
-
- <!-- ### LOOPS ########################################################## -->
- <section>
- <title>Loops</title>
- <para>Activities can implement loops based on transitions or on activity composition.
- Loops can contain wait states.
- </para>
- <para>To support high numbers of automatic loop executions, the Process Virtual Machine
- tranformed the propagation of execution from tail recursion to a while loop.
- </para>
- </section>
-
- <!-- ### DEFAULT PROCEED BEHAVIOUR ###################################### -->
- <section id="implicitproceedbehaviour">
- <title>Implicit proceed behaviour</title>
- <para>An <literal>ActivityBehaviour</literal> can
- explicitely propagate the execution with following methods:
- </para>
- <itemizedlist>
- <listitem><literal>waitForSignal()</literal></listitem>
- <listitem><literal>take(Transition)</literal></listitem>
- <listitem><literal>end(*)</literal></listitem>
- <listitem><literal>execute(Activity)</literal></listitem>
- <listitem><literal>createExecution(*)</literal></listitem>
- </itemizedlist>
-
- <para>As a side note, some of these methods are not exposed in the
- interfaces, but only in the implementation. Those methods are still
- in 'incubation'. So if you want to use those, you can use them at your
- own risk by casting the ActivityExecution interface to the implementation
- class ExecutionImpl.
- </para>
-
- <para>When <literal>ActivityBehaviour</literal> implementations used for activity behviour
- don't call any of the following execution propagation methods, then, after
- the activity is executed, the execution will apply the implicit proceed behaviour.
- </para>
- <para>The implicit proceed behaviour is defined as follows:</para>
- <itemizedlist>
- <listitem>If the current activity has a default outgoing transition, take it.</listitem>
- <listitem>If the current activity has a parent activity, move back to the parent activity.</listitem>
- <listitem>Otherwise, end this execution.</listitem>
- </itemizedlist>
- <para>Process languages can overwrite the implicit proceed behaviour
- by overriding the <literal>proceed</literal> method in
- <literal>ExecutionImpl</literal>.
- </para>
- </section>
-
- <!-- ### FUNCTIONAL ACTIVITIES ################################ -->
- <section id="functionalactivities">
- <title>Functional activities</title>
- <para>ActivityBehaviours that also can be used as event listeners are called functional
- activities. Examples of automatic activities are sending an email, doing a database
- update, generating a pdf, calculating an average, etc. All of these are automatic
- activities that do not change the execution flow. Here's how such activities can
- be implemented:
- </para>
- <programlisting>public class FunctionalActivity implements ActivityBehaviour, EventListener {
- public void execute(ActivityExecution execution) {
- perform(execution);
- }
- public void notify(EventListenerExecution execution) {
- perform(execution);
- }
- void perform(OpenExecution execution) {
- ...do functional work...
- }
- }</programlisting>
- <para>The <literal>perform</literal> method takes an <literal>OpenExecution</literal>,
- which is the supertype of both <literal>ActivityExecution</literal> and
- <literal>EventListenerExecution</literal>. <literal>OpenExecution</literal>
- does not allow any of the specific purpose methods, but still
- the current state and the process definition can be inspected as well
- as the variables, which contain the context information for the process
- execution.
- </para>
- <para>None of these methods actually invoke execution propagation methods.
- So after the perform method is completed, the execution will
- <link linkend="implicitproceedbehaviour">proceed in the default way</link>.
- </para>
- </section>
-
-
- <!-- ### EXECUTION AND THREADS ########################################## -->
- <section id="executionandthreads">
- <title>Execution and threads</title>
- <para>This section explains how the Process Virtual Machine boroughs the thread
- from the client to bring an execution from one wait state to another.
- </para>
- <para>When a client invokes a method (like e.g. the signal method) on an execution,
- by default, the Process Virtual Machine will use that thread to progress the execution
- until it reached a wait state. Once the next wait state has been reached, the
- method returns and the client gets the thread back. This is the default way
- for the Process Virtual Machine to operate. Two more levels of asynchonous
- execution complement this default behaviour:
- <link linkend="asynchronouscontinuations">Asynchronous continuations</link>
- and in the future we'll also provide a way to invoke service methods asynchronously.
- </para>
- <para>TODO: update the example that is now commented</para>
- <!--
- <para>The next process will show the basics concretely. It has three wait states
- and four automatic activities.
- </para>
- <figure id="process.automatic">
- <title>Process with many sequential automatic activities.</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/process.automatic.png"/></imageobject></mediaobject>
- </figure>
- <para>Here's how to build the process:</para>
- <programlisting>ClientProcessDefinition processDefinition = ProcessFactory.build("automatic")
- .<emphasis role="bold">activity("wait 1").initial()</emphasis>.behaviour(new <emphasis role="bold">WaitState</emphasis>())
- .transition().to("automatic 1")
- .<emphasis role="bold">activity("automatic 1")</emphasis>.behaviour(new <emphasis role="bold">Display("one")</emphasis>)
- .transition().to("wait 2")
- .<emphasis role="bold">activity("wait 2")</emphasis>.behaviour(new <emphasis role="bold">WaitState</emphasis>())
- .transition().to("automatic 2")
- .<emphasis role="bold">activity("automatic 2")</emphasis>.behaviour(new <emphasis role="bold">Display("two")</emphasis>)
- .transition().to("automatic 3")
- .<emphasis role="bold">activity("automatic 3")</emphasis>.behaviour(new <emphasis role="bold">Display("three")</emphasis>)
- .transition().to("automatic 4")
- .<emphasis role="bold">activity("automatic 4")</emphasis>.behaviour(new <emphasis role="bold">Display("four")</emphasis>)
- .transition().to("wait 3")
- .<emphasis role="bold">activity("wait 3")</emphasis>.behaviour(new <emphasis role="bold">WaitState</emphasis>())
-.done();</programlisting>
- <para>Let's walk you through one execution of this process.
- </para>
- <programlisting>ClientExecution execution = processDefinition.startProcessInstance();</programlisting>
- <para>Starting a new execution means that the initial activity is executed. So if an automatic
- activity is the initial activity, this means that immediately the first unnamed outgoing transition
- is taken. This happens all inside of the invocation of <literal>startProcessInstance</literal>.
- </para>
- <para>In this case however, the initial activity is a wait state. So
- the method <literal>startProcessInstance</literal> returns immediately and the execution will be
- positioned in the initial activity 'wait 1'.
- </para>
- <figure id="execution.automatic.wait1">
- <title>A new execution will be positioned in 'wait 1'.</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/execution.automatic.wait1.png"/></imageobject></mediaobject>
- </figure>
- <para>Then an external trigger is given with the signal method.</para>
- <programlisting>execution.signal();</programlisting>
- <para>As explained above when <link linkend="externalactivityexample">introducing the WaitState</link>,
- that signal will cause the default transition to be taken. The
- transition will move the execution to activity <literal>automatic 1</literal> and execute it.
- The execute method of the <literal>Display</literal> activity in <literal>automatic 1</literal>
- print a line to the console and it will <emphasis role="bold">not</emphasis> call
- <literal>execution.waitForSignal()</literal>. Therefore, the execution will proceed by
- taking the default transition out of <literal>automatic 1</literal>. At this stage, the
- signal method is still blocking. Another way to think about it is that the execution
- methods like <literal>signal</literal> will use the thread of the client to interpret
- the process definition until a wait state is reached.
- </para>
- <para>Then the execution arrives in <literal>wait 2</literal> and executes
- the <literal>WaitState</literal> activity. That method will invoke
- the <literal>execution.waitForSignal()</literal>, which will cause the signal method
- to return. That is when the thread is given back to the client that invoked the
- <literal>signal</literal> method.
- </para>
- <para>So when the signal method returns, the execution is positioned in <literal>wait 2</literal>.</para>
- <figure id="execution.automatic.wait2">
- <title>One signal brought the execution from 'initial' to 'wait 2'.</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/execution.automatic.wait2.png"/></imageobject></mediaobject>
- </figure>
- <para>Then the execution is now waiting for an external trigger just as an object
- (more precisely an object graph) in memory until the next external trigger is given
- with the signal method.
- </para>
- <programlisting>execution.signal();</programlisting>
- <para>This second invocation of signal will take the execution similarly all the
- way to <literal>wait 3</literal> before it returns.
- </para>
- <figure id="automatic.wait3">
- <title>The second signal brought the execution all the way to 'wait 3'.</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/ch04.automatic.wait3.png"/></imageobject></mediaobject>
- </figure>
- -->
- <para>The benefits of using this paradigm is that the same process definition
- can be executed in <link linkend="clientexecutionmode">client execution mode</link>
- (in-memory without persistence) as well as in <link linkend="persistentexecutionmode">
- persistent execution mode</link>, depending on the application and on the environment.
- </para>
- <para>When executing a process in persistent mode, this is how you typically want
- to bind that process execution to transactions of the database:
- </para>
- <figure id="transactions.png">
- <title>Transactions over time in persistent execution mode.</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/transactions.png"/></imageobject></mediaobject>
- </figure>
- <para>In most situations, the computational work that needs to be done as part of
- the process after an external trigger (the red pieces) is pretty minimal. Typically
- transactions combining the process execution and processing the request from the
- UI takes typically less then a second. Whereas the wait state in business processes
- typically can span for hours, days or even years. The clue is to clearly distinct
- when a wait state starts so that only the computational work done before the start
- of that wait state should be included in the transaction.
- </para>
- <para>Think of
- it this way: "When an approval arrives, what are all the automated processing that
- needs to be done before the process system needs to wait for another external
- trigger?" Unless pdf's need to be generated or mass emails need to be send,
- the amount of time that this takes is usually neglectable. That is why in the
- default persistent execution mode, the process work is executed in the thread
- of the client.
- </para>
- <para>This reasoning even holds in case of concurrent paths of execution.
- When a single path of execution splits into concurrent paths of execution,
- the process overhead of calculating that is neglectable. So that is why it
- makes sense for a fork or split activity implementation that targets persistent
- execution mode to spawn the concurrent paths sequentially in the same thread.
- Basically it's all just computational work as part of the same transaction.
- This can only be done because the fork/split knows that each concurrent path
- of execution will return whenever a wait state is encountered.
- </para>
- <para>Since this is a difficult concept to grasp, I'll explain it again with other
- words. Look at it from the overhead that is produced by the process execution
- itself in persistent execution mode. If in a transaction, an execution is given
- an external trigger and that causes the execution to split into multiple concurrent
- paths of execution. Then the process overhead of calculating this is neglectable.
- Also the overhead of the generated SQL is neglectable. And since all the work done
- in the concurrent branches must be done inside that single transaction, there is
- typically no point in having fork/split implementations spawn the concurrent
- paths of execution in multiple threads.
- </para>
- <para>To make executable processes, developers need to know exactly what the automatic activities
- are, what the wait states are and which threads will be allocated to the process execution.
- For business analysts that draw the analysis process, things are a bit simpler. For the
- activities they draw, they usually know whether it's a human or a system that is responsible.
- But they typically don't not how this translates to threads and transactions.
- </para>
- <para>So for the developer, the first job is to analyse what needs to be executed
- within the thread of control of the process and what is outside. Looking for the external
- triggers can be a good start to find the wait states in a process, just like verbs and nouns
- can be the rule of thumb in building UML class diagrams.
- </para>
- </section>
-
- <!-- ### PROCESS CONCURRENCY ############################################ -->
- <section>
- <title>Process concurrency</title>
- <para>To model process concurrency, there is a parent-child tree structure on the
- execution. The idea is that the main path of execution is the root of that tree.
- The main path of execution is also called the process instance. It is the execution
- that is created when starting or creating a new process instance for a given
- process definition.
- </para>
- <para>Now, because the main path of execution is the same object as the
- process instance, this keeps the usage simple in case of simple processes
- without concurrency.
- </para>
- <figure id="execution.structure">
- <title>UML class diagram of the basic execution structure</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/class.diagram.process.execution.png"/></imageobject></mediaobject>
- </figure>
- <para>To establish multiple concurrent paths of execution, activity implementations
- like a fork or split can create child executions with method
- <literal>ActivityExecution.createExecution</literal>. Activity implementations
- like join or merge can stop these concurrent paths of execution by calling
- method <literal>stop</literal> on the concurrent execution.
- </para>
- <para>Only leaf executions can be active. Non-leave executions should be
- inactive. This tree structure of executions doesn't enforce a particular type of
- concurrency or join behaviour. It's up to the forks or and-splits and to the joins
- or and-merges to use the execution tree structure in any way they want to define
- the wanted concurrency behaviour. Here you see an example
- of concurrent executions.
- </para>
- <figure id="concurrency">
- <title>Concurrent paths of execution</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/execution.concurrency.png"/></imageobject></mediaobject>
- </figure>
- <para>There is a billing and a shipping path of execution. In this case, the
- flat bar activities represent activities that fork and join. The execution shows a three
- executions. The main path of execution is inactive (represented as gray) and the
- billing and shipping paths of execution are active and point to the activity
- <literal>bill</literal> and <literal>ship</literal> respectively.
- </para>
- <para>It's up to the activity behaviour implementations how they want to use this
- execution structure. Suppose that multiple tasks have to be completed before the
- execution is to proceed. The activity behaviour can spawn a series of child executions
- for this. Or alternatively, the task component could support task groups that
- are associated to one single execution. In that case, the task component becomes
- responsible for synchronizing the tasks, thereby moving this responsibility
- outside the scope of the execution tree structure.
- </para>
- </section>
-
- <!-- ### EXCEPTION HANDLERS ############################################# -->
- <section>
- <title>Exception handlers</title>
- <para>In all the code that is associated to a process
- like <literal>Activity</literal>s, <literal>EventListeners</literal> and
- <literal>Condition</literal>s, it's possible to associate exception handlers. This
- can be thought of as including try-catch blocks in
- the method implementations of those implementations. But in order to build more reusable building
- blocks for both the delegation classes and the exception handling logic, exception handlers are
- added to the core process model.
- </para>
- <para>An exception handler can be associated to any process element. When an exception
- occurs in a delegation class, a matching exception handler will be searched for. If
- such an exception handler is found, it will get a chance to handle the exception.
- </para>
- <para>If an exception handler completes without problems, then the exception is considered
- handled and the execution resumes right after the delegation code that was called. For example,
- a transition has three actions and the second action throws an exception that is handled
- by an exception handler, then
- </para>
- <para>Writing automatic activities that are exception handler aware is easy. The
- default is to proceed anyway. No method needs to be called on the execution. So
- if an automatic activity throws an exception that is handled by an exception handler,
- the execution will just proceed after that activity. It becomes a big more difficult
- for control flow activities. They might have to include try-finally blocks to
- invoke the proper methods on the execution before an exception handler gets a
- chance to handle the exception. For example, if an activity is a wait state and
- an exception occurs, then there is a risk that the thread jumps over the
- invocation of <literal>execution.waitForSignal()</literal>, causing the execution
- to proceed after the activity.
- </para>
- <para>TODO: exceptionhandler.isRethrowMasked</para>
- <para>TODO: transactional exception handlers</para>
- <para>TODO: we never catch errors</para>
- </section>
-
- <!-- ### PROCESS MODIFICATIONS ########################################## -->
- <section>
- <title>Process modifications</title>
- <para>TODO: process modifications</para>
- </section>
-
- <!-- ### LOCKING AND EXECUTION STATE #################################### -->
- <section>
- <title>Locking and execution state</title>
- <para>The state of an execution is either active or locked. An active
- execution is either executing or waiting for an external trigger. If an
- execution is not in <literal>STATE_ACTIVE</literal>, then it is locked.
- A locked execution is read only and cannot receive any external triggers.
- </para>
- <para>When a new execution is created, it is in STATE_ACTIVE. To change
- the state to a locked state, use lock(String). Some STATE_* constants
- are provided that represent the most commonly used locked states. But
- the state '...' in the picture indicates that any string can be provided
- as the state in the lock method.
- </para>
- <figure id="execution.states">
- <title>States of an execution</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/ch04.execution.states.png"/></imageobject></mediaobject>
- </figure>
- <para>If an execution is locked, methods that change the execution will
- throw a PvmException and the message will reference the actual locking state.
- Firing events, updating variables, updating priority and adding comments
- are not considered to change an execution. Also creation and removal of child
- executions are unchecked, which means that those methods can be invoked by
- external API clients and activity behaviour methods, even while the execution
- is in a locked state.
- </para>
- <para>Make sure that comparisons between getState() and the STATE_* constants
- are done with .equals and not with '==' because if executions are loaded
- from persistent storage, a new string is created instead of the constants.
- </para>
- <para>An execution implementation will be locked:
- </para>
- <itemizedlist>
- <listitem>When it is ended</listitem>
- <listitem>When it is suspended</listitem>
- <listitem>During asynchronous continuations</listitem>
- </itemizedlist>
- <para>Furthermore, locking can be used by Activity implementations to make
- executions read only during wait states hen responsibility for the execution is
- transferred to an external entity such as:
- </para>
- <itemizedlist>
- <listitem>A human task</listitem>
- <listitem>A service invocation</listitem>
- <listitem>A wait state that ends when a scanner detects that a file appears</listitem>
- </itemizedlist>
- <para>In these situations the strategy is that the external entity should get
- full control over the execution because it wants to control what is allowed
- and what not. To get that control, they lock the execution so that all interactions
- have to go through the external entity.
- </para>
- <para>One of the main reasons to create external entities is that they can live
- on after the execution has already proceeded. For example, in case
- of a service invocation, a timer could cause the execution to take the timeout transition.
- When the response arrives after the timeout, the service invocation entity should
- make sure it doesn't signal the execution. So the service invocation can be
- seen as a activity instance (aka activity instance) and is unique for every execution
- of the activity.
- </para>
- <para>External entities themselves are responsible for managing the execution
- lock. If the timers and client applications are consequent in addressing the
- external entities instead of the execution directly, then locking is in theory
- unnecessary. It's up to the activity behaviour implementations whether they want
- to take the overhead of locking and unlocking.
- </para>
- </section>
-
-</chapter>
Copied: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch08-ProcessAnatomy.xml (from rev 5958, jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch07-ProcessAnatomy.xml)
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch08-ProcessAnatomy.xml (rev 0)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch08-ProcessAnatomy.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -0,0 +1,67 @@
+<chapter id="processanatomy">
+ <title>Process anatomy</title>
+
+ <para>Above we already touched briefly on the two main process constructs:
+ Activities, transitions and activity composition. This chapter explores in full
+ all the possibilities of the process definition structures.
+ </para>
+
+ <para>There are basically two forms of process languages: graph based and composite
+ process languages. First of all, the process supports both. Even graph based execution
+ and activity composition can be used in combination to implement something like UML super states.
+ Furthermore, automatic functional activities can be implemented so that they can be
+ used with transitions as well as with activity composition.
+ </para>
+
+ <figure id="process.anatomy">
+ <title>UML class diagram of the logical process structure</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/process.anatomy.classes.png"/></imageobject></mediaobject>
+ </figure>
+
+ <para>By separating the structure of a process from the behaviour of the activities,
+ any process model can be formed in the PVM. It's up to the activity implementations
+ to use this structure. Activities can also impose restrictions on the diagram
+ structures they can support. Typically activities that control process concurrency
+ will impose restrictions on the process model structures that they can support.
+ Next we'll show a series of example diagram structures that can be formed
+ with the PVM process model.
+ </para>
+
+ <figure id="transition">
+ <title>Any two activities can be connected with a transition.</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/transition.png"/></imageobject></mediaobject>
+ </figure>
+
+ <figure id="self.transition">
+ <title>A self transition.</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/self.transition.png"/></imageobject></mediaobject>
+ </figure>
+ <figure id="composite.activity">
+ <title>Composite activity is a list of nested activities.</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/composite.activity.png"/></imageobject></mediaobject>
+ </figure>
+ <figure id="transition.into.composite">
+ <title>Transition to a activity inside a composite.</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/transition.into.composite.png"/></imageobject></mediaobject>
+ </figure>
+ <figure id="transition.out.of.composite">
+ <title>Transition from a activity inside a composite to a activity outside the composite.</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/transition.out.of.composite.png"/></imageobject></mediaobject>
+ </figure>
+ <figure id="transition.inheritence">
+ <title>Transition of composite activities are inherited. The activity inside can take the transition of the composite activity.</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/transition.inheritence.png"/></imageobject></mediaobject>
+ </figure>
+ <figure id="transition.to.outer">
+ <title>Transition from a activity to an outer composite.</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/transition.to.outer.png"/></imageobject></mediaobject>
+ </figure>
+ <figure id="transition.to.inner">
+ <title>Transition from a composite activity to an inner composed activity.</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/transition.to.inner.png"/></imageobject></mediaobject>
+ </figure>
+ <figure id="initial.in.composite">
+ <title>An initial activity inside a composite activity.</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/initial.in.composite.png"/></imageobject></mediaobject>
+ </figure>
+</chapter>
\ No newline at end of file
Deleted: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch09-Configuration.xml
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch09-Configuration.xml 2009-12-15 10:55:41 UTC (rev 5959)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch09-Configuration.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -1,153 +0,0 @@
-<chapter id="configuration">
- <title>Configuration</title>
-
- <section>
- <title>Configuration basics</title>
-
- <para>The userguide explains how to install jBPM into the most
- common runtime environments. That is the most simple and convenient
- way to get started with jBPM. Please use those instructions.
- These docs provide some background information for developers
- that want to understand more about the way how configurations are
- handled. Use at your own risk :-)
- </para>
- <para>The jbpm.jar contains a number of default configuration
- files that can be imported by the user configuration file.
- </para>
- <para>This way, it's easy to include
- or exclude features for users. And also the configuration details are kept in
- the implementation so users that only import those configuration files
- will not be affected when we release changes in those configuration files.
- </para>
- <para>Configuration files that can be imported by the user's <literal>jbpm.cfg.xml</literal>:</para>
- <itemizedlist>
- <listitem>jbpm.businesscalendar.cfg.xml</listitem>
- <listitem>jbpm.default.cfg.xml</listitem>
- <listitem>jbpm.identity.cfg.xml</listitem>
- <listitem>jbpm.jbossremote.cfg.xml</listitem>
- <listitem>jbpm.jobexecutor.cfg.xml</listitem>
- <listitem>jbpm.tx.hibernate.cfg.xml</listitem>
- <listitem>jbpm.tx.jta.cfg.xml</listitem>
- </itemizedlist>
- <para><literal>jbpm.default.cfg.xml</literal>: Contains the default configurations
- like the services, the hibernate configuration (configured from resource jbpm.hibernate.cfg.xml),
- hibernate session factory, business calendar and so on.
- </para>
- <para>A typical configuration for standard java would look like this:
- </para>
- <programlisting><?xml version="1.0" encoding="UTF-8"?>
-
- <jbpm-configuration>
-
- <import resource="jbpm.default.cfg.xml" />
- <import resource="jbpm.businesscalendar.cfg.xml" />
- <import resource="jbpm.tx.hibernate.cfg.xml" />
- <import resource="jbpm.jpdl.cfg.xml" />
- <import resource="jbpm.identity.cfg.xml" />
- <import resource="jbpm.jobexecutor.cfg.xml" />
-
- </jbpm-configuration></programlisting>
-
- <para>When you want to change the configuration, first consider
- to change an import with one of the other provided importable
- configuration files.
- </para>
-
- <para>For example, in a JTA environment, replace the import of
- <literal>jbpm.tx.hibernate.cfg.xml</literal>
- with <literal>jbpm.tx.jta.cfg.xml</literal>
- </para>
-
- <para>The second way to define a more customized configuration is to
- specify configuration items directly into the <literal>jbpm.cfg.xml</literal>.
- For an example, see <xref linkend="customizingtheidentitycomponent" /> below.
- The more you customize, the more likely you are doing things we didn't
- anticipate.
- </para>
-
- <para>The jbpm.jar contains also following hibernate mapping configuration files:</para>
- <programlisting>
-jbpm.execution.hbm.xml
-jbpm.history.hbm.xml
-jbpm.identity.hbm.xml
-jbpm.repository.hbm.xml
-jbpm.task.hbm.xml</programlisting>
- <para>These all map the java domain model objects to a relational database.
- </para>
- <para>Other various configuration files that are included in jbpm.jar:</para>
- <programlisting>
-jbpm.task.lifecycle.xml
-jbpm.variable.types.xml
-jbpm.wire.bindings.xml
-jbpm.jpdl.activities.xml
-jbpm.jpdl.eventlisteners.xml</programlisting>
-
- <para>Normally it is not necessary to dive into the parsing itself. It's most
- a matter of figuring out how to specify the configuration that you want :-)
- But just in case: To get started on the parsing for the configuration files, see
- </para>
- <itemizedlist>
- <listitem>class org.jbpm.pvm.internal.env.JbpmConfigurationParser</listitem>
- <listitem>resource modules/pvm/src/main/resources/jbpm.wire.bindings.xml</listitem>
- <listitem>package modules/pvm/src/main/java/org/jbpm/pvm/internal/wire/binding</listitem>
- </itemizedlist>
- </section>
-
- <section id="customizingthebusinesscalendar">
- <title>Customizing the business calendar</title>
- <para>To provide a custom implementation for the business calendar,
- specify a custom business calendar implementation like this in
- the jbpm.cfg.xml
- </para>
- <programlisting><jbpm-configuration>
-
- <import resource="jbpm.default.cfg.xml" />
- ...
-
- <process-engine-context>
- <object class="org.jbpm.test.custombusinesscalendarimpl.CustomBusinessCalendar" />
- </process-engine-context>
-
-</jbpm-configuration></programlisting>
- <para>Here's an example implementation</para>
- <programlisting>public class CustomBusinessCalendar implements BusinessCalendar {
-
- public Date add(Date date, String duration) {
- if ("my next birthday".equals(duration)) {
- GregorianCalendar gregorianCalendar = new GregorianCalendar();
- gregorianCalendar.set(Calendar.MONTH, Calendar.JULY);
- gregorianCalendar.set(Calendar.DAY_OF_MONTH, 21);
- return gregorianCalendar.getTime();
- }
- return null;
- }
-}</programlisting>
- </section>
-
- <section id="customizingtheidentitycomponent">
- <title>Customizing the identity component</title>
- <para>There are 2 identity components that we support out of the box:
- </para>
- <itemizedlist>
- <listitem>jBPM's built-in identity component: ships with the jBPM project distro</listitem>
- <listitem>JBoss IDM: ships in the JBoss product platforms</listitem>
- </itemizedlist>
- <para>The <literal>jboss/build.xml</literal> installation scripts can be used
- to install jBPM in JBoss using the JBoss IDM component. There is some
- property in that build file to overwrite the default built-in identity component
- with the value for the JBoss IDM component.
- </para>
- <para>If you want to plug in your own identity component, remove the
- following line in the <literal>jbpm.cfg.xml</literal>:
- </para>
- <programlisting><import resource="jbpm.identity.cfg.xml" /></programlisting>
- <para>And in the same file, add following section</para>
- <programlisting><transaction-context>
- <object class="your.package.YourIdentitySessionImpl" />
-</transaction-context></programlisting>
- <para>YourIdentitySessionImpl should implement <literal>org.jbpm.pvm.internal.identity.spi.IdentitySession</literal>
- Making this identity pluggable is not our first target, but it was taken into the design. Let us know how it goes.
- </para>
- </section>
-
-</chapter>
\ No newline at end of file
Copied: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch09-ImplementingAdvancedActivities.xml (from rev 5958, jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch08-ImplementingAdvancedActivities.xml)
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch09-ImplementingAdvancedActivities.xml (rev 0)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch09-ImplementingAdvancedActivities.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -0,0 +1,398 @@
+<chapter id="advancedgraphexecution">
+ <title>Advanced graph execution</title>
+
+ <!-- ### LOOPS ########################################################## -->
+ <section>
+ <title>Loops</title>
+ <para>Activities can implement loops based on transitions or on activity composition.
+ Loops can contain wait states.
+ </para>
+ <para>To support high numbers of automatic loop executions, the Process Virtual Machine
+ tranformed the propagation of execution from tail recursion to a while loop.
+ </para>
+ </section>
+
+ <!-- ### DEFAULT PROCEED BEHAVIOUR ###################################### -->
+ <section id="implicitproceedbehaviour">
+ <title>Implicit proceed behaviour</title>
+ <para>An <literal>ActivityBehaviour</literal> can
+ explicitely propagate the execution with following methods:
+ </para>
+ <itemizedlist>
+ <listitem><literal>waitForSignal()</literal></listitem>
+ <listitem><literal>take(Transition)</literal></listitem>
+ <listitem><literal>end(*)</literal></listitem>
+ <listitem><literal>execute(Activity)</literal></listitem>
+ <listitem><literal>createExecution(*)</literal></listitem>
+ </itemizedlist>
+
+ <para>As a side note, some of these methods are not exposed in the
+ interfaces, but only in the implementation. Those methods are still
+ in 'incubation'. So if you want to use those, you can use them at your
+ own risk by casting the ActivityExecution interface to the implementation
+ class ExecutionImpl.
+ </para>
+
+ <para>When <literal>ActivityBehaviour</literal> implementations used for activity behviour
+ don't call any of the following execution propagation methods, then, after
+ the activity is executed, the execution will apply the implicit proceed behaviour.
+ </para>
+ <para>The implicit proceed behaviour is defined as follows:</para>
+ <itemizedlist>
+ <listitem>If the current activity has a default outgoing transition, take it.</listitem>
+ <listitem>If the current activity has a parent activity, move back to the parent activity.</listitem>
+ <listitem>Otherwise, end this execution.</listitem>
+ </itemizedlist>
+ <para>Process languages can overwrite the implicit proceed behaviour
+ by overriding the <literal>proceed</literal> method in
+ <literal>ExecutionImpl</literal>.
+ </para>
+ </section>
+
+ <!-- ### FUNCTIONAL ACTIVITIES ################################ -->
+ <section id="functionalactivities">
+ <title>Functional activities</title>
+ <para>ActivityBehaviours that also can be used as event listeners are called functional
+ activities. Examples of automatic activities are sending an email, doing a database
+ update, generating a pdf, calculating an average, etc. All of these are automatic
+ activities that do not change the execution flow. Here's how such activities can
+ be implemented:
+ </para>
+ <programlisting>public class FunctionalActivity implements ActivityBehaviour, EventListener {
+ public void execute(ActivityExecution execution) {
+ perform(execution);
+ }
+ public void notify(EventListenerExecution execution) {
+ perform(execution);
+ }
+ void perform(OpenExecution execution) {
+ ...do functional work...
+ }
+ }</programlisting>
+ <para>The <literal>perform</literal> method takes an <literal>OpenExecution</literal>,
+ which is the supertype of both <literal>ActivityExecution</literal> and
+ <literal>EventListenerExecution</literal>. <literal>OpenExecution</literal>
+ does not allow any of the specific purpose methods, but still
+ the current state and the process definition can be inspected as well
+ as the variables, which contain the context information for the process
+ execution.
+ </para>
+ <para>None of these methods actually invoke execution propagation methods.
+ So after the perform method is completed, the execution will
+ <link linkend="implicitproceedbehaviour">proceed in the default way</link>.
+ </para>
+ </section>
+
+
+ <!-- ### EXECUTION AND THREADS ########################################## -->
+ <section id="executionandthreads">
+ <title>Execution and threads</title>
+ <para>This section explains how the Process Virtual Machine boroughs the thread
+ from the client to bring an execution from one wait state to another.
+ </para>
+ <para>When a client invokes a method (like e.g. the signal method) on an execution,
+ by default, the Process Virtual Machine will use that thread to progress the execution
+ until it reached a wait state. Once the next wait state has been reached, the
+ method returns and the client gets the thread back. This is the default way
+ for the Process Virtual Machine to operate. Two more levels of asynchonous
+ execution complement this default behaviour:
+ <link linkend="asynchronouscontinuations">Asynchronous continuations</link>
+ and in the future we'll also provide a way to invoke service methods asynchronously.
+ </para>
+ <para>TODO: update the example that is now commented</para>
+ <!--
+ <para>The next process will show the basics concretely. It has three wait states
+ and four automatic activities.
+ </para>
+ <figure id="process.automatic">
+ <title>Process with many sequential automatic activities.</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/process.automatic.png"/></imageobject></mediaobject>
+ </figure>
+ <para>Here's how to build the process:</para>
+ <programlisting>ClientProcessDefinition processDefinition = ProcessFactory.build("automatic")
+ .<emphasis role="bold">activity("wait 1").initial()</emphasis>.behaviour(new <emphasis role="bold">WaitState</emphasis>())
+ .transition().to("automatic 1")
+ .<emphasis role="bold">activity("automatic 1")</emphasis>.behaviour(new <emphasis role="bold">Display("one")</emphasis>)
+ .transition().to("wait 2")
+ .<emphasis role="bold">activity("wait 2")</emphasis>.behaviour(new <emphasis role="bold">WaitState</emphasis>())
+ .transition().to("automatic 2")
+ .<emphasis role="bold">activity("automatic 2")</emphasis>.behaviour(new <emphasis role="bold">Display("two")</emphasis>)
+ .transition().to("automatic 3")
+ .<emphasis role="bold">activity("automatic 3")</emphasis>.behaviour(new <emphasis role="bold">Display("three")</emphasis>)
+ .transition().to("automatic 4")
+ .<emphasis role="bold">activity("automatic 4")</emphasis>.behaviour(new <emphasis role="bold">Display("four")</emphasis>)
+ .transition().to("wait 3")
+ .<emphasis role="bold">activity("wait 3")</emphasis>.behaviour(new <emphasis role="bold">WaitState</emphasis>())
+.done();</programlisting>
+ <para>Let's walk you through one execution of this process.
+ </para>
+ <programlisting>ClientExecution execution = processDefinition.startProcessInstance();</programlisting>
+ <para>Starting a new execution means that the initial activity is executed. So if an automatic
+ activity is the initial activity, this means that immediately the first unnamed outgoing transition
+ is taken. This happens all inside of the invocation of <literal>startProcessInstance</literal>.
+ </para>
+ <para>In this case however, the initial activity is a wait state. So
+ the method <literal>startProcessInstance</literal> returns immediately and the execution will be
+ positioned in the initial activity 'wait 1'.
+ </para>
+ <figure id="execution.automatic.wait1">
+ <title>A new execution will be positioned in 'wait 1'.</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/execution.automatic.wait1.png"/></imageobject></mediaobject>
+ </figure>
+ <para>Then an external trigger is given with the signal method.</para>
+ <programlisting>execution.signal();</programlisting>
+ <para>As explained above when <link linkend="externalactivityexample">introducing the WaitState</link>,
+ that signal will cause the default transition to be taken. The
+ transition will move the execution to activity <literal>automatic 1</literal> and execute it.
+ The execute method of the <literal>Display</literal> activity in <literal>automatic 1</literal>
+ print a line to the console and it will <emphasis role="bold">not</emphasis> call
+ <literal>execution.waitForSignal()</literal>. Therefore, the execution will proceed by
+ taking the default transition out of <literal>automatic 1</literal>. At this stage, the
+ signal method is still blocking. Another way to think about it is that the execution
+ methods like <literal>signal</literal> will use the thread of the client to interpret
+ the process definition until a wait state is reached.
+ </para>
+ <para>Then the execution arrives in <literal>wait 2</literal> and executes
+ the <literal>WaitState</literal> activity. That method will invoke
+ the <literal>execution.waitForSignal()</literal>, which will cause the signal method
+ to return. That is when the thread is given back to the client that invoked the
+ <literal>signal</literal> method.
+ </para>
+ <para>So when the signal method returns, the execution is positioned in <literal>wait 2</literal>.</para>
+ <figure id="execution.automatic.wait2">
+ <title>One signal brought the execution from 'initial' to 'wait 2'.</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/execution.automatic.wait2.png"/></imageobject></mediaobject>
+ </figure>
+ <para>Then the execution is now waiting for an external trigger just as an object
+ (more precisely an object graph) in memory until the next external trigger is given
+ with the signal method.
+ </para>
+ <programlisting>execution.signal();</programlisting>
+ <para>This second invocation of signal will take the execution similarly all the
+ way to <literal>wait 3</literal> before it returns.
+ </para>
+ <figure id="automatic.wait3">
+ <title>The second signal brought the execution all the way to 'wait 3'.</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/ch04.automatic.wait3.png"/></imageobject></mediaobject>
+ </figure>
+ -->
+ <para>The benefits of using this paradigm is that the same process definition
+ can be executed in <link linkend="clientexecutionmode">client execution mode</link>
+ (in-memory without persistence) as well as in <link linkend="persistentexecutionmode">
+ persistent execution mode</link>, depending on the application and on the environment.
+ </para>
+ <para>When executing a process in persistent mode, this is how you typically want
+ to bind that process execution to transactions of the database:
+ </para>
+ <figure id="transactions.png">
+ <title>Transactions over time in persistent execution mode.</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/transactions.png"/></imageobject></mediaobject>
+ </figure>
+ <para>In most situations, the computational work that needs to be done as part of
+ the process after an external trigger (the red pieces) is pretty minimal. Typically
+ transactions combining the process execution and processing the request from the
+ UI takes typically less then a second. Whereas the wait state in business processes
+ typically can span for hours, days or even years. The clue is to clearly distinct
+ when a wait state starts so that only the computational work done before the start
+ of that wait state should be included in the transaction.
+ </para>
+ <para>Think of
+ it this way: "When an approval arrives, what are all the automated processing that
+ needs to be done before the process system needs to wait for another external
+ trigger?" Unless pdf's need to be generated or mass emails need to be send,
+ the amount of time that this takes is usually neglectable. That is why in the
+ default persistent execution mode, the process work is executed in the thread
+ of the client.
+ </para>
+ <para>This reasoning even holds in case of concurrent paths of execution.
+ When a single path of execution splits into concurrent paths of execution,
+ the process overhead of calculating that is neglectable. So that is why it
+ makes sense for a fork or split activity implementation that targets persistent
+ execution mode to spawn the concurrent paths sequentially in the same thread.
+ Basically it's all just computational work as part of the same transaction.
+ This can only be done because the fork/split knows that each concurrent path
+ of execution will return whenever a wait state is encountered.
+ </para>
+ <para>Since this is a difficult concept to grasp, I'll explain it again with other
+ words. Look at it from the overhead that is produced by the process execution
+ itself in persistent execution mode. If in a transaction, an execution is given
+ an external trigger and that causes the execution to split into multiple concurrent
+ paths of execution. Then the process overhead of calculating this is neglectable.
+ Also the overhead of the generated SQL is neglectable. And since all the work done
+ in the concurrent branches must be done inside that single transaction, there is
+ typically no point in having fork/split implementations spawn the concurrent
+ paths of execution in multiple threads.
+ </para>
+ <para>To make executable processes, developers need to know exactly what the automatic activities
+ are, what the wait states are and which threads will be allocated to the process execution.
+ For business analysts that draw the analysis process, things are a bit simpler. For the
+ activities they draw, they usually know whether it's a human or a system that is responsible.
+ But they typically don't not how this translates to threads and transactions.
+ </para>
+ <para>So for the developer, the first job is to analyse what needs to be executed
+ within the thread of control of the process and what is outside. Looking for the external
+ triggers can be a good start to find the wait states in a process, just like verbs and nouns
+ can be the rule of thumb in building UML class diagrams.
+ </para>
+ </section>
+
+ <!-- ### PROCESS CONCURRENCY ############################################ -->
+ <section>
+ <title>Process concurrency</title>
+ <para>To model process concurrency, there is a parent-child tree structure on the
+ execution. The idea is that the main path of execution is the root of that tree.
+ The main path of execution is also called the process instance. It is the execution
+ that is created when starting or creating a new process instance for a given
+ process definition.
+ </para>
+ <para>Now, because the main path of execution is the same object as the
+ process instance, this keeps the usage simple in case of simple processes
+ without concurrency.
+ </para>
+ <figure id="execution.structure">
+ <title>UML class diagram of the basic execution structure</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/class.diagram.process.execution.png"/></imageobject></mediaobject>
+ </figure>
+ <para>To establish multiple concurrent paths of execution, activity implementations
+ like a fork or split can create child executions with method
+ <literal>ActivityExecution.createExecution</literal>. Activity implementations
+ like join or merge can stop these concurrent paths of execution by calling
+ method <literal>stop</literal> on the concurrent execution.
+ </para>
+ <para>Only leaf executions can be active. Non-leave executions should be
+ inactive. This tree structure of executions doesn't enforce a particular type of
+ concurrency or join behaviour. It's up to the forks or and-splits and to the joins
+ or and-merges to use the execution tree structure in any way they want to define
+ the wanted concurrency behaviour. Here you see an example
+ of concurrent executions.
+ </para>
+ <figure id="concurrency">
+ <title>Concurrent paths of execution</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/execution.concurrency.png"/></imageobject></mediaobject>
+ </figure>
+ <para>There is a billing and a shipping path of execution. In this case, the
+ flat bar activities represent activities that fork and join. The execution shows a three
+ executions. The main path of execution is inactive (represented as gray) and the
+ billing and shipping paths of execution are active and point to the activity
+ <literal>bill</literal> and <literal>ship</literal> respectively.
+ </para>
+ <para>It's up to the activity behaviour implementations how they want to use this
+ execution structure. Suppose that multiple tasks have to be completed before the
+ execution is to proceed. The activity behaviour can spawn a series of child executions
+ for this. Or alternatively, the task component could support task groups that
+ are associated to one single execution. In that case, the task component becomes
+ responsible for synchronizing the tasks, thereby moving this responsibility
+ outside the scope of the execution tree structure.
+ </para>
+ </section>
+
+ <!-- ### EXCEPTION HANDLERS ############################################# -->
+ <section>
+ <title>Exception handlers</title>
+ <para>In all the code that is associated to a process
+ like <literal>Activity</literal>s, <literal>EventListeners</literal> and
+ <literal>Condition</literal>s, it's possible to associate exception handlers. This
+ can be thought of as including try-catch blocks in
+ the method implementations of those implementations. But in order to build more reusable building
+ blocks for both the delegation classes and the exception handling logic, exception handlers are
+ added to the core process model.
+ </para>
+ <para>An exception handler can be associated to any process element. When an exception
+ occurs in a delegation class, a matching exception handler will be searched for. If
+ such an exception handler is found, it will get a chance to handle the exception.
+ </para>
+ <para>If an exception handler completes without problems, then the exception is considered
+ handled and the execution resumes right after the delegation code that was called. For example,
+ a transition has three actions and the second action throws an exception that is handled
+ by an exception handler, then
+ </para>
+ <para>Writing automatic activities that are exception handler aware is easy. The
+ default is to proceed anyway. No method needs to be called on the execution. So
+ if an automatic activity throws an exception that is handled by an exception handler,
+ the execution will just proceed after that activity. It becomes a big more difficult
+ for control flow activities. They might have to include try-finally blocks to
+ invoke the proper methods on the execution before an exception handler gets a
+ chance to handle the exception. For example, if an activity is a wait state and
+ an exception occurs, then there is a risk that the thread jumps over the
+ invocation of <literal>execution.waitForSignal()</literal>, causing the execution
+ to proceed after the activity.
+ </para>
+ <para>TODO: exceptionhandler.isRethrowMasked</para>
+ <para>TODO: transactional exception handlers</para>
+ <para>TODO: we never catch errors</para>
+ </section>
+
+ <!-- ### PROCESS MODIFICATIONS ########################################## -->
+ <section>
+ <title>Process modifications</title>
+ <para>TODO: process modifications</para>
+ </section>
+
+ <!-- ### LOCKING AND EXECUTION STATE #################################### -->
+ <section>
+ <title>Locking and execution state</title>
+ <para>The state of an execution is either active or locked. An active
+ execution is either executing or waiting for an external trigger. If an
+ execution is not in <literal>STATE_ACTIVE</literal>, then it is locked.
+ A locked execution is read only and cannot receive any external triggers.
+ </para>
+ <para>When a new execution is created, it is in STATE_ACTIVE. To change
+ the state to a locked state, use lock(String). Some STATE_* constants
+ are provided that represent the most commonly used locked states. But
+ the state '...' in the picture indicates that any string can be provided
+ as the state in the lock method.
+ </para>
+ <figure id="execution.states">
+ <title>States of an execution</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/ch04.execution.states.png"/></imageobject></mediaobject>
+ </figure>
+ <para>If an execution is locked, methods that change the execution will
+ throw a PvmException and the message will reference the actual locking state.
+ Firing events, updating variables, updating priority and adding comments
+ are not considered to change an execution. Also creation and removal of child
+ executions are unchecked, which means that those methods can be invoked by
+ external API clients and activity behaviour methods, even while the execution
+ is in a locked state.
+ </para>
+ <para>Make sure that comparisons between getState() and the STATE_* constants
+ are done with .equals and not with '==' because if executions are loaded
+ from persistent storage, a new string is created instead of the constants.
+ </para>
+ <para>An execution implementation will be locked:
+ </para>
+ <itemizedlist>
+ <listitem>When it is ended</listitem>
+ <listitem>When it is suspended</listitem>
+ <listitem>During asynchronous continuations</listitem>
+ </itemizedlist>
+ <para>Furthermore, locking can be used by Activity implementations to make
+ executions read only during wait states hen responsibility for the execution is
+ transferred to an external entity such as:
+ </para>
+ <itemizedlist>
+ <listitem>A human task</listitem>
+ <listitem>A service invocation</listitem>
+ <listitem>A wait state that ends when a scanner detects that a file appears</listitem>
+ </itemizedlist>
+ <para>In these situations the strategy is that the external entity should get
+ full control over the execution because it wants to control what is allowed
+ and what not. To get that control, they lock the execution so that all interactions
+ have to go through the external entity.
+ </para>
+ <para>One of the main reasons to create external entities is that they can live
+ on after the execution has already proceeded. For example, in case
+ of a service invocation, a timer could cause the execution to take the timeout transition.
+ When the response arrives after the timeout, the service invocation entity should
+ make sure it doesn't signal the execution. So the service invocation can be
+ seen as a activity instance (aka activity instance) and is unique for every execution
+ of the activity.
+ </para>
+ <para>External entities themselves are responsible for managing the execution
+ lock. If the timers and client applications are consequent in addressing the
+ external entities instead of the execution directly, then locking is in theory
+ unnecessary. It's up to the activity behaviour implementations whether they want
+ to take the overhead of locking and unlocking.
+ </para>
+ </section>
+
+</chapter>
Copied: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch10-Configuration.xml (from rev 5958, jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch09-Configuration.xml)
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch10-Configuration.xml (rev 0)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch10-Configuration.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -0,0 +1,153 @@
+<chapter id="configuration">
+ <title>Configuration</title>
+
+ <section>
+ <title>Configuration basics</title>
+
+ <para>The userguide explains how to install jBPM into the most
+ common runtime environments. That is the most simple and convenient
+ way to get started with jBPM. Please use those instructions.
+ These docs provide some background information for developers
+ that want to understand more about the way how configurations are
+ handled. Use at your own risk :-)
+ </para>
+ <para>The jbpm.jar contains a number of default configuration
+ files that can be imported by the user configuration file.
+ </para>
+ <para>This way, it's easy to include
+ or exclude features for users. And also the configuration details are kept in
+ the implementation so users that only import those configuration files
+ will not be affected when we release changes in those configuration files.
+ </para>
+ <para>Configuration files that can be imported by the user's <literal>jbpm.cfg.xml</literal>:</para>
+ <itemizedlist>
+ <listitem>jbpm.businesscalendar.cfg.xml</listitem>
+ <listitem>jbpm.default.cfg.xml</listitem>
+ <listitem>jbpm.identity.cfg.xml</listitem>
+ <listitem>jbpm.jbossremote.cfg.xml</listitem>
+ <listitem>jbpm.jobexecutor.cfg.xml</listitem>
+ <listitem>jbpm.tx.hibernate.cfg.xml</listitem>
+ <listitem>jbpm.tx.jta.cfg.xml</listitem>
+ </itemizedlist>
+ <para><literal>jbpm.default.cfg.xml</literal>: Contains the default configurations
+ like the services, the hibernate configuration (configured from resource jbpm.hibernate.cfg.xml),
+ hibernate session factory, business calendar and so on.
+ </para>
+ <para>A typical configuration for standard java would look like this:
+ </para>
+ <programlisting><?xml version="1.0" encoding="UTF-8"?>
+
+ <jbpm-configuration>
+
+ <import resource="jbpm.default.cfg.xml" />
+ <import resource="jbpm.businesscalendar.cfg.xml" />
+ <import resource="jbpm.tx.hibernate.cfg.xml" />
+ <import resource="jbpm.jpdl.cfg.xml" />
+ <import resource="jbpm.identity.cfg.xml" />
+ <import resource="jbpm.jobexecutor.cfg.xml" />
+
+ </jbpm-configuration></programlisting>
+
+ <para>When you want to change the configuration, first consider
+ to change an import with one of the other provided importable
+ configuration files.
+ </para>
+
+ <para>For example, in a JTA environment, replace the import of
+ <literal>jbpm.tx.hibernate.cfg.xml</literal>
+ with <literal>jbpm.tx.jta.cfg.xml</literal>
+ </para>
+
+ <para>The second way to define a more customized configuration is to
+ specify configuration items directly into the <literal>jbpm.cfg.xml</literal>.
+ For an example, see <xref linkend="customizingtheidentitycomponent" /> below.
+ The more you customize, the more likely you are doing things we didn't
+ anticipate.
+ </para>
+
+ <para>The jbpm.jar contains also following hibernate mapping configuration files:</para>
+ <programlisting>
+jbpm.execution.hbm.xml
+jbpm.history.hbm.xml
+jbpm.identity.hbm.xml
+jbpm.repository.hbm.xml
+jbpm.task.hbm.xml</programlisting>
+ <para>These all map the java domain model objects to a relational database.
+ </para>
+ <para>Other various configuration files that are included in jbpm.jar:</para>
+ <programlisting>
+jbpm.task.lifecycle.xml
+jbpm.variable.types.xml
+jbpm.wire.bindings.xml
+jbpm.jpdl.activities.xml
+jbpm.jpdl.eventlisteners.xml</programlisting>
+
+ <para>Normally it is not necessary to dive into the parsing itself. It's most
+ a matter of figuring out how to specify the configuration that you want :-)
+ But just in case: To get started on the parsing for the configuration files, see
+ </para>
+ <itemizedlist>
+ <listitem>class org.jbpm.pvm.internal.env.JbpmConfigurationParser</listitem>
+ <listitem>resource modules/pvm/src/main/resources/jbpm.wire.bindings.xml</listitem>
+ <listitem>package modules/pvm/src/main/java/org/jbpm/pvm/internal/wire/binding</listitem>
+ </itemizedlist>
+ </section>
+
+ <section id="customizingthebusinesscalendar">
+ <title>Customizing the business calendar</title>
+ <para>To provide a custom implementation for the business calendar,
+ specify a custom business calendar implementation like this in
+ the jbpm.cfg.xml
+ </para>
+ <programlisting><jbpm-configuration>
+
+ <import resource="jbpm.default.cfg.xml" />
+ ...
+
+ <process-engine-context>
+ <object class="org.jbpm.test.custombusinesscalendarimpl.CustomBusinessCalendar" />
+ </process-engine-context>
+
+</jbpm-configuration></programlisting>
+ <para>Here's an example implementation</para>
+ <programlisting>public class CustomBusinessCalendar implements BusinessCalendar {
+
+ public Date add(Date date, String duration) {
+ if ("my next birthday".equals(duration)) {
+ GregorianCalendar gregorianCalendar = new GregorianCalendar();
+ gregorianCalendar.set(Calendar.MONTH, Calendar.JULY);
+ gregorianCalendar.set(Calendar.DAY_OF_MONTH, 21);
+ return gregorianCalendar.getTime();
+ }
+ return null;
+ }
+}</programlisting>
+ </section>
+
+ <section id="customizingtheidentitycomponent">
+ <title>Customizing the identity component</title>
+ <para>There are 2 identity components that we support out of the box:
+ </para>
+ <itemizedlist>
+ <listitem>jBPM's built-in identity component: ships with the jBPM project distro</listitem>
+ <listitem>JBoss IDM: ships in the JBoss product platforms</listitem>
+ </itemizedlist>
+ <para>The <literal>jboss/build.xml</literal> installation scripts can be used
+ to install jBPM in JBoss using the JBoss IDM component. There is some
+ property in that build file to overwrite the default built-in identity component
+ with the value for the JBoss IDM component.
+ </para>
+ <para>If you want to plug in your own identity component, remove the
+ following line in the <literal>jbpm.cfg.xml</literal>:
+ </para>
+ <programlisting><import resource="jbpm.identity.cfg.xml" /></programlisting>
+ <para>And in the same file, add following section</para>
+ <programlisting><transaction-context>
+ <object class="your.package.YourIdentitySessionImpl" />
+</transaction-context></programlisting>
+ <para>YourIdentitySessionImpl should implement <literal>org.jbpm.pvm.internal.identity.spi.IdentitySession</literal>
+ Making this identity pluggable is not our first target, but it was taken into the design. Let us know how it goes.
+ </para>
+ </section>
+
+</chapter>
\ No newline at end of file
Deleted: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch10-Persistence.xml
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch10-Persistence.xml 2009-12-15 10:55:41 UTC (rev 5959)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch10-Persistence.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -1,28 +0,0 @@
-<chapter id="persistence">
- <title>Persistence</title>
-
- <para>Currently jBPM's persistence is based on hibernate. But in the future we might
- switch to JPA. That is why we recommend to stick with the API as much as possible as
- the API will hide you from those changes.
- </para>
-
- <para>Here's the jBPM database schema in an ER diagram. Thanks to
- <ulink url="http://dev.mysql.com/workbench/">MySQL Workbench></ulink>.
- </para>
-
- <figure id="erd.repo.and.runtime">
- <title>The jBPM repository and runtime schema ER diagram</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/erd.repo.and.runtime.png"/></imageobject></mediaobject>
- </figure>
-
- <figure id="erd.history">
- <title>The jBPM history schema ER diagram</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/erd.history.png"/></imageobject></mediaobject>
- </figure>
-
- <figure id="erd.identity">
- <title>The jBPM identity schema ER diagram</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/erd.identity.png"/></imageobject></mediaobject>
- </figure>
-
-</chapter>
\ No newline at end of file
Deleted: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch11-JobExecutor.xml
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch11-JobExecutor.xml 2009-12-15 10:55:41 UTC (rev 5959)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch11-JobExecutor.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -1,132 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<chapter id="jobexecutor">
- <title>JobExecutor</title>
-
- <para>
- For jPDL features like asynchronous continuations and timers, jBPM
- relies on transactional asynchronous messaging and
- timers. Those are not available on the standard Java platform.
- Therefore, jBPM includes the JobExecutor component, which executes
- asynchronous messages and timers in any (potentially clustered)
- environment.
- </para>
-
- <section id="overview">
- <title>Overview</title>
- <para>
- By default, when calling a jBPM service operation (eg. TaskService,
- ExecutionService, etc.), the jBPM logic is executed on the same thread
- as where the call came from. In most cases, this is sufficient since
- most steps in a process don't take much time. This means that
- signalling a process instance from one wait state to another, passing
- by several other steps in the business process, can be done in one
- transaction.
- </para>
- <para>
- However, in some occasions business processes can be made more efficient by
- introducing asynchronous continuations. By marking an activity as
- asynchronous, the jBPM engine will take care that the logic
- encapsulated in the activity isn't executed on the thread of the
- caller, but on a separate dedicated thread. The same mechanism is used
- for timers and asynchronous mailing (which means mails will be sent
- later, in a separate thread). The following picture shows which components
- come into play when using this mechanism.
- </para>
- <figure id="jobexecutor.overview.image">
- <title>JobExecutor components overview</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/jobexecutor.overview.png"/></imageobject></mediaobject>
- </figure>
- <para>
- When using timers or asynchronous continuations in a business process, the
- jBPM engine will store a 'job' into the database (a job contains mainly a
- duedate and continuation logic). Do note that this mechanism is
- pluggable, which means that in the future other destinations could be
- used (JMS, JCR, etc).
- </para>
- <para>
- Now the JobExecutor comes in to play, which is in fact a manager
- for several subcomponents:
-
- <itemizedlist>
- <listitem>
- A <emphasis role="bold">shared BlockingQueue</emphasis>,
- which is used to temporary store job identifiers of jobs which
- are executable (e.g. due date is passed).
- </listitem>
- <listitem>
- Every JobExecutor has one <emphasis role="bold">DispatcherThread.</emphasis>
- This thread will query the database for 'acquirable jobs' (e.g. timers
- which due date is passed), using a dedicated command through the CommandService.
- Since the dispatcher uses the CommandService, the command is
- automatically made transactional and wrapped by the configured
- interceptors. As long as jobs are available the dispatcher will put
- job identifiers on the shared queue, until the queue is either full
- (the thread will automatically be blocked by the JVM until a slot is
- free) or until no new jobs can be found in the database. If the latter
- case, the dispatcher will wait for a configured time (ie the 'idle
- time').
- </listitem>
- <listitem>
- The JobExecutor also maintains a pool of job executor threads. The number of
- executor threads can be configured and influences the size of the shared
- queue used to transfer and hold submitted jobs. Each executor thread will take a
- job from the queue. The shared queue blocks the executor threads until a job
- is queued. The new job will be acquired by exactly one waiting executor thread.
- After taking a job from the queue, the job is transactionally
- executed using a dedicated command through the CommandService. Therefore,
- the job will be executed completely on the executor thread
- instead of the caller thread. In consequence, the order in which the jobs
- are executed is unknown since there are multiple competing executor threads.
- However, it is certain that only one job will be done per transaction,
- except for <emphasis>exclusive</emphasis> jobs. In this case,
- all exclusive jobs are sequentially executed.
- </listitem>
- </itemizedlist>
- </para>
-
- </section>
-
- <section id="configuration">
- <title>Configuration</title>
- <para>
- Enabling the jobExecutor is very easy by adding the following line to the
- jbpm.cfg.xml file (using default settings):
- </para>
- <programlisting>
- <import resource="jbpm.jobexecutor.cfg.xml" />
- </programlisting>
- <para>
- Additional attributes can be set to fine-tune the JobExecutor:
- <itemizedlist>
- <listitem>
- <emphasis role="bold">threads:</emphasis> defines the number of
- JobexecutorThreads (default 3 threads)
- </listitem>
- <listitem>
- <emphasis role="bold">idle:</emphasis> number of milliseconds the dispatcher
- component waits after no new jobs were found in the database (default 5 seconds)
- </listitem>
- <listitem>
- <emphasis role="bold">idle-max:</emphasis> each time an exception occurs,
- the idle period will be doubled until the 'idle-max' is reached
- (back-off mechanism used to avoid a constant load on a failing database)
- </listitem>
- <listitem>
- <emphasis role="bold">lock-millis:</emphasis> Number of milliseconds
- that a job will be locked after being acquired by the dispatcher.
- This prevents starvation in case one of more JobExecutorThreads would die
- (eg when used in a cluster).
- </listitem>
- </itemizedlist>
- <programlisting>
-
- <process-engine-context>
-
- <job-executor threads="4" idle="15000" idle-max="60000" lock-millis="3600000" />
-
- </process-engine-context>
- </programlisting>
- </para>
- </section>
-
-</chapter>
Copied: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch11-Persistence.xml (from rev 5958, jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch10-Persistence.xml)
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch11-Persistence.xml (rev 0)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch11-Persistence.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -0,0 +1,28 @@
+<chapter id="persistence">
+ <title>Persistence</title>
+
+ <para>Currently jBPM's persistence is based on hibernate. But in the future we might
+ switch to JPA. That is why we recommend to stick with the API as much as possible as
+ the API will hide you from those changes.
+ </para>
+
+ <para>Here's the jBPM database schema in an ER diagram. Thanks to
+ <ulink url="http://dev.mysql.com/workbench/">MySQL Workbench></ulink>.
+ </para>
+
+ <figure id="erd.repo.and.runtime">
+ <title>The jBPM repository and runtime schema ER diagram</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/erd.repo.and.runtime.png"/></imageobject></mediaobject>
+ </figure>
+
+ <figure id="erd.history">
+ <title>The jBPM history schema ER diagram</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/erd.history.png"/></imageobject></mediaobject>
+ </figure>
+
+ <figure id="erd.identity">
+ <title>The jBPM identity schema ER diagram</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/erd.identity.png"/></imageobject></mediaobject>
+ </figure>
+
+</chapter>
\ No newline at end of file
Deleted: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch12-AdvancedEmail.xml
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch12-AdvancedEmail.xml 2009-12-15 10:55:41 UTC (rev 5959)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch12-AdvancedEmail.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -1,196 +0,0 @@
-<chapter id="mailsupport">
- <title>Advanced 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.
- </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 at minitrue' /> (2)
- <to addresses='julia at minitrue, obrien at 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/smtp/package-summary.html">
- 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 at 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.html">
- Sun Regex Patterns</ulink>.</para>
- <programlisting><![CDATA[<jbpm-configuration>
-<transaction-context>
- <mail-session>
- <mail-server>
- <address-filter>
- <include>.+ at jbpm.org</include>
- </address-filter>
- <session-properties>
- <property name="mail.smtp.host" value="int.smtp.jbpm.org" />
- <property name="mail.from" value="noreply at jbpm.org" />
- </session-properties>
- </mail-server>
- <mail-server>
- <address-filter>
- <exclude>.+ at jbpm.org</exclude>
- </address-filter>
- <session-properties>
- <property name="mail.smtp.host" value="ext.smtp.jbpm.org" />
- <property name="mail.from" value="noreply at 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/devguide/src/main/docbook/en/modules/ch12-JobExecutor.xml (from rev 5958, jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch11-JobExecutor.xml)
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch12-JobExecutor.xml (rev 0)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch12-JobExecutor.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<chapter id="jobexecutor">
+ <title>JobExecutor</title>
+
+ <para>
+ For jPDL features like asynchronous continuations and timers, jBPM
+ relies on transactional asynchronous messaging and
+ timers. Those are not available on the standard Java platform.
+ Therefore, jBPM includes the JobExecutor component, which executes
+ asynchronous messages and timers in any (potentially clustered)
+ environment.
+ </para>
+
+ <section id="overview">
+ <title>Overview</title>
+ <para>
+ By default, when calling a jBPM service operation (eg. TaskService,
+ ExecutionService, etc.), the jBPM logic is executed on the same thread
+ as where the call came from. In most cases, this is sufficient since
+ most steps in a process don't take much time. This means that
+ signalling a process instance from one wait state to another, passing
+ by several other steps in the business process, can be done in one
+ transaction.
+ </para>
+ <para>
+ However, in some occasions business processes can be made more efficient by
+ introducing asynchronous continuations. By marking an activity as
+ asynchronous, the jBPM engine will take care that the logic
+ encapsulated in the activity isn't executed on the thread of the
+ caller, but on a separate dedicated thread. The same mechanism is used
+ for timers and asynchronous mailing (which means mails will be sent
+ later, in a separate thread). The following picture shows which components
+ come into play when using this mechanism.
+ </para>
+ <figure id="jobexecutor.overview.image">
+ <title>JobExecutor components overview</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/jobexecutor.overview.png"/></imageobject></mediaobject>
+ </figure>
+ <para>
+ When using timers or asynchronous continuations in a business process, the
+ jBPM engine will store a 'job' into the database (a job contains mainly a
+ duedate and continuation logic). Do note that this mechanism is
+ pluggable, which means that in the future other destinations could be
+ used (JMS, JCR, etc).
+ </para>
+ <para>
+ Now the JobExecutor comes in to play, which is in fact a manager
+ for several subcomponents:
+
+ <itemizedlist>
+ <listitem>
+ A <emphasis role="bold">shared BlockingQueue</emphasis>,
+ which is used to temporary store job identifiers of jobs which
+ are executable (e.g. due date is passed).
+ </listitem>
+ <listitem>
+ Every JobExecutor has one <emphasis role="bold">DispatcherThread.</emphasis>
+ This thread will query the database for 'acquirable jobs' (e.g. timers
+ which due date is passed), using a dedicated command through the CommandService.
+ Since the dispatcher uses the CommandService, the command is
+ automatically made transactional and wrapped by the configured
+ interceptors. As long as jobs are available the dispatcher will put
+ job identifiers on the shared queue, until the queue is either full
+ (the thread will automatically be blocked by the JVM until a slot is
+ free) or until no new jobs can be found in the database. If the latter
+ case, the dispatcher will wait for a configured time (ie the 'idle
+ time').
+ </listitem>
+ <listitem>
+ The JobExecutor also maintains a pool of job executor threads. The number of
+ executor threads can be configured and influences the size of the shared
+ queue used to transfer and hold submitted jobs. Each executor thread will take a
+ job from the queue. The shared queue blocks the executor threads until a job
+ is queued. The new job will be acquired by exactly one waiting executor thread.
+ After taking a job from the queue, the job is transactionally
+ executed using a dedicated command through the CommandService. Therefore,
+ the job will be executed completely on the executor thread
+ instead of the caller thread. In consequence, the order in which the jobs
+ are executed is unknown since there are multiple competing executor threads.
+ However, it is certain that only one job will be done per transaction,
+ except for <emphasis>exclusive</emphasis> jobs. In this case,
+ all exclusive jobs are sequentially executed.
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ </section>
+
+ <section id="configuration">
+ <title>Configuration</title>
+ <para>
+ Enabling the jobExecutor is very easy by adding the following line to the
+ jbpm.cfg.xml file (using default settings):
+ </para>
+ <programlisting>
+ <import resource="jbpm.jobexecutor.cfg.xml" />
+ </programlisting>
+ <para>
+ Additional attributes can be set to fine-tune the JobExecutor:
+ <itemizedlist>
+ <listitem>
+ <emphasis role="bold">threads:</emphasis> defines the number of
+ JobexecutorThreads (default 3 threads)
+ </listitem>
+ <listitem>
+ <emphasis role="bold">idle:</emphasis> number of milliseconds the dispatcher
+ component waits after no new jobs were found in the database (default 5 seconds)
+ </listitem>
+ <listitem>
+ <emphasis role="bold">idle-max:</emphasis> each time an exception occurs,
+ the idle period will be doubled until the 'idle-max' is reached
+ (back-off mechanism used to avoid a constant load on a failing database)
+ </listitem>
+ <listitem>
+ <emphasis role="bold">lock-millis:</emphasis> Number of milliseconds
+ that a job will be locked after being acquired by the dispatcher.
+ This prevents starvation in case one of more JobExecutorThreads would die
+ (eg when used in a cluster).
+ </listitem>
+ </itemizedlist>
+ <programlisting>
+
+ <process-engine-context>
+
+ <job-executor threads="4" idle="15000" idle-max="60000" lock-millis="3600000" />
+
+ </process-engine-context>
+ </programlisting>
+ </para>
+ </section>
+
+</chapter>
Copied: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch13-AdvancedEmail.xml (from rev 5958, jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch12-AdvancedEmail.xml)
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch13-AdvancedEmail.xml (rev 0)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch13-AdvancedEmail.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -0,0 +1,196 @@
+<chapter id="mailsupport">
+ <title>Advanced 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.
+ </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 at minitrue' /> (2)
+ <to addresses='julia at minitrue, obrien at 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/smtp/package-summary.html">
+ 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 at 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.html">
+ Sun Regex Patterns</ulink>.</para>
+ <programlisting><![CDATA[<jbpm-configuration>
+<transaction-context>
+ <mail-session>
+ <mail-server>
+ <address-filter>
+ <include>.+ at jbpm.org</include>
+ </address-filter>
+ <session-properties>
+ <property name="mail.smtp.host" value="int.smtp.jbpm.org" />
+ <property name="mail.from" value="noreply at jbpm.org" />
+ </session-properties>
+ </mail-server>
+ <mail-server>
+ <address-filter>
+ <exclude>.+ at jbpm.org</exclude>
+ </address-filter>
+ <session-properties>
+ <property name="mail.smtp.host" value="ext.smtp.jbpm.org" />
+ <property name="mail.from" value="noreply at 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
Deleted: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch13-SoftwareLogging.xml
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch13-SoftwareLogging.xml 2009-12-15 10:55:41 UTC (rev 5959)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch13-SoftwareLogging.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -1,99 +0,0 @@
-<chapter id="softwarelogging">
- <title>Software logging</title>
-
- <section>
- <title>Configuration</title>
- <para>PVM can use JDK logging (java.util.logging) or log4j. When the first message is
- logged, PVM logging will make the selection with following procedure:
- <orderedlist>
- <listitem>If a <literal>logging.properties</literal> resource is found
- on the classpath (using the context classloader), then JDK logging will
- be used and that file will be used to initialize the JDK logging.
- </listitem>
- <listitem>If log4j is found on the classpath, then log4j will be used.
- The check for log4j will be done by checking availability of class
- <literal>org.apache.log4j.LogManager</literal> with the context classloader.
- </listitem>
- <listitem>If none of the above, JDK logging will be used.</listitem>
- </orderedlist>
- </para>
- </section>
-
- <section>
- <title>Categories</title>
- <para>The PVM classes use their class name as the category for the logger.
- </para>
- <para>To have a basic understanding of what the PVM classes are doing,
- turning on the <literal>debug</literal> level is great. Level
- <literal>trace</literal> might be spitting out too much for that
- purpose.
- </para>
- </section>
-
- <section>
- <title>JDK logging</title>
- <para>In JDK logging, <literal>debug</literal> maps to <literal>fine</literal>
- and <literal>trace</literal> maps to <literal>finest</literal>.
- Level <literal>finer</literal> is not used.
- </para>
- <para><literal>org.jbpm.pvm.internal.log.LogFormatter</literal> is part of
- the pvm library and it can create a nice one-line output for log messages.
- It also has a neat feature that creates a unique indentation per thread.
- To configure it, this is a typical <literal>logging.properties</literal>
- </para>
- <programlisting>handlers = java.util.logging.ConsoleHandler
-java.util.logging.ConsoleHandler.level = FINEST
-java.util.logging.ConsoleHandler.formatter = org.jbpm.pvm.internal.log.LogFormatter
-
-# For example, set the com.xyz.foo logger to only log SEVERE messages:
-# com.xyz.foo.level = SEVERE
-
-.level = SEVERE
-org.jbpm.level=FINE
-org.jbpm.tx.level=FINE
-org.jbpm.pvm.internal.wire.level=FINE</programlisting>
-
-<!--
- <para>For production usage, jBPM also includes an error triggered log handler. This is
- a log handler that will only keep the most recent log messages in
- memory and these will only be flushed to a file in case an error occurs.
- </para>
- <para>to configure it, add <literal>org.jbpm.util.ErrorTriggeredFileHandler</literal>
- to the handlers in the logging properties like this:
- </para>
- <programlisting>handlers = java.util.logging.ConsoleHandler org.jbpm.util.ErrorTriggeredFileHandler</programlisting>
- <para>Next snippet shows how in the same logging.properties, the error
- triggered file handler can be configured. The given values are the default
- values.
- </para>
- <programlisting>org.jbpm.util.ErrorTriggeredFileHandler.size = 500
-org.jbpm.util.ErrorTriggeredFileHandler.push = SEVERE
-org.jbpm.util.ErrorTriggeredFileHandler.pattern = %h/jbpm%u.log</programlisting>
- <para>Alternatively to using the org.jbpm.util.ErrorTriggeredFileHandler, the
- JDK handlers FileHandler and MemoryHandler can used in combination to get
- similar results with a bit more configuration.
- </para>
-
--->
- </section>
-
- <section>
- <title>Debugging persistence</title>
- <para>When testing the persistence, following logging configurations can be
- valuable. Category <literal>org.hibernate.SQL</literal> shows the SQL statement that is executed
- and category <literal>org.hibernate.type</literal> shows the values of the parameters that are
- set in the queries.
- </para>
- <programlisting>org.hibernate.SQL.level=FINEST
-org.hibernate.type.level=FINEST</programlisting>
- <para>And in case you get a failed batch as a cause in a hibernate exception,
- you might want to set the batch size to 0 like this in the hibernate properties:
- </para>
- <programlisting>hibernate.jdbc.batch_size = 0</programlisting>
- <para>Also in the hibernate properties, the following properties allow for
- detailed logs of the SQL that hibernate spits out:</para>
- <programlisting>hibernate.show_sql = true
-hibernate.format_sql = true
-hibernate.use_sql_comments = true</programlisting>
- </section>
-</chapter>
\ No newline at end of file
Deleted: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch14-History.xml
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch14-History.xml 2009-12-15 10:55:41 UTC (rev 5959)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch14-History.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -1,36 +0,0 @@
-<chapter id="history">
- <title>History</title>
-
- <para>History information is the information that will be maintained in the database
- for querying purposes. This information is kept in the database after the
- process or task has ended. But it is always up to date with the runtime
- information. History information is updated inside of the runtime
- transaction.
- </para>
-
- <para>We maintain history information on 4 entities: process instance, activity instance
- task and variable. Each entity has a list of details associated to it.
- Preferably use the history queries to access this information through the API.
- </para>
-
- <para>HistoryEvents are fired during process execution and dispatched to the configured
- HistorySession. (see HistoryEvent.fire) All the HistoryEvents are delegated to a HistorySession. The default HistorySessionImpl
- will invoke the process() method on the history events themselves.
- </para>
-
- <para>The HistoryEvents are temporary events. In the process method, they build up the information
- in the history model. There is a HistoryProcessInstance and there is a whole class hierarchy starting with HistoryActivityInstance.
- </para>
-
- <para>In the HistoryEvent.process methods, the history events create model entities or merge
- information into the history entities. For instance, a ProcessInstanceCreate history event will
- create a HistoryProcessInstance entity/record. And the ProcessInstanceEnd will set the endTime
- property in the existing HistoryProcessInstance entity/record.
- </para>
-
- <para>Similar pattern for the activities. But for automatic activities, there is an optimisation
- so that only 1 event is created and all the information is stored in one single insert (as all
- this happens inside 1 transaction).
- </para>
-
-</chapter>
\ No newline at end of file
Copied: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch14-SoftwareLogging.xml (from rev 5958, jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch13-SoftwareLogging.xml)
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch14-SoftwareLogging.xml (rev 0)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch14-SoftwareLogging.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -0,0 +1,99 @@
+<chapter id="softwarelogging">
+ <title>Software logging</title>
+
+ <section>
+ <title>Configuration</title>
+ <para>PVM can use JDK logging (java.util.logging) or log4j. When the first message is
+ logged, PVM logging will make the selection with following procedure:
+ <orderedlist>
+ <listitem>If a <literal>logging.properties</literal> resource is found
+ on the classpath (using the context classloader), then JDK logging will
+ be used and that file will be used to initialize the JDK logging.
+ </listitem>
+ <listitem>If log4j is found on the classpath, then log4j will be used.
+ The check for log4j will be done by checking availability of class
+ <literal>org.apache.log4j.LogManager</literal> with the context classloader.
+ </listitem>
+ <listitem>If none of the above, JDK logging will be used.</listitem>
+ </orderedlist>
+ </para>
+ </section>
+
+ <section>
+ <title>Categories</title>
+ <para>The PVM classes use their class name as the category for the logger.
+ </para>
+ <para>To have a basic understanding of what the PVM classes are doing,
+ turning on the <literal>debug</literal> level is great. Level
+ <literal>trace</literal> might be spitting out too much for that
+ purpose.
+ </para>
+ </section>
+
+ <section>
+ <title>JDK logging</title>
+ <para>In JDK logging, <literal>debug</literal> maps to <literal>fine</literal>
+ and <literal>trace</literal> maps to <literal>finest</literal>.
+ Level <literal>finer</literal> is not used.
+ </para>
+ <para><literal>org.jbpm.pvm.internal.log.LogFormatter</literal> is part of
+ the pvm library and it can create a nice one-line output for log messages.
+ It also has a neat feature that creates a unique indentation per thread.
+ To configure it, this is a typical <literal>logging.properties</literal>
+ </para>
+ <programlisting>handlers = java.util.logging.ConsoleHandler
+java.util.logging.ConsoleHandler.level = FINEST
+java.util.logging.ConsoleHandler.formatter = org.jbpm.pvm.internal.log.LogFormatter
+
+# For example, set the com.xyz.foo logger to only log SEVERE messages:
+# com.xyz.foo.level = SEVERE
+
+.level = SEVERE
+org.jbpm.level=FINE
+org.jbpm.tx.level=FINE
+org.jbpm.pvm.internal.wire.level=FINE</programlisting>
+
+<!--
+ <para>For production usage, jBPM also includes an error triggered log handler. This is
+ a log handler that will only keep the most recent log messages in
+ memory and these will only be flushed to a file in case an error occurs.
+ </para>
+ <para>to configure it, add <literal>org.jbpm.util.ErrorTriggeredFileHandler</literal>
+ to the handlers in the logging properties like this:
+ </para>
+ <programlisting>handlers = java.util.logging.ConsoleHandler org.jbpm.util.ErrorTriggeredFileHandler</programlisting>
+ <para>Next snippet shows how in the same logging.properties, the error
+ triggered file handler can be configured. The given values are the default
+ values.
+ </para>
+ <programlisting>org.jbpm.util.ErrorTriggeredFileHandler.size = 500
+org.jbpm.util.ErrorTriggeredFileHandler.push = SEVERE
+org.jbpm.util.ErrorTriggeredFileHandler.pattern = %h/jbpm%u.log</programlisting>
+ <para>Alternatively to using the org.jbpm.util.ErrorTriggeredFileHandler, the
+ JDK handlers FileHandler and MemoryHandler can used in combination to get
+ similar results with a bit more configuration.
+ </para>
+
+-->
+ </section>
+
+ <section>
+ <title>Debugging persistence</title>
+ <para>When testing the persistence, following logging configurations can be
+ valuable. Category <literal>org.hibernate.SQL</literal> shows the SQL statement that is executed
+ and category <literal>org.hibernate.type</literal> shows the values of the parameters that are
+ set in the queries.
+ </para>
+ <programlisting>org.hibernate.SQL.level=FINEST
+org.hibernate.type.level=FINEST</programlisting>
+ <para>And in case you get a failed batch as a cause in a hibernate exception,
+ you might want to set the batch size to 0 like this in the hibernate properties:
+ </para>
+ <programlisting>hibernate.jdbc.batch_size = 0</programlisting>
+ <para>Also in the hibernate properties, the following properties allow for
+ detailed logs of the SQL that hibernate spits out:</para>
+ <programlisting>hibernate.show_sql = true
+hibernate.format_sql = true
+hibernate.use_sql_comments = true</programlisting>
+ </section>
+</chapter>
\ No newline at end of file
Copied: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch15-History.xml (from rev 5958, jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch14-History.xml)
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch15-History.xml (rev 0)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch15-History.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -0,0 +1,36 @@
+<chapter id="history">
+ <title>History</title>
+
+ <para>History information is the information that will be maintained in the database
+ for querying purposes. This information is kept in the database after the
+ process or task has ended. But it is always up to date with the runtime
+ information. History information is updated inside of the runtime
+ transaction.
+ </para>
+
+ <para>We maintain history information on 4 entities: process instance, activity instance
+ task and variable. Each entity has a list of details associated to it.
+ Preferably use the history queries to access this information through the API.
+ </para>
+
+ <para>HistoryEvents are fired during process execution and dispatched to the configured
+ HistorySession. (see HistoryEvent.fire) All the HistoryEvents are delegated to a HistorySession. The default HistorySessionImpl
+ will invoke the process() method on the history events themselves.
+ </para>
+
+ <para>The HistoryEvents are temporary events. In the process method, they build up the information
+ in the history model. There is a HistoryProcessInstance and there is a whole class hierarchy starting with HistoryActivityInstance.
+ </para>
+
+ <para>In the HistoryEvent.process methods, the history events create model entities or merge
+ information into the history entities. For instance, a ProcessInstanceCreate history event will
+ create a HistoryProcessInstance entity/record. And the ProcessInstanceEnd will set the endTime
+ property in the existing HistoryProcessInstance entity/record.
+ </para>
+
+ <para>Similar pattern for the activities. But for automatic activities, there is an optimisation
+ so that only 1 event is created and all the information is stored in one single insert (as all
+ this happens inside 1 transaction).
+ </para>
+
+</chapter>
\ No newline at end of file
Deleted: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch15-JBossIntegration.xml
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch15-JBossIntegration.xml 2009-12-15 10:55:41 UTC (rev 5959)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch15-JBossIntegration.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -1,140 +0,0 @@
-<chapter id="jbossintegration">
- <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-deployment-use-cases.html">here</ulink>
- </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/devguide/src/main/docbook/en/modules/ch16-JBossIntegration.xml (from rev 5958, jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch15-JBossIntegration.xml)
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch16-JBossIntegration.xml (rev 0)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch16-JBossIntegration.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -0,0 +1,140 @@
+<chapter id="jbossintegration">
+ <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-deployment-use-cases.html">here</ulink>
+ </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/devguide/src/main/docbook/en/modules/ch16-SpringIntegration.xml
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch16-SpringIntegration.xml 2009-12-15 10:55:41 UTC (rev 5959)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch16-SpringIntegration.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -1,151 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<chapter id="springIntegration">
- <title>Spring Integration</title>
-
- <para>
- The embeddability of the jBPM engine in different environments has always
- been one of its core strengths, but often extra libraries to do the integration
- were required. Since jBPM4 however, it is now possible to natively
- integrate jBPM with <ulink url="http://www.springsource.org/about">Spring</ulink>.
- This section will explain which steps are required for such an integration.
- </para>
-
- <para>
- The Spring integration has started out as a community effort by
- <ulink url="http://www.inze.be/andries/">Andries Inzé</ulink>.
- Do note that Spring integration currently is in 'incubation', before
- it is moved to the user guide.
- </para>
-
- <section id="spring_overview">
- <title>Overview</title>
- <para>
- The default jBPM behaviour is to open a transaction for each operation
- that is called on the service API. In a typical Spring setup, applications are
- accessed from the web tier and enter a transactional boundary by invoking
- operations on service beans. These service beans will then access the jBPM services.
- All these operations run typically in a single transaction (ie one transaction
- per request from the browser), which invalidates the standard jBPM
- transaction handling approach. Instead of starting and committing
- a transaction for every service operation, the existing transaction
- should be used (or a new one started if none exists).
- </para>
- </section>
-
- <section id="spring_configuration">
- <title>Configuration</title>
- <para>
- The easiest way to integrate Spring with jBPM is to import the <emphasis role="bold">jbpm.tx.spring.cfg.xml</emphasis>
- in your jbpm.cfg.xml file:
- <programlisting>
-<import resource="jbpm.tx.spring.cfg.xml" />
- </programlisting>
- This configuration uses the single transaction manager which is defined in the Spring configuration.
- Start from the content of this file if you need to tweak the jBPM-Spring integration
- configuration.
- </para>
- <para>
- If you start from an existing configuration, replace the standard-transaction-interceptor with the
- spring-transaction-interceptor. The hibernate session needs the attribute current=”true”,
- depending if you are using the 'current Session' strategy in Spring.
- Also, the <transaction/> must be removed from the transaction-context if you want the
- transactions to be handled by Spring only.
- This forces jBPM to search for the current session, which will then be provided by Spring.
- <programlisting>
- <process-engine-context>
- <command-service>
- <emphasis role="bold"><spring-transaction-interceptor /></emphasis>
- ...
- </command-service>
- ...
- </process-engine-context>
- <transaction-context>
- ...
- <emphasis role="bold"><hibernate-session current="true"/></emphasis>
- </transaction-context>
- </programlisting>
- </para>
-
- <para>
- The spring-transaction-interceptor will look by default for a PlatformTransactionManager
- implementation by doing a search by type on the defined beans. In the case of multiple
- transaction managers, it is possible to specifically define the name of the transaction manager
- that must be used by the interceptor:
- <programlisting>
-<spring-transaction-interceptor transaction-manager="<emphasis role="bold">myTransactionManager</emphasis>" />
- </programlisting>
- </para>
-
- <para>
- The Spring integration provides a special context, which is added to
- the set of contexts where the jBPM engine will look for beans.
- Using this SpringContext, it is now possible to retrieve beans from the
- Spring Application Context. For the Spring context to be known, a
- SpringConfiguration must be created. This class extends the JbpmConfiguration
- but will add itself as a context. The single constructor take the location of the jBPM configuration.
-
- <programlisting>
- <bean id="jbpmConfiguration" class="org.jbpm.pvm.internal.cfg.SpringConfiguration">
- <constructor-arg value="be/inze/spring/demo/jbpm.cfg.xml" />
- </bean>
- </programlisting>
- </para>
-
- <para>
- Using this configuration, a ProcessEngine can be created:
- <programlisting>
-<bean id="processEngine" factory-bean="jbpmConfiguration" factory-method="buildProcessEngine" />
- </programlisting>
- </para>
-
- <para>
- The jBPM services can also be defined in the Spring applicationContext, as following:
- <programlisting>
-<bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService" />
-<bean id="executionService" factory-bean="processEngine" factory-method="getExecutionService" />
- </programlisting>
- </para>
-
- </section>
-
- <section id="spring_usage">
- <title>Usage</title>
-
- <para>
- The previous section already showed how the jBPM services can be made
- accessible for other Spring services. The other use case is calling
- Spring beans from within a process. This can be done by using
- an expression which resolves to the name of a Spring bean.
-
- <programlisting>
-<java name="echo" expr="#{echoService}" method="sayHello" >
- <transition name="to accept" to="join1"/>
- </java>
- </programlisting>
-
- The scripting engine will look into all contexts from the bean named echoService.
- If you configured the ScriptManager as above, Spring will be the last context to search for.
- You can also add a Spring bean to the Spring Application context
- (eg IdentitySessionImpl with id <emphasis role="italic">identitySession</emphasis>)
- and use it in the jBPM config (eg by adding <env class="identitySession" />)
- </para>
-
- </section>
-
- <section id="spring_testing">
- <title>Testing</title>
-
- <para>
- Use the <emphasis role="bold">AbstractTransactionalJbpmTestCase</emphasis>
- to test a process in isolation (ie without impact on the database).
- This class extends from
- the <emphasis role="italic">AbstractTransactionalDataSourceSpringContextTests</emphasis>
- class, which means that testing a process comes down to exactly the same
- approach as testing a DAO.
- </para>
-
- </section>
-
-
-
-</chapter>
Deleted: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch17-Signavio.xml
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch17-Signavio.xml 2009-12-15 10:55:41 UTC (rev 5959)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch17-Signavio.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -1,94 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<chapter id="signavio">
-
- <title>Signavio web modeler</title>
-
- <section id="signavioIntroduction">
-
- <title>Introduction</title>
-
- <para>Since version 4.1, jBPM ships with a completely open-source web-based BPMN
- modeling tool called 'Signavio'. This Signavio web modeler is the result
- of a close collaboration between the JBoss jBPM team,
- <ulink url="http://www.signavio.com/en.html">the company also named 'Signavio'</ulink>
- and the Hasso Plattner Instut (HPI) in Germany. Signavio is based on the
- web-based modeling tool <ulink url="http://bpt.hpi.uni-potsdam.de/Oryx">
- Oryx</ulink>, which was developed in open-source by HPI. Both HPI and
- Signavio have comitted themselves to continue investing in Oryx and Signavio.
- More information about the initiative can be found
- <ulink url="http://code.google.com/p/signavio-oryx-initiative/">here</ulink>.</para>
-
- <para>
- <mediaobject><imageobject><imagedata align="center" fileref="images/signavio.screenshot.png"/></imageobject></mediaobject>
- </para>
-
- <para>
- Using the Signavio web-based BPMN modeler, it is possible to let business
- analyst model the business processes through their browser. The file format
- which is used to store the BPMN processes is actually jPDL. This means that
- the resulting processes can directly be imported into the Eclipse GPD and vice-versa. The process
- files will be stored on the hard disk, in
- <literal>$jbpm_home/signavio-repository</literal> if you've used the default
- installation scripts.
- </para>
-
- <para>
- NOTE: The web-based BPMN modeling tool which ships with jBPM is 100% open-source
- (MIT-licence). The company <ulink url="http://www.signavio.com/en.html">Signavio</ulink>
- also offers commercial versions of the same modeling tool, enhanced with additional
- features. Do note that new features, beneficial for the jBPM project, always
- will be comitted in the open-source repository of the modeling tool.
- </para>
-
- </section>
-
- <section id="signavioInstallation">
-
- <title>Installation</title>
-
- <para>
- There are several ways of installing Signavio into your web container:
- <itemizedlist>
- <listitem>
- Use the demo.setup.jboss/tomcat scripts in <literal>$jbpm_home/install</literal>
- </listitem>
- <listitem>
- Use the install.signavio.into.jboss/tomcat scripts in <literal>$jbpm_home/install</literal>
- </listitem>
- <listitem>
- Copy the <literal>$jbpm_home/install/src/signavio/jbpmeditor.war</literal>
- to your web container
- </listitem>
- </itemizedlist>
- </para>
-
- </section>
-
- <section id="signavioConfiguration">
-
- <title>Configuration</title>
-
- <para>
- Most of the Signavio configuration parameters can be changed in the
- <literal>web.xml</literal> file, which you can find in <literal>jbpmeditor.war/WEB-INF/</literal>.
- The only parameters which is of real importance is the <literal>fileSystemRootDirectory</literal>
- parameter. The value of this parameter must point to an existing folder
- on your hard disk and indicates where the processes must be stored:
- <programlisting>
-</context-param>
- <context-param>
- <description>Filesystem directory that is used to store models</description>
- <param-name>fileSystemRootDirectory</param-name><param-value>/home/jbarrez/dev/temp/jbpm-4.3-SNAPSHOT/signavio-repository</param-value>
-</context-param>
- </programlisting>
- </para>
-
- <para>
- If you use the installation scripts provided in <literal>$jbpm_home/install</literal>,
- this parameter is automatically set to <literal>$jbpm_home/signavio-repository</literal>
- during installation.
- </para>
-
- </section>
-
-</chapter>
Copied: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch17-SpringIntegration.xml (from rev 5958, jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch16-SpringIntegration.xml)
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch17-SpringIntegration.xml (rev 0)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch17-SpringIntegration.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -0,0 +1,151 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<chapter id="springIntegration">
+ <title>Spring Integration</title>
+
+ <para>
+ The embeddability of the jBPM engine in different environments has always
+ been one of its core strengths, but often extra libraries to do the integration
+ were required. Since jBPM4 however, it is now possible to natively
+ integrate jBPM with <ulink url="http://www.springsource.org/about">Spring</ulink>.
+ This section will explain which steps are required for such an integration.
+ </para>
+
+ <para>
+ The Spring integration has started out as a community effort by
+ <ulink url="http://www.inze.be/andries/">Andries Inzé</ulink>.
+ Do note that Spring integration currently is in 'incubation', before
+ it is moved to the user guide.
+ </para>
+
+ <section id="spring_overview">
+ <title>Overview</title>
+ <para>
+ The default jBPM behaviour is to open a transaction for each operation
+ that is called on the service API. In a typical Spring setup, applications are
+ accessed from the web tier and enter a transactional boundary by invoking
+ operations on service beans. These service beans will then access the jBPM services.
+ All these operations run typically in a single transaction (ie one transaction
+ per request from the browser), which invalidates the standard jBPM
+ transaction handling approach. Instead of starting and committing
+ a transaction for every service operation, the existing transaction
+ should be used (or a new one started if none exists).
+ </para>
+ </section>
+
+ <section id="spring_configuration">
+ <title>Configuration</title>
+ <para>
+ The easiest way to integrate Spring with jBPM is to import the <emphasis role="bold">jbpm.tx.spring.cfg.xml</emphasis>
+ in your jbpm.cfg.xml file:
+ <programlisting>
+<import resource="jbpm.tx.spring.cfg.xml" />
+ </programlisting>
+ This configuration uses the single transaction manager which is defined in the Spring configuration.
+ Start from the content of this file if you need to tweak the jBPM-Spring integration
+ configuration.
+ </para>
+ <para>
+ If you start from an existing configuration, replace the standard-transaction-interceptor with the
+ spring-transaction-interceptor. The hibernate session needs the attribute current=”true”,
+ depending if you are using the 'current Session' strategy in Spring.
+ Also, the <transaction/> must be removed from the transaction-context if you want the
+ transactions to be handled by Spring only.
+ This forces jBPM to search for the current session, which will then be provided by Spring.
+ <programlisting>
+ <process-engine-context>
+ <command-service>
+ <emphasis role="bold"><spring-transaction-interceptor /></emphasis>
+ ...
+ </command-service>
+ ...
+ </process-engine-context>
+ <transaction-context>
+ ...
+ <emphasis role="bold"><hibernate-session current="true"/></emphasis>
+ </transaction-context>
+ </programlisting>
+ </para>
+
+ <para>
+ The spring-transaction-interceptor will look by default for a PlatformTransactionManager
+ implementation by doing a search by type on the defined beans. In the case of multiple
+ transaction managers, it is possible to specifically define the name of the transaction manager
+ that must be used by the interceptor:
+ <programlisting>
+<spring-transaction-interceptor transaction-manager="<emphasis role="bold">myTransactionManager</emphasis>" />
+ </programlisting>
+ </para>
+
+ <para>
+ The Spring integration provides a special context, which is added to
+ the set of contexts where the jBPM engine will look for beans.
+ Using this SpringContext, it is now possible to retrieve beans from the
+ Spring Application Context. For the Spring context to be known, a
+ SpringConfiguration must be created. This class extends the JbpmConfiguration
+ but will add itself as a context. The single constructor take the location of the jBPM configuration.
+
+ <programlisting>
+ <bean id="jbpmConfiguration" class="org.jbpm.pvm.internal.cfg.SpringConfiguration">
+ <constructor-arg value="be/inze/spring/demo/jbpm.cfg.xml" />
+ </bean>
+ </programlisting>
+ </para>
+
+ <para>
+ Using this configuration, a ProcessEngine can be created:
+ <programlisting>
+<bean id="processEngine" factory-bean="jbpmConfiguration" factory-method="buildProcessEngine" />
+ </programlisting>
+ </para>
+
+ <para>
+ The jBPM services can also be defined in the Spring applicationContext, as following:
+ <programlisting>
+<bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService" />
+<bean id="executionService" factory-bean="processEngine" factory-method="getExecutionService" />
+ </programlisting>
+ </para>
+
+ </section>
+
+ <section id="spring_usage">
+ <title>Usage</title>
+
+ <para>
+ The previous section already showed how the jBPM services can be made
+ accessible for other Spring services. The other use case is calling
+ Spring beans from within a process. This can be done by using
+ an expression which resolves to the name of a Spring bean.
+
+ <programlisting>
+<java name="echo" expr="#{echoService}" method="sayHello" >
+ <transition name="to accept" to="join1"/>
+ </java>
+ </programlisting>
+
+ The scripting engine will look into all contexts from the bean named echoService.
+ If you configured the ScriptManager as above, Spring will be the last context to search for.
+ You can also add a Spring bean to the Spring Application context
+ (eg IdentitySessionImpl with id <emphasis role="italic">identitySession</emphasis>)
+ and use it in the jBPM config (eg by adding <env class="identitySession" />)
+ </para>
+
+ </section>
+
+ <section id="spring_testing">
+ <title>Testing</title>
+
+ <para>
+ Use the <emphasis role="bold">AbstractTransactionalJbpmTestCase</emphasis>
+ to test a process in isolation (ie without impact on the database).
+ This class extends from
+ the <emphasis role="italic">AbstractTransactionalDataSourceSpringContextTests</emphasis>
+ class, which means that testing a process comes down to exactly the same
+ approach as testing a DAO.
+ </para>
+
+ </section>
+
+
+
+</chapter>
Copied: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch18-Signavio.xml (from rev 5958, jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch17-Signavio.xml)
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch18-Signavio.xml (rev 0)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch18-Signavio.xml 2009-12-15 15:51:09 UTC (rev 5960)
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<chapter id="signavio">
+
+ <title>Signavio web modeler</title>
+
+ <section id="signavioIntroduction">
+
+ <title>Introduction</title>
+
+ <para>Since version 4.1, jBPM ships with a completely open-source web-based BPMN
+ modeling tool called 'Signavio'. This Signavio web modeler is the result
+ of a close collaboration between the JBoss jBPM team,
+ <ulink url="http://www.signavio.com/en.html">the company also named 'Signavio'</ulink>
+ and the Hasso Plattner Instut (HPI) in Germany. Signavio is based on the
+ web-based modeling tool <ulink url="http://bpt.hpi.uni-potsdam.de/Oryx">
+ Oryx</ulink>, which was developed in open-source by HPI. Both HPI and
+ Signavio have comitted themselves to continue investing in Oryx and Signavio.
+ More information about the initiative can be found
+ <ulink url="http://code.google.com/p/signavio-oryx-initiative/">here</ulink>.</para>
+
+ <para>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/signavio.screenshot.png"/></imageobject></mediaobject>
+ </para>
+
+ <para>
+ Using the Signavio web-based BPMN modeler, it is possible to let business
+ analyst model the business processes through their browser. The file format
+ which is used to store the BPMN processes is actually jPDL. This means that
+ the resulting processes can directly be imported into the Eclipse GPD and vice-versa. The process
+ files will be stored on the hard disk, in
+ <literal>$jbpm_home/signavio-repository</literal> if you've used the default
+ installation scripts.
+ </para>
+
+ <para>
+ NOTE: The web-based BPMN modeling tool which ships with jBPM is 100% open-source
+ (MIT-licence). The company <ulink url="http://www.signavio.com/en.html">Signavio</ulink>
+ also offers commercial versions of the same modeling tool, enhanced with additional
+ features. Do note that new features, beneficial for the jBPM project, always
+ will be comitted in the open-source repository of the modeling tool.
+ </para>
+
+ </section>
+
+ <section id="signavioInstallation">
+
+ <title>Installation</title>
+
+ <para>
+ There are several ways of installing Signavio into your web container:
+ <itemizedlist>
+ <listitem>
+ Use the demo.setup.jboss/tomcat scripts in <literal>$jbpm_home/install</literal>
+ </listitem>
+ <listitem>
+ Use the install.signavio.into.jboss/tomcat scripts in <literal>$jbpm_home/install</literal>
+ </listitem>
+ <listitem>
+ Copy the <literal>$jbpm_home/install/src/signavio/jbpmeditor.war</literal>
+ to your web container
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ </section>
+
+ <section id="signavioConfiguration">
+
+ <title>Configuration</title>
+
+ <para>
+ Most of the Signavio configuration parameters can be changed in the
+ <literal>web.xml</literal> file, which you can find in <literal>jbpmeditor.war/WEB-INF/</literal>.
+ The only parameters which is of real importance is the <literal>fileSystemRootDirectory</literal>
+ parameter. The value of this parameter must point to an existing folder
+ on your hard disk and indicates where the processes must be stored:
+ <programlisting>
+</context-param>
+ <context-param>
+ <description>Filesystem directory that is used to store models</description>
+ <param-name>fileSystemRootDirectory</param-name><param-value>/home/jbarrez/dev/temp/jbpm-4.3-SNAPSHOT/signavio-repository</param-value>
+</context-param>
+ </programlisting>
+ </para>
+
+ <para>
+ If you use the installation scripts provided in <literal>$jbpm_home/install</literal>,
+ this parameter is automatically set to <literal>$jbpm_home/signavio-repository</literal>
+ during installation.
+ </para>
+
+ </section>
+
+</chapter>
More information about the jbpm-commits
mailing list