[jbpm-commits] JBoss JBPM SVN: r4875 - in jbpm4/trunk/modules: examples/src/test/java/org/jbpm/examples/async and 17 other directories.
do-not-reply at jboss.org
do-not-reply at jboss.org
Sat May 23 06:38:46 EDT 2009
Author: tom.baeyens at jboss.com
Date: 2009-05-23 06:38:45 -0400 (Sat, 23 May 2009)
New Revision: 4875
Added:
jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/async/eventlistener/
jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/async/eventlistener/AsyncEventListenerTest.java
jbpm4/trunk/modules/examples/src/test/resources/org/jbpm/examples/async/eventlistener/
jbpm4/trunk/modules/examples/src/test/resources/org/jbpm/examples/async/eventlistener/process.jpdl.xml
jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/model/op/ExecuteEventListenerMessage.java
Modified:
jbpm4/trunk/modules/api/src/main/resources/jpdl-4.0.xsd
jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/async/activity/Application.java
jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/async/fork/Application.java
jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/async/fork/AsyncForkTest.java
jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/hql/HqlTest.java
jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/mail/inline/InlineMailTest.java
jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/mail/template/TemplateMailTest.java
jbpm4/trunk/modules/examples/src/test/resources/org/jbpm/examples/mail/inline/process.jpdl.xml
jbpm4/trunk/modules/examples/src/test/resources/org/jbpm/examples/mail/template/process.jpdl.xml
jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/activity/JoinActivity.java
jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/activity/JoinBinding.java
jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/activity/MailActivity.java
jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/xml/JpdlParser.java
jbpm4/trunk/modules/jpdl/src/main/resources/jbpm.jpdl.eventlisteners.xml
jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/model/ActivityImpl.java
jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/model/op/ExecuteEventListener.java
jbpm4/trunk/modules/pvm/src/main/resources/jbpm.execution.hbm.xml
jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch05-Jpdl.xml
Log:
JBPM-2256 async event listeners
Modified: jbpm4/trunk/modules/api/src/main/resources/jpdl-4.0.xsd
===================================================================
--- jbpm4/trunk/modules/api/src/main/resources/jpdl-4.0.xsd 2009-05-22 14:06:47 UTC (rev 4874)
+++ jbpm4/trunk/modules/api/src/main/resources/jpdl-4.0.xsd 2009-05-23 10:38:45 UTC (rev 4875)
@@ -239,6 +239,18 @@
<element ref="tns:transition" minOccurs="0" maxOccurs="unbounded" />
</sequence>
<attributeGroup ref="tns:activityAttributes" />
+ <attribute name="multiplicity" type="int" />
+ <attribute name="lockmode" default="upgrade">
+ <simpleType>
+ <restriction base="string">
+ <enumeration value="none"/>
+ <enumeration value="read"/>
+ <enumeration value="upgrade"/>
+ <enumeration value="upgrade_nowait"/>
+ <enumeration value="write"/>
+ </restriction>
+ </simpleType>
+ </attribute>
</complexType>
</element>
Modified: jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/async/activity/Application.java
===================================================================
--- jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/async/activity/Application.java 2009-05-22 14:06:47 UTC (rev 4874)
+++ jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/async/activity/Application.java 2009-05-23 10:38:45 UTC (rev 4875)
@@ -28,8 +28,10 @@
public class Application {
public void generatePdf() {
+ // assume long automatic calculations here
}
public void calculatePrimes() {
+ // assume long automatic calculations here
}
}
Added: jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/async/eventlistener/AsyncEventListenerTest.java
===================================================================
--- jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/async/eventlistener/AsyncEventListenerTest.java (rev 0)
+++ jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/async/eventlistener/AsyncEventListenerTest.java 2009-05-23 10:38:45 UTC (rev 4875)
@@ -0,0 +1,76 @@
+/*
+ * 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.examples.async.eventlistener;
+
+import java.io.IOException;
+
+import javax.mail.MessagingException;
+
+import org.jbpm.api.ProcessInstance;
+import org.jbpm.api.job.Job;
+import org.jbpm.test.JbpmTestCase;
+import org.subethamail.wiser.Wiser;
+
+
+/**
+ * @author Tom Baeyens
+ */
+public class AsyncEventListenerTest extends JbpmTestCase {
+
+ long deploymentDbid;
+ Wiser wiser = null;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ deploymentDbid = repositoryService.createDeployment()
+ .addResourceFromClasspath("org/jbpm/examples/async/eventlistener/process.jpdl.xml")
+ .deploy();
+
+ // start mail server
+ wiser = new Wiser();
+ wiser.setPort(2525);
+ wiser.start();
+ }
+
+ protected void tearDown() throws Exception {
+ wiser.stop();
+
+ repositoryService.deleteDeploymentCascade(deploymentDbid);
+
+ super.tearDown();
+ }
+
+ public void testAsyncEventListener() throws Exception{
+ ProcessInstance processInstance = executionService.startProcessInstanceByKey("AsyncEventListener");
+ String processInstanceId = processInstance.getId();
+
+ assertEquals(0, wiser.getMessages().size());
+
+ Job job = managementService.createJobQuery()
+ .processInstanceId(processInstanceId)
+ .uniqueResult();
+ managementService.executeJob(job.getDbid());
+
+ assertEquals(1, wiser.getMessages().size());
+ }
+}
Property changes on: jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/async/eventlistener/AsyncEventListenerTest.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/async/fork/Application.java
===================================================================
--- jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/async/fork/Application.java 2009-05-22 14:06:47 UTC (rev 4874)
+++ jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/async/fork/Application.java 2009-05-23 10:38:45 UTC (rev 4875)
@@ -28,8 +28,10 @@
public class Application {
public void shipGoods() {
+ // assume automatic calculations here
}
public void sendBill() {
+ // assume automatic calculations here
}
}
Modified: jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/async/fork/AsyncForkTest.java
===================================================================
--- jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/async/fork/AsyncForkTest.java 2009-05-22 14:06:47 UTC (rev 4874)
+++ jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/async/fork/AsyncForkTest.java 2009-05-23 10:38:45 UTC (rev 4875)
@@ -21,6 +21,7 @@
*/
package org.jbpm.examples.async.fork;
+import java.util.Date;
import java.util.List;
import org.jbpm.api.ProcessInstance;
@@ -57,8 +58,6 @@
.processInstanceId(processInstanceId)
.list();
- System.out.println(jobs);
-
assertEquals(2, jobs.size());
Job job = jobs.get(0);
@@ -68,5 +67,13 @@
job = jobs.get(1);
managementService.executeJob(job.getDbid());
+
+ Date endTime = historyService
+ .createHistoryProcessInstanceQuery()
+ .processInstanceId(processInstance.getId())
+ .uniqueResult()
+ .getEndTime();
+
+ assertNotNull(endTime);
}
}
Modified: jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/hql/HqlTest.java
===================================================================
--- jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/hql/HqlTest.java 2009-05-22 14:06:47 UTC (rev 4874)
+++ jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/hql/HqlTest.java 2009-05-23 10:38:45 UTC (rev 4875)
@@ -25,7 +25,7 @@
import java.util.HashSet;
import java.util.Set;
-import org.jbpm.api.Execution;
+import org.jbpm.api.ProcessInstance;
import org.jbpm.api.task.Task;
import org.jbpm.test.JbpmTestCase;
@@ -75,17 +75,17 @@
}
public void testHql() {
- Execution execution = executionService.startProcessInstanceByKey("Hql");
- String executionId = execution.getId();
+ ProcessInstance processInstance = executionService.startProcessInstanceByKey("Hql");
+ String processInstanceId = processInstance.getId();
Set<String> expectedTaskNames = new HashSet<String>();
expectedTaskNames.add("dishes");
expectedTaskNames.add("iron");
- Collection<String> taskNames = (Collection<String>) executionService.getVariable(executionId, "tasknames with i");
+ Collection<String> taskNames = (Collection<String>) executionService.getVariable(processInstanceId, "tasknames with i");
taskNames = new HashSet<String>(taskNames);
assertEquals(expectedTaskNames, taskNames);
- Object activities = executionService.getVariable(executionId, "tasks");
+ Object activities = executionService.getVariable(processInstanceId, "tasks");
assertEquals("3", activities.toString());
}
}
Modified: jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/mail/inline/InlineMailTest.java
===================================================================
--- jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/mail/inline/InlineMailTest.java 2009-05-22 14:06:47 UTC (rev 4874)
+++ jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/mail/inline/InlineMailTest.java 2009-05-23 10:38:45 UTC (rev 4875)
@@ -44,6 +44,8 @@
*/
public class InlineMailTest extends JbpmTestCase {
+ Wiser wiser = null;
+
protected void setUp() throws Exception {
super.setUp();
@@ -62,9 +64,16 @@
identityService.createMembership("obrien", "innerparty");
identityService.createMembership("charr", "thinkpol");
identityService.createMembership("obrien", "thinkpol");
+
+ // start mail server
+ wiser = new Wiser();
+ wiser.setPort(2525);
+ wiser.start();
}
protected void tearDown() throws Exception {
+ wiser.stop();
+
// delete actors
identityService.deleteGroup("thinkpol");
identityService.deleteGroup("innerparty");
@@ -76,54 +85,46 @@
}
public void testInlineMail() throws MessagingException, IOException {
- Wiser wiser = new Wiser();
- wiser.setPort(2525);
- wiser.start();
- try {
- // prepare dynamic values
- String newspaper = "times";
- Calendar calendar = Calendar.getInstance();
- calendar.clear();
- calendar.set(1983, Calendar.DECEMBER, 3);
- Date date = calendar.getTime();
- // assemble variables
- Map<String, Object> variables = new HashMap<String, Object>();
- variables.put("newspaper", newspaper);
- variables.put("date", date);
- // start process instance
- executionService.startProcessInstanceByKey("InlineMail", variables);
+ // prepare dynamic values
+ String newspaper = "times";
+ Calendar calendar = Calendar.getInstance();
+ calendar.clear();
+ calendar.set(1983, Calendar.DECEMBER, 3);
+ Date date = calendar.getTime();
+ // assemble variables
+ Map<String, Object> variables = new HashMap<String, Object>();
+ variables.put("newspaper", newspaper);
+ variables.put("date", date);
+ // start process instance
+ executionService.startProcessInstanceByKey("InlineMail", variables);
- // examine produced message
- List<WiserMessage> wisMessages = wiser.getMessages();
- // winston, bb, innerparty(obrien), thinkpol(charr, obrien)
- assertEquals(5, wisMessages.size());
+ // examine produced message
+ List<WiserMessage> wisMessages = wiser.getMessages();
+ // winston, bb, innerparty(obrien), thinkpol(charr, obrien)
+ assertEquals(5, wisMessages.size());
- for (WiserMessage wisMessage : wisMessages) {
- Message message = wisMessage.getMimeMessage();
- // from
- Address[] from = message.getFrom();
- assertEquals(1, from.length);
- assertEquals("noreply at jbpm.org", from[0].toString());
- // to
- Address[] expectedTo = InternetAddress.parse("winston at minitrue");
- Address[] to = message.getRecipients(RecipientType.TO);
- assert Arrays.equals(expectedTo, to) : Arrays.asList(to);
- // cc
- Address[] expectedCc = InternetAddress.parse("bb at oceania, obrien at miniluv");
- System.out.println(Arrays.toString(expectedCc));
- Address[] cc = message.getRecipients(RecipientType.CC);
- System.out.println(Arrays.toString(cc));
- assert Arrays.equals(expectedCc, cc) : Arrays.asList(cc);
- // bcc - recipients undisclosed
- assertNull(message.getRecipients(RecipientType.BCC));
- // subject
- assertEquals("rectify " + newspaper, message.getSubject());
- // text
- assertTextPresent(newspaper + ' ' + date + " reporting bb dayorder", (String) message.getContent());
- }
+ for (WiserMessage wisMessage : wisMessages) {
+ Message message = wisMessage.getMimeMessage();
+ // from
+ Address[] from = message.getFrom();
+ assertEquals(1, from.length);
+ assertEquals("noreply at jbpm.org", from[0].toString());
+ // to
+ Address[] expectedTo = InternetAddress.parse("winston at minitrue");
+ Address[] to = message.getRecipients(RecipientType.TO);
+ assert Arrays.equals(expectedTo, to) : Arrays.asList(to);
+ // cc
+ Address[] expectedCc = InternetAddress.parse("bb at oceania, obrien at miniluv");
+ System.out.println(Arrays.toString(expectedCc));
+ Address[] cc = message.getRecipients(RecipientType.CC);
+ System.out.println(Arrays.toString(cc));
+ assert Arrays.equals(expectedCc, cc) : Arrays.asList(cc);
+ // bcc - recipients undisclosed
+ assertNull(message.getRecipients(RecipientType.BCC));
+ // subject
+ assertEquals("rectify " + newspaper, message.getSubject());
+ // text
+ assertTextPresent(newspaper + ' ' + date + " reporting bb dayorder", (String) message.getContent());
}
- finally {
- wiser.stop();
- }
}
}
Modified: jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/mail/template/TemplateMailTest.java
===================================================================
--- jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/mail/template/TemplateMailTest.java 2009-05-22 14:06:47 UTC (rev 4874)
+++ jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/mail/template/TemplateMailTest.java 2009-05-23 10:38:45 UTC (rev 4875)
@@ -44,6 +44,8 @@
*/
public class TemplateMailTest extends JbpmTestCase {
+ Wiser wiser = null;
+
protected void setUp() throws Exception {
super.setUp();
@@ -62,9 +64,16 @@
identityService.createMembership("obrien", "innerparty");
identityService.createMembership("charr", "thinkpol");
identityService.createMembership("obrien", "thinkpol");
+
+ // start mail server
+ wiser = new Wiser();
+ wiser.setPort(2525);
+ wiser.start();
}
protected void tearDown() throws Exception {
+ wiser.stop();
+
// delete actors
identityService.deleteGroup("thinkpol");
identityService.deleteGroup("innerparty");
@@ -76,57 +85,49 @@
}
public void testTemplateMail() throws MessagingException, IOException {
- Wiser wiser = new Wiser();
- wiser.setPort(2525);
- wiser.start();
- try {
- // prepare dynamic values
- String addressee = "winston at minitrue";
- String newspaper = "times";
- Calendar calendar = Calendar.getInstance();
- calendar.clear();
- calendar.set(1983, Calendar.DECEMBER, 3);
- Date date = calendar.getTime();
- String details = "reporting bb dayorder doubleplusungood refs unpersons rewrite "
- + "fullwise upsub antefiling";
- // assemble variables
- Map<String, Object> variables = new HashMap<String, Object>();
- variables.put("addressee", addressee);
- variables.put("newspaper", newspaper);
- variables.put("date", date);
- variables.put("details", details);
- // start process instance
- executionService.startProcessInstanceByKey("TemplateMail", variables);
+ // prepare dynamic values
+ String addressee = "winston at minitrue";
+ String newspaper = "times";
+ Calendar calendar = Calendar.getInstance();
+ calendar.clear();
+ calendar.set(1983, Calendar.DECEMBER, 3);
+ Date date = calendar.getTime();
+ String details = "reporting bb dayorder doubleplusungood refs unpersons rewrite "
+ + "fullwise upsub antefiling";
+ // assemble variables
+ Map<String, Object> variables = new HashMap<String, Object>();
+ variables.put("addressee", addressee);
+ variables.put("newspaper", newspaper);
+ variables.put("date", date);
+ variables.put("details", details);
+ // start process instance
+ executionService.startProcessInstanceByKey("TemplateMail", variables);
- // examine produced messages
- List<WiserMessage> wisMessages = wiser.getMessages();
- // winston, bb, innerparty(obrien), thinkpol(charr, obrien)
- assertEquals(5, wisMessages.size());
+ // examine produced messages
+ List<WiserMessage> wisMessages = wiser.getMessages();
+ // winston, bb, innerparty(obrien), thinkpol(charr, obrien)
+ assertEquals(5, wisMessages.size());
- for (WiserMessage wisMessage : wisMessages) {
- Message message = wisMessage.getMimeMessage();
- // from
- Address[] from = message.getFrom();
- assertEquals(1, from.length);
- assertEquals("noreply at jbpm.org", from[0].toString());
- // to
- Address[] expectedTo = InternetAddress.parse(addressee);
- Address[] to = message.getRecipients(RecipientType.TO);
- assert Arrays.equals(expectedTo, to) : Arrays.asList(to);
- // cc
- Address[] expectedCc = InternetAddress.parse("bb at oceania, obrien at miniluv");
- Address[] cc = message.getRecipients(RecipientType.CC);
- assert Arrays.equals(expectedCc, cc) : Arrays.asList(cc);
- // bcc - recipients undisclosed
- assertNull(message.getRecipients(RecipientType.BCC));
- // subject
- assertEquals("rectify " + newspaper, message.getSubject());
- // text
- assertEquals(newspaper + ' ' + date + ' ' + details, (String) message.getContent());
- }
+ for (WiserMessage wisMessage : wisMessages) {
+ Message message = wisMessage.getMimeMessage();
+ // from
+ Address[] from = message.getFrom();
+ assertEquals(1, from.length);
+ assertEquals("noreply at jbpm.org", from[0].toString());
+ // to
+ Address[] expectedTo = InternetAddress.parse(addressee);
+ Address[] to = message.getRecipients(RecipientType.TO);
+ assert Arrays.equals(expectedTo, to) : Arrays.asList(to);
+ // cc
+ Address[] expectedCc = InternetAddress.parse("bb at oceania, obrien at miniluv");
+ Address[] cc = message.getRecipients(RecipientType.CC);
+ assert Arrays.equals(expectedCc, cc) : Arrays.asList(cc);
+ // bcc - recipients undisclosed
+ assertNull(message.getRecipients(RecipientType.BCC));
+ // subject
+ assertEquals("rectify " + newspaper, message.getSubject());
+ // text
+ assertEquals(newspaper + ' ' + date + ' ' + details, (String) message.getContent());
}
- finally {
- wiser.stop();
- }
}
}
Added: jbpm4/trunk/modules/examples/src/test/resources/org/jbpm/examples/async/eventlistener/process.jpdl.xml
===================================================================
--- jbpm4/trunk/modules/examples/src/test/resources/org/jbpm/examples/async/eventlistener/process.jpdl.xml (rev 0)
+++ jbpm4/trunk/modules/examples/src/test/resources/org/jbpm/examples/async/eventlistener/process.jpdl.xml 2009-05-23 10:38:45 UTC (rev 4875)
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<process name="AsyncEventListener" xmlns="http://jbpm.org/4.0/jpdl">
+
+ <start name="start" g="22,69,80,40">
+ <transition to="wait">
+ <mail continue="async">
+ <to addresses="you at yourcompany" />
+ <subject>hello</subject>
+ <text>hello</text>
+ </mail>
+ </transition>
+ </start>
+
+ <state name="wait"/>
+
+</process>
Property changes on: jbpm4/trunk/modules/examples/src/test/resources/org/jbpm/examples/async/eventlistener/process.jpdl.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: jbpm4/trunk/modules/examples/src/test/resources/org/jbpm/examples/mail/inline/process.jpdl.xml
===================================================================
--- jbpm4/trunk/modules/examples/src/test/resources/org/jbpm/examples/mail/inline/process.jpdl.xml 2009-05-22 14:06:47 UTC (rev 4874)
+++ jbpm4/trunk/modules/examples/src/test/resources/org/jbpm/examples/mail/inline/process.jpdl.xml 2009-05-23 10:38:45 UTC (rev 4875)
@@ -2,11 +2,11 @@
<process name="InlineMail">
- <start>
+ <start g="20,25,80,40">
<transition to="send rectify note" />
</start>
- <mail name="send rectify note" language="juel">
+ <mail name="send rectify note" language="juel" g="99,25,115,45">
<to addresses="winston at minitrue" />
<cc users="bb" groups="innerparty" />
<bcc groups="thinkpol" />
@@ -27,6 +27,6 @@
<transition to="end" />
</mail>
- <state name="end" />
+ <state name="end" g="240,25,98,45"/>
</process>
\ No newline at end of file
Modified: jbpm4/trunk/modules/examples/src/test/resources/org/jbpm/examples/mail/template/process.jpdl.xml
===================================================================
--- jbpm4/trunk/modules/examples/src/test/resources/org/jbpm/examples/mail/template/process.jpdl.xml 2009-05-22 14:06:47 UTC (rev 4874)
+++ jbpm4/trunk/modules/examples/src/test/resources/org/jbpm/examples/mail/template/process.jpdl.xml 2009-05-23 10:38:45 UTC (rev 4875)
@@ -1,15 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
-<process name="TemplateMail">
-
- <start>
- <transition to="send rectify note" />
- </start>
-
- <mail name="send rectify note" template="rectify-template">
- <transition to="end" />
- </mail>
-
- <state name="end" />
-
+<process name="TemplateMail" xmlns="http://jbpm.org/4.0/jpdl">
+
+ <start g="20,25,80,40">
+ <transition to="send rectify note"/>
+ </start>
+
+ <mail name="send rectify note"
+ template="rectify-template"
+ g="99,25,115,45">
+ <transition to="end"/>
+ </mail>
+
+ <state name="end" g="240,25,98,45"/>
+
</process>
\ No newline at end of file
Modified: jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/activity/JoinActivity.java
===================================================================
--- jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/activity/JoinActivity.java 2009-05-22 14:06:47 UTC (rev 4874)
+++ jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/activity/JoinActivity.java 2009-05-23 10:38:45 UTC (rev 4875)
@@ -22,14 +22,15 @@
package org.jbpm.jpdl.internal.activity;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
+import org.hibernate.LockMode;
+import org.hibernate.Session;
import org.jbpm.api.Execution;
import org.jbpm.api.JbpmException;
import org.jbpm.api.activity.ActivityExecution;
+import org.jbpm.api.env.Environment;
import org.jbpm.api.model.Activity;
-import org.jbpm.api.model.OpenExecution;
import org.jbpm.api.model.Transition;
import org.jbpm.pvm.internal.model.ExecutionImpl;
@@ -42,6 +43,7 @@
private static final long serialVersionUID = 1L;
int multiplicity = -1;
+ LockMode lockMode = LockMode.UPGRADE;
public void execute(ActivityExecution execution) {
execute((ExecutionImpl)execution);
@@ -60,6 +62,10 @@
execution.take(transition);
} else if (Execution.STATE_ACTIVE_CONCURRENT.equals(execution.getState())) {
+
+ // force version increment in the parent execution
+ Session session = Environment.getFromCurrent(Session.class);
+ session.lock(execution.getParent(), lockMode);
execution.setState(Execution.STATE_INACTIVE_JOIN);
execution.waitForSignal();
@@ -118,4 +124,11 @@
joinedExecution.end();
}
}
+
+ public void setMultiplicity(int multiplicity) {
+ this.multiplicity = multiplicity;
+ }
+ public void setLockMode(LockMode lockMode) {
+ this.lockMode = lockMode;
+ }
}
Modified: jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/activity/JoinBinding.java
===================================================================
--- jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/activity/JoinBinding.java 2009-05-22 14:06:47 UTC (rev 4874)
+++ jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/activity/JoinBinding.java 2009-05-23 10:38:45 UTC (rev 4875)
@@ -21,6 +21,7 @@
*/
package org.jbpm.jpdl.internal.activity;
+import org.hibernate.LockMode;
import org.jbpm.pvm.internal.xml.Parse;
import org.jbpm.pvm.internal.xml.Parser;
import org.w3c.dom.Element;
@@ -36,7 +37,29 @@
}
public Object parse(Element element, Parse parse, Parser parser) {
- return new JoinActivity();
+ JoinActivity joinActivity = new JoinActivity();
+
+ if (element.hasAttribute("multiplicicty")) {
+ String multiplicictyText = element.getAttribute("multiplicicty");
+ try {
+ int multiplicity = Integer.parseInt(multiplicictyText);
+ joinActivity.setMultiplicity(multiplicity);
+ } catch (NumberFormatException e) {
+ parse.addProblem("multiplicity "+multiplicictyText+" is not a valid integer", element);
+ }
+ }
+
+ if (element.hasAttribute("lockmode")) {
+ String lockModeText = element.getAttribute("lockmode");
+ LockMode lockMode = LockMode.parse(lockModeText.toUpperCase());
+ if (lockMode==null) {
+ parse.addProblem("lockmode "+lockModeText+" is not a valid lock mode", element);
+ } else {
+ joinActivity.setLockMode(lockMode);
+ }
+ }
+
+ return joinActivity;
}
}
Modified: jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/activity/MailActivity.java
===================================================================
--- jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/activity/MailActivity.java 2009-05-22 14:06:47 UTC (rev 4874)
+++ jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/activity/MailActivity.java 2009-05-23 10:38:45 UTC (rev 4875)
@@ -39,7 +39,6 @@
private static final long serialVersionUID = 1L;
- @Override
void perform(OpenExecution execution) throws Exception {
Collection<Message> messages = mailProducer.produce(execution);
Environment.getFromCurrent(MailSession.class).send(messages);
Modified: jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/xml/JpdlParser.java
===================================================================
--- jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/xml/JpdlParser.java 2009-05-22 14:06:47 UTC (rev 4874)
+++ jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/xml/JpdlParser.java 2009-05-23 10:38:45 UTC (rev 4875)
@@ -250,10 +250,12 @@
parseTransitions(nestedElement, activity, parse);
String continuationText = XmlUtil.attribute(nestedElement, "continue");
- if ("async".equals(continuationText)) {
- activity.setContinuation(Continuation.ASYNCHRONOUS);
- } else if ("exclusive".equals(continuationText)) {
- activity.setContinuation(Continuation.EXCLUSIVE);
+ if (continuationText!=null) {
+ if ("async".equals(continuationText)) {
+ activity.setContinuation(Continuation.ASYNCHRONOUS);
+ } else if ("exclusive".equals(continuationText)) {
+ activity.setContinuation(Continuation.EXCLUSIVE);
+ }
}
ActivityBehaviour activityBehaviour = (ActivityBehaviour) activityBinding.parse(nestedElement, parse, this);
@@ -338,18 +340,20 @@
}
}
- public void parseOnEvent(Element element, ObservableElementImpl scopeElement, String eventName, Parse parse) {
+ public void parseOnEvent(Element element, ObservableElementImpl observableElement, String eventName, Parse parse) {
if (eventName!=null) {
- EventImpl event = scopeElement.getEvent(eventName);
+ EventImpl event = observableElement.getEvent(eventName);
if (event==null) {
- event = scopeElement.createEvent(eventName);
+ event = observableElement.createEvent(eventName);
}
String continuationText = XmlUtil.attribute(element, "continue");
- if ("async".equals(continuationText)) {
- event.setContinuation(Continuation.ASYNCHRONOUS);
- } else if ("exclusive".equals(continuationText)) {
- event.setContinuation(Continuation.EXCLUSIVE);
+ if (continuationText!=null) {
+ if ("async".equals(continuationText)) {
+ event.setContinuation(Continuation.ASYNCHRONOUS);
+ } else if ("exclusive".equals(continuationText)) {
+ event.setContinuation(Continuation.EXCLUSIVE);
+ }
}
for (Element eventListenerElement: XmlUtil.elements(element)) {
@@ -359,15 +363,27 @@
EventListenerReference eventListenerReference = event.createEventListenerReference(eventListener);
continuationText = XmlUtil.attribute(eventListenerElement, "continue");
- if ("async".equals(continuationText)) {
- eventListenerReference.setContinuation(Continuation.ASYNCHRONOUS);
- } else if ("exclusive".equals(continuationText)) {
- eventListenerReference.setContinuation(Continuation.EXCLUSIVE);
+ if (continuationText!=null) {
+ if (observableElement instanceof ActivityImpl) {
+ if (observableElement.getName()==null) {
+ parse.addProblem("async continuation on event listener requires activity name", eventListenerElement);
+ }
+ } else if (observableElement instanceof TransitionImpl) {
+ TransitionImpl transition = (TransitionImpl) observableElement;
+ if (transition.getSource().getName()==null) {
+ parse.addProblem("async continuation on event listener requires name in the transition source activity", eventListenerElement);
+ }
+ }
+ if ("async".equals(continuationText)) {
+ eventListenerReference.setContinuation(Continuation.ASYNCHRONOUS);
+ } else if ("exclusive".equals(continuationText)) {
+ eventListenerReference.setContinuation(Continuation.EXCLUSIVE);
+ }
}
} else {
String tagName = XmlUtil.getTagLocalName(eventListenerElement);
- if ( ! ( (scopeElement instanceof TransitionImpl)
+ if ( ! ( (observableElement instanceof TransitionImpl)
&& ( "condition".equals(tagName)
|| "timer".equals(tagName)
)
Modified: jbpm4/trunk/modules/jpdl/src/main/resources/jbpm.jpdl.eventlisteners.xml
===================================================================
--- jbpm4/trunk/modules/jpdl/src/main/resources/jbpm.jpdl.eventlisteners.xml 2009-05-22 14:06:47 UTC (rev 4874)
+++ jbpm4/trunk/modules/jpdl/src/main/resources/jbpm.jpdl.eventlisteners.xml 2009-05-23 10:38:45 UTC (rev 4875)
@@ -5,4 +5,5 @@
<eventlistener binding="org.jbpm.jpdl.internal.activity.HqlBinding" />
<eventlistener binding="org.jbpm.jpdl.internal.activity.SqlBinding" />
<eventlistener binding="org.jbpm.jpdl.internal.activity.ScriptBinding" />
+ <eventlistener binding="org.jbpm.jpdl.internal.activity.MailBinding" />
</eventlisteners>
Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/model/ActivityImpl.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/model/ActivityImpl.java 2009-05-22 14:06:47 UTC (rev 4874)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/model/ActivityImpl.java 2009-05-23 10:38:45 UTC (rev 4875)
@@ -84,6 +84,7 @@
public TransitionImpl createOutgoingTransition() {
// create a new transition
TransitionImpl transition = new TransitionImpl();
+ transition.setProcessDefinition(processDefinition);
// wire it between the source and destination
addOutgoingTransition(transition);
Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/model/op/ExecuteEventListener.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/model/op/ExecuteEventListener.java 2009-05-22 14:06:47 UTC (rev 4874)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/model/op/ExecuteEventListener.java 2009-05-23 10:38:45 UTC (rev 4875)
@@ -25,7 +25,6 @@
import org.jbpm.api.model.ObservableElement;
import org.jbpm.internal.log.Log;
import org.jbpm.pvm.internal.job.MessageImpl;
-import org.jbpm.pvm.internal.model.ActivityImpl;
import org.jbpm.pvm.internal.model.EventImpl;
import org.jbpm.pvm.internal.model.EventListenerReference;
import org.jbpm.pvm.internal.model.ExecutionImpl;
@@ -82,7 +81,7 @@
}
public MessageImpl< ? > createAsyncMessage(ExecutionImpl execution) {
- return null;
+ return new ExecuteEventListenerMessage(execution, observableElement, event, eventListenerReference);
}
public String toString() {
Added: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/model/op/ExecuteEventListenerMessage.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/model/op/ExecuteEventListenerMessage.java (rev 0)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/model/op/ExecuteEventListenerMessage.java 2009-05-23 10:38:45 UTC (rev 4875)
@@ -0,0 +1,99 @@
+/*
+ * 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.internal.model.op;
+
+import org.jbpm.api.env.Environment;
+import org.jbpm.api.listener.EventListener;
+import org.jbpm.api.model.ObservableElement;
+import org.jbpm.api.session.RepositorySession;
+import org.jbpm.pvm.internal.job.MessageImpl;
+import org.jbpm.pvm.internal.model.ActivityImpl;
+import org.jbpm.pvm.internal.model.EventImpl;
+import org.jbpm.pvm.internal.model.EventListenerReference;
+import org.jbpm.pvm.internal.model.ExecutionImpl;
+import org.jbpm.pvm.internal.model.ObservableElementImpl;
+import org.jbpm.pvm.internal.model.ProcessDefinitionImpl;
+import org.jbpm.pvm.internal.model.TransitionImpl;
+
+
+/**
+ * @author Tom Baeyens
+ */
+public class ExecuteEventListenerMessage extends MessageImpl<Object> {
+
+ private static final long serialVersionUID = 1L;
+
+ protected String processDefinitionId;
+ protected String activityName;
+ protected Integer transitionIndex;
+ protected String eventName;
+ protected Integer eventListenerIndex;
+
+ public ExecuteEventListenerMessage() {
+ }
+
+ public ExecuteEventListenerMessage(ExecutionImpl execution, ObservableElement observableElement, EventImpl event, EventListenerReference eventListenerReference) {
+ super(execution);
+ if (observableElement instanceof ProcessDefinitionImpl) {
+ ProcessDefinitionImpl processDefinition = (ProcessDefinitionImpl) observableElement;
+ processDefinitionId = processDefinition.getId();
+ } else if (observableElement instanceof ActivityImpl) {
+ ActivityImpl activity = (ActivityImpl) observableElement;
+ processDefinitionId = activity.getProcessDefinition().getId();
+ activityName = activity.getName();
+ } else if (observableElement instanceof TransitionImpl) {
+ TransitionImpl transition = (TransitionImpl) observableElement;
+ processDefinitionId = transition.getProcessDefinition().getId();
+ activityName = transition.getSource().getName();
+ transitionIndex = transition.getSource().getOutgoingTransitions().indexOf(transition);
+ }
+
+ eventName = event.getName();
+ eventListenerIndex = event.getListenerReferences().indexOf(eventListenerReference);
+ }
+
+ public Object execute(Environment environment) throws Exception {
+ ObservableElementImpl observableElement = null;
+
+ RepositorySession repositorySession = environment.get(RepositorySession.class);
+ ProcessDefinitionImpl processDefinition = (ProcessDefinitionImpl) repositorySession.findProcessDefinitionById(processDefinitionId);
+ if (activityName!=null) {
+ ActivityImpl activity = processDefinition.findActivity(activityName);
+ if (transitionIndex!=null) {
+ TransitionImpl transition = (TransitionImpl) activity.getOutgoingTransitions().get(transitionIndex);
+ observableElement = transition;
+ } else {
+ observableElement = activity;
+ }
+ } else {
+ observableElement = processDefinition;
+ }
+
+ EventImpl event = observableElement.getEvent(eventName);
+ EventListenerReference eventListenerReference = event.getListenerReferences().get(eventListenerIndex);
+ EventListener eventListener = eventListenerReference.get();
+
+ eventListener.notify(execution);
+
+ return null;
+ }
+}
Property changes on: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/model/op/ExecuteEventListenerMessage.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: jbpm4/trunk/modules/pvm/src/main/resources/jbpm.execution.hbm.xml
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/resources/jbpm.execution.hbm.xml 2009-05-22 14:06:47 UTC (rev 4874)
+++ jbpm4/trunk/modules/pvm/src/main/resources/jbpm.execution.hbm.xml 2009-05-23 10:38:45 UTC (rev 4875)
@@ -231,18 +231,21 @@
index="IDX_JOB_CMDDESCR"/ -->
<subclass name="org.jbpm.pvm.internal.job.MessageImpl" discriminator-value="Msg">
- <subclass name="org.jbpm.pvm.internal.model.op.ExecuteActivityMessage" discriminator-value="ExeActivityMsg" />
- <subclass name="org.jbpm.pvm.internal.model.op.SignalMessage" discriminator-value="SignalMsg">
+ <subclass name="org.jbpm.pvm.internal.model.op.ExecuteActivityMessage" discriminator-value="ExeAct" />
+ <subclass name="org.jbpm.pvm.internal.model.op.SignalMessage" discriminator-value="Signal">
<property name="signalName" column="SIGNAL_" />
- <!-- many-to-one name="activity"
- column="NODE_"
- cascade="none"
- foreign-key="FK_JOB_NODE"/ -->
</subclass>
- <subclass name="org.jbpm.pvm.internal.model.op.TransitionEndActivityMessage" discriminator-value="TrEndActMsg" />
- <subclass name="org.jbpm.pvm.internal.model.op.TransitionTakeMessage" discriminator-value="TrTakeMsg" />
- <subclass name="org.jbpm.pvm.internal.model.op.TransitionStartActivityMessage" discriminator-value="TrStartActMsg" />
- <subclass name="org.jbpm.pvm.internal.job.CommandMessage" discriminator-value="CmdMsg" />
+ <subclass name="org.jbpm.pvm.internal.model.op.TransitionEndActivityMessage" discriminator-value="TrEndAct" />
+ <subclass name="org.jbpm.pvm.internal.model.op.TransitionTakeMessage" discriminator-value="TrTake" />
+ <subclass name="org.jbpm.pvm.internal.model.op.TransitionStartActivityMessage" discriminator-value="TrStartAct" />
+ <subclass name="org.jbpm.pvm.internal.model.op.ExecuteEventListenerMessage" discriminator-value="ExeEvtLst">
+ <property name="processDefinitionId" column="PROCDEF_" />
+ <property name="activityName" column="ACT_" />
+ <property name="transitionIndex" column="TRIDX_" />
+ <property name="eventName" column="EVENT_" />
+ <property name="eventListenerIndex" column="EVTLSTIDX_" />
+ </subclass>
+ <subclass name="org.jbpm.pvm.internal.job.CommandMessage" discriminator-value="Cmd" />
</subclass>
<subclass name="org.jbpm.pvm.internal.job.TimerImpl" discriminator-value="Timer">
Modified: jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch05-Jpdl.xml
===================================================================
--- jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch05-Jpdl.xml 2009-05-22 14:06:47 UTC (rev 4874)
+++ jbpm4/trunk/modules/userguide/src/main/docbook/en/modules/ch05-Jpdl.xml 2009-05-23 10:38:45 UTC (rev 4875)
@@ -480,6 +480,41 @@
<para>With the <literal>fork</literal> and <literal>join</literal> activities,
concurrent paths of executions can be modeled.
</para>
+ <table><title><literal>join</literal> attributes:</title>
+ <tgroup cols="5" rowsep="1" colsep="1">
+ <thead>
+ <row>
+ <entry>Attribute</entry>
+ <entry>Type</entry>
+ <entry>Default</entry>
+ <entry>Required?</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>multiplicity</literal></entry>
+ <entry>integer</entry>
+ <entry>nbr of incoming transitions</entry>
+ <entry>optional</entry>
+ <entry>The number of executions that should arrive in this join
+ before the join activates and push an execution out the single
+ outgoing transition of the join.
+ </entry>
+ </row>
+ <row>
+ <entry><literal>lockmode</literal></entry>
+ <entry>{none, read, upgrade, upgrade_nowait, write}</entry>
+ <entry>upgrade</entry>
+ <entry>optional</entry>
+ <entry>the hibernate lock mode applied on the parent execution to
+ prevent that 2 concurrent transactions see each other as not yet
+ arrived at the join, causing a process deadlock.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
<para>For example:</para>
<figure id="process.concurrency">
<title>The concurrency example process</title>
@@ -2213,7 +2248,7 @@
asynchronous message is committed and then processed, it will start a new transaction
and resume execution where it left off.
</para>
-- <table><title>Any activity attribute:</title>
+ <table><title>Attribute of any activity, <literal>transition</literal> or <literal>on</literal>:</title>
<tgroup cols="5" rowsep="1" colsep="1">
<thead>
<row>
@@ -2230,15 +2265,35 @@
<entry>{sync | async | exclusive}</entry>
<entry>sync</entry>
<entry>optional</entry>
- <entry>indicates if an asynchronous continuation should be performed
- before the activity is executed.
+ <entry><para>indicates if an asynchronous continuation should be performed
+ before the element is executed.</para>
</entry>
</row>
</tbody>
</tgroup>
</table>
+ <itemizedlist>
+ <listitem><emphasis role="bold">sync</emphasis> (default) keep executing
+ the element as part of the ongoing transaction.
+ </listitem>
+ <listitem><emphasis role="bold">async</emphasis> introduces an asynchronous
+ continuation (aka safe point).
+ The ongoing transaction is committed and the element is executed in a
+ new transaction. Transactional asynchronous messaging is used by the jBPM
+ implementation to achieve this.
+ </listitem>
+ <listitem><emphasis role="bold">exclusive</emphasis> introduces a asynchronous
+ continuation (aka safe point).
+ The ongoing transaction is committed and the element is executed in a
+ new transaction. Transactional asynchronous messaging is used by the jBPM
+ implementation to achieve this. Exclusive messages will not be processed
+ concurrently. The JobExecutor(s) will serialize all exclusive job
+ executions. This can be used to prevent optimistic locking failures in case
+ multiple, potentially conflicting jobs are scheduled in the same transaction.
+ </listitem>
+ </itemizedlist>
<para>Let's look at a couple of examples.</para>
-
+
<section id="asyncactivity">
<title>Async activity</title>
<figure id="process.async.activity">
@@ -2268,6 +2323,16 @@
<end name="end"/>
</process></programlisting>
+ <programlisting>public class Application {
+
+ public void generatePdf() {
+ // assume long automatic calculations here
+ }
+
+ public void calculatePrimes() {
+ // assume long automatic calculations here
+ }
+}</programlisting>
<programlisting>ProcessInstance processInstance =
executionService.startProcessInstanceByKey("AsyncActivity");
String processInstanceId = processInstance.getId();</programlisting>
@@ -2277,13 +2342,13 @@
</para>
<para>But with <literal>continue="async"</literal> the execution only
goes untill it is about to execute activity <literal>generate pdf</literal>. Then
- An asynchronous continuation message is send and the <literal>startProcessInstanceByKey</literal>
+ an asynchronous continuation message is send and the <literal>startProcessInstanceByKey</literal>
method returns.
</para>
- <para>In a normal configuration, the job executor will pick up the message and execute
- it. But for testing scenarios and for these examples we want to control
- when messages are executed so the job executor is not configured. Therefor
- we have to execute the jobs manually like this:
+ <para>In a normal configuration, the job executor will automatically pick up
+ the message and execute it. But for testing scenarios and for these examples we
+ want to control when messages are executed so the job executor is not configured.
+ Therefor we have to execute the jobs manually like this:
</para>
<programlisting>Job job = managementService.createJobQuery()
.processInstanceId(processInstanceId)
@@ -2297,6 +2362,91 @@
is executed, that transaction will run the execution till the end.
</para>
</section>
+
+ <section id="asyncfork">
+ <title>Async fork</title>
+ <figure id="process.async.fork">
+ <title>The async fork example process</title>
+ <mediaobject><imageobject><imagedata align="center" fileref="images/process.async.fork.png"/></imageobject></mediaobject>
+ </figure>
+ <programlisting><process name="AsyncFork" xmlns="http://jbpm.org/4.0/jpdl">
+
+ <start >
+ <transition to="fork"/>
+ </start>
+
+ <fork >
+ <emphasis role="bold"><on event="end" continue="exclusive" /></emphasis>
+ <transition />
+ <transition />
+ </fork>
+
+ <java class="org.jbpm.examples.async.fork.Application" >
+ <transition />
+ </java>
+
+ <java class="org.jbpm.examples.async.fork.Application" >
+ <transition />
+ </java>
+
+ <join >
+ <transition to="end"/>
+ </join>
+
+ <end />
+
+</process></programlisting>
+ <programlisting>public class Application {
+
+ public void shipGoods() {
+ // assume automatic calculations here
+ }
+
+ public void sendBill() {
+ // assume automatic calculations here
+ }
+}</programlisting>
+ <para>By placing the asynchronous continuation on the <literal>end</literal>
+ event of the fork (<literal><on event="end" continue="exclusive" /></literal>),
+ each forked execution that takes a transition out of the
+ fork will be continued asynchronously.
+ </para>
+ <para>Value <literal>exclusive</literal> was selected to serialize the executions of
+ the 2 asynchonous continuation jobs resulting from the fork. The respective transactions
+ that will execute activities <literal>ship goods</literal>
+ and <literal>send bill</literal> will both arrive at the join. At the join, both
+ transactions will synchronize on the same execution (read: update the same execution
+ row in the DB), resulting in a potential optimistic locking failure.
+ </para>
+ <programlisting>ProcessInstance processInstance = executionService.startProcessInstanceByKey("AsyncFork");
+String processInstanceId = processInstance.getId();
+
+List<Job> jobs = managementService.createJobQuery()
+ .processInstanceId(processInstanceId)
+ .list();
+
+assertEquals(2, jobs.size());
+
+Job job = jobs.get(0);
+
+// here we simulate execution of the job,
+// which is normally done by the job executor
+managementService.executeJob(job.getDbid());
+
+job = jobs.get(1);
+
+// here we simulate execution of the job,
+// which is normally done by the job executor
+managementService.executeJob(job.getDbid());
+
+Date endTime = historyService
+ .createHistoryProcessInstanceQuery()
+ .processInstanceId(processInstance.getId())
+ .uniqueResult()
+ .getEndTime();
+
+assertNotNull(endTime);</programlisting>
+ </section>
</section>
<section id="timer">
More information about the jbpm-commits
mailing list