[jbpm-commits] JBoss JBPM SVN: r2219 - in jbpm4/pvm/trunk/modules: core/src/test/java/org/jbpm/pvm/api/basicfeatures and 14 other directories.
do-not-reply at jboss.org
do-not-reply at jboss.org
Fri Sep 12 12:04:50 EDT 2008
Author: tom.baeyens at jboss.com
Date: 2008-09-12 12:04:50 -0400 (Fri, 12 Sep 2008)
New Revision: 2219
Added:
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/db/embedded/AutomaticActivity.java
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/db/embedded/Loan.java
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/db/embedded/WaitState.java
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/images/loan.execution.png
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/images/loan.process.png
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch02-ExecutionModes.xml
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch03-Architecture.xml
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch04-SoftwareLogging.xml
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-AdvancedGraphExecution.xml
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-AsynchronousContinuations.xml
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-BasicGraphExecution.xml
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-DelegationClasses.xml
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-Environment.xml
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-History.xml
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-Persistence.xml
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-ProcessLanguages.xml
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-Services.xml
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-Timers.xml
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-Variables.xml
Removed:
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/db/embedded/Order.java
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/images/first.graph.process.png
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/images/order.process.png
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch02-SoftwareLogging.xml
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch03-BasicGraphExecution.xml
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch03-Environments.xml
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch04-AdvancedGraphExecution.xml
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch04-Services.xml
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch05-DelegationClasses.xml
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch06-Variables.xml
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch07-History.xml
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch08-Environment.xml
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch09-Persistence.xml
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch11-AsynchronousContinuations.xml
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch12-Timers.xml
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch13-ProcessLanguages.xml
Modified:
jbpm4/pvm/trunk/modules/core/src/main/java/org/jbpm/pvm/client/ClientProcessDefinition.java
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/BasicExecutionFlowTest.java
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/EventPropagationTest.java
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/EventTest.java
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/ExceptionHandlerTest.java
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/ExternalDecisionTest.java
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/LoopingTest.java
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/ScopeStateTest.java
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/ScopeVariableDeclarationTest.java
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/ScopeVariableTest.java
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/SubProcessTest.java
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/TransitionAsWaitStateTest.java
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/TransitionBasedConcurrencyTest.java
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/TransitionEventsTest.java
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/VariableTest.java
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/db/continuation/ContinuationTest.java
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/db/continuation/WaitState.java
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/db/embedded/EmbeddedPersistenceTest.java
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/internal/expr/GroovyExpressionTest.java
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/internal/expr/JuelExpressionTest.java
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/internal/jobexecutor/JobExecutorTest.java
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/samples/ex01/BasicProcessExecutionTest.java
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/samples/ex04/ExternalDecisionTest.java
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/samples/ex05/InternalDecisionTest.java
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/samples/ex06/HumanTaskTest.java
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/samples/ex08/SequenceTest.java
jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/samples/ex09/EventPropagationTest.java
jbpm4/pvm/trunk/modules/manual/src/main/diagrams/diagrams.mdzip
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/images/class.diagram.process.definition.png
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/images/class.diagram.process.execution.png
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/master.xml
jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch01-Introduction.xml
Log:
docs updates
Modified: jbpm4/pvm/trunk/modules/core/src/main/java/org/jbpm/pvm/client/ClientProcessDefinition.java
===================================================================
--- jbpm4/pvm/trunk/modules/core/src/main/java/org/jbpm/pvm/client/ClientProcessDefinition.java 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/core/src/main/java/org/jbpm/pvm/client/ClientProcessDefinition.java 2008-09-12 16:04:50 UTC (rev 2219)
@@ -21,19 +21,38 @@
*/
package org.jbpm.pvm.client;
+import org.jbpm.pvm.model.OpenExecution;
import org.jbpm.pvm.model.OpenProcessDefinition;
-/**
+/** adds factory methods for creating and beginning new process instances.
+ *
* @author Tom Baeyens
*/
public interface ClientProcessDefinition extends OpenProcessDefinition {
+ /** creates a new process instances. The returned process instance
+ * is not started yet. This way,
+ * {@link OpenExecution#setVariable(String, Object) variables can be set}
+ * before execution is started. Invoke {@link ClientProcessInstance#begin()}
+ * to start execution of the process. */
ClientProcessInstance createProcessInstance();
+ /** creates a new process instances with a given key. The returned process instance
+ * is not started yet. This way,
+ * {@link OpenExecution#setVariable(String, Object) variables can be set}
+ * before execution is started. Invoke {@link ClientProcessInstance#begin()}
+ * to start execution of the process.
+ * @param key is a user provided reference that uniquely identifies this
+ * process instance in the scope of the process name. */
ClientProcessInstance createProcessInstance(String key);
- ClientProcessInstance beginProcessInstance();
+ /** creates the process instance and immediately start its execution. */
+ ClientExecution beginProcessInstance();
- ClientProcessInstance beginProcessInstance(String key);
+ /** creates the process instance with the given key and immediately start its
+ * execution.
+ * @param key is a user provided reference that uniquely identifies this
+ * process instance in the scope of the process name. */
+ ClientExecution beginProcessInstance(String key);
}
Modified: jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/BasicExecutionFlowTest.java
===================================================================
--- jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/BasicExecutionFlowTest.java 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/BasicExecutionFlowTest.java 2008-09-12 16:04:50 UTC (rev 2219)
@@ -25,13 +25,14 @@
import java.util.List;
import java.util.Map;
-import org.jbpm.pvm.test.base.JbpmTestCase;
import org.jbpm.pvm.activity.Activity;
import org.jbpm.pvm.activity.ActivityExecution;
import org.jbpm.pvm.activity.ExternalActivity;
+import org.jbpm.pvm.client.ClientExecution;
import org.jbpm.pvm.client.ClientProcessDefinition;
import org.jbpm.pvm.client.ClientProcessInstance;
import org.jbpm.pvm.model.ProcessFactory;
+import org.jbpm.pvm.test.base.JbpmTestCase;
/** shows wait states and automatic activities in a simple
* sequence based on transitions.
@@ -88,7 +89,7 @@
.node("f").behaviour(automaticActivity)
.done();
- ClientProcessInstance processInstance = processDefinition.beginProcessInstance();
+ ClientExecution processInstance = processDefinition.beginProcessInstance();
List<String> expectedEvents = new ArrayList<String>();
Modified: jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/EventPropagationTest.java
===================================================================
--- jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/EventPropagationTest.java 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/EventPropagationTest.java 2008-09-12 16:04:50 UTC (rev 2219)
@@ -30,7 +30,7 @@
import org.jbpm.pvm.activity.ActivityExecution;
import org.jbpm.pvm.activity.ExternalActivity;
import org.jbpm.pvm.client.ClientProcessDefinition;
-import org.jbpm.pvm.client.ClientProcessInstance;
+import org.jbpm.pvm.client.ClientExecution;
import org.jbpm.pvm.listener.EventListener;
import org.jbpm.pvm.listener.EventListenerExecution;
import org.jbpm.pvm.model.Event;
@@ -90,7 +90,7 @@
.node("end").behaviour(new WaitState())
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
execution.signal();
assertEquals("event(node-end) on initial", recorder.events.get(0));
@@ -108,7 +108,7 @@
.node("end").behaviour(new WaitState())
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
execution.signal();
assertEquals("event(node-begin) on end", recorder.events.get(0));
@@ -126,7 +126,7 @@
.node("end").behaviour(new WaitState())
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
execution.signal();
assertEquals("event(transition-take) on go", recorder.events.get(0));
@@ -173,7 +173,7 @@
.node("end").behaviour(new WaitState())
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
assertEquals(0, recorder.events.size());
execution.signal();
assertEquals("event(node-end) on one", recorder.events.get(0));
@@ -200,7 +200,7 @@
.node("end").behaviour(new WaitState())
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
assertEquals(0, recorder.events.size());
execution.signal();
@@ -227,7 +227,7 @@
.node("end").behaviour(new WaitState())
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
assertEquals("event(node-begin) on one", recorder.events.get(0));
assertEquals(1, recorder.events.size());
execution.signal();
@@ -252,7 +252,7 @@
.node("end").behaviour(new WaitState())
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
assertEquals(0, recorder.events.size());
execution.signal();
@@ -287,7 +287,7 @@
.compositeEnd()
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
assertEquals(0, processRecorder.events.size());
execution.signal("hello");
@@ -336,7 +336,7 @@
.compositeEnd()
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
// the middle action should not be executed for an event that was propagated from the nested state
execution.signal("hello");
Modified: jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/EventTest.java
===================================================================
--- jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/EventTest.java 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/EventTest.java 2008-09-12 16:04:50 UTC (rev 2219)
@@ -30,7 +30,7 @@
import org.jbpm.pvm.activity.ActivityExecution;
import org.jbpm.pvm.activity.ExternalActivity;
import org.jbpm.pvm.client.ClientProcessDefinition;
-import org.jbpm.pvm.client.ClientProcessInstance;
+import org.jbpm.pvm.client.ClientExecution;
import org.jbpm.pvm.internal.model.ExecutionImpl;
import org.jbpm.pvm.internal.model.ProcessDefinitionImpl;
import org.jbpm.pvm.listener.EventListener;
@@ -94,7 +94,7 @@
.node("end").behaviour(new WaitState())
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
assertEquals("initial", execution.getNode().getName());
execution.signal();
@@ -125,7 +125,7 @@
.node("end").behaviour(new WaitState())
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
assertEquals("initial", execution.getNode().getName());
execution.signal("t");
@@ -157,7 +157,7 @@
.listener(nodeBeginAction)
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
assertEquals("initial", execution.getNode().getName());
execution.signal();
@@ -206,7 +206,7 @@
.node("end").behaviour(new WaitState())
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
assertEquals("initial", execution.getNode().getName());
assertNull(execution.getVariable("msg"));
Modified: jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/ExceptionHandlerTest.java
===================================================================
--- jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/ExceptionHandlerTest.java 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/ExceptionHandlerTest.java 2008-09-12 16:04:50 UTC (rev 2219)
@@ -27,7 +27,7 @@
import org.jbpm.pvm.activity.ActivityExecution;
import org.jbpm.pvm.activity.ExternalActivity;
import org.jbpm.pvm.client.ClientProcessDefinition;
-import org.jbpm.pvm.client.ClientProcessInstance;
+import org.jbpm.pvm.client.ClientExecution;
import org.jbpm.pvm.listener.EventListener;
import org.jbpm.pvm.listener.EventListenerExecution;
import org.jbpm.pvm.model.Event;
@@ -76,7 +76,7 @@
.node("end").behaviour(new WaitState())
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
assertEquals("initial", execution.getNode().getName());
assertEquals(0, catcher.timesInvoked);
@@ -98,7 +98,7 @@
.node("end").behaviour(new WaitState())
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
assertEquals("initial", execution.getNode().getName());
assertEquals(0, catcher.timesInvoked);
@@ -120,7 +120,7 @@
.node("end").behaviour(new WaitState())
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
assertEquals("initial", execution.getNode().getName());
assertEquals(0, catcher.timesInvoked);
@@ -142,7 +142,7 @@
.exceptionHandlerEnd()
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
assertEquals("initial", execution.getNode().getName());
assertEquals(0, catcher.timesInvoked);
@@ -168,7 +168,7 @@
.node("end").behaviour(new WaitState())
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
assertEquals("initial", execution.getNode().getName());
try {
@@ -200,7 +200,7 @@
.node("end").behaviour(new WaitState())
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
assertEquals("initial", execution.getNode().getName());
try {
@@ -224,7 +224,7 @@
.node("end").behaviour(new WaitState())
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
assertEquals("initial", execution.getNode().getName());
try {
@@ -257,7 +257,7 @@
.node("end").behaviour(new WaitState())
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
try {
execution.signal();
@@ -288,7 +288,7 @@
.node("end").behaviour(new WaitState())
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
assertEquals("initial", execution.getNode().getName());
execution.signal();
@@ -314,7 +314,7 @@
.node("end").behaviour(new WaitState())
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
try {
execution.signal();
fail("expected exception");
Modified: jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/ExternalDecisionTest.java
===================================================================
--- jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/ExternalDecisionTest.java 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/ExternalDecisionTest.java 2008-09-12 16:04:50 UTC (rev 2219)
@@ -27,7 +27,7 @@
import org.jbpm.pvm.activity.ActivityExecution;
import org.jbpm.pvm.activity.ExternalActivity;
import org.jbpm.pvm.client.ClientProcessDefinition;
-import org.jbpm.pvm.client.ClientProcessInstance;
+import org.jbpm.pvm.client.ClientExecution;
import org.jbpm.pvm.samples.ex04.Decision;
import org.jbpm.pvm.model.ProcessFactory;
@@ -73,7 +73,7 @@
public void testGoodRating() {
ClientProcessDefinition processDefinition = createCreditProcess();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
execution.signal("good");
@@ -82,7 +82,7 @@
public void testAverageRating() {
ClientProcessDefinition processDefinition = createCreditProcess();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
execution.signal("average");
@@ -91,7 +91,7 @@
public void testBadRating() {
ClientProcessDefinition processDefinition = createCreditProcess();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
execution.signal("bad");
Modified: jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/LoopingTest.java
===================================================================
--- jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/LoopingTest.java 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/LoopingTest.java 2008-09-12 16:04:50 UTC (rev 2219)
@@ -9,7 +9,7 @@
import org.jbpm.pvm.activity.ActivityExecution;
import org.jbpm.pvm.activity.ExternalActivity;
import org.jbpm.pvm.client.ClientProcessDefinition;
-import org.jbpm.pvm.client.ClientProcessInstance;
+import org.jbpm.pvm.client.ClientExecution;
import org.jbpm.pvm.model.ProcessFactory;
public class LoopingTest extends JbpmTestCase {
@@ -93,7 +93,7 @@
.node("end").behaviour(new WaitState())
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
List<Object> expectedIndexes = new ArrayList<Object>();
for (int i=0; i<loops; i++) expectedIndexes.add(i);
Modified: jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/ScopeStateTest.java
===================================================================
--- jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/ScopeStateTest.java 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/ScopeStateTest.java 2008-09-12 16:04:50 UTC (rev 2219)
@@ -23,7 +23,6 @@
import java.util.Map;
-import org.jbpm.pvm.test.base.JbpmTestCase;
import org.jbpm.pvm.Execution;
import org.jbpm.pvm.activity.Activity;
import org.jbpm.pvm.activity.ActivityExecution;
@@ -31,6 +30,7 @@
import org.jbpm.pvm.client.ClientProcessDefinition;
import org.jbpm.pvm.client.ClientProcessInstance;
import org.jbpm.pvm.model.ProcessFactory;
+import org.jbpm.pvm.test.base.JbpmTestCase;
/**
* @author Tom Baeyens
Modified: jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/ScopeVariableDeclarationTest.java
===================================================================
--- jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/ScopeVariableDeclarationTest.java 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/ScopeVariableDeclarationTest.java 2008-09-12 16:04:50 UTC (rev 2219)
@@ -28,7 +28,7 @@
import org.jbpm.pvm.activity.ActivityExecution;
import org.jbpm.pvm.activity.ExternalActivity;
import org.jbpm.pvm.client.ClientProcessDefinition;
-import org.jbpm.pvm.client.ClientProcessInstance;
+import org.jbpm.pvm.client.ClientExecution;
import org.jbpm.pvm.model.Node;
import org.jbpm.pvm.model.OpenExecution;
import org.jbpm.pvm.model.ProcessFactory;
@@ -66,7 +66,7 @@
.node("a").initial().behaviour(new WaitState())
.done();
- ClientProcessInstance processInstance = processDefinition.beginProcessInstance();
+ ClientExecution processInstance = processDefinition.beginProcessInstance();
assertTrue(processInstance.hasVariable("flight"));
assertNull(processInstance.getVariable("flight"));
@@ -78,7 +78,7 @@
.node("a").initial().behaviour(new WaitState())
.done();
- ClientProcessInstance processInstance = processDefinition.beginProcessInstance();
+ ClientExecution processInstance = processDefinition.beginProcessInstance();
assertTrue(processInstance.hasVariable("flight"));
assertEquals("B52", processInstance.getVariable("flight"));
@@ -103,7 +103,7 @@
Map<String, Object> expectedVariables = new HashMap<String, Object>();
- ClientProcessInstance processInstance = processDefinition.beginProcessInstance();
+ ClientExecution processInstance = processDefinition.beginProcessInstance();
expectedVariables.put("flight", "B52");
assertEquals(expectedVariables, processInstance.getVariables());
@@ -135,7 +135,7 @@
.compositeEnd()
.done();
- ClientProcessInstance processInstance = processDefinition.beginProcessInstance();
+ ClientExecution processInstance = processDefinition.beginProcessInstance();
OpenExecution executionC = processInstance.getExecution("c");
OpenExecution executionI = executionC.getExecution("i");
@@ -187,7 +187,7 @@
.compositeEnd()
.done();
- ClientProcessInstance processInstance = processDefinition.beginProcessInstance();
+ ClientExecution processInstance = processDefinition.beginProcessInstance();
OpenExecution outerExecution = processInstance.getExecution("outer");
OpenExecution leftMiddleExecution = outerExecution.getExecution("left-middle");
OpenExecution leftInnerExecution = leftMiddleExecution.getExecution("left-inner");
Modified: jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/ScopeVariableTest.java
===================================================================
--- jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/ScopeVariableTest.java 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/ScopeVariableTest.java 2008-09-12 16:04:50 UTC (rev 2219)
@@ -28,7 +28,7 @@
import org.jbpm.pvm.activity.ActivityExecution;
import org.jbpm.pvm.activity.ExternalActivity;
import org.jbpm.pvm.client.ClientProcessDefinition;
-import org.jbpm.pvm.client.ClientProcessInstance;
+import org.jbpm.pvm.client.ClientExecution;
import org.jbpm.pvm.model.OpenExecution;
import org.jbpm.pvm.model.ProcessFactory;
@@ -65,7 +65,7 @@
.node("c").behaviour(new WaitState())
.done();
- ClientProcessInstance processInstance = processDefinition.beginProcessInstance();
+ ClientExecution processInstance = processDefinition.beginProcessInstance();
processInstance.setVariable("destination", "anywhere");
processInstance.signal();
@@ -90,7 +90,7 @@
.node("c").behaviour(new WaitState())
.done();
- ClientProcessInstance processInstance = processDefinition.beginProcessInstance();
+ ClientExecution processInstance = processDefinition.beginProcessInstance();
processInstance.signal();
OpenExecution bScope = processInstance.getExecution("b");
@@ -116,7 +116,7 @@
.node("c").behaviour(new WaitState())
.done();
- ClientProcessInstance processInstance = processDefinition.beginProcessInstance();
+ ClientExecution processInstance = processDefinition.beginProcessInstance();
processInstance.signal();
OpenExecution bScope = processInstance.getExecution("b");
@@ -142,7 +142,7 @@
.node("c").behaviour(new WaitState())
.done();
- ClientProcessInstance processInstance = processDefinition.beginProcessInstance();
+ ClientExecution processInstance = processDefinition.beginProcessInstance();
processInstance.signal();
OpenExecution bScope = processInstance.getExecution("b");
@@ -166,7 +166,7 @@
.node("c").behaviour(new WaitState())
.done();
- ClientProcessInstance processInstance = processDefinition.beginProcessInstance();
+ ClientExecution processInstance = processDefinition.beginProcessInstance();
processInstance.signal();
OpenExecution bScope = processInstance.getExecution("b");
Modified: jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/SubProcessTest.java
===================================================================
--- jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/SubProcessTest.java 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/SubProcessTest.java 2008-09-12 16:04:50 UTC (rev 2219)
@@ -28,7 +28,7 @@
import org.jbpm.pvm.activity.ActivityExecution;
import org.jbpm.pvm.activity.ExternalActivity;
import org.jbpm.pvm.client.ClientProcessDefinition;
-import org.jbpm.pvm.client.ClientProcessInstance;
+import org.jbpm.pvm.client.ClientExecution;
import org.jbpm.pvm.model.ProcessFactory;
/**
@@ -44,7 +44,7 @@
this.subProcess = subProcess;
}
public void execute(ActivityExecution execution) throws Exception {
- ClientProcessInstance subProcessInstance = execution.beginSubProcessInstance(subProcess);
+ ClientExecution subProcessInstance = execution.beginSubProcessInstance(subProcess);
if (!subProcessInstance.isEnded()) {
execution.waitForSignal();
}
@@ -91,10 +91,10 @@
.node("super3").behaviour(new WaitState())
.done();
- ClientProcessInstance superProcesInstance = superProcess.beginProcessInstance();
+ ClientExecution superProcesInstance = superProcess.beginProcessInstance();
assertEquals("super2", superProcesInstance.getNode().getName());
- ClientProcessInstance subProcessInstance = (ClientProcessInstance) superProcesInstance.getSubProcessInstance();
+ ClientExecution subProcessInstance = (ClientExecution) superProcesInstance.getSubProcessInstance();
assertNotNull(subProcessInstance);
assertEquals("sub2", subProcessInstance.getNode().getName());
Modified: jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/TransitionAsWaitStateTest.java
===================================================================
--- jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/TransitionAsWaitStateTest.java 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/TransitionAsWaitStateTest.java 2008-09-12 16:04:50 UTC (rev 2219)
@@ -28,7 +28,7 @@
import org.jbpm.pvm.activity.ActivityExecution;
import org.jbpm.pvm.activity.ExternalActivity;
import org.jbpm.pvm.client.ClientProcessDefinition;
-import org.jbpm.pvm.client.ClientProcessInstance;
+import org.jbpm.pvm.client.ClientExecution;
import org.jbpm.pvm.listener.EventListenerExecution;
import org.jbpm.pvm.model.Condition;
import org.jbpm.pvm.model.ProcessFactory;
@@ -71,7 +71,7 @@
.node("make profit").behaviour(new WaitState())
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
assertNull(execution.getNode());
Modified: jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/TransitionBasedConcurrencyTest.java
===================================================================
--- jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/TransitionBasedConcurrencyTest.java 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/TransitionBasedConcurrencyTest.java 2008-09-12 16:04:50 UTC (rev 2219)
@@ -11,7 +11,7 @@
import org.jbpm.pvm.activity.ActivityExecution;
import org.jbpm.pvm.activity.ExternalActivity;
import org.jbpm.pvm.client.ClientProcessDefinition;
-import org.jbpm.pvm.client.ClientProcessInstance;
+import org.jbpm.pvm.client.ClientExecution;
import org.jbpm.pvm.model.Node;
import org.jbpm.pvm.model.OpenExecution;
import org.jbpm.pvm.model.ProcessFactory;
@@ -128,7 +128,7 @@
.node("end").behaviour(new WaitState())
.done();
- ClientProcessInstance main = processDefinition.beginProcessInstance();
+ ClientExecution main = processDefinition.beginProcessInstance();
assertEquals("fork", main.getNode().getName());
assertEquals(Execution.STATE_INACTIVE, main.getState());
Modified: jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/TransitionEventsTest.java
===================================================================
--- jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/TransitionEventsTest.java 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/TransitionEventsTest.java 2008-09-12 16:04:50 UTC (rev 2219)
@@ -29,7 +29,7 @@
import org.jbpm.pvm.activity.ActivityExecution;
import org.jbpm.pvm.activity.ExternalActivity;
import org.jbpm.pvm.client.ClientProcessDefinition;
-import org.jbpm.pvm.client.ClientProcessInstance;
+import org.jbpm.pvm.client.ClientExecution;
import org.jbpm.pvm.listener.EventListener;
import org.jbpm.pvm.listener.EventListenerExecution;
import org.jbpm.pvm.model.Event;
@@ -106,7 +106,7 @@
.listener(outsideListener)
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
assertEquals(0, processListener.events.size());
assertEquals(0, outsideListener.events.size());
@@ -181,7 +181,7 @@
.compositeEnd()
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
assertEquals(0, processListener.events.size());
assertEquals(0, outsideListener.events.size());
@@ -248,7 +248,7 @@
.compositeEnd()
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
assertEquals(0, processListener.events.size());
assertEquals(0, compositeListener.events.size());
@@ -321,7 +321,7 @@
.listener(outsideListener)
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
assertEquals(0, processListener.events.size());
assertEquals(0, outsideListener.events.size());
@@ -418,7 +418,7 @@
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
assertEquals("source inside", execution.getNode().getName());
Modified: jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/VariableTest.java
===================================================================
--- jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/VariableTest.java 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/basicfeatures/VariableTest.java 2008-09-12 16:04:50 UTC (rev 2219)
@@ -26,12 +26,13 @@
import java.util.Map;
import java.util.Set;
-import org.jbpm.pvm.test.base.JbpmTestCase;
import org.jbpm.pvm.activity.ActivityExecution;
import org.jbpm.pvm.activity.ExternalActivity;
+import org.jbpm.pvm.client.ClientExecution;
import org.jbpm.pvm.client.ClientProcessDefinition;
import org.jbpm.pvm.client.ClientProcessInstance;
import org.jbpm.pvm.model.ProcessFactory;
+import org.jbpm.pvm.test.base.JbpmTestCase;
/**
* @author Tom Baeyens
@@ -52,7 +53,7 @@
.node("a").initial().behaviour(new WaitState())
.done();
- ClientProcessInstance processInstance = processDefinition.beginProcessInstance();
+ ClientExecution processInstance = processDefinition.beginProcessInstance();
processInstance.setVariable("customer", "coca-cola");
assertEquals("coca-cola", processInstance.getVariable("customer"));
@@ -69,7 +70,7 @@
.node("a").initial().behaviour(new WaitState())
.done();
- ClientProcessInstance processInstance = processDefinition.beginProcessInstance();
+ ClientExecution processInstance = processDefinition.beginProcessInstance();
processInstance.setVariable("customer", "coca-cola");
@@ -82,7 +83,7 @@
.node("a").initial().behaviour(new WaitState())
.done();
- ClientProcessInstance processInstance = processDefinition.beginProcessInstance();
+ ClientExecution processInstance = processDefinition.beginProcessInstance();
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("customer", "coca-cola");
@@ -101,7 +102,7 @@
.node("a").initial().behaviour(new WaitState())
.done();
- ClientProcessInstance processInstance = processDefinition.beginProcessInstance();
+ ClientExecution processInstance = processDefinition.beginProcessInstance();
processInstance.setVariable("customer", "coca-cola");
processInstance.setVariable("address", "usa");
@@ -119,7 +120,7 @@
.node("a").initial().behaviour(new WaitState())
.done();
- ClientProcessInstance processInstance = processDefinition.beginProcessInstance();
+ ClientExecution processInstance = processDefinition.beginProcessInstance();
processInstance.setVariable("customer", "coca-cola");
processInstance.setVariable("address", "usa");
@@ -153,7 +154,7 @@
.node("a").initial().behaviour(new WaitState())
.done();
- ClientProcessInstance processInstance = processDefinition.beginProcessInstance();
+ ClientExecution processInstance = processDefinition.beginProcessInstance();
processInstance.setVariable("customer", "coca-cola");
processInstance.setVariable("address", "usa");
@@ -170,7 +171,7 @@
.node("a").initial().behaviour(new WaitState())
.done();
- ClientProcessInstance processInstance = processDefinition.beginProcessInstance();
+ ClientExecution processInstance = processDefinition.beginProcessInstance();
processInstance.setVariable("customer", "coca-cola");
processInstance.setVariable("address", "usa");
@@ -188,7 +189,7 @@
.node("a").initial().behaviour(new WaitState())
.done();
- ClientProcessInstance processInstance = processDefinition.beginProcessInstance();
+ ClientExecution processInstance = processDefinition.beginProcessInstance();
assertNull(processInstance.getVariable("answer to life, the universe and everything"));
}
@@ -221,7 +222,7 @@
.node("a").initial().behaviour(new WaitState())
.done();
- ClientProcessInstance processInstance = processDefinition.beginProcessInstance();
+ ClientExecution processInstance = processDefinition.beginProcessInstance();
processInstance.setVariable("niks", null);
processInstance.setVariable("nada", null);
Modified: jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/db/continuation/ContinuationTest.java
===================================================================
--- jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/db/continuation/ContinuationTest.java 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/db/continuation/ContinuationTest.java 2008-09-12 16:04:50 UTC (rev 2219)
@@ -30,7 +30,7 @@
import org.hibernate.Session;
import org.jbpm.pvm.client.ClientProcessDefinition;
-import org.jbpm.pvm.client.ClientProcessInstance;
+import org.jbpm.pvm.client.ClientExecution;
import org.jbpm.pvm.env.Environment;
import org.jbpm.pvm.env.EnvironmentFactory;
import org.jbpm.pvm.internal.cmd.Command;
@@ -117,7 +117,7 @@
public Object execute(Environment environment) throws Exception {
PvmDbSession pvmDbSession = environment.get(PvmDbSession.class);
ClientProcessDefinition processDefinition = pvmDbSession.findLatestProcessDefinitionByName("continuations");
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
pvmDbSession.save(execution);
return null;
}
Modified: jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/db/continuation/WaitState.java
===================================================================
--- jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/db/continuation/WaitState.java 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/db/continuation/WaitState.java 2008-09-12 16:04:50 UTC (rev 2219)
@@ -43,8 +43,4 @@
public void signal(ActivityExecution execution, String signal, Map<String, Object> parameters) throws Exception {
throw new UnsupportedOperationException();
}
-
- /** records event[currentNodeName] if there is a recorder */
- public void record(String event, ActivityExecution execution) {
- }
}
\ No newline at end of file
Added: jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/db/embedded/AutomaticActivity.java
===================================================================
--- jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/db/embedded/AutomaticActivity.java (rev 0)
+++ jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/db/embedded/AutomaticActivity.java 2008-09-12 16:04:50 UTC (rev 2219)
@@ -0,0 +1,38 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jbpm.pvm.api.db.embedded;
+
+import org.jbpm.pvm.activity.Activity;
+import org.jbpm.pvm.activity.ActivityExecution;
+
+/** a node behaviour implementation that records its execution and then
+ * just proceeds.
+ *
+ * @author Tom Baeyens
+ */
+public class AutomaticActivity implements Activity {
+
+ private static final long serialVersionUID = 1L;
+
+ public void execute(ActivityExecution execution) throws Exception {
+ }
+}
\ No newline at end of file
Modified: jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/db/embedded/EmbeddedPersistenceTest.java
===================================================================
--- jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/db/embedded/EmbeddedPersistenceTest.java 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/db/embedded/EmbeddedPersistenceTest.java 2008-09-12 16:04:50 UTC (rev 2219)
@@ -36,48 +36,57 @@
Session session;
Transaction transaction;
- public void testOrder() {
+ public void testLoanApprove() {
Configuration configuration = new Configuration();
configuration.configure("org/jbpm/pvm/api/db/embedded/hibernate.cfg.xml");
sessionFactory = configuration.buildSessionFactory();
startTransaction();
- Order order = new Order();
- session.save(order);
- assertEquals("arrived", order.getState());
+ Loan loan = new Loan("john doe", 234.0);
+ session.save(loan);
+ assertEquals("evaluate", loan.getState());
newTransaction();
- order = (Order) session.get(Order.class, order.getDbid());
- assertEquals("arrived", order.getState());
- order.receive();
- assertEquals("validate", order.getState());
+ loan = (Loan) session.get(Loan.class, loan.getDbid());
+ assertEquals("evaluate", loan.getState());
+ loan.approve();
+ assertEquals("end", loan.getState());
newTransaction();
- order = (Order) session.get(Order.class, order.getDbid());
- assertEquals("validate", order.getState());
- order.approve();
- assertEquals("ship goods", order.getState());
+ loan = (Loan) session.get(Loan.class, loan.getDbid());
+ assertEquals("validate", loan.getState());
+
+ commitTransaction();
+ }
+
+ public void testLoanReject() {
+ Configuration configuration = new Configuration();
+ configuration.configure("org/jbpm/pvm/api/db/embedded/hibernate.cfg.xml");
+ sessionFactory = configuration.buildSessionFactory();
+
+ startTransaction();
+
+ Loan loan = new Loan("john doe", 234.0);
+ session.save(loan);
+ assertEquals("evaluate", loan.getState());
newTransaction();
- order = (Order) session.get(Order.class, order.getDbid());
- assertEquals("ship goods", order.getState());
- order.paymentReceived();
- assertEquals("archive", order.getState());
+ loan = (Loan) session.get(Loan.class, loan.getDbid());
+ assertEquals("evaluate", loan.getState());
+ loan.approve();
+ assertEquals("end", loan.getState());
newTransaction();
- order = (Order) session.get(Order.class, order.getDbid());
- assertEquals("archive", order.getState());
- order.archived();
- assertEquals("end", order.getState());
-
- commitTransaction();
+ loan = (Loan) session.get(Loan.class, loan.getDbid());
+ assertEquals("validate", loan.getState());
}
+
void newTransaction() {
commitTransaction();
startTransaction();
Copied: jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/db/embedded/Loan.java (from rev 2182, jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/db/embedded/Order.java)
===================================================================
--- jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/db/embedded/Loan.java (rev 0)
+++ jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/db/embedded/Loan.java 2008-09-12 16:04:50 UTC (rev 2219)
@@ -0,0 +1,91 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jbpm.pvm.api.db.embedded;
+
+
+import org.jbpm.pvm.client.ClientExecution;
+import org.jbpm.pvm.client.ClientProcessDefinition;
+import org.jbpm.pvm.model.ProcessFactory;
+
+/**
+ * @author Tom Baeyens
+ */
+public class Loan {
+
+ // the loan process definition as a static resource
+ private static final ClientProcessDefinition processDefinition = ProcessFactory
+ .build("loan")
+ .node("submit loan request").initial().behaviour(AutomaticActivity.class)
+ .transition().to("evaluate")
+ .node("evaluate").behaviour(WaitState.class)
+ .transition("approve").to("wire money")
+ .transition("reject").to("end")
+ .node("wire money").behaviour(AutomaticActivity.class)
+ .transition().to("archive")
+ .node("archive").behaviour(WaitState.class)
+ .transition().to("end")
+ .node("end").behaviour(WaitState.class)
+ .done();
+
+ long dbid;
+ String customer;
+ double amount;
+ ClientExecution execution;
+
+ // constructor for persistence
+ protected Loan() {
+ }
+
+ public Loan(String customer, double amount) {
+ this.customer = customer;
+ this.amount = amount;
+ this.execution = processDefinition.beginProcessInstance();
+ }
+
+ public void approve() {
+ execution.signal("approve");
+ }
+
+ public void reject() {
+ execution.signal("reject");
+ }
+
+ public void archiveComplete() {
+ execution.signal();
+ }
+
+ public String getState() {
+ return execution.getNode().getName();
+ }
+
+ // getters //////////////////////////////////////////////////////////////////
+
+ public long getDbid() {
+ return dbid;
+ }
+ public String getCustomer() {
+ return customer;
+ }
+ public double getAmount() {
+ return amount;
+ }
+}
Property changes on: jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/db/embedded/Loan.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:mergeinfo
+
Name: svn:eol-style
+ LF
Deleted: jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/db/embedded/Order.java
===================================================================
--- jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/db/embedded/Order.java 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/db/embedded/Order.java 2008-09-12 16:04:50 UTC (rev 2219)
@@ -1,108 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2005, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jbpm.pvm.api.db.embedded;
-
-
-import java.util.Map;
-
-import org.jbpm.pvm.activity.ActivityExecution;
-import org.jbpm.pvm.activity.ExternalActivity;
-import org.jbpm.pvm.client.ClientProcessDefinition;
-import org.jbpm.pvm.client.ClientProcessInstance;
-import org.jbpm.pvm.model.ProcessFactory;
-
-/**
- * @author Tom Baeyens
- */
-public class Order {
-
- private static final ClientProcessDefinition processDefinition = createProcessDefinition();
-
- long dbid;
- ClientProcessInstance processInstance;
-
- public Order() {
- processInstance = getProcessDefinition().beginProcessInstance();
- }
-
- public static ClientProcessDefinition getProcessDefinition() {
- return processDefinition;
- }
-
- private static ClientProcessDefinition createProcessDefinition() {
- ClientProcessDefinition processDefinition = ProcessFactory.build("order")
- .node("arrived").initial().behaviour(WaitState.class)
- .transition("receive").to("validate")
- .node("validate").behaviour(WaitState.class)
- .transition("approve").to("ship goods")
- .transition("reject").to("end")
- .node("ship goods").behaviour(WaitState.class)
- .transition("payment received").to("archive")
- .node("archive").behaviour(WaitState.class)
- .transition("archived").to("end")
- .node("end").behaviour(WaitState.class)
- .done();
-
- return processDefinition;
- }
-
- public long getDbid() {
- return dbid;
- }
-
- public void setDbid(long dbid) {
- this.dbid = dbid;
- }
-
- public void receive() {
- processInstance.signal("receive");
- }
-
- public void approve() {
- processInstance.signal("approve");
- }
-
- public void reject() {
- processInstance.signal("reject");
- }
-
- public void paymentReceived() {
- processInstance.signal("payment received");
- }
-
- public void archived() {
- processInstance.signal("archived");
- }
-
- public String getState() {
- return processInstance.getNode().getName();
- }
-
- public static class WaitState implements ExternalActivity {
- private static final long serialVersionUID = 1L;
- public void execute(ActivityExecution execution) {
- execution.waitForSignal();
- }
- public void signal(ActivityExecution execution, String signalName, Map<String, Object> parameters){
- }
- }
-}
Added: jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/db/embedded/WaitState.java
===================================================================
--- jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/db/embedded/WaitState.java (rev 0)
+++ jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/api/db/embedded/WaitState.java 2008-09-12 16:04:50 UTC (rev 2219)
@@ -0,0 +1,46 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jbpm.pvm.api.db.embedded;
+
+import java.util.Map;
+
+import org.jbpm.pvm.activity.ActivityExecution;
+import org.jbpm.pvm.activity.ExternalActivity;
+
+/**
+ * @author Tom Baeyens
+ */
+public class WaitState implements ExternalActivity {
+
+ private static final long serialVersionUID = 1L;
+
+ public WaitState() {
+ }
+
+ public void execute(ActivityExecution execution) throws Exception {
+ execution.waitForSignal();
+ }
+
+ public void signal(ActivityExecution execution, String signalName, Map<String, Object> parameters) throws Exception {
+ execution.take(signalName);
+ }
+}
\ No newline at end of file
Modified: jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/internal/expr/GroovyExpressionTest.java
===================================================================
--- jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/internal/expr/GroovyExpressionTest.java 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/internal/expr/GroovyExpressionTest.java 2008-09-12 16:04:50 UTC (rev 2219)
@@ -21,7 +21,7 @@
*/
package org.jbpm.pvm.internal.expr;
-import org.jbpm.pvm.client.ClientProcessInstance;
+import org.jbpm.pvm.client.ClientExecution;
import org.jbpm.pvm.env.Environment;
import org.jbpm.pvm.env.EnvironmentFactory;
import org.jbpm.pvm.env.PvmEnvironmentFactory;
@@ -52,7 +52,7 @@
ScriptManager scriptManager = environmentFactory.get(ScriptManager.class);
- ClientProcessInstance execution = ProcessFactory.build()
+ ClientExecution execution = ProcessFactory.build()
.node("initial").initial().behaviour(WaitState.class)
.done().beginProcessInstance();
Modified: jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/internal/expr/JuelExpressionTest.java
===================================================================
--- jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/internal/expr/JuelExpressionTest.java 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/internal/expr/JuelExpressionTest.java 2008-09-12 16:04:50 UTC (rev 2219)
@@ -21,7 +21,7 @@
*/
package org.jbpm.pvm.internal.expr;
-import org.jbpm.pvm.client.ClientProcessInstance;
+import org.jbpm.pvm.client.ClientExecution;
import org.jbpm.pvm.env.Environment;
import org.jbpm.pvm.env.EnvironmentFactory;
import org.jbpm.pvm.env.PvmEnvironmentFactory;
@@ -52,7 +52,7 @@
ScriptManager scriptManager = environmentFactory.get(ScriptManager.class);
- ClientProcessInstance execution = ProcessFactory.build()
+ ClientExecution execution = ProcessFactory.build()
.node("initial").initial().behaviour(WaitState.class)
.done().beginProcessInstance();
Modified: jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/internal/jobexecutor/JobExecutorTest.java
===================================================================
--- jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/internal/jobexecutor/JobExecutorTest.java 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/internal/jobexecutor/JobExecutorTest.java 2008-09-12 16:04:50 UTC (rev 2219)
@@ -35,7 +35,7 @@
import org.jbpm.pvm.activity.ActivityExecution;
import org.jbpm.pvm.activity.ExternalActivity;
import org.jbpm.pvm.client.ClientProcessDefinition;
-import org.jbpm.pvm.client.ClientProcessInstance;
+import org.jbpm.pvm.client.ClientExecution;
import org.jbpm.pvm.env.Environment;
import org.jbpm.pvm.internal.cmd.Command;
import org.jbpm.pvm.internal.job.CommandMessage;
@@ -286,7 +286,7 @@
PvmDbSession pvmDbSession = environment.get(PvmDbSession.class);
MessageSession messageSession = environment.get(MessageSession.class);
for (int i=0; i<nbrOfTestExecutions; i++) {
- ClientProcessInstance execution = processDefinition.beginProcessInstance("execution-"+i);
+ ClientExecution execution = processDefinition.beginProcessInstance("execution-"+i);
pvmDbSession.save(execution);
for (int j=0; j<nbrOfTestMessagesPerExecution; j++) {
Modified: jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/samples/ex01/BasicProcessExecutionTest.java
===================================================================
--- jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/samples/ex01/BasicProcessExecutionTest.java 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/samples/ex01/BasicProcessExecutionTest.java 2008-09-12 16:04:50 UTC (rev 2219)
@@ -24,7 +24,7 @@
import junit.framework.TestCase;
import org.jbpm.pvm.client.ClientProcessDefinition;
-import org.jbpm.pvm.client.ClientProcessInstance;
+import org.jbpm.pvm.client.ClientExecution;
import org.jbpm.pvm.model.ProcessFactory;
import org.jbpm.pvm.samples.activities.AutomaticActivity;
import org.jbpm.pvm.samples.activities.WaitState;
@@ -47,7 +47,7 @@
.node("e").behaviour(WaitState.class)
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
assertEquals("a", execution.getNode().getName());
Modified: jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/samples/ex04/ExternalDecisionTest.java
===================================================================
--- jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/samples/ex04/ExternalDecisionTest.java 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/samples/ex04/ExternalDecisionTest.java 2008-09-12 16:04:50 UTC (rev 2219)
@@ -27,7 +27,7 @@
import org.jbpm.pvm.samples.activities.AutomaticActivity;
import org.jbpm.pvm.samples.activities.WaitState;
import org.jbpm.pvm.client.ClientProcessDefinition;
-import org.jbpm.pvm.client.ClientProcessInstance;
+import org.jbpm.pvm.client.ClientExecution;
import org.jbpm.pvm.model.OpenProcessDefinition;
import org.jbpm.pvm.model.ProcessFactory;
@@ -54,7 +54,7 @@
public void testGoodRating() {
ClientProcessDefinition processDefinition = createCreditProcess();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
execution.signal("good");
assertEquals("priority delivery", execution.getNode().getName());
@@ -63,7 +63,7 @@
public void testAverageRating() {
ClientProcessDefinition processDefinition = createCreditProcess();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
execution.signal("average");
assertEquals("bulk delivery", execution.getNode().getName());
@@ -72,7 +72,7 @@
public void testBadRating() {
ClientProcessDefinition processDefinition = createCreditProcess();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
execution.signal("bad");
assertEquals("payment upfront", execution.getNode().getName());
Modified: jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/samples/ex05/InternalDecisionTest.java
===================================================================
--- jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/samples/ex05/InternalDecisionTest.java 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/samples/ex05/InternalDecisionTest.java 2008-09-12 16:04:50 UTC (rev 2219)
@@ -26,7 +26,7 @@
import org.jbpm.pvm.Execution;
import org.jbpm.pvm.samples.activities.WaitState;
import org.jbpm.pvm.client.ClientProcessDefinition;
-import org.jbpm.pvm.client.ClientProcessInstance;
+import org.jbpm.pvm.client.ClientExecution;
import org.jbpm.pvm.model.OpenProcessDefinition;
import org.jbpm.pvm.model.ProcessFactory;
@@ -53,7 +53,7 @@
public void testGoodRating() {
ClientProcessDefinition processDefinition = createCreditProcess();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
execution.setVariable("creditRate", 7);
execution.signal();
@@ -63,7 +63,7 @@
public void testAverageRating() {
ClientProcessDefinition processDefinition = createCreditProcess();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
execution.setVariable("creditRate", 2);
execution.signal();
@@ -73,7 +73,7 @@
public void testBadRating() {
ClientProcessDefinition processDefinition = createCreditProcess();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
execution.setVariable("creditRate", -9);
execution.signal();
Modified: jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/samples/ex06/HumanTaskTest.java
===================================================================
--- jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/samples/ex06/HumanTaskTest.java 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/samples/ex06/HumanTaskTest.java 2008-09-12 16:04:50 UTC (rev 2219)
@@ -25,7 +25,7 @@
import junit.framework.TestCase;
import org.jbpm.pvm.client.ClientProcessDefinition;
-import org.jbpm.pvm.client.ClientProcessInstance;
+import org.jbpm.pvm.client.ClientExecution;
import org.jbpm.pvm.model.ProcessFactory;
import org.jbpm.pvm.samples.activities.WaitState;
@@ -42,7 +42,7 @@
.node("business as usual").behaviour(new WaitState())
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
assertEquals("shred evidence", execution.getNode().getName());
Modified: jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/samples/ex08/SequenceTest.java
===================================================================
--- jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/samples/ex08/SequenceTest.java 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/samples/ex08/SequenceTest.java 2008-09-12 16:04:50 UTC (rev 2219)
@@ -24,7 +24,7 @@
import junit.framework.TestCase;
import org.jbpm.pvm.client.ClientProcessDefinition;
-import org.jbpm.pvm.client.ClientProcessInstance;
+import org.jbpm.pvm.client.ClientExecution;
import org.jbpm.pvm.model.ProcessFactory;
import org.jbpm.pvm.samples.activities.Display;
import org.jbpm.pvm.samples.activities.WaitState;
@@ -45,7 +45,7 @@
.compositeEnd()
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
execution.signal();
assertTrue(execution.isEnded());
assertEquals("sequence", execution.getNode().getName());
Modified: jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/samples/ex09/EventPropagationTest.java
===================================================================
--- jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/samples/ex09/EventPropagationTest.java 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/core/src/test/java/org/jbpm/pvm/samples/ex09/EventPropagationTest.java 2008-09-12 16:04:50 UTC (rev 2219)
@@ -24,7 +24,7 @@
import junit.framework.TestCase;
import org.jbpm.pvm.client.ClientProcessDefinition;
-import org.jbpm.pvm.client.ClientProcessInstance;
+import org.jbpm.pvm.client.ClientExecution;
import org.jbpm.pvm.model.Event;
import org.jbpm.pvm.model.ProcessFactory;
import org.jbpm.pvm.samples.activities.WaitState;
@@ -47,7 +47,7 @@
.node("c").behaviour(new WaitState())
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
execution.signal();
execution.signal();
}
@@ -66,7 +66,7 @@
.node("c").behaviour(new WaitState())
.done();
- ClientProcessInstance execution = processDefinition.beginProcessInstance();
+ ClientExecution execution = processDefinition.beginProcessInstance();
execution.signal();
execution.signal();
}
Modified: jbpm4/pvm/trunk/modules/manual/src/main/diagrams/diagrams.mdzip
===================================================================
(Binary files differ)
Modified: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/images/class.diagram.process.definition.png
===================================================================
(Binary files differ)
Modified: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/images/class.diagram.process.execution.png
===================================================================
(Binary files differ)
Deleted: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/images/first.graph.process.png
===================================================================
(Binary files differ)
Added: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/images/loan.execution.png
===================================================================
(Binary files differ)
Property changes on: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/images/loan.execution.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/images/loan.process.png
===================================================================
(Binary files differ)
Property changes on: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/images/loan.process.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Deleted: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/images/order.process.png
===================================================================
(Binary files differ)
Modified: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/master.xml
===================================================================
--- jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/master.xml 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/master.xml 2008-09-12 16:04:50 UTC (rev 2219)
@@ -2,20 +2,9 @@
<!DOCTYPE book [
<!ENTITY ch01-Introduction SYSTEM "modules/ch01-Introduction.xml">
- <!ENTITY ch02-SoftwareLogging SYSTEM "modules/ch02-SoftwareLogging.xml">
- <!ENTITY ch03-Environments SYSTEM "modules/ch03-Environments.xml">
- <!ENTITY ch04-Services SYSTEM "modules/ch04-Services.xml">
-
- <!ENTITY ch03-BasicGraphExecution SYSTEM "modules/ch03-BasicGraphExecution.xml">
- <!ENTITY ch04-AdvancedGraphExecution SYSTEM "modules/ch04-AdvancedGraphExecution.xml">
- <!ENTITY ch05-DelegationClasses SYSTEM "modules/ch05-DelegationClasses.xml">
- <!ENTITY ch06-Variables SYSTEM "modules/ch06-Variables.xml">
- <!ENTITY ch07-History SYSTEM "modules/ch07-History.xml">
- <!ENTITY ch08-Environment SYSTEM "modules/ch08-Environment.xml">
- <!ENTITY ch09-Persistence SYSTEM "modules/ch09-Persistence.xml">
- <!ENTITY ch11-AsynchronousContinuations SYSTEM "modules/ch11-AsynchronousContinuations.xml">
- <!ENTITY ch12-Timers SYSTEM "modules/ch12-Timers.xml">
- <!ENTITY ch13-ProcessLanguages SYSTEM "modules/ch13-ProcessLanguages.xml">
+ <!ENTITY ch02-ExecutionModes SYSTEM "modules/ch02-ExecutionModes.xml">
+ <!ENTITY ch03-Architecture SYSTEM "modules/ch03-Architecture.xml">
+ <!ENTITY ch04-SoftwareLogging SYSTEM "modules/ch04-SoftwareLogging.xml">
]>
<book lang="en">
@@ -30,8 +19,8 @@
<toc />
&ch01-Introduction;
- &ch02-SoftwareLogging;
- &ch03-Environments;
- &ch04-Services;
+ &ch02-ExecutionModes;
+ &ch03-Architecture;
+ &ch04-SoftwareLogging;
</book>
\ No newline at end of file
Modified: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch01-Introduction.xml
===================================================================
--- jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch01-Introduction.xml 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch01-Introduction.xml 2008-09-12 16:04:50 UTC (rev 2219)
@@ -20,39 +20,61 @@
<title>What is it</title>
<para>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. Many executions can be
- started for one process definition.
+ be represented graphically as a diagram.
</para>
<figure id="example.process.graph">
<title>Example process definition</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/first.graph.process.png"/></imageobject></mediaobject>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/loan.process.png"/></imageobject></mediaobject>
</figure>
<para>Typically, process definitions are static. A process definition is composed of
nodes and transitions. The runtime behaviour of a node is encapsulated in a so called
- Activity and it's decoupled from the process graph structure. The Process Virtual
- Machine doesn't contain any such activity implementations. It only provides the
- execution environment and a set of basic operations such as taking a transition.
- It also gives the user a simple way of implementing the process
- constructs as concrete <literal>Activity</literal> implementations.
+ 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>Activities can also be wait states. This means that the node control flow goes
- outside the process system. For example a human task or invoking an asynchronous service.
+ <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>Activity</literal>
+ implementations as Java components. Activities can also be wait states. This means
+ that the node control flow goes outside the process system. For example a human task
+ or invoking an service asynchronously.
</para>
- <para>An execution is a pointer that keeps track of the current node. 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>Many executions can be started for one process definition. An execution is a pointer
+ that keeps track of the current node.
</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>Process structure class diagram</title>
+ <title>Execution class diagram</title>
<mediaobject><imageobject><imagedata align="center" fileref="images/class.diagram.process.execution.png"/></imageobject></mediaobject>
</figure>
</section>
<section>
+ <title>Features</title>
+ <para>The key features of this library are
+ <itemizedlist>
+ <listitem>Create executable processes that are based on a diagram structure</listitem>
+ <listitem>Runtime behaviour of the nodes can be provided as Activity implementations</listitem>
+ <listitem>Activities can be wait states</listitem>
+ <listitem>There are no constraints on the process graph structure</listitem>
+ <listitem>Processes diagrams can be based on composition (aka block structured)</listitem>
+ <listitem>Processes diagrams can be a mix of graph based and composition</listitem>
+ <listitem>During wait states, the runtime state of a process execution can be persisted</listitem>
+ <listitem>Persistence is optional</listitem>
+ </itemizedlist>
+ </para>
+ </section>
+
+ <section>
<title>Purpose</title>
<para>The Process Virtual Machine is designed in such a way that it's easy to build
workflow, BPM, orchestration and other graph based execution langauges on top
@@ -70,18 +92,24 @@
with it. For instance, it's very easy to build a very simple (and dedicated) workflow
language to specify approvals related to documents in a document management system.
</para>
- <para>The key features of this library are
+ <para>BPM as a discipline refers to the management level effort to optimise efficiency
+ of an organisation by analysing and optimising the procedures of how people and systems
+ work together. In designing the Process Virtual Machine and the jPDL language
+ in particular, we have spend great care on facilitating the link between BPM analysis
+ notations and executable process languages. Here are the most known modeling notations:
+ </para>
<itemizedlist>
- <listitem>Create executable processes that are based on a diagram structure</listitem>
- <listitem>Runtime behaviour of the nodes can be provided as Activity implementations</listitem>
- <listitem>Activities can be wait states</listitem>
- <listitem>There are no constraints on the process graph structure</listitem>
- <listitem>Processes diagrams can be based on composition (aka block structured)</listitem>
- <listitem>Processes diagrams can be a mix of graph based and composition</listitem>
- <listitem>During wait states, the runtime state of a process execution can be persisted</listitem>
- <listitem>Persistence is optional</listitem>
+ <listitem>BPMN: OMG latest notation for modeling business processes.
+ This is a modeling notation that is targetted explicitely to be bound
+ to executable processes.
+ </listitem>
+ <listitem>UML activity diagrams: OMG notation for modeling business
+ processes. Mostly used in business context.</listitem>
+ <listitem>UML state diagrams: OMG modeling notation for defining technical
+ state machines. More used in a technical context.</listitem>
+ <listitem>EPC: Event driven process chains. Rich notation for modeling
+ business processes driven by SAP and IDS Scheer.</listitem>
</itemizedlist>
- </para>
</section>
-
+
</chapter>
Copied: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch02-ExecutionModes.xml (from rev 2183, jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch03-Environments.xml)
===================================================================
--- jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch02-ExecutionModes.xml (rev 0)
+++ jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch02-ExecutionModes.xml 2008-09-12 16:04:50 UTC (rev 2219)
@@ -0,0 +1,118 @@
+<chapter id="overview">
+ <title>Overview</title>
+
+ <section id="executionmodes">
+ <title>Execution modes</title>
+
+ <para>There are basically three process execution modes: object, persistent
+ and embedded. For the persistent and embedded execution modes, the process
+ execution has to participate in a transaction. In that case, the process
+ execution has to take place inside of an Environment. The environment will be
+ used to bind process execution updates to a transaction in the application
+ transaction. The environment can be used to bind to e.g. a JDBC connection,
+ JTA, BMT, Spring transactions and so on.
+ </para>
+
+ <section id="objectexecutionmode">
+ <title>Object execution mode</title>
+ <para>Object execution mode is the simplest form of working with the Process
+ Virtual Machine. This means working with the process definition and execution
+ objects directly through the client API. Let's show this by an example. We
+ start by creating a <literal>ClientProcessDefinition</literal> that looks like this:
+ </para>
+ <figure id="loan.process">
+ <title>The loan process</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/loan.process.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting>ClientProcessDefinition <emphasis role="bold">processDefinition</emphasis> = ProcessFactory.build()
+ .node("a").initial().behaviour(AutomaticActivity.class)
+ .transition().to("b")
+ .node("b").behaviour(AutomaticActivity.class)
+ .transition().to("c")
+ .node("c").behaviour(WaitState.class)
+ .transition().to("d")
+ .node("d").behaviour(AutomaticActivity.class)
+ .transition().to("f")
+ .node("e").behaviour(AutomaticActivity.class)
+ .transition().to("e")
+ .node("f").behaviour(WaitState.class)
+.done();</programlisting>
+ <para>The <literal>ProcessFactory</literal> is a helper class that provides convenience
+ for building an object graph that represents a process definition.
+ <literal>AutomaticActivity</literal> just acts as a pass through activity without anything
+ happening and <literal>WaitState</literal> will wait until an external signal is given. Both
+ activity implementations will be covered in more depth later.
+ </para>
+ <para>A process
+ </para>
+ </section>
+
+ <section id="persistentexecutionmode">
+ <title>Persistent execution mode</title>
+ <para>Embedded execution mode means that process definitions, the runtime
+ executions and the history information all is stored in the PVM database
+ schema.
+ </para>
+ </section>
+
+ <section id="embeddedexecutionmode">
+ <title>Embedded execution mode</title>
+ <para>Embedded execution mode means that the state of a process is stored
+ as a string column inside a user domain object like e.g. an Order.
+ </para>
+ </section>
+ </section>
+
+ <section 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. Each of the APIs has a
+ specific purpose
+ </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>Activity</literal>
+ interface. Activity 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>Configuration</title>
+ <para>
+ </para>
+ </section>
+ <section>
+ <title>Environment</title>
+ <para>
+ </para>
+ </section>
+ <section>
+ <title>Commands</title>
+ <para>
+ </para>
+ </section>
+ <section>
+ <title>Services</title>
+ <para>
+ </para>
+ </section>
+ </section>
+
+</chapter>
\ No newline at end of file
Property changes on: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch02-ExecutionModes.xml
___________________________________________________________________
Name: svn:mergeinfo
+
Deleted: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch02-SoftwareLogging.xml
===================================================================
--- jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch02-SoftwareLogging.xml 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch02-SoftwareLogging.xml 2008-09-12 16:04:50 UTC (rev 2219)
@@ -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
Added: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch03-Architecture.xml
===================================================================
--- jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch03-Architecture.xml (rev 0)
+++ jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch03-Architecture.xml 2008-09-12 16:04:50 UTC (rev 2219)
@@ -0,0 +1,118 @@
+<chapter id="overview">
+ <title>Overview</title>
+
+ <section id="executionmodes">
+ <title>Execution modes</title>
+
+ <para>There are basically three process execution modes: object, persistent
+ and embedded. For the persistent and embedded execution modes, the process
+ execution has to participate in a transaction. In that case, the process
+ execution has to take place inside of an Environment. The environment will be
+ used to bind process execution updates to a transaction in the application
+ transaction. The environment can be used to bind to e.g. a JDBC connection,
+ JTA, BMT, Spring transactions and so on.
+ </para>
+
+ <section id="objectexecutionmode">
+ <title>Object execution mode</title>
+ <para>Object execution mode is the simplest form of working with the Process
+ Virtual Machine. This means working with the process definition and execution
+ objects directly through the client API. Let's show this by an example. We
+ start by creating a <literal>ClientProcessDefinition</literal> that looks like this:
+ </para>
+ <figure id="loan.process">
+ <title>The loan process</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/loan.process.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting>ClientProcessDefinition <emphasis role="bold">processDefinition</emphasis> = ProcessFactory.build()
+ .node("a").initial().behaviour(AutomaticActivity.class)
+ .transition().to("b")
+ .node("b").behaviour(AutomaticActivity.class)
+ .transition().to("c")
+ .node("c").behaviour(WaitState.class)
+ .transition().to("d")
+ .node("d").behaviour(AutomaticActivity.class)
+ .transition().to("f")
+ .node("e").behaviour(AutomaticActivity.class)
+ .transition().to("e")
+ .node("f").behaviour(WaitState.class)
+.done();</programlisting>
+ <para>The <literal>ProcessFactory</literal> is a helper class that provides convenience
+ for building an object graph that represents a process definition.
+ <literal>AutomaticActivity</literal> just acts as a pass through activity without anything
+ happening and <literal>WaitState</literal> will wait until an external signal is given. Both
+ activity implementations will be covered in more depth later.
+ </para>
+ <para>A process
+ </para>
+ </section>
+
+ <section id="persistentexecutionmode">
+ <title>Persistent execution mode</title>
+ <para>Embedded execution mode means that process definitions, the runtime
+ executions and the history information all is stored in the PVM database
+ schema.
+ </para>
+ </section>
+
+ <section id="embeddedexecutionmode">
+ <title>Embedded execution mode</title>
+ <para>Embedded execution mode means that the state of a process is stored
+ as a string column inside a user domain object like e.g. an Order.
+ </para>
+ </section>
+ </section>
+
+ <section 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. Each of the APIs has a
+ specific purpose
+ </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>Activity</literal>
+ interface. Activity 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>Configuration</title>
+ <para>
+ </para>
+ </section>
+ <section>
+ <title>Environment</title>
+ <para>
+ </para>
+ </section>
+ <section>
+ <title>Commands</title>
+ <para>
+ </para>
+ </section>
+ <section>
+ <title>Services</title>
+ <para>
+ </para>
+ </section>
+ </section>
+
+</chapter>
\ No newline at end of file
Deleted: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch03-BasicGraphExecution.xml
===================================================================
--- jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch03-BasicGraphExecution.xml 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch03-BasicGraphExecution.xml 2008-09-12 16:04:50 UTC (rev 2219)
@@ -1,553 +0,0 @@
-<chapter id="basicgraphexecution">
- <title>Basic graph execution</title>
-
- <!-- ### Activity ####################################################### -->
- <section id="activity">
- <title>Activity</title>
- <para>The PVM library doesn't have a fixed set of process constructs.
- Instead, runtime behaviour of a node is delegated to an <literal>Activity</literal>.
- In other words, <literal>Activity</literal> is an interface to implement the runtime
- behaviour of process constructs in plain Java. Also, <literal>Activity</literal>
- implementations can be subscrribed as listeners to
- <link linkend="events">process events</link>.
- </para>
- <programlisting>public <emphasis role="bold">interface Activity</emphasis> extends Serializable {
- void <emphasis role="bold">execute</emphasis>(Execution execution) throws Exception;
-}</programlisting>
- <para><literal>Activity</literal>'s can be used as node behaviour and as listeners to process
- events. When an activity is used as the node behaviour, it is in full control of the further
- propagation of the execution. In other words, a node behaviour can decide what the execution
- should do next. For example, it can take a transition
- with <literal>execution.take(Transition)</literal>, go into a wait state with
- <literal>execution.waitForSignal()</literal>. Or the node behaviour can not invoke
- any of the above, in that case the Process Virtual Machine will just
- <link linkend="defaultproceedbehaviour">proceed the execution in a default way</link>.
- </para>
- <para>Events are only fired during process execution. Since during an event the
- execution is already 'in motion', event listeners can not control the propagation
- of execution. Therefore, <literal>Activity</literal> implementations can only
- be used as event listeners if they don't invoke any of the execution propagation
- methods.
- </para>
- <para>This way, it is very easy to implement automatic activities that can be
- used as node behaviour as well as event listeners. Examples of automatic activities
- are sending an email, doing a database update, generating a pdf, calculating an average,
- etc. All of these can be executed by the process system and they can be used both as
- node behaviour as well as event listeners. In case they are used as node behaviour
- they can rely on the default proceed behaviour.
- </para>
- </section>
-
- <!-- ### Activity example ############################################### -->
- <section id="activityexample">
- <title>Activity 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">Activity</emphasis> {
-
- String message;
-
- public Display(String message) {
- this.message = message;
- }
-
- public void execute(Execution 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>Activty example process</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/process.png"/></imageobject></mediaobject>
- </figure>
- <programlisting>ProcessDefinition processDefinition = ProcessFactory.build()
- .<emphasis role="bold">node("a").initial()</emphasis>.behaviour(<emphasis role="bold">new Display("hello")</emphasis>)
- .transition().to("b")
- .<emphasis role="bold">node("b")</emphasis>.behaviour(<emphasis role="bold">new Display("world")</emphasis>)
-.done();</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>
- </section>
-
- <!-- ### ExternalActivity ############################################### -->
- <section id="externalactivity">
- <title>ExternalActivity</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>ExternalActivity</literal>
- adds two methods to the <literal>Activity</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 node, the
- <literal>execute</literal>-method of the node 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 node behaves as a wait state, then the execution will
- wait in that node until the execution's <literal>signal</literal> method
- is invoked. The execution will delegate that signal to the behaviour Activity
- of the current node.
- </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 node 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 ExternalActivity {
-
- public void <emphasis role="bold">execute</emphasis>(Execution execution) {
- execution.waitForSignal();
- }
-
- public void <emphasis role="bold">signal</emphasis>(Execution execution,
- String signal,
- Map<String, Object> parameters) {
- execution.take(signal);
- }
-}</programlisting>
- <para>The <literal>execute</literal>-method calls
- <literal>execution.waitForSignal()</literal>. This call is
- necessary to prevent automatic propagation of the execution. By calling
- <literal>execution.waitForSignal()</literal>, the node will
- behave as a wait state.
- </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 nodes will be WaitState's.
- </para>
- <figure id="process.diagram">
- <title>Process diagram</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/process.png"/></imageobject></mediaobject>
- </figure>
- <programlisting>ProcessDefinition processDefinition = ProcessFactory.build()
- .<emphasis role="bold">node("a").initial()</emphasis>.behaviour(<emphasis role="bold">new WaitState()</emphasis>)
- .transition().to("b")
- .<emphasis role="bold">node("b")</emphasis>.behaviour(<emphasis role="bold">new WaitState()</emphasis>)
-.done();</programlisting>
-
-<programlisting>Execution execution = processDefinition.startExecution();</programlisting>
-<programlisting>execution.signal();</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 is a simplified version of a loan approval process. Graphically,
- it looks like this:
- </para>
- <figure id="the.first.graph.process">
- <title>The first graph process</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/first.graph.process.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>ProcessDefinition processDefinition = ProcessFactory.build()
- .<emphasis role="bold">node("accept loan request").initial()</emphasis>.behaviour(new WaitState())
- .transition().to("loan evaluation")
- .<emphasis role="bold">node("loan evaluation")</emphasis>.behaviour(new WaitState())
- .transition("approve").to("wire the money")
- .transition("reject").to("end")
- .<emphasis role="bold">node("wire the money")</emphasis>.behaviour(new Display("automatic payment"))
- .transition().to("end")
- .<emphasis role="bold">node("end")</emphasis>.behaviour(new WaitState())
-.done();</programlisting>
- <para>For more details about the ProcessFactory, see the javadocs. 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 node <literal>wire the money</literal> is an automatic node. The
- <literal>Display</literal> implementation 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. All the other nodes are
- wait states.
- </para>
- <para>A new execution for the process above can be started like this
- </para>
- <programlisting>Execution execution = processDefinition.startExecution();</programlisting>
- <para>Starting a new execution implies that the initial node is executed. Since in
- this case it's a wait state, the new execution will be positioned in the
- node 'accept loan request' when the <literal>startExecution</literal>-method returns.
- </para>
- <figure id="first.execution.state.accept">
- <title>Execution positioned in 'accept loan request'</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/execution.state.accept.png"/></imageobject></mediaobject>
- </figure>
- <para>Now we can give this execution an external trigger with the <literal>signal</literal>-
- method on the execution. Invoking the signal method will take the execution to the next
- wait state.
- </para>
- <programlisting>execution.signal();</programlisting>
- <figure id="execution.state.evaluation">
- <title>Execution positioned in 'loan evaluation'</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/execution.state.evaluation.png"/></imageobject></mediaobject>
- </figure>
- <para>Now, the execution is at an interesting point. There are two transitions out of
- the state 'loan evaluation'. One transition is called 'approve' and one transition
- is called 'reject'. As we explained above in the WaitState implementation, the transition
- taken corresponds to the signal that is given. Let's feed in the 'approve' signal like this:
- </para>
- <programlisting>execution.signal("approve");</programlisting>
- <para>The 'approve' signal will cause the execution to take the 'approve' transition and
- it will arrive in the node 'wire the money'.
- </para>
- <para>In <literal>wire the 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 default behaviour will be to just proceed.
- </para>
- <para><link linkend="defaultproceedbehaviour">Proceeding</link> in this case means that
- the default outgoing transition is taken and the execution will arrive in the <literal>end</literal>
- node, which is a wait state.</para>
- <para>So only when the <literal>end</literal> wait state is reached, the <literal>signal("approve")</literal>
- returns. That is because all of the things that needed to be done between the original
- state and this new state could be executed by the process system. Executing till the
- next wait state is the default behaviour and that behaviour can be changed with
- </para>
- <para><emphasis role="bold">TODO: add link to async continuations</emphasis></para>
- <para>asynchronous continuations in case
- transactions should not include all calculations till the next wait state. For
- more about this, see <xref linkend="executionandthreads" />.
- </para>
- <para>Another signal invocation will bring it eventually in the end state.</para>
- <figure id="execution.state.end">
- <title>Execution positioned in 'end'</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/execution.state.end.png"/></imageobject></mediaobject>
- </figure>
- </section>
-
- <!-- ### MOTIVATION ##################################################### -->
- <section id="motivation">
- <title>Motivation</title>
- <para>There are basically two forms of process languages: graph based and composite
- process languages. First of all, this design supports both. Even graph based execution
- and node composition can be used in combination to implement something like UML super states.
- </para>
- <para>In this design, control flow activity implementations will have to be
- aware of whether they are dependent on transitions (graph based) or whether they are
- using the composite node structure. The goal of this design is that all non-control
- flow activities can be implemented in the same way so that you can use them in graph
- based process languages as well as in composite process languages.
- </para>
- </section>
-
- <!-- ### EVENTS ######################################################### -->
- <section id="events">
- <title>Events</title>
- <para>Events are points in the process definition to which a list of
- activities can be subscribed as listeners. 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>
- <itemizedlist>
- <listitem><literal>Transition.EVENT_TRANSITION_TAKE = "transition-take"</literal> :
- fired on transitions when transitions are taken.
- </listitem>
- <listitem><literal>Node.EVENT_NODE_ENTER = "node-enter"</literal> : fired on the node
- when execution enters that node. This happens when execution takes a transition
- to that node, when a child node is being executed with <literal>execution.execute(Node)</literal>
- or when a transition is taken from a node outside that node to a contained node.
- The latter refers to super states in state machines.
- </listitem>
- <listitem><literal>Node.EVENT_NODE_LEAVE = "node-leave"</literal> : fired on the node
- when a transition is taken out of that node or when a child node execution is
- finished and the execution is propagated to the parent node.
- </listitem>
- <listitem><literal>ProcessDefinition.EVENT_PROCESS_START = "process-start"</literal> : fired on a process
- when a new process is started.
- </listitem>
- <listitem><literal>ProcessDefinition.EVENT_PROCESS_END = "process-end"</literal> : fired on a process
- when a new process is ended. This might include a executions that are ended
- with a cancelled or error state.
- </listitem>
- </itemizedlist>
- <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 <link linkend="activity"><literal>Activity</literal>s</link> can be associated to an
- event. But activities on events can not influence the control flow of the execution since
- they are merely listeners to an execution wich is already in progress. This is different from
- activities that serve as the behaviour for nodes. Node behaviour activities are responsible
- for propagating the execution. So if an activity in an event invokes any of the
- following methods, then it will result in an exception.
- </para>
-
- <itemizedlist>
- <listitem><literal>waitForSignal()</literal></listitem>
- <listitem><literal>take(Transition)</literal></listitem>
- <listitem><literal>end(*)</literal></listitem>
- <listitem><literal>execute(Node)</literal></listitem>
- </itemizedlist>
-
- <para>We'll reuse the <literal><link linkend="activity">Display</link></literal>
- activity from above in a simple process: two nodes connected by a
- transition. The Display listener will be subscribed to the transition event.</para>
- <figure id="action.process">
- <title>The process to which a listener activity will be associated</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/process.png"/></imageobject></mediaobject>
- </figure>
- <programlisting>ProcessDefinition processDefinition = ProcessFactory.build()
- .node("a").initial().behaviour(new WaitState())
- <emphasis role="bold">.event("node-leave")
- .listener(new Display("leaving a"))
- .listener(new Display("second message while leaving a"))</emphasis>
- .transition().to("b")
- <emphasis role="bold">.listener(new Display("taking transition"))</emphasis>
- .node("b").behaviour(new WaitState())
- <emphasis role="bold">.event("node-enter")
- .listener(new Display("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 nodes that get executed
- for all events that occur within that process element. For example this feature
- allows to register a listener on a process definition or a composite node on
- <literal>node-leave</literal> events. Such action will be executed if that node is
- left. And if that listener is registered on a composite node, it will also be executed
- for all nodes that are left within that composite node.
- </para>
- <para>To show this clearly, we'll create a <literal>DisplaySource</literal> activity
- 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 Activity {
-
- public void execute(Execution 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 activity
- itself should not be displayed in the diagram. A <literal>DisplaySource</literal> activity
- will be added as a listener to the event <literal>node-leave</literal> on the composite node.
- </para>
- <para>The next process shows how the <literal>DisplaySource</literal> activity is registered
- as a listener to to the 'node-leave' event on the <literal>composite</literal> node:</para>
- <figure id="propagation.process">
- <title>A process with an invisible activity on a node-leave event on a composite node.</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/propagation.process.png"/></imageobject></mediaobject>
- </figure>
- <programlisting>ProcessDefinition processDefinition = ProcessFactory.build("propagate")
- .compositeNode("composite")
- <emphasis role="bold">.event(Node.EVENT_NODE_LEAVE)
- .listener(new DisplaySource())</emphasis>
- .node("a").initial().behaviour(new WaitState())
- .transition().to("b")
- .node("b").behaviour(new WaitState())
- .transition().to("c")
- .compositeEnd()
- .node("c").behaviour(new WaitState())
-.done();</programlisting>
- <para>Next we'll start an execution.</para>
- <programlisting>Execution execution = processDefinition.startExecution();</programlisting>
- <para>After starting a new execution, the execution will be in node <literal>a</literal> as
- that is the initial node. No nodes 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 node-leave event will be fired on node a. That event will be propagated to the
- composite node and to the process definition. Since our propagation logger is placed
- on node composite it will receive the event and print the following message:
- </para>
- <programlisting>leaving node(a)</programlisting>
- <para>Another</para>
- <programlisting>execution.signal();</programlisting>
- <para>will take the transition from b to c. That will fire two node-leave events. One on
- node b and one on node composite. So the following lines will be appended to the console
- output:</para>
- <programlisting>leaving node(b)
-leaving node(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 nodes. Each node can be a leaf node or it can be a
- composite node, which means that it contains a list of nested nodes. Nested nodes
- 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 nodes 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 nodes. Every node can have
- a set of nested nodes. 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>. 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="propagation.disabled.process">
- <title>A process with a listener to 'node-leave' events with propagation disabled.</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/propagation.process.png"/></imageobject></mediaobject>
- </figure>
- <para>Building the process with the process factory:
- </para>
- <programlisting>ProcessDefinition processDefinition = ProcessFactory.build("propagate")
- .compositeNode("composite")
- <emphasis role="bold">.event(Node.EVENT_NODE_LEAVE)
- .listener(new DisplaySource())
- .propagationDisabled()</emphasis>
- .node("a").initial().behaviour(new WaitState())
- .transition().to("b")
- .node("b").behaviour(new WaitState())
- .transition().to("c")
- .nodesEnd()
- .node("c").behaviour(new WaitState())
-.done();</programlisting>
- <para>So when the first signal is given for this process, again the node-leave event will be
- fired on node a, but now the listener on the composite node will not be executed cause
- propagated events have been disabled. Disabling propagation is a property on the listener
- and doesn't influence the other listeners. The event will always be fired and propagated
- over the whole parent hierarchy.
- </para>
- <programlisting>Execution execution = processDefinition.startExecution();
-execution.signal();
-</programlisting>
- <para>Next, the second signal will take the transition from b to c.
- </para>
- <programlisting>execution.signal()</programlisting>
- <para>Again two node-leave
- events are fired just like above on nodes b and composite respectively. The first event
- is the node-leave event on node b. That will be propagated to the composite node. So the
- listener will not be executed for this event cause it has propagation disabled. But the
- listener will be executed for the node-leave event on the composite node. That is not
- propagated, but fired directly on the composite node. So the listener will now be executed
- only once for the composite node as shown in the following console output:
- </para>
- <programlisting>leaving node(composite)</programlisting>
- </section>
-
- <!-- ### PROCESS STRUCTURE ############################################## -->
- <section>
- <title>Process structure</title>
- <para>Above we already touched briefly on the two main process constructs:
- Nodes, transitions and node composition. This section will elaborate
- on all the basic combination possibilities.
- </para>
- <figure id="process.structure">
- <title>UML class diagram of the basic process structure</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/process.structure.classes.png"/></imageobject></mediaobject>
- </figure>
- <para>Next is a series of example diagram structures that can be formed
- with the PVM process model.
- </para>
- <figure id="transition">
- <title>Any two nodes 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.node">
- <title>Composite node is a list of nested nodes.</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/composite.node.png"/></imageobject></mediaobject>
- </figure>
- <figure id="transition.into.composite">
- <title>Transition to a node 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 node inside a composite to a node 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 nodes are inherited. The node inside can take the transition of the composite node.</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/transition.inheritence.png"/></imageobject></mediaobject>
- </figure>
- <figure id="transition.to.outer">
- <title>Transition from a node 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 node to an inner composed node.</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/transition.to.inner.png"/></imageobject></mediaobject>
- </figure>
- <figure id="initial.in.composite">
- <title>An initial node inside a composite node.</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/initial.in.composite.png"/></imageobject></mediaobject>
- </figure>
- </section>
-
-</chapter>
Deleted: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch03-Environments.xml
===================================================================
--- jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch03-Environments.xml 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch03-Environments.xml 2008-09-12 16:04:50 UTC (rev 2219)
@@ -1,88 +0,0 @@
-<chapter id="environments">
- <title>Environments</title>
-
- <para>There are basically three process execution modes: object, persistent
- and embedded. For the persistent and embedded execution modes, the process
- execution has to participate in a transaction. In that case, the process
- execution has to take place inside of an Environment. The environment will be
- used to bind process execution updates to a transaction in the application
- transaction. The environment can be used to bind to e.g. a JDBC connection,
- JTA, BMT, Spring transactions and so on.
- </para>
-
- <section>
- <title>APIs</title>
- <para>The Process Virtual Machine has 4 integrated API's that together offer a complete coverage
- of working with processes.
- </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>Activity</literal>
- interface. Activity 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 id="objectexecutionmode">
- <title>Object execution mode</title>
- <para>Object execution mode is the simplest form of working with the Process
- Virtual Machine. This means working with the process definition and execution
- objects directly through the client API. Let's show this by an example. We
- start by creating a <literal>ClientProcessDefinition</literal> that looks like this:
- </para>
- <figure id="order.process">
- <title>The Order process</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/order.process.png"/></imageobject></mediaobject>
- </figure>
- <programlisting>ClientProcessDefinition <emphasis role="bold">processDefinition</emphasis> = ProcessFactory.build()
- .node("a").initial().behaviour(AutomaticActivity.class)
- .transition().to("b")
- .node("b").behaviour(AutomaticActivity.class)
- .transition().to("c")
- .node("c").behaviour(WaitState.class)
- .transition().to("d")
- .node("d").behaviour(AutomaticActivity.class)
- .transition().to("f")
- .node("e").behaviour(AutomaticActivity.class)
- .transition().to("e")
- .node("f").behaviour(WaitState.class)
-.done();</programlisting>
- <para>The <literal>ProcessFactory</literal> is a helper class that provides convenience
- for building an object graph that represents a process definition.
- <literal>AutomaticActivity</literal> just acts as a pass through activity without anything
- happening and <literal>WaitState</literal> will wait until an external signal is given. Both
- activity implementations will be covered in more depth later.
- </para>
- <para>A process
- </para>
- </section>
-
- <section id="persistentexecutionmode">
- <title>Persistent execution mode</title>
- <para>Embedded execution mode means that process definitions, the runtime
- executions and the history information all is stored in the PVM database
- schema.
- </para>
- </section>
-
- <section id="embeddedexecutionmode">
- <title>Embedded execution mode</title>
- <para>Embedded execution mode means that the state of a process is stored
- as a string column inside a user domain object like e.g. an Order.
- </para>
- </section>
-
-</chapter>
\ No newline at end of file
Deleted: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch04-AdvancedGraphExecution.xml
===================================================================
--- jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch04-AdvancedGraphExecution.xml 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch04-AdvancedGraphExecution.xml 2008-09-12 16:04:50 UTC (rev 2219)
@@ -1,297 +0,0 @@
-<chapter id="advancedgraphexecution">
- <title>Advanced graph execution</title>
-
- <!-- ### LOOPS ########################################################## -->
- <section>
- <title>Loops</title>
- <para>Loops can be based on transitions or on node 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. This means
- that all the methods in the <literal>Execution</literal> class that propagate the
- execution like <literal>take</literal> or <literal>execute</literal> will not be
- executed when you call them. Instead, the method invocations will be appended to a list.
- The first invocation of such a method will start a loop that will execute all invocations
- till that list is empty. These invocations are called atomic operations.
- </para>
- </section>
-
- <!-- ### SUB PROCESSES ################################################## -->
- <section>
- <title>Sub processes</title>
- <para>TODO: sub processes</para>
- </section>
-
- <!-- ### DEFAULT PROCEED BEHAVIOUR ###################################### -->
- <section id="defaultproceedbehaviour">
- <title>Default proceed behaviour</title>
- <para>When an <literal>Activity</literal> is used as node behaviour, it 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(Node)</literal></listitem>
- <listitem><literal>createExecution(*)</literal></listitem>
- </itemizedlist>
- <para>When <literal>Activity</literal> implementations used for node behviour
- don't call any of the following execution propagation methods, then, after
- the activity is executed, the execution will just proceed.
- </para>
- <para>By default proceeding will perform the first action that applies
- in the following list:</para>
- <itemizedlist>
- <listitem>If the current node has a default outgoing transition, take it.</listitem>
- <listitem>If the current node has a parent node, move back to the parent node.</listitem>
- <listitem>Otherwise, end this execution.</listitem>
- </itemizedlist>
- <para>Process languages can overwrite the default proceed behaviour
- by overriding the <literal>proceed</literal> method in
- <literal>ExecutionImpl</literal>.
- </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 the <link linkend="architecture">asynchronous command service</link>.
- </para>
- <para>The next process will show the basics concretely. It has three wait states
- and four automatic nodes.
- </para>
- <figure id="automatic">
- <title>Process with many sequential automatic activities.</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/ch04.automatic.png"/></imageobject></mediaobject>
- </figure>
- <para>Here's how to build the process:</para>
- <programlisting>ProcessDefinition processDefinition = ProcessFactory.build("automatic")
- .<emphasis role="bold">node("wait 1").initial()</emphasis>.behaviour(new <emphasis role="bold">WaitState</emphasis>())
- .transition().to("automatic 1")
- .<emphasis role="bold">node("automatic 1")</emphasis>.behaviour(new <emphasis role="bold">Display("one")</emphasis>)
- .transition().to("wait 2")
- .<emphasis role="bold">node("wait 2")</emphasis>.behaviour(new <emphasis role="bold">WaitState</emphasis>())
- .transition().to("automatic 2")
- .<emphasis role="bold">node("automatic 2")</emphasis>.behaviour(new <emphasis role="bold">Display("two")</emphasis>)
- .transition().to("automatic 3")
- .<emphasis role="bold">node("automatic 3")</emphasis>.behaviour(new <emphasis role="bold">Display("three")</emphasis>)
- .transition().to("automatic 4")
- .<emphasis role="bold">node("automatic 4")</emphasis>.behaviour(new <emphasis role="bold">Display("four")</emphasis>)
- .transition().to("wait 3")
- .<emphasis role="bold">node("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>Execution execution = processDefinition.startExecution();</programlisting>
- <para>Starting a new execution means that the initial node is executed. So if an automatic
- activity would be configured as the behaviour in the initial node, the process will start executing
- immediatly in the startExecution. In this case however, the initial node is a wait state. So
- the startExecution method returns immediately and the execution will be positioned in the initial
- node 'wait 1'.
- </para>
- <figure id="automatic.wait1">
- <title>A new execution will be positioned in 'wait 1'.</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/ch04.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 introducing the WaitState, that signal will cause the default transition to be taken. The
- transition will move the execution to node <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>. The signal method is still blocking
- cause this action and the transitions are taken
- by that same thread. 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 signal method.
- </para>
- <para>So when the signal method returns, the execution is positioned in <literal>wait 2</literal>.</para>
- <figure id="automatic.wait2">
- <title>One signal brought the execution from 'initial' to 'wait 2'.</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/ch04.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>To make executable processes, developers need to know exactly what the automatic activities,
- 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.
- This implies that on the level of the Process Virtual Machine, there is no differentiation
- between complete process instances and paths of execution within a process instance.
- One of the main motivations for this design is that the API actually is not made more
- complex then necessary for simple processes with only one single path of execution.
- </para>
- <figure id="execution.structure">
- <title>UML class diagram of the basic execution structure</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/ch04.execution.structure.classes.png"/></imageobject></mediaobject>
- </figure>
- <para>To extablish multiple concurrent paths of execution, child executions can be
- created. 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/ch04.concurrency.png"/></imageobject></mediaobject>
- </figure>
- <para>There is a billing and a shipping path of execution. In this case, the
- flat bar nodes represent nodes 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 node
- <literal>bill</literal> and <literal>ship</literal> respectively.
- </para>
- <para>It's up to the node 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 node 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 <link linkend="delegationclasses">code that is associated to a process</link>
- like Activity's, Actions and Conditions, it's possible to include try-catch blocks in
- the method implementations to handle exceptions. 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 STATE_ACTIVE, then it is locked. A locked execution
- is read only.
- </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 node 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 node instance (aka activity instance) and is unique for every execution
- of the node.
- </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 node behaviour implementations whether they want
- to take the overhead of locking and unlocking.
- </para>
- </section>
-
-</chapter>
Deleted: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch04-Services.xml
===================================================================
--- jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch04-Services.xml 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch04-Services.xml 2008-09-12 16:04:50 UTC (rev 2219)
@@ -1,82 +0,0 @@
-<chapter id="services">
- <title>Services</title>
-
- <para>Services can be fetched from the EnvironmentFactory, which in it's turn
- can be created from a configuration file.
- </para>
-
- <programlisting>EnvironmentFactory environmentFactory = new PvmEnvironmentFactory("pvm.cfg.xml");
-ProcessService processService = environmentFactory.get(ProcessService.class);</programlisting>
-
- <para>Services are thread safe so only 1 single service object should be maintained
- by the application and it can serve all requests for the application.
- </para>
-
-
-
- <section id="architecture">
- <title>Architecture</title>
- <para>Service methods are implemented through command classes.
- Each method creates a command object and the command is executed with
- the <literal>execute</literal> method of the <literal>CommandService</literal>.
- The <literal>CommandService</literal> is responsible for setting up the
- environment.
- </para>
- <para>There are four command services:
- </para>
- <itemizedlist>
- <listitem><literal>command-service</literal> will just
- execute the command and pass in the current environment.</listitem>
- <listitem>(UNTESTED) <literal>async-command-service</literal> will send an
- asynchronous message. So right after that in a separate transaction,
- the message is consumed and the command is executed.</listitem>
- <listitem>(TODO) <literal>cmt-command-service</literal> will delegate
- execution of the command to a local SLSB that has transaction attribute
- <literal>required</literal>.</listitem>
- <listitem>(TODO) <literal>remote-command-service</literal> will delegate
- execution of the command to a remote SLSB.</listitem>
- </itemizedlist>
- <para>Each of the command services can be configured with a list of
- interceptors that span around the command execution. Following
- interceptors are available:</para>
- <itemizedlist>
- <listitem><literal>environment-interceptor</literal>: Will execute the
- command within an <link linkend="environmentblock">environment block</link>.
- </listitem>
- <listitem>(UNTESTED) <literal>authorization-interceptor</literal>: Will perform
- an authrorization check before the command is executed. The
- authorization interceptor will look up the AuthorizationSession
- from the environment to delegate the actual authorization check to.
- </listitem>
- <listitem><literal>retry-interceptor</literal>: Will catch hibernate's
- optmistic locking exceptions (StaleStateException) and retries
- to execute the command for a configurable number of times
- </listitem>
- <listitem><literal>transaction-interceptor</literal>: Will get
- the transaction from the current context and invoke
- setRollbackOnly() on it in case an exception comes out of
- the command execution.
- </listitem>
- </itemizedlist>
- <para>Following configuration can be used in default standard persistence
- situations:
- </para>
- <programlisting><contexts>
- <environment-factory>
-
- <pvm-service />
-
- <command-service>
- <retry-interceptor />
- <environment-interceptor />
- <transaction-interceptor />
- </command-service>
-
- ...
- </environment-factory>
- ...
-
-</contexts></programlisting>
- </section>
-
-</chapter>
\ No newline at end of file
Copied: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch04-SoftwareLogging.xml (from rev 2183, jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch02-SoftwareLogging.xml)
===================================================================
--- jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch04-SoftwareLogging.xml (rev 0)
+++ jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch04-SoftwareLogging.xml 2008-09-12 16:04:50 UTC (rev 2219)
@@ -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
Property changes on: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch04-SoftwareLogging.xml
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:mergeinfo
+
Name: svn:eol-style
+ LF
Deleted: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch05-DelegationClasses.xml
===================================================================
--- jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch05-DelegationClasses.xml 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch05-DelegationClasses.xml 2008-09-12 16:04:50 UTC (rev 2219)
@@ -1,53 +0,0 @@
-<chapter id="delegationclasses">
- <title>Delegation classes</title>
-
- <section>
- <title>What are delegation classes</title>
- <para>Delegation classes are the classes that implement
- <literal>Activity</literal> or <literal>Condition</literal>. From the Process
- Virtual Machine's perspective, these are external classes that provide
- programming logic that is inserted into the PVM's graph execution.
- Delegation classes can be provided by the process languages as well
- as by the end users.
- </para>
- </section>
-
- <section>
- <title>Configuration of delegation classes</title>
- <para>Delegation classes can be made configurable. Member fields can
- contain configuration parameters so that a delegation class can be
- configured differently each time it is used. For example, in the
- <literal><link linkend="activity">Display</link></literal> activity,
- the message that is to be printed to the console is a configuration
- parameter.
- </para>
- <para>Delegation classes should be stateless. This means that executing the interface
- methods should not change values of the member fields. Changing member field values
- of delegation classes during execution methods is actually changing the process
- while it's executing. That is not threadsafe and usually leads to unexpected
- results. As an exception, getters and setters might be made available to inject
- the configuration cause they are used before the delegation object is actually
- used in the process execution.
- </para>
- </section>
-
- <section>
- <title>Object references</title>
- <para>TODO</para>
- </section>
-
- <section>
- <title>Design time versus runtime</title>
- <para>TODO: the node behaviour allows for design time as well as runtime behaviour.</para>
- </section>
-
- <section>
- <title>UserCodeInterceptor</title>
- <para>TODO: UserCodeInterceptor</para>
- </section>
-
- <section>
- <title>Member field configurations versus properties</title>
- <para>TODO: document field configurations versus properties</para>
- </section>
-</chapter>
\ No newline at end of file
Deleted: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch06-Variables.xml
===================================================================
--- jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch06-Variables.xml 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch06-Variables.xml 2008-09-12 16:04:50 UTC (rev 2219)
@@ -1,3 +0,0 @@
-<chapter id="variables">
- <title>Variables</title>
-</chapter>
\ No newline at end of file
Deleted: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch07-History.xml
===================================================================
--- jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch07-History.xml 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch07-History.xml 2008-09-12 16:04:50 UTC (rev 2219)
@@ -1,15 +0,0 @@
-<chapter id="history">
- <title>History</title>
-
- <section id="processlogs">
- <title>Process logs</title>
- </section>
-
- <section id="businessintelligence">
- <title>Business Intelligence (BI)</title>
- </section>
-
- <section id="businessactivitymonitoring">
- <title>Business Activity Monitoring (BAM)</title>
- </section>
-</chapter>
\ No newline at end of file
Deleted: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch08-Environment.xml
===================================================================
--- jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch08-Environment.xml 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch08-Environment.xml 2008-09-12 16:04:50 UTC (rev 2219)
@@ -1,139 +0,0 @@
-<chapter id="environment">
- <title>Environment</title>
-
- <section>
- <title>Introduction</title>
- <para>The environment component together with the wire context is a kind of
- Inversion of Control (IoC) container. It reads configuration information that
- describes how objects should be instantiated, configured and wired together.
- </para>
- <para>The environment is used to retrieve resources and services needed by
- <literal>Activity</literal> implementations and the Process Virtual Machine
- itself. The main purpose is to make various aspects of the Process Virtual Machine
- configurable so that the PVM and the languages that run on top can work
- in a standard Java environment as well as an enterprise Java environment.
- </para>
- <para>The environment is partitioned into a set of contexts. Each context
- can have its own lifecycle. For instance, the environment-factory context will
- strech over the full lifetime of the application. The block context only
- for the duration of a try-finally block. Typically a block context represents
- a database transaction. Each context exposes a list of key-value
- pairs.
- </para>
- </section>
-
- <section id="environmentfactory">
- <title>EnvironmentFactory</title>
- <para>To start working with an environment, you need an EnvironmentFactory.
- One single environment factory object can be used throughout the complete
- lifetime of the application. So typically this is kept in a static
- member field. The EnvironmentFactory itself is the environment-factory context.
- </para>
- <para>An <literal>EnvironmentFactory</literal> is typically obtained by
- parsing a configuration file like this:
- </para>
- <programlisting>static EnvironmentFactory environmentFactory =
- EnvironmentFactory.parse(new ResourceStreamSource("pvm.cfg.xml");</programlisting>
- <para>See javadocs package org.jbpm.stream for more types of stream sources.
- </para>
- <para>There is a default parser in the environment factory that will
- create <literal>DefaultEnvironmentFactory</literal>s. The idea is that we'll
- also support spring as an IoC container. But that is still TODO. Feel free
- to help us out :-). The parser can be configured with the static setter
- method <literal>EnvironmentFactory.setParser(Parser)</literal>
- </para>
- </section>
-
- <section id="environmentblock">
- <title>Environment block</title>
- <para>An environment exists for the duration of a try-finally block. This is how
- an environment block looks like:
- </para>
- <programlisting><emphasis role="bold">Environment environment = environmentFactory.openEnvironment();
-try {
-
- ...
-
-} finally {
- environment.close();
-}</emphasis></programlisting>
- <para>The environment block defines another lifespan: the <literal>block</literal> context.
- A transaction would be a typical example of an object that is defined in the block
- context.
- </para>
- <para>Inside such a block, objects can be looked up from the environment by name
- or by type. If objects can looked up from the environment with method
- <literal>environment.get(String name)</literal> or
- <literal><T> T environment.get(Class<T>)</literal>.
- </para>
- <para>when an environment is created, it has a <literal>environment-factory</literal> context
- and a <literal>block</literal>
- context.
- </para>
- <para>In the default implementation, the <literal>environment-factory</literal> context and
- the <literal>block</literal> context are <literal>WireContext</literal>s. A
- <literal>WireContext</literal> contains a description of how its objects are
- created and wired together to form object graphs.
- </para>
- </section>
-
- <section>
- <title>Example</title>
- <para>To start with a simple example, we'll need a <literal>Book</literal>:</para>
- <programlisting>public class <emphasis role="bold">Book</emphasis> {
- ...
- public Book() {}
- ...
-}</programlisting>
- <para>Then let's create an environment factory that knows how to create book</para>
- <programlisting>static EnvironmentFactory environmentFactory = EnvironmentFactory.parseXmlString(
- "<contexts>" +
- " <environment-factory>" +
- " <object name='book' class='org.jbpm.examples.ch09.Book' />" +
- " </environment-factory>" +
- "</contexts>"
-));</programlisting>
- <para>Now we'll create an environment block with this environment factory and
- we'll look up the book in the environment. First the lookup is done by
- type and secondly by name.
- </para>
- <programlisting>Environment environment = environmentFactory.openEnvironment();
-try {
-
- Book book = <emphasis role="bold">environment.get(Book.class);</emphasis>
- assertNotNull(book);
-
- assertSame(book, <emphasis role="bold">environment.get("book")</emphasis>);
-
-} finally {
- environment.close();
-}</programlisting>
- <para>To prevent that you have to pass the environment as a parameter in
- all methods, the current environment is maintained in a threadlocal stack:
- </para>
- <programlisting>Environment environment = Environment.getCurrent();</programlisting>
- </section>
-
- <section id="context">
- <title>Context</title>
- <para>Contexts can be added and removed dynamically. Anything can be exposed
- as a <literal>Context</literal>.
- </para>
- <programlisting>public interface <emphasis role="bold">Context</emphasis> {
-
- <emphasis role="bold">Object get(String key);
- <T> T get(Class<T> type);
- Set<String> keys();</emphasis>
-
- ...
-}</programlisting>
- <para>When doing a lookup on the environment, there is a default search order
- in which the contexts will be scanned for the requested object. The default
- order is the inverse of the sequence in which the contexts were added. E.g.
- if an object is defined in both the environment-factory context and in the block context,
- the block context is considered more applicable and that will be scanned first.
- Alternatively, an explicit search order can be passed in with the
- <literal>get</literal> lookups as an optional parameter.
- </para>
- </section>
-</chapter>
\ No newline at end of file
Deleted: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch09-Persistence.xml
===================================================================
--- jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch09-Persistence.xml 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch09-Persistence.xml 2008-09-12 16:04:50 UTC (rev 2219)
@@ -1,266 +0,0 @@
-<chapter id="persistence">
- <title>Persistence</title>
-
- <section>
- <title>Standard environment configuration</title>
- <para>This section describes how the environment can be configured to use
- hibernate in a standard Java environment.
- </para>
- <programlisting>01 | <contexts>
-02 |
-03 | <environment-factory>
-04 |<emphasis role="bold"> <hibernate-session-factory /></emphasis>
-05 |<emphasis role="bold"> <hibernate-configuration></emphasis>
-06 |<emphasis role="bold"> <properties resource="hibernate.properties" /></emphasis>
-07 |<emphasis role="bold"> <mappings resource="org/jbpm/pvm/pvm.hibernate.mappings.xml" /></emphasis>
-08 |<emphasis role="bold"> <cache-configuration </emphasis>
-09 |<emphasis role="bold"> resource="org/jbpm/pvm/pvm.cache.xml" </emphasis>
-10 |<emphasis role="bold"> usage="nonstrict-read-write" /></emphasis>
-11 |<emphasis role="bold"> </hibernate-configuration></emphasis>
-12 | </environment-factory>
-13 |
-14 | <block>
-15 |<emphasis role="bold"> <standard-transaction /></emphasis>
-16 |<emphasis role="bold"> <hibernate-session /></emphasis>
-17 |<emphasis role="bold"> <pvm-db-session /></emphasis>
-18 | </block>
-19 |
-20 | </contexts></programlisting>
- <para><literal>line 04</literal> specifies a hibernate session factory in the
- environment-factory context. This means that a hibernate session factory is lazy
- created when it is first needed and cached in the
- <literal>EnvironmentFactory</literal>.
- </para>
- <para>A hibernate session factory is build calling the
- method <literal>buildSessionFactory()</literal> on a hibernate configuration.
- By default, the hibernate configuration will be looked up by type.
- </para>
- <para><literal>line 05</literal> specifies a hibernate configuration.
- </para>
- <para><literal>line 06</literal> specifies the that the resource file
- <literal>hibernate.properties</literal> should be loaded into the configuration.
- </para>
- <para><literal>line 07</literal> (note the plural form of mapping<emphasis role="bold">s</emphasis>)
- specifies that resources <literal>org/jbpm/pvm/pvm.hibernate.mappings.xml</literal> contain references
- to hibernate mapping files or resources that should be included into the
- configuration. Also note the plural form of <literal>resources</literal>.
- This means that not one, but all the resource files on the whole classpath will be found.
- This way new library components containing a <literal>org/jbpm/pvm/pvm.hibernate.mappings.xml</literal>
- resource can plug automatically into the same hibernate session by just being added to
- the classpath.
- </para>
- <para>Alternatively, individual hibernate mapping files can be referenced with the
- singular <literal>mapping</literal> element.
- </para>
- <para><literal>line 08 - 10</literal> provide a single place to specify the
- hibernate caching strategy for all the PVM classes and collections.
- </para>
- <para><literal>line 15</literal> specifies a standard transaction. This is
- a very simple global transaction strategy without recovery that can be used
- in standard environments to get all-or-nothing semantics over multiple
- transactional resources.
- </para>
- <para><literal>line 16</literal> specifies the hibernate session that will
- automatically register itself with the standard transaction.
- </para>
- <para><literal>line 17</literal> specifies a <literal>PvmDbSession</literal>.
- That is a class that adds methods that bind to specific queries to be executed
- on the hibernate session.
- </para>
- </section>
-
- <section>
- <title>Standard hibernate configuration</title>
- <para>Here is a set of default properties to configure hibernate with
- hsqldb in a standard Java environment.
- </para>
- <programlisting>hibernate.dialect org.hibernate.dialect.HSQLDialect
-hibernate.connection.driver_class org.hsqldb.jdbcDriver
-hibernate.connection.url jdbc:hsqldb:mem:.
-hibernate.connection.username sa
-hibernate.connection.password
-hibernate.cache.use_second_level_cache true
-hibernate.cache.provider_class org.hibernate.cache.HashtableCacheProvider</programlisting>
- <para>Optionally in development the schema export can be used to
- create the schema when the session factory is created and drop the
- schema when the session factory is closed.
- </para>
- <programlisting>hibernate.hbm2ddl.auto create-drop</programlisting>
- <para>For more information about hibernate configurations, see the hibernate
- reference manual.
- </para>
- </section>
-
- <section>
- <title>Standard transaction</title>
- <para>By default, the <literal><hibernate-session /></literal> will
- start a hibernate transaction with <literal>session.beginTransaction()</literal>.
- Then the hibernate transaction is wrapped in a <literal>org.jbpm.pvm.internal.hibernate.HibernateTransactionResource</literal>
- and that resource is enlisted with the <literal><standard-transaction /></literal>
- (<literal>org.jbpm.tx.StandardTransaction</literal>)
- </para>
- <para>Inside of the environment block, the transaction is available
- through <literal>environment.getTransaction()</literal>. So inside an
- environment block, the transaction can be rolled back with
- <literal>environment.getTransaction().setRollbackOnly()</literal>
- </para>
- <para>When created, the standard transaction will register itself to be notified on the
- close of the environment. So in side the close, the standard transaction will
- commit or rollback depending on whether <literal>setRollbackOnly()</literal>
- was called.
- </para>
- <para>So in the configuration shown above, each environment block will be
- a separate transaction. At least, if the hibernate session is used.</para>
- </section>
-
- <section>
- <title>Basics of process persistence</title>
- <para>In the next example, we'll show how this hibernate persistence is
- used with a concrete example. The 'persistent process' is a simple
- three-step process:
- </para>
- <figure id="the.persistent.process">
- <title>The persistent process</title>
- <mediaobject><imageobject><imagedata align="center" fileref="images/ch09.persistent.process.png"/></imageobject></mediaobject>
- </figure>
- <para>The activities in the three nodes will be wait states just like
- in <xref linkend="externalactivityexample" />
- </para>
- <para>To make sure we can persist this class, we create the hibernate mapping for
- it and add it to the configuration like this:
- </para>
- <programlisting><hibernate-configuration>
- <properties resource="hibernate.properties" />
- <mappings resource="org/jbpm/pvm/pvm.hibernate.mappings.xml" />
- <emphasis role="bold"><mapping resource="org/jbpm/examples/ch09/state.hbm.xml" /></emphasis>
- <cache-configuration
- resource="org/jbpm/pvm/pvm.cache.xml"
- usage="nonstrict-read-write" /></programlisting>
- <para>The next code pieces show the contents of one unit test method. The method
- will first create the environment factory. Then, in a first transaction, a process
- definition will be created and saved into the database. Then the next transaction will
- create a new execution of that process. And the following two transactions will
- provide external triggers to the execution.
- </para>
- <programlisting>EnvironmentFactory environmentFactory = EnvironmentFactory.parse(new ResourceStreamSource(
- "org/jbpm/examples/ch09/environment.cfg.xml"
-));</programlisting>
- <para>Then in a first transaction, a process is created and saved in the database.
- This is typically referred to as deploying a process and it only needs to be done
- once.
- </para>
- <programlisting>Environment environment = environmentFactory.openEnvironment();
-try {
- PvmDbSession pvmDbSession = environment.get(PvmDbSession.class);
-
- ProcessDefinition processDefinition = ProcessFactory.build("persisted process")
- .node("one").initial().behaviour(new State())
- .transition().to("two")
- .node("two").behaviour(new State())
- .transition().to("three")
- .node("three").behaviour(new State())
- .done();
-
- pvmDbSession.save(processDefinition);
-} finally {
- environment.close();
-}</programlisting>
- <para>In the previous transaction, the process definition, the nodes and transitions
- will be inserted into the database tables.
- </para>
- <para>Next we'll show how a new process execution can be started for this
- process definition. Note that in this case, we provide <link linkend="businesskey">a
- business key</link> called 'first'. This will make it easy for us to retrieve
- the same execution from the database in subsequent transactions. After starting
- the new process execution, it will wait in node 'one' cause the behaviour is a
- wait state.
- </para>
- <programlisting>environment = environmentFactory.openEnvironment();
-try {
- PvmDbSession pvmDbSession = environment.get(PvmDbSession.class);
-
- ProcessDefinition processDefinition = pvmDbSession.findProcessDefinition("persisted process");
- assertNotNull(processDefinition);
-
- Execution execution = processDefinition.startExecution("first");
- assertEquals("one", execution.getNode().getName());
- pvmDbSession.save(execution);
-
-} finally {
- environment.close();
-}</programlisting>
- <para>In the previous transaction, a new execution record will be inserted into
- the database.
- </para>
- <para>Next we feed in an external trigger into this existing process execution.
- We load the execution, provide a signal and just save it back into the database.
- </para>
- <programlisting>environment = environmentFactory.openEnvironment();
-try {
- PvmDbSession pvmDbSession = environment.get(PvmDbSession.class);
-
- Execution execution = pvmDbSession.findExecution("persisted process", "first");
- assertNotNull(execution);
- assertEquals("one", execution.getNode().getName());
-
- // external trigger that will cause the execution to execute until
- // it reaches the next wait state
- execution.signal();
-
- assertEquals("two", execution.getNode().getName());
-
- pvmDbSession.save(execution);
-
-} finally {
- environment.close();
-}</programlisting>
- <para>The previous transaction will result in an update of the existing
- execution, reassigning the foreign key to reference another record in
- the node table.
- </para>
- <programlisting>UPDATE JBPM_EXECUTION
-SET
- NODE_=?,
- DBVERSION_=?,
- ...
-WHERE DBID_=?
- AND DBVERSION_=?</programlisting>
- <para>The version in this SQL shows the automatic optimistic locking that
- is baked into the PVM persistence so that process persistence can easily
- scale to multiple JVM's or multiple machines.
- </para>
- <para>In the example code, there is one more transaction that is
- completely similar to the previous which takes the execution from
- node 'two' to node 'three'.
- </para>
- <para>All of this shows that the PVM can move from one wait state to
- another wait state transactionally. Each transaction correcponds to
- a state transition.
- </para>
- <para>Note that in case of automatic activities, multiple activities
- will be executed before the execution reaches a wait state. Typically
- that is desired behaviour. In case the automatic activities take too
- long or you don't want to block the original transaction to wait for
- the completion of those automatic activities, check out <xref linkend="asynchronouscontinuations"/>
- to learn about how it's possible to demarcate transactions in the process
- definition, which can also be seen as safe-points during process execution.
- </para>
- </section>
-
- <section id="businesskey">
- <title>Business key</title>
- <para>TODO</para>
- </section>
-
-
- <para>TODO: General persistence architecture
- </para>
- <para>TODO: Object references
- </para>
- <para>TODO: Threads, concurrency with respect to forks and joins
- </para>
- <para>TODO: Caching
- </para>
- <para>TODO: Process instance migration
- </para>
-</chapter>
\ No newline at end of file
Deleted: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch11-AsynchronousContinuations.xml
===================================================================
--- jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch11-AsynchronousContinuations.xml 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch11-AsynchronousContinuations.xml 2008-09-12 16:04:50 UTC (rev 2219)
@@ -1,3 +0,0 @@
-<chapter id="asynchronouscontinuations">
- <title>Asynchronous continuations</title>
-</chapter>
Deleted: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch12-Timers.xml
===================================================================
--- jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch12-Timers.xml 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch12-Timers.xml 2008-09-12 16:04:50 UTC (rev 2219)
@@ -1,3 +0,0 @@
-<chapter id="timers">
- <title>Timers</title>
-</chapter>
\ No newline at end of file
Deleted: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch13-ProcessLanguages.xml
===================================================================
--- jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch13-ProcessLanguages.xml 2008-09-12 15:44:22 UTC (rev 2218)
+++ jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch13-ProcessLanguages.xml 2008-09-12 16:04:50 UTC (rev 2219)
@@ -1,19 +0,0 @@
-<chapter id="processlanguages">
- <title>Process languages</title>
-
- <para>TODO: xml parser infrastructure
- </para>
- <para>TODO: inherit from ProcessDefinitionImpl, ExecutionImpl
- </para>
- <para>TODO: overriding the default proceed()
- </para>
- <para>TODO: node type implementations
- </para>
- <para>TODO: persistence
- </para>
- <para>TODO: compensation: languages like bpel and bpnm define that
- as a normal contination that fits within the process
- structures available in the pvm (taking a transition and
- executing a nested node).
- </para>
-</chapter>
\ No newline at end of file
Copied: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-AdvancedGraphExecution.xml (from rev 2183, jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch04-AdvancedGraphExecution.xml)
===================================================================
--- jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-AdvancedGraphExecution.xml (rev 0)
+++ jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-AdvancedGraphExecution.xml 2008-09-12 16:04:50 UTC (rev 2219)
@@ -0,0 +1,297 @@
+<chapter id="advancedgraphexecution">
+ <title>Advanced graph execution</title>
+
+ <!-- ### LOOPS ########################################################## -->
+ <section>
+ <title>Loops</title>
+ <para>Loops can be based on transitions or on node 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. This means
+ that all the methods in the <literal>Execution</literal> class that propagate the
+ execution like <literal>take</literal> or <literal>execute</literal> will not be
+ executed when you call them. Instead, the method invocations will be appended to a list.
+ The first invocation of such a method will start a loop that will execute all invocations
+ till that list is empty. These invocations are called atomic operations.
+ </para>
+ </section>
+
+ <!-- ### SUB PROCESSES ################################################## -->
+ <section>
+ <title>Sub processes</title>
+ <para>TODO: sub processes</para>
+ </section>
+
+ <!-- ### DEFAULT PROCEED BEHAVIOUR ###################################### -->
+ <section id="defaultproceedbehaviour">
+ <title>Default proceed behaviour</title>
+ <para>When an <literal>Activity</literal> is used as node behaviour, it 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(Node)</literal></listitem>
+ <listitem><literal>createExecution(*)</literal></listitem>
+ </itemizedlist>
+ <para>When <literal>Activity</literal> implementations used for node behviour
+ don't call any of the following execution propagation methods, then, after
+ the activity is executed, the execution will just proceed.
+ </para>
+ <para>By default proceeding will perform the first action that applies
+ in the following list:</para>
+ <itemizedlist>
+ <listitem>If the current node has a default outgoing transition, take it.</listitem>
+ <listitem>If the current node has a parent node, move back to the parent node.</listitem>
+ <listitem>Otherwise, end this execution.</listitem>
+ </itemizedlist>
+ <para>Process languages can overwrite the default proceed behaviour
+ by overriding the <literal>proceed</literal> method in
+ <literal>ExecutionImpl</literal>.
+ </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 the <link linkend="architecture">asynchronous command service</link>.
+ </para>
+ <para>The next process will show the basics concretely. It has three wait states
+ and four automatic nodes.
+ </para>
+ <figure id="automatic">
+ <title>Process with many sequential automatic activities.</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/ch04.automatic.png"/></imageobject></mediaobject>
+ </figure>
+ <para>Here's how to build the process:</para>
+ <programlisting>ProcessDefinition processDefinition = ProcessFactory.build("automatic")
+ .<emphasis role="bold">node("wait 1").initial()</emphasis>.behaviour(new <emphasis role="bold">WaitState</emphasis>())
+ .transition().to("automatic 1")
+ .<emphasis role="bold">node("automatic 1")</emphasis>.behaviour(new <emphasis role="bold">Display("one")</emphasis>)
+ .transition().to("wait 2")
+ .<emphasis role="bold">node("wait 2")</emphasis>.behaviour(new <emphasis role="bold">WaitState</emphasis>())
+ .transition().to("automatic 2")
+ .<emphasis role="bold">node("automatic 2")</emphasis>.behaviour(new <emphasis role="bold">Display("two")</emphasis>)
+ .transition().to("automatic 3")
+ .<emphasis role="bold">node("automatic 3")</emphasis>.behaviour(new <emphasis role="bold">Display("three")</emphasis>)
+ .transition().to("automatic 4")
+ .<emphasis role="bold">node("automatic 4")</emphasis>.behaviour(new <emphasis role="bold">Display("four")</emphasis>)
+ .transition().to("wait 3")
+ .<emphasis role="bold">node("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>Execution execution = processDefinition.startExecution();</programlisting>
+ <para>Starting a new execution means that the initial node is executed. So if an automatic
+ activity would be configured as the behaviour in the initial node, the process will start executing
+ immediatly in the startExecution. In this case however, the initial node is a wait state. So
+ the startExecution method returns immediately and the execution will be positioned in the initial
+ node 'wait 1'.
+ </para>
+ <figure id="automatic.wait1">
+ <title>A new execution will be positioned in 'wait 1'.</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/ch04.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 introducing the WaitState, that signal will cause the default transition to be taken. The
+ transition will move the execution to node <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>. The signal method is still blocking
+ cause this action and the transitions are taken
+ by that same thread. 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 signal method.
+ </para>
+ <para>So when the signal method returns, the execution is positioned in <literal>wait 2</literal>.</para>
+ <figure id="automatic.wait2">
+ <title>One signal brought the execution from 'initial' to 'wait 2'.</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/ch04.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>To make executable processes, developers need to know exactly what the automatic activities,
+ 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.
+ This implies that on the level of the Process Virtual Machine, there is no differentiation
+ between complete process instances and paths of execution within a process instance.
+ One of the main motivations for this design is that the API actually is not made more
+ complex then necessary for simple processes with only one single path of execution.
+ </para>
+ <figure id="execution.structure">
+ <title>UML class diagram of the basic execution structure</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/ch04.execution.structure.classes.png"/></imageobject></mediaobject>
+ </figure>
+ <para>To extablish multiple concurrent paths of execution, child executions can be
+ created. 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/ch04.concurrency.png"/></imageobject></mediaobject>
+ </figure>
+ <para>There is a billing and a shipping path of execution. In this case, the
+ flat bar nodes represent nodes 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 node
+ <literal>bill</literal> and <literal>ship</literal> respectively.
+ </para>
+ <para>It's up to the node 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 node 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 <link linkend="delegationclasses">code that is associated to a process</link>
+ like Activity's, Actions and Conditions, it's possible to include try-catch blocks in
+ the method implementations to handle exceptions. 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 STATE_ACTIVE, then it is locked. A locked execution
+ is read only.
+ </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 node 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 node instance (aka activity instance) and is unique for every execution
+ of the node.
+ </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 node behaviour implementations whether they want
+ to take the overhead of locking and unlocking.
+ </para>
+ </section>
+
+</chapter>
Property changes on: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-AdvancedGraphExecution.xml
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:mergeinfo
+
Name: svn:eol-style
+ LF
Copied: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-AsynchronousContinuations.xml (from rev 2183, jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch11-AsynchronousContinuations.xml)
===================================================================
--- jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-AsynchronousContinuations.xml (rev 0)
+++ jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-AsynchronousContinuations.xml 2008-09-12 16:04:50 UTC (rev 2219)
@@ -0,0 +1,3 @@
+<chapter id="asynchronouscontinuations">
+ <title>Asynchronous continuations</title>
+</chapter>
Property changes on: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-AsynchronousContinuations.xml
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:mergeinfo
+
Name: svn:eol-style
+ LF
Copied: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-BasicGraphExecution.xml (from rev 2183, jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch03-BasicGraphExecution.xml)
===================================================================
--- jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-BasicGraphExecution.xml (rev 0)
+++ jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-BasicGraphExecution.xml 2008-09-12 16:04:50 UTC (rev 2219)
@@ -0,0 +1,553 @@
+<chapter id="basicgraphexecution">
+ <title>Basic graph execution</title>
+
+ <!-- ### Activity ####################################################### -->
+ <section id="activity">
+ <title>Activity</title>
+ <para>The PVM library doesn't have a fixed set of process constructs.
+ Instead, runtime behaviour of a node is delegated to an <literal>Activity</literal>.
+ In other words, <literal>Activity</literal> is an interface to implement the runtime
+ behaviour of process constructs in plain Java. Also, <literal>Activity</literal>
+ implementations can be subscrribed as listeners to
+ <link linkend="events">process events</link>.
+ </para>
+ <programlisting>public <emphasis role="bold">interface Activity</emphasis> extends Serializable {
+ void <emphasis role="bold">execute</emphasis>(Execution execution) throws Exception;
+}</programlisting>
+ <para><literal>Activity</literal>'s can be used as node behaviour and as listeners to process
+ events. When an activity is used as the node behaviour, it is in full control of the further
+ propagation of the execution. In other words, a node behaviour can decide what the execution
+ should do next. For example, it can take a transition
+ with <literal>execution.take(Transition)</literal>, go into a wait state with
+ <literal>execution.waitForSignal()</literal>. Or the node behaviour can not invoke
+ any of the above, in that case the Process Virtual Machine will just
+ <link linkend="defaultproceedbehaviour">proceed the execution in a default way</link>.
+ </para>
+ <para>Events are only fired during process execution. Since during an event the
+ execution is already 'in motion', event listeners can not control the propagation
+ of execution. Therefore, <literal>Activity</literal> implementations can only
+ be used as event listeners if they don't invoke any of the execution propagation
+ methods.
+ </para>
+ <para>This way, it is very easy to implement automatic activities that can be
+ used as node behaviour as well as event listeners. Examples of automatic activities
+ are sending an email, doing a database update, generating a pdf, calculating an average,
+ etc. All of these can be executed by the process system and they can be used both as
+ node behaviour as well as event listeners. In case they are used as node behaviour
+ they can rely on the default proceed behaviour.
+ </para>
+ </section>
+
+ <!-- ### Activity example ############################################### -->
+ <section id="activityexample">
+ <title>Activity 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">Activity</emphasis> {
+
+ String message;
+
+ public Display(String message) {
+ this.message = message;
+ }
+
+ public void execute(Execution 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>Activty example process</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/process.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting>ProcessDefinition processDefinition = ProcessFactory.build()
+ .<emphasis role="bold">node("a").initial()</emphasis>.behaviour(<emphasis role="bold">new Display("hello")</emphasis>)
+ .transition().to("b")
+ .<emphasis role="bold">node("b")</emphasis>.behaviour(<emphasis role="bold">new Display("world")</emphasis>)
+.done();</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>
+ </section>
+
+ <!-- ### ExternalActivity ############################################### -->
+ <section id="externalactivity">
+ <title>ExternalActivity</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>ExternalActivity</literal>
+ adds two methods to the <literal>Activity</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 node, the
+ <literal>execute</literal>-method of the node 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 node behaves as a wait state, then the execution will
+ wait in that node until the execution's <literal>signal</literal> method
+ is invoked. The execution will delegate that signal to the behaviour Activity
+ of the current node.
+ </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 node 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 ExternalActivity {
+
+ public void <emphasis role="bold">execute</emphasis>(Execution execution) {
+ execution.waitForSignal();
+ }
+
+ public void <emphasis role="bold">signal</emphasis>(Execution execution,
+ String signal,
+ Map<String, Object> parameters) {
+ execution.take(signal);
+ }
+}</programlisting>
+ <para>The <literal>execute</literal>-method calls
+ <literal>execution.waitForSignal()</literal>. This call is
+ necessary to prevent automatic propagation of the execution. By calling
+ <literal>execution.waitForSignal()</literal>, the node will
+ behave as a wait state.
+ </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 nodes will be WaitState's.
+ </para>
+ <figure id="process.diagram">
+ <title>Process diagram</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/process.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting>ProcessDefinition processDefinition = ProcessFactory.build()
+ .<emphasis role="bold">node("a").initial()</emphasis>.behaviour(<emphasis role="bold">new WaitState()</emphasis>)
+ .transition().to("b")
+ .<emphasis role="bold">node("b")</emphasis>.behaviour(<emphasis role="bold">new WaitState()</emphasis>)
+.done();</programlisting>
+
+<programlisting>Execution execution = processDefinition.startExecution();</programlisting>
+<programlisting>execution.signal();</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 is a simplified version of a loan approval process. Graphically,
+ it looks like this:
+ </para>
+ <figure id="the.first.graph.process">
+ <title>The first graph process</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/first.graph.process.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>ProcessDefinition processDefinition = ProcessFactory.build()
+ .<emphasis role="bold">node("accept loan request").initial()</emphasis>.behaviour(new WaitState())
+ .transition().to("loan evaluation")
+ .<emphasis role="bold">node("loan evaluation")</emphasis>.behaviour(new WaitState())
+ .transition("approve").to("wire the money")
+ .transition("reject").to("end")
+ .<emphasis role="bold">node("wire the money")</emphasis>.behaviour(new Display("automatic payment"))
+ .transition().to("end")
+ .<emphasis role="bold">node("end")</emphasis>.behaviour(new WaitState())
+.done();</programlisting>
+ <para>For more details about the ProcessFactory, see the javadocs. 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 node <literal>wire the money</literal> is an automatic node. The
+ <literal>Display</literal> implementation 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. All the other nodes are
+ wait states.
+ </para>
+ <para>A new execution for the process above can be started like this
+ </para>
+ <programlisting>Execution execution = processDefinition.startExecution();</programlisting>
+ <para>Starting a new execution implies that the initial node is executed. Since in
+ this case it's a wait state, the new execution will be positioned in the
+ node 'accept loan request' when the <literal>startExecution</literal>-method returns.
+ </para>
+ <figure id="first.execution.state.accept">
+ <title>Execution positioned in 'accept loan request'</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/execution.state.accept.png"/></imageobject></mediaobject>
+ </figure>
+ <para>Now we can give this execution an external trigger with the <literal>signal</literal>-
+ method on the execution. Invoking the signal method will take the execution to the next
+ wait state.
+ </para>
+ <programlisting>execution.signal();</programlisting>
+ <figure id="execution.state.evaluation">
+ <title>Execution positioned in 'loan evaluation'</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/execution.state.evaluation.png"/></imageobject></mediaobject>
+ </figure>
+ <para>Now, the execution is at an interesting point. There are two transitions out of
+ the state 'loan evaluation'. One transition is called 'approve' and one transition
+ is called 'reject'. As we explained above in the WaitState implementation, the transition
+ taken corresponds to the signal that is given. Let's feed in the 'approve' signal like this:
+ </para>
+ <programlisting>execution.signal("approve");</programlisting>
+ <para>The 'approve' signal will cause the execution to take the 'approve' transition and
+ it will arrive in the node 'wire the money'.
+ </para>
+ <para>In <literal>wire the 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 default behaviour will be to just proceed.
+ </para>
+ <para><link linkend="defaultproceedbehaviour">Proceeding</link> in this case means that
+ the default outgoing transition is taken and the execution will arrive in the <literal>end</literal>
+ node, which is a wait state.</para>
+ <para>So only when the <literal>end</literal> wait state is reached, the <literal>signal("approve")</literal>
+ returns. That is because all of the things that needed to be done between the original
+ state and this new state could be executed by the process system. Executing till the
+ next wait state is the default behaviour and that behaviour can be changed with
+ </para>
+ <para><emphasis role="bold">TODO: add link to async continuations</emphasis></para>
+ <para>asynchronous continuations in case
+ transactions should not include all calculations till the next wait state. For
+ more about this, see <xref linkend="executionandthreads" />.
+ </para>
+ <para>Another signal invocation will bring it eventually in the end state.</para>
+ <figure id="execution.state.end">
+ <title>Execution positioned in 'end'</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/execution.state.end.png"/></imageobject></mediaobject>
+ </figure>
+ </section>
+
+ <!-- ### MOTIVATION ##################################################### -->
+ <section id="motivation">
+ <title>Motivation</title>
+ <para>There are basically two forms of process languages: graph based and composite
+ process languages. First of all, this design supports both. Even graph based execution
+ and node composition can be used in combination to implement something like UML super states.
+ </para>
+ <para>In this design, control flow activity implementations will have to be
+ aware of whether they are dependent on transitions (graph based) or whether they are
+ using the composite node structure. The goal of this design is that all non-control
+ flow activities can be implemented in the same way so that you can use them in graph
+ based process languages as well as in composite process languages.
+ </para>
+ </section>
+
+ <!-- ### EVENTS ######################################################### -->
+ <section id="events">
+ <title>Events</title>
+ <para>Events are points in the process definition to which a list of
+ activities can be subscribed as listeners. 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>
+ <itemizedlist>
+ <listitem><literal>Transition.EVENT_TRANSITION_TAKE = "transition-take"</literal> :
+ fired on transitions when transitions are taken.
+ </listitem>
+ <listitem><literal>Node.EVENT_NODE_ENTER = "node-enter"</literal> : fired on the node
+ when execution enters that node. This happens when execution takes a transition
+ to that node, when a child node is being executed with <literal>execution.execute(Node)</literal>
+ or when a transition is taken from a node outside that node to a contained node.
+ The latter refers to super states in state machines.
+ </listitem>
+ <listitem><literal>Node.EVENT_NODE_LEAVE = "node-leave"</literal> : fired on the node
+ when a transition is taken out of that node or when a child node execution is
+ finished and the execution is propagated to the parent node.
+ </listitem>
+ <listitem><literal>ProcessDefinition.EVENT_PROCESS_START = "process-start"</literal> : fired on a process
+ when a new process is started.
+ </listitem>
+ <listitem><literal>ProcessDefinition.EVENT_PROCESS_END = "process-end"</literal> : fired on a process
+ when a new process is ended. This might include a executions that are ended
+ with a cancelled or error state.
+ </listitem>
+ </itemizedlist>
+ <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 <link linkend="activity"><literal>Activity</literal>s</link> can be associated to an
+ event. But activities on events can not influence the control flow of the execution since
+ they are merely listeners to an execution wich is already in progress. This is different from
+ activities that serve as the behaviour for nodes. Node behaviour activities are responsible
+ for propagating the execution. So if an activity in an event invokes any of the
+ following methods, then it will result in an exception.
+ </para>
+
+ <itemizedlist>
+ <listitem><literal>waitForSignal()</literal></listitem>
+ <listitem><literal>take(Transition)</literal></listitem>
+ <listitem><literal>end(*)</literal></listitem>
+ <listitem><literal>execute(Node)</literal></listitem>
+ </itemizedlist>
+
+ <para>We'll reuse the <literal><link linkend="activity">Display</link></literal>
+ activity from above in a simple process: two nodes connected by a
+ transition. The Display listener will be subscribed to the transition event.</para>
+ <figure id="action.process">
+ <title>The process to which a listener activity will be associated</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/process.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting>ProcessDefinition processDefinition = ProcessFactory.build()
+ .node("a").initial().behaviour(new WaitState())
+ <emphasis role="bold">.event("node-leave")
+ .listener(new Display("leaving a"))
+ .listener(new Display("second message while leaving a"))</emphasis>
+ .transition().to("b")
+ <emphasis role="bold">.listener(new Display("taking transition"))</emphasis>
+ .node("b").behaviour(new WaitState())
+ <emphasis role="bold">.event("node-enter")
+ .listener(new Display("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 nodes that get executed
+ for all events that occur within that process element. For example this feature
+ allows to register a listener on a process definition or a composite node on
+ <literal>node-leave</literal> events. Such action will be executed if that node is
+ left. And if that listener is registered on a composite node, it will also be executed
+ for all nodes that are left within that composite node.
+ </para>
+ <para>To show this clearly, we'll create a <literal>DisplaySource</literal> activity
+ 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 Activity {
+
+ public void execute(Execution 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 activity
+ itself should not be displayed in the diagram. A <literal>DisplaySource</literal> activity
+ will be added as a listener to the event <literal>node-leave</literal> on the composite node.
+ </para>
+ <para>The next process shows how the <literal>DisplaySource</literal> activity is registered
+ as a listener to to the 'node-leave' event on the <literal>composite</literal> node:</para>
+ <figure id="propagation.process">
+ <title>A process with an invisible activity on a node-leave event on a composite node.</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/propagation.process.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting>ProcessDefinition processDefinition = ProcessFactory.build("propagate")
+ .compositeNode("composite")
+ <emphasis role="bold">.event(Node.EVENT_NODE_LEAVE)
+ .listener(new DisplaySource())</emphasis>
+ .node("a").initial().behaviour(new WaitState())
+ .transition().to("b")
+ .node("b").behaviour(new WaitState())
+ .transition().to("c")
+ .compositeEnd()
+ .node("c").behaviour(new WaitState())
+.done();</programlisting>
+ <para>Next we'll start an execution.</para>
+ <programlisting>Execution execution = processDefinition.startExecution();</programlisting>
+ <para>After starting a new execution, the execution will be in node <literal>a</literal> as
+ that is the initial node. No nodes 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 node-leave event will be fired on node a. That event will be propagated to the
+ composite node and to the process definition. Since our propagation logger is placed
+ on node composite it will receive the event and print the following message:
+ </para>
+ <programlisting>leaving node(a)</programlisting>
+ <para>Another</para>
+ <programlisting>execution.signal();</programlisting>
+ <para>will take the transition from b to c. That will fire two node-leave events. One on
+ node b and one on node composite. So the following lines will be appended to the console
+ output:</para>
+ <programlisting>leaving node(b)
+leaving node(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 nodes. Each node can be a leaf node or it can be a
+ composite node, which means that it contains a list of nested nodes. Nested nodes
+ 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 nodes 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 nodes. Every node can have
+ a set of nested nodes. 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>. 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="propagation.disabled.process">
+ <title>A process with a listener to 'node-leave' events with propagation disabled.</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/propagation.process.png"/></imageobject></mediaobject>
+ </figure>
+ <para>Building the process with the process factory:
+ </para>
+ <programlisting>ProcessDefinition processDefinition = ProcessFactory.build("propagate")
+ .compositeNode("composite")
+ <emphasis role="bold">.event(Node.EVENT_NODE_LEAVE)
+ .listener(new DisplaySource())
+ .propagationDisabled()</emphasis>
+ .node("a").initial().behaviour(new WaitState())
+ .transition().to("b")
+ .node("b").behaviour(new WaitState())
+ .transition().to("c")
+ .nodesEnd()
+ .node("c").behaviour(new WaitState())
+.done();</programlisting>
+ <para>So when the first signal is given for this process, again the node-leave event will be
+ fired on node a, but now the listener on the composite node will not be executed cause
+ propagated events have been disabled. Disabling propagation is a property on the listener
+ and doesn't influence the other listeners. The event will always be fired and propagated
+ over the whole parent hierarchy.
+ </para>
+ <programlisting>Execution execution = processDefinition.startExecution();
+execution.signal();
+</programlisting>
+ <para>Next, the second signal will take the transition from b to c.
+ </para>
+ <programlisting>execution.signal()</programlisting>
+ <para>Again two node-leave
+ events are fired just like above on nodes b and composite respectively. The first event
+ is the node-leave event on node b. That will be propagated to the composite node. So the
+ listener will not be executed for this event cause it has propagation disabled. But the
+ listener will be executed for the node-leave event on the composite node. That is not
+ propagated, but fired directly on the composite node. So the listener will now be executed
+ only once for the composite node as shown in the following console output:
+ </para>
+ <programlisting>leaving node(composite)</programlisting>
+ </section>
+
+ <!-- ### PROCESS STRUCTURE ############################################## -->
+ <section>
+ <title>Process structure</title>
+ <para>Above we already touched briefly on the two main process constructs:
+ Nodes, transitions and node composition. This section will elaborate
+ on all the basic combination possibilities.
+ </para>
+ <figure id="process.structure">
+ <title>UML class diagram of the basic process structure</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/process.structure.classes.png"/></imageobject></mediaobject>
+ </figure>
+ <para>Next is a series of example diagram structures that can be formed
+ with the PVM process model.
+ </para>
+ <figure id="transition">
+ <title>Any two nodes 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.node">
+ <title>Composite node is a list of nested nodes.</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/composite.node.png"/></imageobject></mediaobject>
+ </figure>
+ <figure id="transition.into.composite">
+ <title>Transition to a node 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 node inside a composite to a node 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 nodes are inherited. The node inside can take the transition of the composite node.</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/transition.inheritence.png"/></imageobject></mediaobject>
+ </figure>
+ <figure id="transition.to.outer">
+ <title>Transition from a node 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 node to an inner composed node.</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/transition.to.inner.png"/></imageobject></mediaobject>
+ </figure>
+ <figure id="initial.in.composite">
+ <title>An initial node inside a composite node.</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/initial.in.composite.png"/></imageobject></mediaobject>
+ </figure>
+ </section>
+
+</chapter>
Property changes on: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-BasicGraphExecution.xml
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:mergeinfo
+
Name: svn:eol-style
+ LF
Copied: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-DelegationClasses.xml (from rev 2183, jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch05-DelegationClasses.xml)
===================================================================
--- jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-DelegationClasses.xml (rev 0)
+++ jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-DelegationClasses.xml 2008-09-12 16:04:50 UTC (rev 2219)
@@ -0,0 +1,53 @@
+<chapter id="delegationclasses">
+ <title>Delegation classes</title>
+
+ <section>
+ <title>What are delegation classes</title>
+ <para>Delegation classes are the classes that implement
+ <literal>Activity</literal> or <literal>Condition</literal>. From the Process
+ Virtual Machine's perspective, these are external classes that provide
+ programming logic that is inserted into the PVM's graph execution.
+ Delegation classes can be provided by the process languages as well
+ as by the end users.
+ </para>
+ </section>
+
+ <section>
+ <title>Configuration of delegation classes</title>
+ <para>Delegation classes can be made configurable. Member fields can
+ contain configuration parameters so that a delegation class can be
+ configured differently each time it is used. For example, in the
+ <literal><link linkend="activity">Display</link></literal> activity,
+ the message that is to be printed to the console is a configuration
+ parameter.
+ </para>
+ <para>Delegation classes should be stateless. This means that executing the interface
+ methods should not change values of the member fields. Changing member field values
+ of delegation classes during execution methods is actually changing the process
+ while it's executing. That is not threadsafe and usually leads to unexpected
+ results. As an exception, getters and setters might be made available to inject
+ the configuration cause they are used before the delegation object is actually
+ used in the process execution.
+ </para>
+ </section>
+
+ <section>
+ <title>Object references</title>
+ <para>TODO</para>
+ </section>
+
+ <section>
+ <title>Design time versus runtime</title>
+ <para>TODO: the node behaviour allows for design time as well as runtime behaviour.</para>
+ </section>
+
+ <section>
+ <title>UserCodeInterceptor</title>
+ <para>TODO: UserCodeInterceptor</para>
+ </section>
+
+ <section>
+ <title>Member field configurations versus properties</title>
+ <para>TODO: document field configurations versus properties</para>
+ </section>
+</chapter>
\ No newline at end of file
Property changes on: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-DelegationClasses.xml
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:mergeinfo
+
Name: svn:eol-style
+ LF
Copied: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-Environment.xml (from rev 2183, jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch08-Environment.xml)
===================================================================
--- jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-Environment.xml (rev 0)
+++ jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-Environment.xml 2008-09-12 16:04:50 UTC (rev 2219)
@@ -0,0 +1,139 @@
+<chapter id="environment">
+ <title>Environment</title>
+
+ <section>
+ <title>Introduction</title>
+ <para>The environment component together with the wire context is a kind of
+ Inversion of Control (IoC) container. It reads configuration information that
+ describes how objects should be instantiated, configured and wired together.
+ </para>
+ <para>The environment is used to retrieve resources and services needed by
+ <literal>Activity</literal> implementations and the Process Virtual Machine
+ itself. The main purpose is to make various aspects of the Process Virtual Machine
+ configurable so that the PVM and the languages that run on top can work
+ in a standard Java environment as well as an enterprise Java environment.
+ </para>
+ <para>The environment is partitioned into a set of contexts. Each context
+ can have its own lifecycle. For instance, the environment-factory context will
+ strech over the full lifetime of the application. The block context only
+ for the duration of a try-finally block. Typically a block context represents
+ a database transaction. Each context exposes a list of key-value
+ pairs.
+ </para>
+ </section>
+
+ <section id="environmentfactory">
+ <title>EnvironmentFactory</title>
+ <para>To start working with an environment, you need an EnvironmentFactory.
+ One single environment factory object can be used throughout the complete
+ lifetime of the application. So typically this is kept in a static
+ member field. The EnvironmentFactory itself is the environment-factory context.
+ </para>
+ <para>An <literal>EnvironmentFactory</literal> is typically obtained by
+ parsing a configuration file like this:
+ </para>
+ <programlisting>static EnvironmentFactory environmentFactory =
+ EnvironmentFactory.parse(new ResourceStreamSource("pvm.cfg.xml");</programlisting>
+ <para>See javadocs package org.jbpm.stream for more types of stream sources.
+ </para>
+ <para>There is a default parser in the environment factory that will
+ create <literal>DefaultEnvironmentFactory</literal>s. The idea is that we'll
+ also support spring as an IoC container. But that is still TODO. Feel free
+ to help us out :-). The parser can be configured with the static setter
+ method <literal>EnvironmentFactory.setParser(Parser)</literal>
+ </para>
+ </section>
+
+ <section id="environmentblock">
+ <title>Environment block</title>
+ <para>An environment exists for the duration of a try-finally block. This is how
+ an environment block looks like:
+ </para>
+ <programlisting><emphasis role="bold">Environment environment = environmentFactory.openEnvironment();
+try {
+
+ ...
+
+} finally {
+ environment.close();
+}</emphasis></programlisting>
+ <para>The environment block defines another lifespan: the <literal>block</literal> context.
+ A transaction would be a typical example of an object that is defined in the block
+ context.
+ </para>
+ <para>Inside such a block, objects can be looked up from the environment by name
+ or by type. If objects can looked up from the environment with method
+ <literal>environment.get(String name)</literal> or
+ <literal><T> T environment.get(Class<T>)</literal>.
+ </para>
+ <para>when an environment is created, it has a <literal>environment-factory</literal> context
+ and a <literal>block</literal>
+ context.
+ </para>
+ <para>In the default implementation, the <literal>environment-factory</literal> context and
+ the <literal>block</literal> context are <literal>WireContext</literal>s. A
+ <literal>WireContext</literal> contains a description of how its objects are
+ created and wired together to form object graphs.
+ </para>
+ </section>
+
+ <section>
+ <title>Example</title>
+ <para>To start with a simple example, we'll need a <literal>Book</literal>:</para>
+ <programlisting>public class <emphasis role="bold">Book</emphasis> {
+ ...
+ public Book() {}
+ ...
+}</programlisting>
+ <para>Then let's create an environment factory that knows how to create book</para>
+ <programlisting>static EnvironmentFactory environmentFactory = EnvironmentFactory.parseXmlString(
+ "<contexts>" +
+ " <environment-factory>" +
+ " <object name='book' class='org.jbpm.examples.ch09.Book' />" +
+ " </environment-factory>" +
+ "</contexts>"
+));</programlisting>
+ <para>Now we'll create an environment block with this environment factory and
+ we'll look up the book in the environment. First the lookup is done by
+ type and secondly by name.
+ </para>
+ <programlisting>Environment environment = environmentFactory.openEnvironment();
+try {
+
+ Book book = <emphasis role="bold">environment.get(Book.class);</emphasis>
+ assertNotNull(book);
+
+ assertSame(book, <emphasis role="bold">environment.get("book")</emphasis>);
+
+} finally {
+ environment.close();
+}</programlisting>
+ <para>To prevent that you have to pass the environment as a parameter in
+ all methods, the current environment is maintained in a threadlocal stack:
+ </para>
+ <programlisting>Environment environment = Environment.getCurrent();</programlisting>
+ </section>
+
+ <section id="context">
+ <title>Context</title>
+ <para>Contexts can be added and removed dynamically. Anything can be exposed
+ as a <literal>Context</literal>.
+ </para>
+ <programlisting>public interface <emphasis role="bold">Context</emphasis> {
+
+ <emphasis role="bold">Object get(String key);
+ <T> T get(Class<T> type);
+ Set<String> keys();</emphasis>
+
+ ...
+}</programlisting>
+ <para>When doing a lookup on the environment, there is a default search order
+ in which the contexts will be scanned for the requested object. The default
+ order is the inverse of the sequence in which the contexts were added. E.g.
+ if an object is defined in both the environment-factory context and in the block context,
+ the block context is considered more applicable and that will be scanned first.
+ Alternatively, an explicit search order can be passed in with the
+ <literal>get</literal> lookups as an optional parameter.
+ </para>
+ </section>
+</chapter>
\ No newline at end of file
Property changes on: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-Environment.xml
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:mergeinfo
+
Name: svn:eol-style
+ LF
Copied: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-History.xml (from rev 2183, jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch07-History.xml)
===================================================================
--- jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-History.xml (rev 0)
+++ jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-History.xml 2008-09-12 16:04:50 UTC (rev 2219)
@@ -0,0 +1,15 @@
+<chapter id="history">
+ <title>History</title>
+
+ <section id="processlogs">
+ <title>Process logs</title>
+ </section>
+
+ <section id="businessintelligence">
+ <title>Business Intelligence (BI)</title>
+ </section>
+
+ <section id="businessactivitymonitoring">
+ <title>Business Activity Monitoring (BAM)</title>
+ </section>
+</chapter>
\ No newline at end of file
Property changes on: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-History.xml
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:mergeinfo
+
Name: svn:eol-style
+ LF
Copied: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-Persistence.xml (from rev 2183, jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch09-Persistence.xml)
===================================================================
--- jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-Persistence.xml (rev 0)
+++ jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-Persistence.xml 2008-09-12 16:04:50 UTC (rev 2219)
@@ -0,0 +1,266 @@
+<chapter id="persistence">
+ <title>Persistence</title>
+
+ <section>
+ <title>Standard environment configuration</title>
+ <para>This section describes how the environment can be configured to use
+ hibernate in a standard Java environment.
+ </para>
+ <programlisting>01 | <contexts>
+02 |
+03 | <environment-factory>
+04 |<emphasis role="bold"> <hibernate-session-factory /></emphasis>
+05 |<emphasis role="bold"> <hibernate-configuration></emphasis>
+06 |<emphasis role="bold"> <properties resource="hibernate.properties" /></emphasis>
+07 |<emphasis role="bold"> <mappings resource="org/jbpm/pvm/pvm.hibernate.mappings.xml" /></emphasis>
+08 |<emphasis role="bold"> <cache-configuration </emphasis>
+09 |<emphasis role="bold"> resource="org/jbpm/pvm/pvm.cache.xml" </emphasis>
+10 |<emphasis role="bold"> usage="nonstrict-read-write" /></emphasis>
+11 |<emphasis role="bold"> </hibernate-configuration></emphasis>
+12 | </environment-factory>
+13 |
+14 | <block>
+15 |<emphasis role="bold"> <standard-transaction /></emphasis>
+16 |<emphasis role="bold"> <hibernate-session /></emphasis>
+17 |<emphasis role="bold"> <pvm-db-session /></emphasis>
+18 | </block>
+19 |
+20 | </contexts></programlisting>
+ <para><literal>line 04</literal> specifies a hibernate session factory in the
+ environment-factory context. This means that a hibernate session factory is lazy
+ created when it is first needed and cached in the
+ <literal>EnvironmentFactory</literal>.
+ </para>
+ <para>A hibernate session factory is build calling the
+ method <literal>buildSessionFactory()</literal> on a hibernate configuration.
+ By default, the hibernate configuration will be looked up by type.
+ </para>
+ <para><literal>line 05</literal> specifies a hibernate configuration.
+ </para>
+ <para><literal>line 06</literal> specifies the that the resource file
+ <literal>hibernate.properties</literal> should be loaded into the configuration.
+ </para>
+ <para><literal>line 07</literal> (note the plural form of mapping<emphasis role="bold">s</emphasis>)
+ specifies that resources <literal>org/jbpm/pvm/pvm.hibernate.mappings.xml</literal> contain references
+ to hibernate mapping files or resources that should be included into the
+ configuration. Also note the plural form of <literal>resources</literal>.
+ This means that not one, but all the resource files on the whole classpath will be found.
+ This way new library components containing a <literal>org/jbpm/pvm/pvm.hibernate.mappings.xml</literal>
+ resource can plug automatically into the same hibernate session by just being added to
+ the classpath.
+ </para>
+ <para>Alternatively, individual hibernate mapping files can be referenced with the
+ singular <literal>mapping</literal> element.
+ </para>
+ <para><literal>line 08 - 10</literal> provide a single place to specify the
+ hibernate caching strategy for all the PVM classes and collections.
+ </para>
+ <para><literal>line 15</literal> specifies a standard transaction. This is
+ a very simple global transaction strategy without recovery that can be used
+ in standard environments to get all-or-nothing semantics over multiple
+ transactional resources.
+ </para>
+ <para><literal>line 16</literal> specifies the hibernate session that will
+ automatically register itself with the standard transaction.
+ </para>
+ <para><literal>line 17</literal> specifies a <literal>PvmDbSession</literal>.
+ That is a class that adds methods that bind to specific queries to be executed
+ on the hibernate session.
+ </para>
+ </section>
+
+ <section>
+ <title>Standard hibernate configuration</title>
+ <para>Here is a set of default properties to configure hibernate with
+ hsqldb in a standard Java environment.
+ </para>
+ <programlisting>hibernate.dialect org.hibernate.dialect.HSQLDialect
+hibernate.connection.driver_class org.hsqldb.jdbcDriver
+hibernate.connection.url jdbc:hsqldb:mem:.
+hibernate.connection.username sa
+hibernate.connection.password
+hibernate.cache.use_second_level_cache true
+hibernate.cache.provider_class org.hibernate.cache.HashtableCacheProvider</programlisting>
+ <para>Optionally in development the schema export can be used to
+ create the schema when the session factory is created and drop the
+ schema when the session factory is closed.
+ </para>
+ <programlisting>hibernate.hbm2ddl.auto create-drop</programlisting>
+ <para>For more information about hibernate configurations, see the hibernate
+ reference manual.
+ </para>
+ </section>
+
+ <section>
+ <title>Standard transaction</title>
+ <para>By default, the <literal><hibernate-session /></literal> will
+ start a hibernate transaction with <literal>session.beginTransaction()</literal>.
+ Then the hibernate transaction is wrapped in a <literal>org.jbpm.pvm.internal.hibernate.HibernateTransactionResource</literal>
+ and that resource is enlisted with the <literal><standard-transaction /></literal>
+ (<literal>org.jbpm.tx.StandardTransaction</literal>)
+ </para>
+ <para>Inside of the environment block, the transaction is available
+ through <literal>environment.getTransaction()</literal>. So inside an
+ environment block, the transaction can be rolled back with
+ <literal>environment.getTransaction().setRollbackOnly()</literal>
+ </para>
+ <para>When created, the standard transaction will register itself to be notified on the
+ close of the environment. So in side the close, the standard transaction will
+ commit or rollback depending on whether <literal>setRollbackOnly()</literal>
+ was called.
+ </para>
+ <para>So in the configuration shown above, each environment block will be
+ a separate transaction. At least, if the hibernate session is used.</para>
+ </section>
+
+ <section>
+ <title>Basics of process persistence</title>
+ <para>In the next example, we'll show how this hibernate persistence is
+ used with a concrete example. The 'persistent process' is a simple
+ three-step process:
+ </para>
+ <figure id="the.persistent.process">
+ <title>The persistent process</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/ch09.persistent.process.png"/></imageobject></mediaobject>
+ </figure>
+ <para>The activities in the three nodes will be wait states just like
+ in <xref linkend="externalactivityexample" />
+ </para>
+ <para>To make sure we can persist this class, we create the hibernate mapping for
+ it and add it to the configuration like this:
+ </para>
+ <programlisting><hibernate-configuration>
+ <properties resource="hibernate.properties" />
+ <mappings resource="org/jbpm/pvm/pvm.hibernate.mappings.xml" />
+ <emphasis role="bold"><mapping resource="org/jbpm/examples/ch09/state.hbm.xml" /></emphasis>
+ <cache-configuration
+ resource="org/jbpm/pvm/pvm.cache.xml"
+ usage="nonstrict-read-write" /></programlisting>
+ <para>The next code pieces show the contents of one unit test method. The method
+ will first create the environment factory. Then, in a first transaction, a process
+ definition will be created and saved into the database. Then the next transaction will
+ create a new execution of that process. And the following two transactions will
+ provide external triggers to the execution.
+ </para>
+ <programlisting>EnvironmentFactory environmentFactory = EnvironmentFactory.parse(new ResourceStreamSource(
+ "org/jbpm/examples/ch09/environment.cfg.xml"
+));</programlisting>
+ <para>Then in a first transaction, a process is created and saved in the database.
+ This is typically referred to as deploying a process and it only needs to be done
+ once.
+ </para>
+ <programlisting>Environment environment = environmentFactory.openEnvironment();
+try {
+ PvmDbSession pvmDbSession = environment.get(PvmDbSession.class);
+
+ ProcessDefinition processDefinition = ProcessFactory.build("persisted process")
+ .node("one").initial().behaviour(new State())
+ .transition().to("two")
+ .node("two").behaviour(new State())
+ .transition().to("three")
+ .node("three").behaviour(new State())
+ .done();
+
+ pvmDbSession.save(processDefinition);
+} finally {
+ environment.close();
+}</programlisting>
+ <para>In the previous transaction, the process definition, the nodes and transitions
+ will be inserted into the database tables.
+ </para>
+ <para>Next we'll show how a new process execution can be started for this
+ process definition. Note that in this case, we provide <link linkend="businesskey">a
+ business key</link> called 'first'. This will make it easy for us to retrieve
+ the same execution from the database in subsequent transactions. After starting
+ the new process execution, it will wait in node 'one' cause the behaviour is a
+ wait state.
+ </para>
+ <programlisting>environment = environmentFactory.openEnvironment();
+try {
+ PvmDbSession pvmDbSession = environment.get(PvmDbSession.class);
+
+ ProcessDefinition processDefinition = pvmDbSession.findProcessDefinition("persisted process");
+ assertNotNull(processDefinition);
+
+ Execution execution = processDefinition.startExecution("first");
+ assertEquals("one", execution.getNode().getName());
+ pvmDbSession.save(execution);
+
+} finally {
+ environment.close();
+}</programlisting>
+ <para>In the previous transaction, a new execution record will be inserted into
+ the database.
+ </para>
+ <para>Next we feed in an external trigger into this existing process execution.
+ We load the execution, provide a signal and just save it back into the database.
+ </para>
+ <programlisting>environment = environmentFactory.openEnvironment();
+try {
+ PvmDbSession pvmDbSession = environment.get(PvmDbSession.class);
+
+ Execution execution = pvmDbSession.findExecution("persisted process", "first");
+ assertNotNull(execution);
+ assertEquals("one", execution.getNode().getName());
+
+ // external trigger that will cause the execution to execute until
+ // it reaches the next wait state
+ execution.signal();
+
+ assertEquals("two", execution.getNode().getName());
+
+ pvmDbSession.save(execution);
+
+} finally {
+ environment.close();
+}</programlisting>
+ <para>The previous transaction will result in an update of the existing
+ execution, reassigning the foreign key to reference another record in
+ the node table.
+ </para>
+ <programlisting>UPDATE JBPM_EXECUTION
+SET
+ NODE_=?,
+ DBVERSION_=?,
+ ...
+WHERE DBID_=?
+ AND DBVERSION_=?</programlisting>
+ <para>The version in this SQL shows the automatic optimistic locking that
+ is baked into the PVM persistence so that process persistence can easily
+ scale to multiple JVM's or multiple machines.
+ </para>
+ <para>In the example code, there is one more transaction that is
+ completely similar to the previous which takes the execution from
+ node 'two' to node 'three'.
+ </para>
+ <para>All of this shows that the PVM can move from one wait state to
+ another wait state transactionally. Each transaction correcponds to
+ a state transition.
+ </para>
+ <para>Note that in case of automatic activities, multiple activities
+ will be executed before the execution reaches a wait state. Typically
+ that is desired behaviour. In case the automatic activities take too
+ long or you don't want to block the original transaction to wait for
+ the completion of those automatic activities, check out <xref linkend="asynchronouscontinuations"/>
+ to learn about how it's possible to demarcate transactions in the process
+ definition, which can also be seen as safe-points during process execution.
+ </para>
+ </section>
+
+ <section id="businesskey">
+ <title>Business key</title>
+ <para>TODO</para>
+ </section>
+
+
+ <para>TODO: General persistence architecture
+ </para>
+ <para>TODO: Object references
+ </para>
+ <para>TODO: Threads, concurrency with respect to forks and joins
+ </para>
+ <para>TODO: Caching
+ </para>
+ <para>TODO: Process instance migration
+ </para>
+</chapter>
\ No newline at end of file
Property changes on: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-Persistence.xml
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:mergeinfo
+
Name: svn:eol-style
+ LF
Copied: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-ProcessLanguages.xml (from rev 2183, jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch13-ProcessLanguages.xml)
===================================================================
--- jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-ProcessLanguages.xml (rev 0)
+++ jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-ProcessLanguages.xml 2008-09-12 16:04:50 UTC (rev 2219)
@@ -0,0 +1,19 @@
+<chapter id="processlanguages">
+ <title>Process languages</title>
+
+ <para>TODO: xml parser infrastructure
+ </para>
+ <para>TODO: inherit from ProcessDefinitionImpl, ExecutionImpl
+ </para>
+ <para>TODO: overriding the default proceed()
+ </para>
+ <para>TODO: node type implementations
+ </para>
+ <para>TODO: persistence
+ </para>
+ <para>TODO: compensation: languages like bpel and bpnm define that
+ as a normal contination that fits within the process
+ structures available in the pvm (taking a transition and
+ executing a nested node).
+ </para>
+</chapter>
\ No newline at end of file
Property changes on: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-ProcessLanguages.xml
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:mergeinfo
+
Name: svn:eol-style
+ LF
Copied: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-Services.xml (from rev 2183, jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch04-Services.xml)
===================================================================
--- jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-Services.xml (rev 0)
+++ jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-Services.xml 2008-09-12 16:04:50 UTC (rev 2219)
@@ -0,0 +1,82 @@
+<chapter id="services">
+ <title>Services</title>
+
+ <para>Services can be fetched from the EnvironmentFactory, which in it's turn
+ can be created from a configuration file.
+ </para>
+
+ <programlisting>EnvironmentFactory environmentFactory = new PvmEnvironmentFactory("pvm.cfg.xml");
+ProcessService processService = environmentFactory.get(ProcessService.class);</programlisting>
+
+ <para>Services are thread safe so only 1 single service object should be maintained
+ by the application and it can serve all requests for the application.
+ </para>
+
+
+
+ <section id="architecture">
+ <title>Architecture</title>
+ <para>Service methods are implemented through command classes.
+ Each method creates a command object and the command is executed with
+ the <literal>execute</literal> method of the <literal>CommandService</literal>.
+ The <literal>CommandService</literal> is responsible for setting up the
+ environment.
+ </para>
+ <para>There are four command services:
+ </para>
+ <itemizedlist>
+ <listitem><literal>command-service</literal> will just
+ execute the command and pass in the current environment.</listitem>
+ <listitem>(UNTESTED) <literal>async-command-service</literal> will send an
+ asynchronous message. So right after that in a separate transaction,
+ the message is consumed and the command is executed.</listitem>
+ <listitem>(TODO) <literal>cmt-command-service</literal> will delegate
+ execution of the command to a local SLSB that has transaction attribute
+ <literal>required</literal>.</listitem>
+ <listitem>(TODO) <literal>remote-command-service</literal> will delegate
+ execution of the command to a remote SLSB.</listitem>
+ </itemizedlist>
+ <para>Each of the command services can be configured with a list of
+ interceptors that span around the command execution. Following
+ interceptors are available:</para>
+ <itemizedlist>
+ <listitem><literal>environment-interceptor</literal>: Will execute the
+ command within an <link linkend="environmentblock">environment block</link>.
+ </listitem>
+ <listitem>(UNTESTED) <literal>authorization-interceptor</literal>: Will perform
+ an authrorization check before the command is executed. The
+ authorization interceptor will look up the AuthorizationSession
+ from the environment to delegate the actual authorization check to.
+ </listitem>
+ <listitem><literal>retry-interceptor</literal>: Will catch hibernate's
+ optmistic locking exceptions (StaleStateException) and retries
+ to execute the command for a configurable number of times
+ </listitem>
+ <listitem><literal>transaction-interceptor</literal>: Will get
+ the transaction from the current context and invoke
+ setRollbackOnly() on it in case an exception comes out of
+ the command execution.
+ </listitem>
+ </itemizedlist>
+ <para>Following configuration can be used in default standard persistence
+ situations:
+ </para>
+ <programlisting><contexts>
+ <environment-factory>
+
+ <pvm-service />
+
+ <command-service>
+ <retry-interceptor />
+ <environment-interceptor />
+ <transaction-interceptor />
+ </command-service>
+
+ ...
+ </environment-factory>
+ ...
+
+</contexts></programlisting>
+ </section>
+
+</chapter>
\ No newline at end of file
Copied: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-Timers.xml (from rev 2183, jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch12-Timers.xml)
===================================================================
--- jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-Timers.xml (rev 0)
+++ jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-Timers.xml 2008-09-12 16:04:50 UTC (rev 2219)
@@ -0,0 +1,3 @@
+<chapter id="timers">
+ <title>Timers</title>
+</chapter>
\ No newline at end of file
Property changes on: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-Timers.xml
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:mergeinfo
+
Name: svn:eol-style
+ LF
Copied: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-Variables.xml (from rev 2183, jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/ch06-Variables.xml)
===================================================================
--- jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-Variables.xml (rev 0)
+++ jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-Variables.xml 2008-09-12 16:04:50 UTC (rev 2219)
@@ -0,0 +1,3 @@
+<chapter id="variables">
+ <title>Variables</title>
+</chapter>
\ No newline at end of file
Property changes on: jbpm4/pvm/trunk/modules/manual/src/main/docbook/en/modules/chxx-Variables.xml
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:mergeinfo
+
Name: svn:eol-style
+ LF
More information about the jbpm-commits
mailing list