JBoss JBPM SVN: r6769 - projects/migration_tool/trunk/src/test/java/test.
by do-not-reply@jboss.org
Author: eschabell
Date: 2010-10-21 14:02:04 -0400 (Thu, 21 Oct 2010)
New Revision: 6769
Modified:
projects/migration_tool/trunk/src/test/java/test/XSLTTest.java
Log:
Added test output of transformed BPMN definition for the happyTest.
Modified: projects/migration_tool/trunk/src/test/java/test/XSLTTest.java
===================================================================
--- projects/migration_tool/trunk/src/test/java/test/XSLTTest.java 2010-10-17 15:59:37 UTC (rev 6768)
+++ projects/migration_tool/trunk/src/test/java/test/XSLTTest.java 2010-10-21 18:02:04 UTC (rev 6769)
@@ -1,15 +1,16 @@
package test;
-import static java.lang.System.out;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
+import java.util.Scanner;
-import javax.swing.Box.Filler;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
@@ -71,9 +72,26 @@
String process = "Single Task";
String dir = singleTaskJpdl;
+ // transform jPDL task.
File resultFile = transformJpdlXml(transformer, dir, process);
-
-
+
+ System.out.println("Reading from file.");
+ StringBuilder text = new StringBuilder();
+ String NL = System.getProperty("line.separator");
+ Scanner scanner = null;
+ try {
+ scanner = new Scanner(new FileInputStream(resultFile));
+ while (scanner.hasNextLine()){
+ text.append(scanner.nextLine() + NL);
+ }
+ } catch (FileNotFoundException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ finally{
+ scanner.close();
+ }
+ System.out.println("Text read in: " + text);
}
public static File transformJpdlXml(Transformer transformer, String dir, String process) {
13 years, 6 months
JBoss JBPM SVN: r6768 - in jbpm4/trunk/modules: pvm/src/main/java/org/jbpm/pvm/internal/hibernate and 1 other directories.
by do-not-reply@jboss.org
Author: rebody
Date: 2010-10-17 11:59:37 -0400 (Sun, 17 Oct 2010)
New Revision: 6768
Modified:
jbpm4/trunk/modules/api/src/main/java/org/jbpm/api/history/HistoryTaskQuery.java
jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/hibernate/QuerySessionImpl.java
jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/HistoryTaskQueryImpl.java
Log:
JBPM-2953 add endedAfter and endedBefore in HistoryTaskQuery
Modified: jbpm4/trunk/modules/api/src/main/java/org/jbpm/api/history/HistoryTaskQuery.java
===================================================================
--- jbpm4/trunk/modules/api/src/main/java/org/jbpm/api/history/HistoryTaskQuery.java 2010-10-17 15:44:46 UTC (rev 6767)
+++ jbpm4/trunk/modules/api/src/main/java/org/jbpm/api/history/HistoryTaskQuery.java 2010-10-17 15:59:37 UTC (rev 6768)
@@ -28,7 +28,7 @@
/** query for history tasks.
- *
+ *
* @author Tom Baeyens
* @author Maciej Swiderski
*/
@@ -53,28 +53,28 @@
/** only select the history task for the given id */
HistoryTaskQuery taskId(String taskId);
-
+
/** only select history tasks within the given processInstanceId */
HistoryTaskQuery processInstanceId(String processInstanceId);
-
+
/** only select history tasks within the given execution */
HistoryTaskQuery executionId(String executionId);
-
+
/** only select history tasks for the given assignee */
HistoryTaskQuery assignee(String assignee);
/** only select history tasks in the given state */
HistoryTaskQuery state(String state);
-
+
/** only select the history task for the given id, allows to specify query operand */
HistoryTaskQuery taskId(QueryOperator operator, String... taskId);
-
+
/** only select history tasks within the given processInstanceId, allows to specify query operand */
HistoryTaskQuery processInstanceId(QueryOperator operator, String... processInstanceId);
-
+
/** only select history tasks within the given execution, allows to specify query operand */
HistoryTaskQuery executionId(QueryOperator operator, String... executionId);
-
+
/** only select history tasks for the given assignee, allows to specify query operand */
HistoryTaskQuery assignee(QueryOperator operator, String... assignee);
@@ -83,7 +83,7 @@
/** only select history tasks that have the given outcome */
HistoryTaskQuery outcome(String outcome);
-
+
/** only select history tasks that have the given outcome, allows to specify query operand */
HistoryTaskQuery outcome(QueryOperator operator, String... outcome);
@@ -102,6 +102,12 @@
/** only select history tasks started before the given time */
HistoryTaskQuery startedBefore(Date time);
+ /** only select history tasks ended after the given time. */
+ HistoryTaskQuery endedAfter(Date time);
+
+ /** only select history tasks ended before the given time. */
+ HistoryTaskQuery endedBefore(Date time);
+
/** only select history tasks that took less then the given duration in milliseconds */
HistoryTaskQuery tookLessThen(long durationInMillis);
@@ -110,10 +116,10 @@
/** execute the query and obtain the list of {@link HistoryTask}s */
List<HistoryTask> list();
-
+
/** execute the query and obtain the unique {@link HistoryTask} */
HistoryTask uniqueResult();
-
- /** execute a count(*) query and returns number of results */
+
+ /** execute a count(*) query and returns number of results */
long count();
}
Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/hibernate/QuerySessionImpl.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/hibernate/QuerySessionImpl.java 2010-10-17 15:44:46 UTC (rev 6767)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/hibernate/QuerySessionImpl.java 2010-10-17 15:59:37 UTC (rev 6768)
@@ -605,6 +605,30 @@
queryProperty.removeCondition("startedAfter");
}
+ if (queryProperty.hasCondition("endedBefore")) {
+ if (alreadyAddWhere) {
+ buff.append(" and ");
+ } else {
+ buff.append(" where ");
+ alreadyAddWhere = true;
+ }
+ buff.append("ht.endTime<:endedBefore");
+ params.put("endedBefore", queryProperty.getCondition("endedBefore").getValue());
+ queryProperty.removeCondition("endedBefore");
+ }
+
+ if (queryProperty.hasCondition("endedAfter")) {
+ if (alreadyAddWhere) {
+ buff.append(" and ");
+ } else {
+ buff.append(" where ");
+ alreadyAddWhere = true;
+ }
+ buff.append("ht.endTime>:endedAfter");
+ params.put("endedAfter", queryProperty.getCondition("endedAfter").getValue());
+ queryProperty.removeCondition("endedAfter");
+ }
+
this.appendWhereClause(buff, queryProperty, params, alreadyAddWhere);
// order by
Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/HistoryTaskQueryImpl.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/HistoryTaskQueryImpl.java 2010-10-17 15:44:46 UTC (rev 6767)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/query/HistoryTaskQueryImpl.java 2010-10-17 15:59:37 UTC (rev 6768)
@@ -50,6 +50,8 @@
* tookLongerThen
* startedBefore
* startedAfter
+ * endedBefore
+ * endedAfter
* order by
*
* @author Tom Baeyens
@@ -70,6 +72,8 @@
protected Long tookLongerThen;
protected Date startedBefore;
protected Date startedAfter;
+ protected Date endedBefore;
+ protected Date endedAfter;
protected Map<String, String> orders = new LinkedHashMap<String, String>();
@@ -138,6 +142,16 @@
return this;
}
+ public HistoryTaskQuery endedAfter(Date time) {
+ this.endedAfter = time;
+ return this;
+ }
+
+ public HistoryTaskQuery endedBefore(Date time) {
+ this.endedBefore = time;
+ return this;
+ }
+
public HistoryTaskQuery tookLessThen(long durationInMillis) {
this.tookLessThen = durationInMillis;
return this;
@@ -258,6 +272,14 @@
queryProperty.addCondition("startedAfter", startedAfter, QueryOperator.GREATER_THAN);
}
+ if (endedBefore != null) {
+ queryProperty.addCondition("endedBefore", endedBefore, QueryOperator.LESS_THAN);
+ }
+
+ if (endedAfter != null) {
+ queryProperty.addCondition("endedAfter", endedAfter, QueryOperator.GREATER_THAN);
+ }
+
// orders
for (Map.Entry<String, String> entry : orders.entrySet()) {
queryProperty.addOrder(entry.getKey(), entry.getValue());
13 years, 6 months
JBoss JBPM SVN: r6767 - in jbpm4/trunk/modules: test-db/src/test/java/org/jbpm/test/activity/subprocess and 1 other directory.
by do-not-reply@jboss.org
Author: rebody
Date: 2010-10-17 11:44:46 -0400 (Sun, 17 Oct 2010)
New Revision: 6767
Modified:
jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/activity/SubProcessActivity.java
jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/activity/subprocess/SubProcessTest.java
Log:
JBPM-2772 get business key for sub process.
Modified: jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/activity/SubProcessActivity.java
===================================================================
--- jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/activity/SubProcessActivity.java 2010-10-17 15:31:46 UTC (rev 6766)
+++ jbpm4/trunk/modules/jpdl/src/main/java/org/jbpm/jpdl/internal/activity/SubProcessActivity.java 2010-10-17 15:44:46 UTC (rev 6767)
@@ -77,10 +77,10 @@
Expression subProcessKeyExpression = Expression.create(subProcessKey, Expression.LANGUAGE_UEL_VALUE);
subProcessKeyEval = (String) subProcessKeyExpression.evaluate(execution);
if (subProcessKeyEval == null) {
- throw new JbpmException("Subprocess key '" + subProcessKey +"' resolved to null.");
+ throw new JbpmException("Subprocess key '" + subProcessKey + "' resolved to null.");
}
} catch (PropertyNotFoundException e) {
- throw new JbpmException("Subprocess key '" + subProcessKey +"' could not be resolved.");
+ throw new JbpmException("Subprocess key '" + subProcessKey + "' could not be resolved.");
}
processDefinition = repositorySession.findProcessDefinitionByKey(subProcessKeyEval);
@@ -100,7 +100,7 @@
String subSwimlaneName = swimlaneMappings.get(swimlaneName);
SwimlaneImpl subSwimlane = subProcessInstance.createSwimlane(subSwimlaneName);
SwimlaneImpl swimlane = executionImpl.getSwimlane(swimlaneName);
- if (swimlane!=null) {
+ if (swimlane != null) {
subSwimlane.initialize(swimlane);
}
}
@@ -111,6 +111,7 @@
executionImpl.historyActivityStart();
+ subProcessInstance.setKey(execution.getProcessInstance().getKey());
subProcessInstance.start();
execution.waitForSignal();
@@ -146,7 +147,7 @@
Activity activity = execution.getActivity();
String subProcessActivityName = subProcessInstance.getActivityName();
- if (outcomeExpression!=null) {
+ if (outcomeExpression != null) {
Object value = outcomeExpression.evaluate(execution);
// if the value is a String and matches the name of an outgoing transition
if ( (value instanceof String)
@@ -164,17 +165,17 @@
}
} finally {
- if (subProcessExecutionContext!=null) {
+ if (subProcessExecutionContext != null) {
environment.removeContext(subProcessExecutionContext);
}
- if (originalExecutionContext!=null) {
+ if (originalExecutionContext != null) {
environment.setContext(originalExecutionContext);
}
}
execution.historyActivityEnd();
- if (transitionName!=null) {
+ if (transitionName != null) {
execution.take(transitionName);
} else {
execution.takeDefaultTransition();
Modified: jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/activity/subprocess/SubProcessTest.java
===================================================================
--- jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/activity/subprocess/SubProcessTest.java 2010-10-17 15:31:46 UTC (rev 6766)
+++ jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/activity/subprocess/SubProcessTest.java 2010-10-17 15:44:46 UTC (rev 6767)
@@ -26,10 +26,12 @@
import java.util.List;
+import org.jbpm.api.Execution;
import org.jbpm.api.ProcessInstance;
import org.jbpm.api.QueryOperator;
import org.jbpm.api.history.HistoryProcessInstance;
import org.jbpm.api.task.Task;
+import org.jbpm.pvm.internal.model.ExecutionImpl;
import org.jbpm.test.JbpmTestCase;
@@ -135,7 +137,7 @@
assertEquals(0, executionService.createProcessInstanceQuery().list().size());
}
-
+
public void testSubProcessHistoryIds() {
deployJpdlXmlString(SUB_PROCESS);
deployJpdlXmlString(MAIN_PROCESS);
@@ -152,17 +154,30 @@
assertProcessInstanceEnded(processInstance);
assertEquals(0, executionService.createProcessInstanceQuery().list().size());
-
-
+
+
List<HistoryProcessInstance> history = historyService.createHistoryProcessInstanceQuery().processInstanceId(QueryOperator.LIKE, "SubProcessReview%").list();
assertNotNull(history);
assertNotNull(history.get(0).getSuperProcessInstanceId());
assertEquals(processInstance.getId(), history.get(0).getSuperProcessInstanceId());
-
+
history = historyService.createHistoryProcessInstanceQuery().superProcessInstanceId(processInstance.getId()).list();
assertNotNull(history);
assertNotNull(history.get(0).getSuperProcessInstanceId());
assertEquals(processInstance.getId(), history.get(0).getSuperProcessInstanceId());
}
+ // Test for JBPM-2772
+ public void testSubProcessWithKey() {
+ deployJpdlXmlString(SUB_PROCESS);
+ deployJpdlXmlString(MAIN_PROCESS);
+
+ ProcessInstance processInstance = executionService.startProcessInstanceByKey("mainProcess", "business key");
+ Execution subProcessInstance = processInstance.getSubProcessInstance();
+ assertEquals("business key", ((ExecutionImpl)subProcessInstance).getKey());
+
+ Task task = taskService.findPersonalTasks("johndoe").get(0);
+ taskService.completeTask(task.getId(), "nok");
+ }
+
}
13 years, 6 months
JBoss JBPM SVN: r6766 - in jbpm4/trunk/modules: pvm/src/main/java/org/jbpm/pvm/internal/history/events and 4 other directories.
by do-not-reply@jboss.org
Author: rebody
Date: 2010-10-17 11:31:46 -0400 (Sun, 17 Oct 2010)
New Revision: 6766
Added:
jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/history/events/SubTaskComplete.java
Modified:
jbpm4/trunk/modules/api/src/main/java/org/jbpm/api/model/Event.java
jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/repository/DeploymentImpl.java
jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/task/TaskImpl.java
jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/util/ReflectUtil.java
jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/xml/Parser.java
Log:
JBPM-2416 add more task audit feature:
task-completed
task-skiped
subTaskComplete
Modified: jbpm4/trunk/modules/api/src/main/java/org/jbpm/api/model/Event.java
===================================================================
--- jbpm4/trunk/modules/api/src/main/java/org/jbpm/api/model/Event.java 2010-10-17 14:44:27 UTC (rev 6765)
+++ jbpm4/trunk/modules/api/src/main/java/org/jbpm/api/model/Event.java 2010-10-17 15:31:46 UTC (rev 6766)
@@ -30,17 +30,28 @@
/** fired when a transition is being taken */
String TAKE = "take";
+
/** fired when a process or an activity starts */
String START = "start";
+
/** fired when a process or an activity ends */
String END = "end";
+
/** fired when a task is assigned */
String ASSIGN = "assign";
+
/** fired when an assignee is reminded of a task */
String REMIND = "remind";
+
/** fired when a task is created */
String TASK_CREATED = "task-created";
+ /** fired when a task is completed. */
+ String TASK_COMPLETED = "task-completed";
+
+ /** fired when a task is skiped. */
+ String TASK_SKIPED = "task-skiped";
+
/** get the name of event. */
String getName();
}
Added: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/history/events/SubTaskComplete.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/history/events/SubTaskComplete.java (rev 0)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/history/events/SubTaskComplete.java 2010-10-17 15:31:46 UTC (rev 6766)
@@ -0,0 +1,67 @@
+/*
+ * 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.history.events;
+
+import org.hibernate.Session;
+
+import org.jbpm.api.history.HistoryTask;
+
+import org.jbpm.pvm.internal.env.EnvironmentImpl;
+import org.jbpm.pvm.internal.history.HistoryEvent;
+import org.jbpm.pvm.internal.history.model.HistoryTaskImpl;
+import org.jbpm.pvm.internal.history.model.HistoryTaskInstanceImpl;
+import org.jbpm.pvm.internal.task.TaskImpl;
+import org.jbpm.pvm.internal.util.Clock;
+
+
+/**
+ * @author Huisheng Xu
+ */
+public class SubTaskComplete extends HistoryEvent {
+ private static final long serialVersionUID = 1L;
+ protected String outcome;
+ protected TaskImpl task;
+
+ public SubTaskComplete(TaskImpl task, String outcome) {
+ this.task = task;
+ this.outcome = outcome;
+ }
+
+ public void process() {
+ Session session = EnvironmentImpl.getFromCurrent(Session.class);
+ HistoryTaskImpl historyTask = (HistoryTaskImpl) session.load(HistoryTaskImpl.class,
+ task.getDbid());
+ historyTask.setOutcome(outcome);
+ historyTask.setEndTime(Clock.getTime());
+ historyTask.setState(HistoryTask.STATE_COMPLETED);
+
+ session.update(historyTask);
+ }
+
+ public String getOutcome() {
+ return outcome;
+ }
+
+ public TaskImpl getTask() {
+ return task;
+ }
+}
Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/repository/DeploymentImpl.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/repository/DeploymentImpl.java 2010-10-17 14:44:27 UTC (rev 6765)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/repository/DeploymentImpl.java 2010-10-17 15:31:46 UTC (rev 6766)
@@ -166,10 +166,14 @@
return resources.keySet();
}
+ public Lob getLob(String resourceName) {
+ return resources.get(resourceName);
+ }
+
/**
* This method should be called before saving the deployment. It will assign a generated dbid
* to the resource Lobs.
- *
+ *
* Note: when using a database, this method must be called within an environment block!
*/
public void initResourceLobDbids() {
Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/task/TaskImpl.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/task/TaskImpl.java 2010-10-17 14:44:27 UTC (rev 6765)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/task/TaskImpl.java 2010-10-17 15:31:46 UTC (rev 6766)
@@ -36,6 +36,7 @@
import org.jbpm.pvm.internal.client.ClientExecution;
import org.jbpm.pvm.internal.env.EnvironmentImpl;
import org.jbpm.pvm.internal.history.HistoryEvent;
+import org.jbpm.pvm.internal.history.events.SubTaskComplete;
import org.jbpm.pvm.internal.history.events.TaskSkip;
import org.jbpm.pvm.internal.history.events.TaskComplete;
import org.jbpm.pvm.internal.history.events.TaskDelete;
@@ -49,7 +50,7 @@
/**
* is one task instance that can be assigned to an actor (read: put in someone's task list) and that
* can trigger the continuation of execution of the token upon completion.
- *
+ *
* @author Tom Baeyens
* @author Ronald van Kuijk
*/
@@ -77,13 +78,13 @@
protected ExecutionImpl execution;
protected ExecutionImpl processInstance;
-
+
// local storage of the execution id such that it
// can be lazily loaded when not needed.
protected String executionId;
-
+
protected String activityName;
-
+
protected SwimlaneImpl swimlane;
protected TaskImpl superTask;
@@ -93,16 +94,16 @@
protected Long superTaskDbid;
public TaskImpl() {
- this.state = Task.STATE_OPEN;
+ this.state = Task.STATE_OPEN;
}
- // parent for variable lookup ///////////////////////////////////////////////
+ // parent for variable lookup ///////////////////////////////////////////////
@Override
public ScopeInstanceImpl getParentVariableScope() {
return execution;
}
-
+
@Override
public TaskImpl getTask() {
return this;
@@ -183,30 +184,36 @@
}
// completion ///////////////////////////////////////////////////////////////
-
+
public void complete() {
complete(TaskConstants.NO_TASK_OUTCOME_SPECIFIED);
- }
+ }
public void complete(String outcome) {
historyTaskComplete(outcome);
-
+
DbSession dbSession = EnvironmentImpl.getFromCurrent(DbSession.class, false);
- if (dbSession!=null){
+ if (dbSession != null) {
dbSession.delete(this);
}
if (isSignalling()) {
- ClientExecution execution = getExecution();
+ ExecutionImpl execution = getExecution();
+ execution.fire(Event.TASK_COMPLETED, execution.getActivity());
execution.signal(outcome);
}
-
+
if (superTask != null) {
superTask.subTaskComplete(this, outcome);
}
}
protected void subTaskComplete(TaskImpl subTask, String outcome) {
+ TaskImpl superTask = subTask.getSuperTask();
+
+ if (superTask.getExecution() != null) {
+ HistoryEvent.fire(new SubTaskComplete(subTask, outcome), execution);
+ }
}
public void delete(String reason) {
@@ -217,11 +224,15 @@
if (outcome == null || outcome.equals("")) {
outcome = TaskConstants.NO_TASK_OUTCOME_SPECIFIED;
}
-
+
+ ExecutionImpl execution = getExecution();
+ if (execution != null) {
+ execution.fire(Event.TASK_SKIPED, execution.getActivity());
+ }
historyTaskSkip(outcome);
-
+
DbSession dbSession = EnvironmentImpl.getFromCurrent(DbSession.class, false);
- if (dbSession!=null){
+ if (dbSession != null) {
dbSession.delete(this);
}
}
@@ -253,7 +264,7 @@
}
public TaskImpl createSubTask(String name) {
- // TODO look up the task definition in the current task's
+ // TODO look up the task definition in the current task's
// subtask definitions and in the process's task definitions
TaskImpl subtask = createSubTask();
subtask.setName(name);
@@ -347,7 +358,7 @@
}
// customized getters and setters //////////////////////////////////////////
-
+
public String getId() {
return Long.toString(dbid);
}
@@ -461,7 +472,7 @@
public String getExecutionId() {
return executionId;
}
-
+
public String getActivityName() {
return activityName;
}
Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/util/ReflectUtil.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/util/ReflectUtil.java 2010-10-17 14:44:27 UTC (rev 6765)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/util/ReflectUtil.java 2010-10-17 15:31:46 UTC (rev 6766)
@@ -4,6 +4,7 @@
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.net.URL;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@@ -22,10 +23,6 @@
public class ReflectUtil {
- private ReflectUtil() {
- // hide default constructor to prevent instantiation
- }
-
private static final Log log = Log.getLog(ReflectUtil.class.getName());
/**
@@ -33,6 +30,10 @@
*/
private static final Map<Class<?>, Class<?>> wrapperPrimitiveMap = createWrapperPrimitiveMap();
+ private ReflectUtil() {
+ // hide default constructor to prevent instantiation
+ }
+
private static Map<Class<?>, Class<?>> createWrapperPrimitiveMap() {
Map<Class<?>, Class<?>> map = new HashMap<Class<?>, Class<?>>();
map.put(Boolean.class, boolean.class);
@@ -79,13 +80,16 @@
try {
method = clazz.getDeclaredMethod(methodName, parameterTypes);
- if (log.isTraceEnabled()) log.trace("found method "+clazz.getName()+"."+methodName+"("+Arrays.toString(parameterTypes)+")");
+ if (log.isTraceEnabled()) {
+ log.trace("found method " + clazz.getName() + "." + methodName + "(" + Arrays.toString(parameterTypes) + ")");
+ }
} catch (NoSuchMethodException e) {
- if (clazz.getSuperclass()!=null) {
+ if (clazz.getSuperclass() != null) {
return getMethod(clazz.getSuperclass(), methodName, parameterTypes, original);
} else {
- throw new JbpmException("couldn't find method '"+original.getName()+"."+methodName+"("+getParameterTypesText(parameterTypes)+")'", e);
+ throw new JbpmException("couldn't find method '" + original.getName() + "." + methodName
+ + "(" + getParameterTypesText(parameterTypes) + ")'", e);
}
}
@@ -93,12 +97,12 @@
}
private static String getParameterTypesText(Class<?>[] parameterTypes) {
- if (parameterTypes==null) return "";
+ if (parameterTypes == null) return "";
StringBuilder parameterTypesText = new StringBuilder();
- for (int i=0; i<parameterTypes.length; i++) {
+ for (int i = 0; i < parameterTypes.length; i++) {
Class<?> parameterType = parameterTypes[i];
parameterTypesText.append(parameterType.getName());
- if (i!=parameterTypes.length-1) {
+ if (i != parameterTypes.length - 1) {
parameterTypesText.append(", ");
}
}
@@ -106,7 +110,7 @@
}
public static <T> T newInstance(Class<T> clazz) {
- if (clazz==null) {
+ if (clazz == null) {
throw new IllegalArgumentException("cannot create new instance without class");
}
try {
@@ -123,7 +127,9 @@
}
Class<T> clazz = constructor.getDeclaringClass();
- if (log.isTraceEnabled()) log.trace("creating new instance for "+clazz+" with args "+Arrays.toString(args));
+ if (log.isTraceEnabled()) {
+ log.trace("creating new instance for " + clazz.getName() + " with args " + Arrays.toString(args));
+ }
if (!constructor.isAccessible()) {
if (log.isTraceEnabled()) log.trace("making constructor accessible");
constructor.setAccessible(true);
@@ -148,19 +154,21 @@
}
try {
Object value = field.get(object);
- if (log.isTraceEnabled()) log.trace("got value '"+value+"' from field '"+field.getName()+"'");
+ if (log.isTraceEnabled()) {
+ log.trace("got value '" + value + "' from field '" + field.getName() + "'");
+ }
return value;
} catch (Exception e) {
- throw new JbpmException("couldn't get '"+field.getName()+"'", e);
+ throw new JbpmException("couldn't get '" + field.getName() + "'", e);
}
}
public static void set(Field field, Object object, Object value) {
- if (field==null) {
+ if (field == null) {
throw new NullPointerException("field is null");
}
try {
- if (log.isTraceEnabled()) log.trace("setting field '"+field.getName()+"' to value '"+value+"'");
+ if (log.isTraceEnabled()) log.trace("setting field '" + field.getName() + "' to value '" + value + "'");
if (!field.isAccessible()) {
if (log.isTraceEnabled()) log.trace("making field accessible");
field.setAccessible(true);
@@ -410,7 +418,7 @@
}
public static void uninstallDeploymentClassLoader(ClassLoader original) {
- if (original!=null) {
+ if (original != null) {
Thread.currentThread().setContextClassLoader(original);
}
}
@@ -446,4 +454,13 @@
}
return Class.forName(name);
}
+
+ public static URL findResource(String name) {
+ ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
+ URL resource = contextClassLoader.getResource(name);
+ if (resource == null) {
+ resource = ReflectUtil.class.getClassLoader().getResource(name);
+ }
+ return resource;
+ }
}
Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/xml/Parser.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/xml/Parser.java 2010-10-17 14:44:27 UTC (rev 6765)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/xml/Parser.java 2010-10-17 15:31:46 UTC (rev 6766)
@@ -40,44 +40,45 @@
import org.jbpm.internal.log.Log;
import org.jbpm.pvm.internal.stream.StreamInput;
+import org.jbpm.pvm.internal.util.ReflectUtil;
import org.jbpm.pvm.internal.util.UrlEntity;
import org.jbpm.pvm.internal.util.XmlUtil;
import org.jbpm.pvm.internal.wire.Descriptor;
import org.jbpm.pvm.internal.wire.descriptor.ArgDescriptor;
import org.jbpm.pvm.internal.wire.xml.WireParser;
-/** makes typical usage of JAXP more convenient, adds a binding framework,
+/** makes typical usage of JAXP more convenient, adds a binding framework,
* entity resolution and error handling.
- *
+ *
* <h2>Purpose</h2>
* <p>This is a base parser for the common pattern where first JAXP is used
* to parse xml into a Document Object Model (DOM), and then, this DOM is
- * examined to build a domain model object. The main purpose of this parser
- * is to serve as a base class for implementing such parsers and to provide
+ * examined to build a domain model object. The main purpose of this parser
+ * is to serve as a base class for implementing such parsers and to provide
* a more convenient API for working with JAXP.
* </p>
- *
- * <p>A {@link Parser} is a thread safe object. For each parse operation, a
- * new {@link Parse} object is created with method {@link #createParse()}.
- * Then the parse object is used to specify the input source, execute the
- * parse operation and extract the results.
+ *
+ * <p>A {@link Parser} is a thread safe object. For each parse operation, a
+ * new {@link Parse} object is created with method {@link #createParse()}.
+ * Then the parse object is used to specify the input source, execute the
+ * parse operation and extract the results.
* </p>
- *
+ *
* <p>{@link Binding}s capture parsing of a certain element type. This way,
* the parser becomes more modular and customizable.
* </p>
- *
- * <p>{@link Entity Entities} are schema's that specify the grammar of the
- * XML files that are parsed by the parser.
+ *
+ * <p>{@link Entity Entities} are schema's that specify the grammar of the
+ * XML files that are parsed by the parser.
* </p>
- *
+ *
* <h2>API Usage</h2>
- * <p>Parsers can be customized by inheritance (that will be covered below),
+ * <p>Parsers can be customized by inheritance (that will be covered below),
* but a parser can also be used as is:
* </p>
*
* <pre><i> 1 </i>| static Parser parser = new Parser();
- *<i> 2 </i>|
+ *<i> 2 </i>|
*<i> 3 </i>| void someMethod() {
*<i> 4 </i>| MyDomainObject mdo = (MyDomainObject) parser
*<i> 5 </i>| .createParse()
@@ -87,45 +88,45 @@
*<i> 9 </i>| .getDocumentObject();
*<i>10 </i>| }
* </pre>
- *
- * <p><b>line 1</b> shows that a single parser can be used for all threads as
+ *
+ * <p><b>line 1</b> shows that a single parser can be used for all threads as
* the parser is maintained in a static member field.
* </p>
*
- * <p><b>line 5</b> shows that a new parse operation is always started with
- * the {@link #createParse()} operation. The {@link Parse} object that is
- * returned will maintain all data that is related to that single parse
- * operation.
+ * <p><b>line 5</b> shows that a new parse operation is always started with
+ * the {@link #createParse()} operation. The {@link Parse} object that is
+ * returned will maintain all data that is related to that single parse
+ * operation.
* </p>
*
- * <p><b>line 6</b> shows how a simple XML string can be provided as the input
- * source for the parse operation. Alternative methods to specify the input
- * source are {@link Parse#setFile(java.io.File)},
- * {@link Parse#setInputStream(java.io.InputStream)},
+ * <p><b>line 6</b> shows how a simple XML string can be provided as the input
+ * source for the parse operation. Alternative methods to specify the input
+ * source are {@link Parse#setFile(java.io.File)},
+ * {@link Parse#setInputStream(java.io.InputStream)},
* {@link Parse#setInputSource(InputSource)},
* {@link Parse#setUrl(java.net.URL)} and
- * {@link Parse#setStreamSource(StreamInput)}.
+ * {@link Parse#setStreamSource(StreamInput)}.
* </p>
*
- * <p><b>line 7</b> shows how the execution of the parse is performed. The
- * input source will be read, the resulting Document Object Model (DOM) will
+ * <p><b>line 7</b> shows how the execution of the parse is performed. The
+ * input source will be read, the resulting Document Object Model (DOM) will
* be walked and potentially problems are produced in the parse.
* </p>
*
* <p><b>line 8</b> shows how an exception can be thrown in case of an error.
- * The parse execution itself tries to keep parsing as much as possible to
+ * The parse execution itself tries to keep parsing as much as possible to
* provide the developer with as much feedback as possible in one parse cycle.
* The {@link Parse#getProblems() problems} are silently captured in the parse
- * object. If an exception is thrown by
- * {@link Parse#checkErrors(String)}, it will contain a report of
+ * object. If an exception is thrown by
+ * {@link Parse#checkErrors(String)}, it will contain a report of
* all the parsing problems. Alternatively, the {@link Parse#getProblems() problems
- * in the parse object} could be examined directly without the need for an exception.
+ * in the parse object} could be examined directly without the need for an exception.
* </p>
*
- * <p><b>line 9</b> shows how the result of the parse operation is extracted
- * from the parse object.
+ * <p><b>line 9</b> shows how the result of the parse operation is extracted
+ * from the parse object.
* </p>
- *
+ *
* <h2 id="binding">Binding</h2>
* <p>Bindings are the link between a certain type of element in your XML document
* and the corresponding java object in your domain model.</p>
@@ -217,16 +218,16 @@
* you start adding more bindings to the specialized parser. Otherwise the
* base parser's bindings will be updated as well.
* </p>
- *
+ *
* <h2 id="buildingcustomparsers">Building custom parsers</h2>
- *
- * <p>This parser is build for inheritance.
- * Overriding method {@link #parseDocumentElement(Element, Parse)} can be an easy
+ *
+ * <p>This parser is build for inheritance.
+ * Overriding method {@link #parseDocumentElement(Element, Parse)} can be an easy
* way to start writing your own logic on walking the Document Object Model (DOM).
- * Such customizations can still be combined with the usage of
+ * Such customizations can still be combined with the usage of
* <a href="#binding">bindings</a>.
* </p>
- *
+ *
* <h2 id="entityresolving">Entity resolving</h2>
* <p>A parser can be configured with a set of entities with the
* {@link #addEntity(String, Entity)} method. The {@link UrlEntity} has
@@ -285,7 +286,7 @@
// document builder methods /////////////////////////////////////////////////
- /** customizable creation of a new document builder. Used by
+ /** customizable creation of a new document builder. Used by
* {@link #buildDocument(Parse)}. */
protected DocumentBuilder createDocumentBuilder(Parse parse) {
try {
@@ -304,12 +305,11 @@
public void setSchemaResources(String... schemaResources) {
// load resources from classpath
- ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
String[] schemaSources = new String[schemaResources.length];
for (int i = 0; i < schemaResources.length; i++) {
String schemaResource = schemaResources[i];
- URL schemaLocation = classLoader.getResource(schemaResource);
+ URL schemaLocation = ReflectUtil.findResource(schemaResource);
if (schemaLocation != null) {
log.info("loading schema resource: " + schemaResource);
schemaSources[i] = schemaLocation.toString();
@@ -388,15 +388,15 @@
}
// runtime parsing methods //////////////////////////////////////////////////
-
- /** main method to start a new parse, check {@link Parse} for specifying
+
+ /** main method to start a new parse, check {@link Parse} for specifying
* input, executing the parse and extracting the results. */
public Parse createParse() {
return new Parse(this);
}
- /** builds a dom from the importedStreamSource and appends the child elements
- * of the document element to the destination element. Problems are reported
+ /** builds a dom from the importedStreamSource and appends the child elements
+ * of the document element to the destination element. Problems are reported
* in the importingParse. */
public void importStream(StreamInput importedStreamInput, Element destination, Parse importingParse) {
try {
@@ -466,15 +466,15 @@
// Document Object Model walking ////////////////////////////////////////////
/** start of the DOM walk.
- *
- * This method is used as part of
+ *
+ * This method is used as part of
* {@link #execute(Parse) the parse execution}.
- *
- * This default implementation behaviour extracts the document element and
+ *
+ * This default implementation behaviour extracts the document element and
* delegates to {@link #parseDocumentElement(Element, Parse)}.
*
* This method can be overridden for customized behaviour.
- *
+ *
* @return the object that is the result from parsing this document. */
public Object parseDocument(Document document, Parse parse) {
Object object = parseDocumentElement(document.getDocumentElement(), parse);
@@ -482,29 +482,29 @@
return object;
}
- /** parses the top level element in the document and produces the object that
- * is the result from the parsing.
+ /** parses the top level element in the document and produces the object that
+ * is the result from the parsing.
*
* @return the object that is the result from parsing this document element. */
public Object parseDocumentElement(Element documentElement, Parse parse) {
return parseElement(documentElement, parse);
}
- /** parses an arbitrary element in the document with the first matching
+ /** parses an arbitrary element in the document with the first matching
* binding found using any of the categories.
- *
+ *
* @return the object that is the result from parsing this element. */
public Object parseElement(Element element, Parse parse) {
return parseElement(element, parse, null);
}
- /** parses an arbitrary element in the document based on the bindings in the
+ /** parses an arbitrary element in the document based on the bindings in the
* given category.
- *
- * @param category is the category in which the tagName should be resolved to
- * a {@link Binding}. If category is null, all the categories will be
+ *
+ * @param category is the category in which the tagName should be resolved to
+ * a {@link Binding}. If category is null, all the categories will be
* scanned for an appropriate binding in random order.
- *
+ *
* @return the object that is the result from parsing this element. */
public Object parseElement(Element element, Parse parse, String category) {
Object object = null;
13 years, 6 months
JBoss JBPM SVN: r6765 - in jbpm4/trunk/modules: devguide/src/main/docbook/en/modules and 2 other directories.
by do-not-reply@jboss.org
Author: rebody
Date: 2010-10-17 10:44:27 -0400 (Sun, 17 Oct 2010)
New Revision: 6765
Modified:
jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/parser/BpmnParser.java
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch03-Bpmn2.xml
jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/bpmn/test/deployment/Bpmn2DeploymentTest.java
jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/bpmn/test/startevent/TimerStartEventTest.java
Log:
JBPM-2830 change the strategy of BPMN name and key convertion
Modified: jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/parser/BpmnParser.java
===================================================================
--- jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/parser/BpmnParser.java 2010-10-16 13:44:02 UTC (rev 6764)
+++ jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/parser/BpmnParser.java 2010-10-17 14:44:27 UTC (rev 6765)
@@ -105,14 +105,15 @@
String id = XmlUtil.attribute(processElement, "id", parse);
String name = XmlUtil.attribute(processElement, "name");
- if (id != null && !"".equals(id)) {
- processDefinition.setName(id);
- } else {
+ if (id == null || "".equals(id.trim())) {
parse.addProblem("Process has no or an empty id");
}
if (name != null) {
- processDefinition.setKey(name);
+ processDefinition.setName(name);
+ processDefinition.setKey(id);
+ } else {
+ processDefinition.setName(id);
}
Element descriptionElement = XmlUtil.element(processElement, "documentation");
Modified: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch03-Bpmn2.xml
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch03-Bpmn2.xml 2010-10-16 13:44:02 UTC (rev 6764)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch03-Bpmn2.xml 2010-10-17 14:44:27 UTC (rev 6765)
@@ -1,63 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter id="bpmn2">
-
+
<title>BPMN 2.0</title>
-
+
<section id="whatIsBpmn">
-
+
<title>What is BPMN 2.0?</title>
-
+
<para>
- The Business Process Modeling Notation (BPMN) is a standard for the
- graphical notation of business process models. The standard is
- maitained by the Object Management Group (OMG).
- </para>
- <para>
- Basically, the BPMN specification defines how a task must look like, which constructs can
- be connected to each other, etc. in a meaning that cannot be
- misinterpreted.
- </para>
+ The Business Process Modeling Notation (BPMN) is a standard for the
+ graphical notation of business process models. The standard is
+ maitained by the Object Management Group (OMG).
+ </para>
+ <para>
+ Basically, the BPMN specification defines how a task must look like, which constructs can
+ be connected to each other, etc. in a meaning that cannot be
+ misinterpreted.
+ </para>
<para>
- Earlier versions of the standard (<= version 1.2) are limited to the modeling
- only, aiming at a common understanding between all stakeholders
- involved in documenting, discussing and implementing business
- processes. The BPMN standard has proven itself, as many modeling tools
- on the market today use the symbols and constructs specified in the
- BPMN standard. In fact, the current JPDL designer also uses BPMN
- symbols.
- </para>
+ Earlier versions of the standard (<= version 1.2) are limited to the modeling
+ only, aiming at a common understanding between all stakeholders
+ involved in documenting, discussing and implementing business
+ processes. The BPMN standard has proven itself, as many modeling tools
+ on the market today use the symbols and constructs specified in the
+ BPMN standard. In fact, the current JPDL designer also uses BPMN
+ symbols.
+ </para>
<para>
- Version 2.0 of the BPMN specification, which is currently in finalization phase and is
- scheduled to be finished soon, allows to add precise technical
- details to the shapes and symbols available in BPMN and at the same
- time specify what the execution semantics of BPMN 'elements' are. By
- using an XML language to specify the executable semantics of a business
- process, the BPMN specification has evolved into a language for
- business processes that can be executed on any BPMN2 compliant process
- engine - while still having the powerful graphical notation.
+ Version 2.0 of the BPMN specification, which is currently in finalization phase and is
+ scheduled to be finished soon, allows to add precise technical
+ details to the shapes and symbols available in BPMN and at the same
+ time specify what the execution semantics of BPMN 'elements' are. By
+ using an XML language to specify the executable semantics of a business
+ process, the BPMN specification has evolved into a language for
+ business processes that can be executed on any BPMN2 compliant process
+ engine - while still having the powerful graphical notation.
</para>
-
+
</section>
-
+
<section id="historyAndGodl">
-
+
<title>History and goal</title>
-
+
<para>
- The jBPM BPMN2 implementation was started in close collaboration with the
- community in augustus 2009 after releasing jBPM 4.0.
- Later, it was decided that the first release (ie documented/QA'd) to
- incorporate parts of the BPMN2 spec would be jBPM 4.3.
- </para>
+ The jBPM BPMN2 implementation was started in close collaboration with the
+ community in augustus 2009 after releasing jBPM 4.0.
+ Later, it was decided that the first release (ie documented/QA'd) to
+ incorporate parts of the BPMN2 spec would be jBPM 4.3.
+ </para>
<para>
- The goal of this effort is to build a <emphasis role="bold">native BPMN2 runtime engine </emphasis>
- (or better said implementing 'BPMN2 exectuable') leveraging the Process
- Virtual Machine (PVM).
- Do note that the primary focus of this release is native executability,
- not the graphical notation - but we recognize its importance for
- further releases.
+ The goal of this effort is to build a <emphasis role="bold">native BPMN2 runtime engine </emphasis>
+ (or better said implementing 'BPMN2 exectuable') leveraging the Process
+ Virtual Machine (PVM).
+ Do note that the primary focus of this release is native executability,
+ not the graphical notation - but we recognize its importance for
+ further releases.
</para>
-
+
<para>
<emphasis role="bold">
Users who are already familiar with jBPM will find that
@@ -71,152 +71,166 @@
So in general, our main goal is to keep everything that was good about jBPM, and enhance
it with a standards based process language.
</para>
-
+
</section>
-
+
<section id="jpdlVsBpmn2" >
-
+
<title>JPDL vs BPMN 2.0</title>
-
- <para>
- One of the first questions that might, rightfully, come to mind is why
- BPMN2 is being implemented while there is jPDL. Both are languages
- have as goal to define executable business processes. From a high-level
- technical point of view, both languages are equivalent. The main
- distinction is that BPMN2 is as vendor-neutral as you can have with
- standards, while JPDL has always been tied to jBPM (although some might
- argue that a vendor lock-in for an open-source process language such as
- JPDL is less a lock-in than with closed-source products).
- </para>
+
+ <para>
+ One of the first questions that might, rightfully, come to mind is why
+ BPMN2 is being implemented while there is jPDL. Both are languages
+ have as goal to define executable business processes. From a high-level
+ technical point of view, both languages are equivalent. The main
+ distinction is that BPMN2 is as vendor-neutral as you can have with
+ standards, while JPDL has always been tied to jBPM (although some might
+ argue that a vendor lock-in for an open-source process language such as
+ JPDL is less a lock-in than with closed-source products).
+ </para>
<para>
- Within jBPM, both language implementations are built on top of the jBPM
- Process Virtual Machine (PVM). This means that both languages share a
- common foundation (persistence, transactions, configuration, but also
- basic process constructs, etc.). As a result, optimizations to the core
- of jBPM often benefits both languages. Leveraging the PVM, the BPMN2
- implementation is built upon a foundation that has already proven
- itself in the past and has a large end-user community.
- </para>
+ Within jBPM, both language implementations are built on top of the jBPM
+ Process Virtual Machine (PVM). This means that both languages share a
+ common foundation (persistence, transactions, configuration, but also
+ basic process constructs, etc.). As a result, optimizations to the core
+ of jBPM often benefits both languages. Leveraging the PVM, the BPMN2
+ implementation is built upon a foundation that has already proven
+ itself in the past and has a large end-user community.
+ </para>
<para>
- When evaluating the languages and comparing them which each other however,
- following points must be taken into consideration:
- <itemizedlist>
+ When evaluating the languages and comparing them which each other however,
+ following points must be taken into consideration:
+ <itemizedlist>
<listitem>BPMN2 is based on a standard accepted by the BPM industry.</listitem>
<listitem>BPMN2 is implementation-unaware. The downside of this is that
- integrating with Java technology will always be easier with JPDL. So,
- from a Java developer's perspective JPDL is simpler and feels more
- natural (some of the 'layers' of BPEL/WSDL are in BPMN as well).</listitem>
+ integrating with Java technology will always be easier with JPDL. So,
+ from a Java developer's perspective JPDL is simpler and feels more
+ natural (some of the 'layers' of BPEL/WSDL are in BPMN as well).</listitem>
<listitem>A focus of JPDL is XML readability. BPMN2 processes will still be
- readable to a certain level, but tooling or a more detailed knowledge
- of the spec will definitely be required to achieve the same level of
- productivity.</listitem>
+ readable to a certain level, but tooling or a more detailed knowledge
+ of the spec will definitely be required to achieve the same level of
+ productivity.</listitem>
<listitem>Java developers who are super-fast in JPDL since they know the JPDL
- language by heart, will find the use of tools sometimes bothersome and
- the language itself overly complicated.</listitem>
+ language by heart, will find the use of tools sometimes bothersome and
+ the language itself overly complicated.</listitem>
<listitem>BPMN2 contains a large set of constructs described in the
- specification. However, the "binding" of interfaces to code is left
- open in the spec (comparable with XPDL), even if WDSL is often considered the
- default. This means that a process portability can be lost when porting
- the process to an engine that doesn't support the same binding
- mechanism. Calling Java classes for example is already going to be such
- a jBPM specific binding.</listitem>
+ specification. However, the "binding" of interfaces to code is left
+ open in the spec (comparable with XPDL), even if WDSL is often considered the
+ default. This means that a process portability can be lost when porting
+ the process to an engine that doesn't support the same binding
+ mechanism. Calling Java classes for example is already going to be such
+ a jBPM specific binding.</listitem>
</itemizedlist>
- </para>
+ </para>
<para>
- It is natural to the political level of BPMN2 specification process to go
- rather slow. JPDL on the other hand will be able to incorporate changes
- faster, integrate with new technologies when they are released and
- evolve generally at a quicker pace compared to BPMN2.
-
- Of course, since both are built on top of the same PVM, it is only
- logical that additions to JPDL can be ported to BPMN2 as an extension
- without much hassle.
- </para>
-
+ It is natural to the political level of BPMN2 specification process to go
+ rather slow. JPDL on the other hand will be able to incorporate changes
+ faster, integrate with new technologies when they are released and
+ evolve generally at a quicker pace compared to BPMN2.
+
+ Of course, since both are built on top of the same PVM, it is only
+ logical that additions to JPDL can be ported to BPMN2 as an extension
+ without much hassle.
+ </para>
+
+ <para>
+ When we deploy a BPMN 2.0 process, follows these rules:
+ <itemizedlist>
+ <listitem>
+ <para>When there is no id attribute on BPMN 2.0 process, deploy failed.</para>
+ </listitem>
+ <listitem>
+ <para>When there is only an id attribute on BPMN 2.0 process, using id attribute as process definition name.</para>
+ </listitem>
+ <listitem>
+ <para>When there is both id and name attributes on BPMN 2.0 process, using id as key, using name as name for process definition.</para>
+ </listitem>
+ </itemizedlist>
+ </para>
</section>
-
+
<section id="Bpmn2Execution" >
-
+
<title>Bpmn 2.0 execution</title>
<para>
- The BPMN2 specification defines a very rich language for modeling and
- executing business processes. However, this also means that it is quite
- hard to get an overview of what's possible with BPMN2. To simplify this
- situation, we've decided to categorize the BPMN2 constructs into three
- 'levels'. The separation itself is primarily based on the book 'BPMN
- method and Style' by Bruce Silver (<ulink url="http://www.bpmnstyle.com/">http://www.bpmnstyle.com/</ulink>), the
- training material of Dr. Jim Arlow
- (<ulink url="http://www.slideshare.net/jimarlow/introductiontobpmn005">http://www.slideshare.net/jimarlow/introductiontobpmn005</ulink>),
- 'How much BPMN do you need'
- (<ulink url="http://www.bpm-research.com/2008/03/03/how-much-bpmn-do-you-need/">http://www.bpm-research.com/2008/03/03/how-much-bpmn-do-you-need/</ulink>),
- and also our own experience.
- </para>
- <para>
- We define three categories of BPMN2 constructs:
- <itemizedlist>
- <listitem><emphasis role="bold">Basic</emphasis>: constructs in this category are
- straight-forward and easy to grasp. Constructs in this category can be used to
- model simple business processes.</listitem>
- <listitem><emphasis role="bold">Advanced</emphasis>: contains more powerful or
- expressive constructs, but this comes with higher modeling and execution semantics
- learning curve. The majority of business processes are implementable with constructs from this
- and the previous category.</listitem>
- <listitem><emphasis role="bold">Complex</emphasis>: constructs in this category are
- used in specific and/or rare cases, or their semantics are difficult to understand.</listitem>
- </itemizedlist>
+ The BPMN2 specification defines a very rich language for modeling and
+ executing business processes. However, this also means that it is quite
+ hard to get an overview of what's possible with BPMN2. To simplify this
+ situation, we've decided to categorize the BPMN2 constructs into three
+ 'levels'. The separation itself is primarily based on the book 'BPMN
+ method and Style' by Bruce Silver (<ulink url="http://www.bpmnstyle.com/">http://www.bpmnstyle.com/</ulink>), the
+ training material of Dr. Jim Arlow
+ (<ulink url="http://www.slideshare.net/jimarlow/introductiontobpmn005">http://www.slideshare.net/jimarlow/introductiontobpmn005</ulink>),
+ 'How much BPMN do you need'
+ (<ulink url="http://www.bpm-research.com/2008/03/03/how-much-bpmn-do-you-need/">http://www.bpm-research.com/2008/03/03/how-much-bpmn-do-you-need/</ulink>),
+ and also our own experience.
+ </para>
+ <para>
+ We define three categories of BPMN2 constructs:
+ <itemizedlist>
+ <listitem><emphasis role="bold">Basic</emphasis>: constructs in this category are
+ straight-forward and easy to grasp. Constructs in this category can be used to
+ model simple business processes.</listitem>
+ <listitem><emphasis role="bold">Advanced</emphasis>: contains more powerful or
+ expressive constructs, but this comes with higher modeling and execution semantics
+ learning curve. The majority of business processes are implementable with constructs from this
+ and the previous category.</listitem>
+ <listitem><emphasis role="bold">Complex</emphasis>: constructs in this category are
+ used in specific and/or rare cases, or their semantics are difficult to understand.</listitem>
+ </itemizedlist>
</para>
-
- </section>
-
+
+ </section>
+
<section id="bpmn2Config">
-
+
<title>Configuration</title>
-
+
<para>
Enabling BPMN 2.0 in your application is extremely simple: just add the following line
to the <emphasis role="bold">jbpm.cfg.xml</emphasis> file.
<programlisting>
-<import resource="jbpm.bpmn.cfg.xml" />
+<import resource="jbpm.bpmn.cfg.xml" />
</programlisting>
This import will enable BPMN 2.0 process deployment by installing a BPMN 2.0 deployer
in the Process Engine. Do note that a Process Engine can cope with both JPDL and BPMN 2.0
processes. This means that in your application, some processes can be JPDL and others
can be BPMN 2.0.
</para>
-
+
<para>
<emphasis role="bold">Process definitions are distinguished by the process engine
based on the extension of the definition file. For BPMN 2.0, use the *.bpmn.xml extension
(where JPDL is having the *.jpdl.xml extension).</emphasis>
</para>
-
+
</section>
-
+
<section id="bpmn2Examples">
-
+
<title>Examples</title>
-
+
<para>
- The examples that are shipped with the distribution also contain examples for every
+ The examples that are shipped with the distribution also contain examples for every
construct that is discussed in the following sections. Look for example BPMN 2.0
processes and test cases in the <emphasis role="bold">org.jbpm.examples.bpmn.* package
</emphasis>.
</para>
-
+
<para>
See the userguide, chapter 2 (Installation), for a walktough on how to import the examples.
Look for the section <emphasis role="bold">'Importing the Examples'</emphasis>.
</para>
-
+
</section>
-
+
<section id="definitionsAndProcess">
-
+
<title>Process root element</title>
-
+
<para>
- The root of an BPMN 2.0 XML process is the <emphasis role="bold">definitions</emphasis>
+ The root of an BPMN 2.0 XML process is the <emphasis role="bold">definitions</emphasis>
elements. As the name states, the subelements will contain the actual definitions of
the business process(es). Every <emphasis role="bold">process</emphasis> child
will be able to have an <emphasis role="bold">id (required)</emphasis> and
@@ -227,36 +241,36 @@
<definitions id="myProcesses"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schema.omg.org/spec/BPMN/2.0 BPMN20.xsd"
- xmlns="http://schema.omg.org/spec/BPMN/2.0"
+ xmlns="http://schema.omg.org/spec/BPMN/2.0"
typeLanguage="http://www.w3.org/2001/XMLSchema"
- expressionLanguage="http://www.w3.org/1999/XPath"
+ expressionLanguage="http://www.w3.org/1999/XPath"
targetNamespace="http://jbpm.org/example/bpmn2">
- <process id="My business processs" name="myBusinessProcess">
-
+ <process id="My business processs" name="myBusinessProcess">
+
...
-
+
</process>
-<definitions>
+<definitions>
</programlisting>
If a name is defined for the process element, it is be used as <emphasis role="bold">key</emphasis>
for that process (ie. starting a process can be done by calling executionService.startProcessInstanceByKey("myBusinessProcess").
If no name is defined, the id will be used as key. So having only an id defined, will allow
- to start a process instance using that id. So basically, name and key are of equivalent
+ to start a process instance using that id. So basically, name and key are of equivalent
in usage, for example to search process definitions. Note that for a key the same rules apply as with
JPDL: whitespace and non alpha-numeric characters are replaced by an underscore.
</para>
-
+
</section>
-
+
<section id="basicConstructs">
-
+
<title>Basic constructs</title>
-
+
<section id="basicConstructsEvents">
-
+
<title>Events</title>
-
+
<para>
Together with activitites and gateways, events are used in practically every business process.
Events allow process modelers to describe business processes in a very natural way, such as
@@ -267,70 +281,70 @@
always work in a very event-driven way. People are not hard-coded sequential creatures,
but they tend to react on things that happen in their environment (ie. events).
In the BPMN specification, a great number of event types are described, to cover the
- range of possible things that might occur in context of a business.
+ range of possible things that might occur in context of a business.
</para>
-
- </section>
-
+
+ </section>
+
<section id="noneStartEvent">
-
+
<title>Event: None start event</title>
-
+
<para>
A start event indicates the start of process (or a subprocess). Graphically, it is visualized
- as a circle with (possibly) a small icon inside. The icon specifies the actual type of event
+ as a circle with (possibly) a small icon inside. The icon specifies the actual type of event
that will trigger the process instance creation.
</para>
-
+
<para>
The 'none start event' is drawn as a circle without an icon inside, which means that the
trigger is unknown or unspecified. The start activity of JPDL basically has the same
- semantics. Process instances whose process definition has a 'none start event' are
+ semantics. Process instances whose process definition has a 'none start event' are
created using the typical API calls on the <emphasis role="bold">executionService</emphasis>.
</para>
-
+
<para>
A none start event is defined as follows. An id is required, a name is optional.
<programlisting>
-<startEvent id="start" name="myStart" />
+<startEvent id="start" name="myStart" />
</programlisting>
</para>
-
+
</section>
<section id="noneEndEvent">
- <title>Event: None end event</title>
+ <title>Event: None end event</title>
- <para>
- An end event indicates the end of an execution path in a process
- instance. Graphically,
- it is visualized as a circle with a thick border with (possibly) a
- small icon inside.
- The icon specifies the type of signal that is thrown when the end is
- reached.
+ <para>
+ An end event indicates the end of an execution path in a process
+ instance. Graphically,
+ it is visualized as a circle with a thick border with (possibly) a
+ small icon inside.
+ The icon specifies the type of signal that is thrown when the end is
+ reached.
</para>
-
+
<para>
The 'none end event' is drawn as a circle with thick border with no icon inside,
which means that no signal is thrown when the execution reaches the event.
The end activity in JPDL has the same semantics as the none end event.
</para>
-
+
<para>
A none end event is defined as follows. An id is required, a name is optional.
<programlisting>
-<endEvent id="end" name="myEnd" />
+<endEvent id="end" name="myEnd" />
</programlisting>
</para>
-
+
<para>
The following example shows a process with only a none start and end event:
<mediaobject><imageobject><imagedata align="center" fileref="images/bpmn2.none.start.end.event.png"/></imageobject></mediaobject>
</para>
-
+
<para>
- The corresponding executable XML for this process looks like this (omitting the
+ The corresponding executable XML for this process looks like this (omitting the
<emphasis>definitions</emphasis> root element for clarity)
<programlisting>
<process id="noneStartEndEvent" name="BPMN2 Example none start and end event">
@@ -342,43 +356,43 @@
<emphasis role="bold"><endEvent id="end" name="End" /></emphasis>
- </process>
+ </process>
</programlisting>
</para>
-
+
<para>
- A process instances can now be created by calling the
+ A process instances can now be created by calling the
<emphasis role="bold">startProcessInstanceXXX</emphasis> operations.
<programlisting>
ProcessInstance processInstance = executionService.startProcessInstanceByKey("noneStartEndEvent");
</programlisting>
</para>
-
+
</section>
-
+
<section id="terminateEndEvent">
-
+
<title>Event: Terminate end event</title>
-
+
<para>
- The difference between a 'terminate' and a <link linkend="noneEndEvent">'none' end event</link>
+ The difference between a 'terminate' and a <link linkend="noneEndEvent">'none' end event</link>
lies in the fact how a path of execution is treated (or a 'token' in BPMN 2.0 terminology).
- The 'terminate' end event will end the complete process instance, whereas the 'none'
+ The 'terminate' end event will end the complete process instance, whereas the 'none'
end event will only end the current path of execution. They both don't throw anything
when the end event is reached.
</para>
-
+
<para>
A terminate end event is defined as follows. An id is required, a name is optional.
<programlisting>
<endEvent id="terminateEnd" name="myTerminateEnd">
<emphasis role="bold"><terminateEventDefinition/></emphasis>
-</endEvent>
+</endEvent>
</programlisting>
</para>
-
+
<para>
- A terminate end event is depicted as an end event (circle with thick border),
+ A terminate end event is depicted as an end event (circle with thick border),
with a full circle as icon inside. In the following example, completing the 'task1'
will end the process instance, while completing the 'task2' will only end the path
of execution which enters the end event, leaving the task1 open.
@@ -386,25 +400,25 @@
See the examples shipped with the jBPM distribution for the unit test and XML counterpart
of this business process.
</para>
-
+
</section>
-
+
<section id="sequenceFlow">
-
+
<title>Sequence Flow</title>
-
+
<para>
A sequence flow is the connection between events, activities and gateways shown as a
solid line with an arrow in a BPMN diagram (JPDL equivalent is the transition).
- Each sequence flow has exactly one <emphasis role="bold">source</emphasis> and exactly one
- <emphasis role="bold">target</emphasis> reference, that contains the <emphasis role="bold">id</emphasis>
+ Each sequence flow has exactly one <emphasis role="bold">source</emphasis> and exactly one
+ <emphasis role="bold">target</emphasis> reference, that contains the <emphasis role="bold">id</emphasis>
of an activity, event or gateway.
<programlisting>
-<sequenceFlow id="myFlow" name="My Flow"
+<sequenceFlow id="myFlow" name="My Flow"
sourceRef="sourceId" targetRef="targetId" />
</programlisting>
</para>
-
+
<para>
An important difference with JPDL is the behaviour of multiple outgoing sequence flows.
In JPDL, only one transition is selected as outgoing transition, unless the activity
@@ -417,23 +431,23 @@
At runtime, only when the condition evaluates to true, that sequence flow will
be taken.
</para>
-
+
<para>
To put a condition on a sequence flow, add a <emphasis role="bold">conditionExpression
</emphasis> element to the sequence flow. Conditions are to be put between <emphasis role="bold">
${}</emphasis>.
<programlisting>
<sequenceFlow id=....>
- <emphasis role="bold"><conditionExpression xsi:type="tFormalExpression">${amount >= 500}</conditionExpression></emphasis>
-</sequenceFlow>
+ <emphasis role="bold"><conditionExpression xsi:type="tFormalExpression">${amount >= 500}</conditionExpression></emphasis>
+</sequenceFlow>
</programlisting>
Note that is currently is necessary to add the <emphasis role="bold">
xsi:type="tFormalExpression"</emphasis> to the <emphasis role="bold">
conditionExpression</emphasis>. A conditional sequence flow is visualized as a mini diamond
- shape at the beginning of the sequence flow. Keep in mind that conditions always can be defined
+ shape at the beginning of the sequence flow. Keep in mind that conditions always can be defined
on sequence flow, but some constructs will not interprete them (eg. parallel gateway).
</para>
-
+
<para>
Activities (such as the user task) and gateways (such as the exclusive gateway) can have a
default sequence flow. This default sequence flow is taken only when all the other outgoing
@@ -443,28 +457,28 @@
The default sequence flow is specified by filling in the <emphasis role="bold">'default'
attribute </emphasis> of the activity or gateway.
</para>
-
+
<para>
Also note that an expression on a default sequence flow is ignored.
</para>
-
+
</section>
-
+
<section id="gateway">
-
+
<title>Gateways</title>
-
+
<para>
- A gateway in BPMN is used to control the flow through the process. More specifically,
- when a token (the BPMN 2.0 conceptual notion of an execution) arrives in a gateway, it can be merged
+ A gateway in BPMN is used to control the flow through the process. More specifically,
+ when a token (the BPMN 2.0 conceptual notion of an execution) arrives in a gateway, it can be merged
or split depending on the gateway type.
</para>
-
+
<para>
- Gateways are depicted as a diamond shape, with an icon inside specifying the type
+ Gateways are depicted as a diamond shape, with an icon inside specifying the type
(exclusive, inclusive, etc.).
</para>
-
+
<para>
On every gateway type, the attribute <emphasis role="bold">gatewayDirection</emphasis>
can be set. following values are possible:
@@ -489,38 +503,38 @@
Take for example the following example: a parallel gateway that has as gatewayDirection
'converging', will have a join behaviour.
<programlisting>
-<parallelGateway id="myJoin" name="My synchronizing join" gatewayDirection="converging" />
+<parallelGateway id="myJoin" name="My synchronizing join" gatewayDirection="converging" />
</programlisting>
- <emphasis role="bold">Note</emphasis>: the 'gatewayDirection' attribute is optional according
+ <emphasis role="bold">Note</emphasis>: the 'gatewayDirection' attribute is optional according
to the specification. This means that we cannot rely on this attribute at runtime to
know which type of behaviour a certain gateway has (for example for a parallel gateway if
- we have joining of forking behaviour). However, the 'gatewayDirection' attribute is used at parsing
- time as a constraint check for the incoming/outgoing sequence flow. So using this
+ we have joining of forking behaviour). However, the 'gatewayDirection' attribute is used at parsing
+ time as a constraint check for the incoming/outgoing sequence flow. So using this
attribute will lower the chance on errors when referencing sequence flow, but is not
required.
</para>
-
+
</section>
-
+
<section id="exclusiveGateway">
-
+
<title>Gateway: Exclusive Gateway</title>
-
+
<para>
An exclusive gateway represents an <emphasis role="bold">exclusive decision</emphasis>
in the process. Exactly one outgoing sequence flow will be taken, depending on the conditions
defined on the sequence flow.
</para>
-
+
<para>
- The corresponding JPDL construct with the same semantics is the
- <emphasis role="bold">decision</emphasis> activity. The full technical name of the
+ The corresponding JPDL construct with the same semantics is the
+ <emphasis role="bold">decision</emphasis> activity. The full technical name of the
exclusive gateway is the <emphasis role="bold">'exclusive data-based gateway'</emphasis>,
but it is also often called the <emphasis role="bold">XOR Gateway</emphasis>.
The XOR gateway is depicted as a diamond with a 'X' icon inside. An empty diamond
without a gateway also signifies an exclusive gateway.
</para>
-
+
<para>
The following diagram shows the usage of an exclusive gateway: depending on the value of the
amount variable, one of the three outgoing sequence flow out of the exclusive gateway
@@ -538,47 +552,47 @@
<sequenceFlow id="flow1" name="fromStartToExclusiveGateway"
sourceRef="start" targetRef="decideBasedOnAmountGateway" />
-
+
<emphasis role="bold"><exclusiveGateway id="decideBasedOnAmountGateway" name="decideBasedOnAmount" /></emphasis>
-
+
<sequenceFlow id="flow2" name="fromGatewayToEndNotEnough"
sourceRef="decideBasedOnAmountGateway" targetRef="endNotEnough">
<emphasis role="bold"><conditionExpression xsi:type="tFormalExpression">
${amount < 100}
</conditionExpression></emphasis>
</sequenceFlow>
-
+
<sequenceFlow id="flow3" name="fromGatewayToEnEnough"
sourceRef="decideBasedOnAmountGateway" targetRef="endEnough">
<emphasis role="bold"><conditionExpression xsi:type="tFormalExpression">
${amount <= 500 && amount >= 100}
</conditionExpression></emphasis>
</sequenceFlow>
-
+
<sequenceFlow id="flow4" name="fromGatewayToMoreThanEnough"
sourceRef="decideBasedOnAmountGateway" targetRef="endMoreThanEnough">
<emphasis role="bold"><conditionExpression xsi:type="tFormalExpression">
${amount > 500}
</conditionExpression></emphasis>
- </sequenceFlow>
+ </sequenceFlow>
<endEvent id="endNotEnough" name="not enough" />
-
+
<endEvent id="endEnough" name="enough" />
-
+
<endEvent id="endMoreThanEnough" name="more than enough" />
- </process>
+ </process>
</programlisting>
This process needs a variable such that the expression can be evaluated at runtime.
Variables can be provided when starting the process instance (similar to JPDL):
<programlisting>
Map<String, Object> vars = new HashMap<String, Object>();
vars.put("amount", amount);
-ProcessInstance processInstance = executionService.startProcessInstanceByKey("exclusiveGateway", vars);
+ProcessInstance processInstance = executionService.startProcessInstanceByKey("exclusiveGateway", vars);
</programlisting>
</para>
-
+
<para>
The exclusive gateway requires that all outgoing sequence flow have conditions defined
on them. An exception to this rule is the default sequence flow.
@@ -587,161 +601,161 @@
when the conditions on the other outgoing sequence flow all evaluate to false.
<programlisting>
<exclusiveGateway id="decision" name="decideBasedOnAmountAndBankType" <emphasis role="bold">default="myFlow"</emphasis>/>
-
+
<sequenceFlow id="myFlow" name="fromGatewayToStandard"
sourceRef="decision" targetRef="standard">
-</sequenceFlow>
+</sequenceFlow>
</programlisting>
- An exclusive gateway can have both convering and diverging functionality. The logic is
+ An exclusive gateway can have both convering and diverging functionality. The logic is
easy to grasp: for every execution that arrives at the gateway, one outgoing sequence
flow is selected to continue the flow. The following diagram is completely legal in
- BPMN 2.0 (omitting names and conditions for clarity).
+ BPMN 2.0 (omitting names and conditions for clarity).
<mediaobject><imageobject><imagedata align="center" fileref="images/bpmn2.exclusive.gateway.splitting.and.merging.png"/></imageobject></mediaobject>
</para>
-
+
</section>
-
+
<section id="parallelGateway">
-
+
<title>Gateway: Parallel Gateway</title>
-
+
<para>
A parallel gateway is used to split or synchronize the respectively incoming or outgoing
sequence flow.
<itemizedlist>
<listitem>
A parallel gateway with one incoming sequence flow and more than one outgoing sequence
- flow is called a <emphasis role="bold">'parallel split</emphasis> or an
+ flow is called a <emphasis role="bold">'parallel split</emphasis> or an
<emphasis role="bold">'AND-split'</emphasis>. All outgoing sequence flow are going to
be taken in parallel. <emphasis role="bold">Note: as defined by the specification,
conditions on the outgoing sequence flow are ignored.</emphasis>
</listitem>
<listitem>
A parallel gateway with multiple incoming sequence flow and one outgoing sequence flow
- is called a <emphasis role="bold">'parallel join'</emphasis> or an
+ is called a <emphasis role="bold">'parallel join'</emphasis> or an
<emphasis role="bold">AND-join</emphasis>. All incoming sequence flow need to arrive
in this parallel joing before the outgoing sequence flow is taken.
</listitem>
</itemizedlist>
A parallel gateway is defined as follows:
<programlisting>
-<parallelGateway id="myParallelGateway" name="My Parallel Gateway" />
+<parallelGateway id="myParallelGateway" name="My Parallel Gateway" />
</programlisting>
- Note that the 'gatewayDirection' attribute can be used to catch modeling errors at parsing
+ Note that the 'gatewayDirection' attribute can be used to catch modeling errors at parsing
time (see above).
</para>
-
+
<para>
The following diagram shows how a parallel gateway can be used. After process start,
both the 'prepare shipment' and 'bill customer' user tasks will be active.
- The parallel gateway is depicted as a diamond shape with a plus icon inside, both for the
+ The parallel gateway is depicted as a diamond shape with a plus icon inside, both for the
splitting and joining behaviour.
<mediaobject><imageobject><imagedata align="center" fileref="images/bpmn2.parallel.gateway.png"/></imageobject></mediaobject>
The XML counterpart of this diagram looks as follows:
<programlisting>
<process id="parallelGateway" name="BPMN2 example parallel gatewar">
-
+
<startEvent id="Start" />
<sequenceFlow id="flow1" name="fromStartToSplit"
sourceRef="Start"
targetRef="parallelGatewaySplit" />
- <emphasis role="bold"><parallelGateway id="parallelGatewaySplit" name="Split"
+ <emphasis role="bold"><parallelGateway id="parallelGatewaySplit" name="Split"
gatewayDirection="diverging"/></emphasis>
<sequenceFlow id="flow2a" name="Leg 1"
sourceRef="parallelGatewaySplit"
targetRef="prepareShipment" />
-
- <userTask id="prepareShipment" name="Prepare shipment"
+
+ <userTask id="prepareShipment" name="Prepare shipment"
implementation="other" />
-
+
<sequenceFlow id="flow2b" name="fromPrepareShipmentToJoin"
sourceRef="prepareShipment"
targetRef="parallelGatewayJoin" />
-
- <sequenceFlow id="flow3a" name="Leg 2"
+
+ <sequenceFlow id="flow3a" name="Leg 2"
sourceRef="parallelGatewaySplit"
targetRef="billCustomer" />
-
- <userTask id="billCustomer" name="Bill customer"
+
+ <userTask id="billCustomer" name="Bill customer"
implementation="other" />
-
+
<sequenceFlow id="flow3b" name="fromLeg2ToJoin"
sourceRef="billCustomer"
targetRef="parallelGatewayJoin" />
- <emphasis role="bold"><parallelGateway id="parallelGatewayJoin" name="Join"
+ <emphasis role="bold"><parallelGateway id="parallelGatewayJoin" name="Join"
gatewayDirection="converging"/></emphasis>
-
- <sequenceFlow id="flow4"
+
+ <sequenceFlow id="flow4"
sourceRef="parallelGatewayJoin"
targetRef="End">
</sequenceFlow>
<endEvent id="End" name="End" />
-
+
</process>
</programlisting>
- A parallel gateway (as is the case for any gateway) can have both splitting and
+ A parallel gateway (as is the case for any gateway) can have both splitting and
merging behaviour. The following diagram is completely legal BPMN 2.0. After process start,
- both task A and B will be active. When both A en B are completed, tasks C,D and E will be
- active.
+ both task A and B will be active. When both A en B are completed, tasks C,D and E will be
+ active.
<mediaobject><imageobject><imagedata align="center" fileref="images/bpmn2.parallel.gateway.splitting.and.merging.png"/></imageobject></mediaobject>
</para>
-
+
</section>
-
+
<section id="inclusiveGateway">
-
+
<title>Gateway: Inclusive Gateway</title>
-
+
<para>
An inclusive gateway - also called an <emphasis role="bold">OR-gateway</emphasis> - is used
- to 'conditionally' split or merge sequence flow. It basically behaves as a parallel
+ to 'conditionally' split or merge sequence flow. It basically behaves as a parallel
gateway, but it also takes in account conditions on the outgoing sequence flow (split behaviour)
and calculates if there are executions left that could reach the gateway (merge behaviour).
</para>
-
+
<para>
The inclusive gateway is depicted as a typical gateway shape with a circle inside (referring to 'OR' semantics).
Unlike the exclusive gateway, all condition expressions are evaluated (diverging or 'split' behaviour).
- For every expression that evaluates to true, a new child execution is created.
+ For every expression that evaluates to true, a new child execution is created.
Sequence flow without a condition will always be taken (ie. a child execution will always be
- created in that case).
+ created in that case).
</para>
-
+
<para>
A converging inclusive gateway ('merge' behaviour) has a somewhat more difficult execution logic.
- When an execution (Token in BPMN 2.0 terminology) arrives at the merging inclusive gateway,
- the following is checked (quoting the specification literally):
-
+ When an execution (Token in BPMN 2.0 terminology) arrives at the merging inclusive gateway,
+ the following is checked (quoting the specification literally):
+
<programlisting>
-For each empty incoming sequence flow, there is no
-Token in the graph anywhere upstream of this sequence flow, i.e., there is no directed path
-(formed by Sequence Flow) from a Token to this sequence flow unless
-a) the path visits the inclusive gateway or
+For each empty incoming sequence flow, there is no
+Token in the graph anywhere upstream of this sequence flow, i.e., there is no directed path
+(formed by Sequence Flow) from a Token to this sequence flow unless
+a) the path visits the inclusive gateway or
b) the path visits a node that has a directed path to a non-empty
incoming sequence flow of the inclusive gateway. "
</programlisting>
-
+
In more simple words: when an execution arrives at the gateway, all active execution are
checked if they can reach the inclusive gateway, by only taking in account the sequence flow
(note: conditions are not evaluated!). When the inclusive gateway is used, it is usally
used in a pair of splitting/merging inclusive gateways. In those cases, the execution
- behaviour is easy enough to grasph by just looking at the model.
-
+ behaviour is easy enough to grasph by just looking at the model.
+
</para>
-
- <para>
- Of course, it is not hard to imagine situations where the executions are split and merged
+
+ <para>
+ Of course, it is not hard to imagine situations where the executions are split and merged
in complex combinations using a variety of constructs including the inclusive gateway.
In those cases, it could very well be that the actual execution behaviour might not be what
the modelers' expects. So be careful when using the inclusive gateway and keep in mind
that it is often the best practice to use inclusive gateways just in pairs.
</para>
-
+
<para>
The following diagram shows how the inclusive gateway can be used.
(example taken from "BPMN method and style" by Bruce Silver)
@@ -753,26 +767,26 @@
"Large deposit" task will be active.
</listitem>
<listitem>
- <emphasis role="bold">Cash more than 10000 and a foreign bank: </emphasis> Both the
+ <emphasis role="bold">Cash more than 10000 and a foreign bank: </emphasis> Both the
"Large deposit" and "Foreign deposit" task will be active.
</listitem>
<listitem>
- <emphasis role="bold">Cash lower than 10000 and a foreign bank: </emphasis> Only the
+ <emphasis role="bold">Cash lower than 10000 and a foreign bank: </emphasis> Only the
"Foreign deposit" task will be active.
</listitem>
<listitem>
- <emphasis role="bold">Cash lower than 10000 and not a foreign bank: </emphasis> In this
+ <emphasis role="bold">Cash lower than 10000 and not a foreign bank: </emphasis> In this
case, both expressions evaluate to false. The default sequence flow will now be chosen.
In this example, this means that the "Standard deposit" task is active.
</listitem>
</itemizedlist>
No matter how many tasks are active after going through the inclusive gateway, the converging
inclusive gateway on the right will wait until all outgoing sequence flow of the inclusive
- gateway on the left have reached the merging gateway (sometimes only one, sometimes two). Take a look at
- <emphasis role="bold">org.jbpm.examples.bpmn.gateway.inclusive.InclusiveGatewayTest</emphasis>
+ gateway on the left have reached the merging gateway (sometimes only one, sometimes two). Take a look at
+ <emphasis role="bold">org.jbpm.examples.bpmn.gateway.inclusive.InclusiveGatewayTest</emphasis>
to see how this example reflects in a unit test.
</para>
-
+
<para>
The XML version of the example above looks as follows:
<programlisting>
@@ -781,33 +795,33 @@
<startEvent id="start" />
<sequenceFlow id="flow1" sourceRef="start" targetRef="inclusiveGatewaySplit" />
-
+
<emphasis role="bold"><inclusiveGateway id="inclusiveGatewaySplit" default="flow3"/></emphasis>
-
+
<sequenceFlow id="flow2" sourceRef=<emphasis role="bold">"inclusiveGatewaySplit"</emphasis> targetRef="largeDeposit">
<conditionExpression xsi:type="tFormalExpression">${cash > 10000}</conditionExpression>
</sequenceFlow>
-
+
<sequenceFlow id="flow3" sourceRef=<emphasis role="bold">"inclusiveGatewaySplit"</emphasis> targetRef="standardDeposit" />
-
+
<sequenceFlow id="flow4" sourceRef=<emphasis role="bold">"inclusiveGatewaySplit"</emphasis> targetRef="foreignDeposit">
<conditionExpression xsi:type="tFormalExpression">${bank == 'foreign'}</conditionExpression>
- </sequenceFlow>
-
+ </sequenceFlow>
+
<userTask id="largeDeposit" name="Large deposit" />
-
+
<sequenceFlow id="flow5" sourceRef="largeDeposit" targetRef=<emphasis role="bold">"inclusiveGatewayMerge"</emphasis> />
-
+
<userTask id="standardDeposit" name="Standard deposit" />
-
+
<sequenceFlow id="flow6" sourceRef="standardDeposit" targetRef=<emphasis role="bold">"inclusiveGatewayMerge"</emphasis> />
-
+
<userTask id="foreignDeposit" name="Foreign deposit" />
-
+
<sequenceFlow id="flow7" sourceRef="foreignDeposit" targetRef=<emphasis role="bold">"inclusiveGatewayMerge"</emphasis> />
-
+
<emphasis role="bold"><inclusiveGateway id="inclusiveGatewayMerge" /></emphasis>
-
+
<sequenceFlow id="flow8" sourceRef="inclusiveGatewayMerge" targetRef="theEnd" />
<endEvent id="theEnd" />
@@ -815,7 +829,7 @@
</process>
</programlisting>
</para>
-
+
<para>
As with any gateway type, the inclusive gateway type can have both merging and splitting
behaviour. In that case, the inclusive gateway will first wait until all executions
@@ -823,74 +837,74 @@
that evauluates to true (or doesn't have a condition).
<mediaobject><imageobject><imagedata align="center" fileref="images/bpmn2.inclusive.gateway.merging.and.splitting.png"/></imageobject></mediaobject>
</para>
-
- </section>
-
+
+ </section>
+
<section id="task">
<title>Tasks</title>
-
+
<para>
A task represents work that needs to be done by an external
entity, such as a human actor or an automated service.
</para>
-
+
<para>
It's important to note that the BPMN semantics of a 'task' differ from the JPDL semantics.
- In JPDL, the concept 'task' is always used in the context of a human actor doing some
+ In JPDL, the concept 'task' is always used in the context of a human actor doing some
type of work. When the process engine encounters a task in JPDL, it will create a task in some human
actor's task list and it will behave as a wait state. In BPMN 2.0 however, there are several
task types, some indicating a wait state (eg. the <emphasis role="bold">User Task</emphasis>
and some indicating an automatic activity (eg. the <emphasis role="bold">Service Task</emphasis>).
So take good care not to confuse the meaning of the task concept when switching languages.
</para>
-
+
<para>
Tasks are depicted by a rounded rectangle, typically containing a text inside. The type
- of the task (user task, service task, script task, etc.) is shown as a little icon on the left top
- corner of the rectangle. Depending on the task type, the engine will execute different
+ of the task (user task, service task, script task, etc.) is shown as a little icon on the left top
+ corner of the rectangle. Depending on the task type, the engine will execute different
functionality.
</para>
-
+
</section>
-
+
<section id="userTask">
-
+
<title>Task: User Task</title>
-
+
<para>
A <emphasis role="bold">User task</emphasis> is the typical 'human task' that is found
in practically every workflow or BPM software out there. When process execution reaches
such a user task, a new human task is created in task list for a given user.
</para>
-
- <para>
+
+ <para>
The main difference with a <link linkend="manualTask">manual task</link> (which also signifies
- work for a human actor) is that the task is known to the process engine. The engine can
- track the completion, assignee, time, etc which is not the case for a manual task.
+ work for a human actor) is that the task is known to the process engine. The engine can
+ track the completion, assignee, time, etc which is not the case for a manual task.
</para>
-
+
<para>
A user task is depicted as a rounded rectangle with a small user icon in the top left corner.
<mediaobject><imageobject><imagedata align="center" fileref="images/bpmn2.user.task.png"/></imageobject></mediaobject>
A user task is defined as follows in the BPMN 2.0 XML:
<programlisting>
-<userTask id="myTask" name="My task" />
- </programlisting>
+<userTask id="myTask" name="My task" />
+ </programlisting>
According to the specification, multiple implementations are possible (Webservice, WS-humantask, etc.),
as stated by using the <emphasis role="bold">implementation</emphasis> attribute.
Currently, only the standard jBPM task mechanism is available, so there is no point (yet)
in defining the 'implementation' attribute.
</para>
-
+
<para>
- The BPMN 2.0 specification contains quite a few ways of assigning user tasks to user(s),
+ The BPMN 2.0 specification contains quite a few ways of assigning user tasks to user(s),
group(s), role(s), etc. The current BPMN 2.0 jBPM implementation allows to assign tasks using
a <emphasis role="bold">resourceAssignmentExpression</emphasis>, combined
with the <emphasis role="bold">humanPerformer or PotentialOwner</emphasis> construct.
It is to be expected that this area will evolve future releases.
</para>
-
+
<para>
A <emphasis role="bold">potentialOwner</emphasis> is used when you want to make a certain
user, group, role, etc. a <emphasis role="bold">candidate</emphasis> for a certain task.
@@ -901,36 +915,36 @@
Currently, only defining this resource is enough (since it is a required attribute by the spec),
but this will be enhanced in a later release (eg. resources can have runtime parameters).
<programlisting>
-<resource id="manager" name="manager" />
+<resource id="manager" name="manager" />
<process ...>
-...
-
+...
+
<userTask id="myTask" name="My task">
<potentialOwner resourceRef="manager" jbpm:type="group">
<resourceAssignmentExpression>
<formalExpression>management</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
-</userTask>
+</userTask>
</programlisting>
- Note that we are using a specific extension here
+ Note that we are using a specific extension here
(<emphasis role="bold">jbpm:type="group"</emphasis>), to define this is a group assignment.
- If this attribute is removed, the group semantics will be used as default (which would be
+ If this attribute is removed, the group semantics will be used as default (which would be
ok in this example).
Now suppose that Peter and Mary are a member of the management group (here using the default
identity service):
<programlisting>
identityService.createGroup("management");
-
+
identityService.createUser("peter", "Peter", "Pan");
<emphasis role="bold">identityService.createMembership("peter", "management");</emphasis>
-
+
identityService.createUser("mary", "Mary", "Littlelamb");
-<emphasis role="bold">identityService.createMembership("mary", "management"); </emphasis>
+<emphasis role="bold">identityService.createMembership("mary", "management"); </emphasis>
</programlisting>
- Then both peter and mary can look in their task list for this task (code snippet from the
+ Then both peter and mary can look in their task list for this task (code snippet from the
example unit test):
<programlisting>
// Peter and Mary are both part of management, so they both should see the task
@@ -938,14 +952,14 @@
assertEquals(1, tasks.size());
<emphasis role="bold"> tasks = taskService.findGroupTasks("mary");</emphasis>
assertEquals(1, tasks.size());
-
+
// Mary claims the task
Task task = tasks.get(0);
taskService.takeTask(task.getId(), "mary");
assertNull(taskService.createTaskQuery().candidate("peter").uniqueResult());
-
+
taskService.completeTask(task.getId());
-assertProcessInstanceEnded(processInstance);
+assertProcessInstanceEnded(processInstance);
</programlisting>
When the assignment should be done to a <emphasis role="bold">candidate user</emphasis>,
just use the <emphasis role="bold">jbpm:type="user"</emphasis> attribute.
@@ -956,47 +970,47 @@
<formalExpression>peter</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
-</userTask>
+</userTask>
</programlisting>
In this example, peter will be able to find the task since he's a candidate user for the task.
<programlisting>
-List<Task> tasks = taskService.createTaskQuery().candidate("peter").list();
+List<Task> tasks = taskService.createTaskQuery().candidate("peter").list();
</programlisting>
</para>
</section>
-
+
<para>
A <emphasis role="bold">human performer</emphasis> is used when you want to assign a task
directly to a certain user, group, role, etc. The way to do this looks very much
like that of the potential owner.
<programlisting>
-<resource id="employee" name="employee" />
+<resource id="employee" name="employee" />
<process ...>
-...
-
+...
+
<userTask id="myTask" name="My User task">
<emphasis role="bold"><humanPerformer resourceRef="employee"></emphasis>
<resourceAssignmentExpression>
<formalExpression>mary</formalExpression>
</resourceAssignmentExpression>
</humanPerformer>
-</userTask>
+</userTask>
</programlisting>
In this example, the task will be directly assigned to Mary. She can now find the task
in her task list:
<programlisting>
-List<Task> tasks = taskService.findPersonalTasks("mary");
+List<Task> tasks = taskService.findPersonalTasks("mary");
</programlisting>
-
-
+
+
</para>
-
+
<para>
- Since the task assignment is done through the use of a
+ Since the task assignment is done through the use of a
<emphasis role="bold">formalExpression</emphasis>, it's also possible to define expressions
- that are evaluated at runtime. The expressions itself need to be put inside a
+ that are evaluated at runtime. The expressions itself need to be put inside a
<emphasis role="bold">${}</emphasis>, as usual in jBPM.
For example, if a process variable 'user' is defined, then it can be used inside an expression.
More complex expressions are of course possible.
@@ -1007,33 +1021,33 @@
<emphasis role="bold"><formalExpression>${user}</formalExpression></emphasis>
</resourceAssignmentExpression>
</humanPerformer>
-</userTask>
+</userTask>
</programlisting>
Note that it is not needed to use the 'jbpm:type' on a humanPerformer element, since only
- direct user assignments can be done. If a task needs to be assigned to a role or group,
+ direct user assignments can be done. If a task needs to be assigned to a role or group,
use the potentialOwner with a group type (when you assign a task to a group, all members
- of that group will always be candidate users for that group - hence the usage of
+ of that group will always be candidate users for that group - hence the usage of
potentialOwner).
</para>
-
+
<section id="serviceTask">
-
+
<title>Task: Java Service Task</title>
-
+
<para>
- A <emphasis role="bold">Service Task</emphasis> is an automatic activity that calls some
+ A <emphasis role="bold">Service Task</emphasis> is an automatic activity that calls some
sort of service, such as a web service, Java service, etc. Currently, only Java service
- invocations are supported by the jBPM engine, but Web service invocations are planned
+ invocations are supported by the jBPM engine, but Web service invocations are planned
for a future release.
<mediaobject><imageobject><imagedata align="center" fileref="images/bpmn2.service.task.png"/></imageobject></mediaobject>
</para>
-
+
<para>
Defining a service task requires quite a few lines of XML (the BPEL influence is certainly
visible here). Of course, in the near future, we expect that tooling will simplify this area
a lot. A service task is defined as follows:
<programlisting>
-<serviceTask id="MyServiceTask" name="My service task"
+<serviceTask id="MyServiceTask" name="My service task"
implementation="Other" operationRef="myOperation" />
</programlisting>
The service task has a required <emphasis role="bold">id</emphasis> and an optional
@@ -1042,12 +1056,12 @@
are WebService, Other or Unspecified. Since we've only implemented the Java invocation,
only the <emphasis role="bold">Other</emphasis> choice will do something useful for the moment.
</para>
-
+
<para>
- The service task will invoke a certain operation that is referenced by the
- <emphasis role="bold">operationRef</emphasis> attribute using the id of an
- <emphasis role="bold">operation</emphasis>. Such an operation is part of an
- <emphasis role="bold">interface</emphasis> as shown below. Every operation has
+ The service task will invoke a certain operation that is referenced by the
+ <emphasis role="bold">operationRef</emphasis> attribute using the id of an
+ <emphasis role="bold">operation</emphasis>. Such an operation is part of an
+ <emphasis role="bold">interface</emphasis> as shown below. Every operation has
at least one <emphasis role="bold">input message</emphasis> and at most one
<emphasis role="bold">output message</emphasis>.
<programlisting>
@@ -1057,7 +1071,7 @@
<inMessageRef>inputMessage</inMessageRef>
<outMessageRef>outputMessage</outMessageRef>
</bpmn:operation>
-</interface>
+</interface>
</programlisting>
For a Java service, the <emphasis role="bold">name of the interface</emphasis> is used
to specificy the fully qualified classname of the Java class. The <emphasis role="bold">
@@ -1065,50 +1079,50 @@
that must be called. The input/output message that represent the parameters/return value of
the Java method are defined as follows:
<programlisting>
-<message id="inputMessage" name="input message" structureRef="myItemDefinition1" />
+<message id="inputMessage" name="input message" structureRef="myItemDefinition1" />
</programlisting>
Several elements in BPMN are so-called 'item-aware', including this message construct.
This means that they are involved in storing or reading items during process execution.
- The data structure to hold these elements is specified using a reference to an
- <emphasis role="bold">ItemDefinition</emphasis>. In this context, the message specifies
- its data structure by referencing an Itemdefinition in the
+ The data structure to hold these elements is specified using a reference to an
+ <emphasis role="bold">ItemDefinition</emphasis>. In this context, the message specifies
+ its data structure by referencing an Itemdefinition in the
<emphasis role="bold">structureRef</emphasis> attribute.
<programlisting>
-
+
<itemDefinition id="myItemDefinition1" >
<jbpm:arg>
<jbpm:object expr="#{var1}" />
</jbpm:arg>
</itemDefinition>
-
+
<itemDefinition id="myItemDefinition2">
<jbpm:var name="returnVar" />
</itemDefinition>
-
+
</programlisting>
Do note that this is not fully standard BPMN 2.0 as by the specification (hence the 'jbpm' prefix).
In fact, according to the specification, the ItemDefinition shouldn't contain more
than a data structure definition. The actual mapping between input paramaters, with a ceratin
data structure, is done in the <emphasis role="bold">ioSpecification</emphasis> section
of the serviceTask. However, the current jBPM BPMN 2.0 implementation hasn't implemented
- that construct yet. So, this means that the current usage as described above, will probably
+ that construct yet. So, this means that the current usage as described above, will probably
change in the near future.
</para>
-
+
<para>
<emphasis role="bold">Important note: Interfaces, ItemDefinitions and messages are
defined outside a <process>.</emphasis> See the example <emphasis role="bold">
ServiceTaskTest</emphasis> for a concrete process and unit test.
- </para>
-
- </section>
-
+ </para>
+
+ </section>
+
<section id="scriptTask">
-
+
<title>Task: Script Task</title>
-
+
<para>
- A script task is a an automatic activity upon which the process engine will execute
+ A script task is a an automatic activity upon which the process engine will execute
a script when the task is reached. The script task is used as follows:
<programlisting>
<scriptTask id="scriptTask" name="Script Task" scriptLanguage="bsh">
@@ -1117,11 +1131,11 @@
System.out.println(input[i] + " x 2 = " + (input[i]*2));
}]]>
</script>
-</scriptTask>
+</scriptTask>
</programlisting>
The script task, besides the required <emphasis role="bold">id</emphasis> and the optional
<emphasis role="bold">name</emphasis>, allows for specifying a <emphasis role="bold">
- scriptLanguage</emphasis> and a <emphasis role="bold">script</emphasis>.
+ scriptLanguage</emphasis> and a <emphasis role="bold">script</emphasis>.
Since we're using JSR-223 ('Scripting for the Java platform'), changing the script language involves
<itemizedlist>
<listitem>changing the <emphasis role="bold">scriptLanguage</emphasis> attribute to the JSR-223 compliant name</listitem>
@@ -1129,17 +1143,17 @@
</itemizedlist>
The XML above is visualized as follows (adding a none start and end event).
</para>
-
+
<mediaobject><imageobject><imagedata align="center" fileref="images/bpmn2.script.task.png"/></imageobject></mediaobject>
-
+
<para>
As shown in the example, process variables can be used inside the scripts. We can now start
a process instance for this example process, while also supplying some random input variables:
<programlisting>
Map<String, Object> variables = new HashMap<String, Object>();
Integer[] values = { 11, 23, 56, 980, 67543, 8762524 };
-variables.put("input", values);
-executionService.startProcessInstanceBykey("scriptTaskExample", variables);
+variables.put("input", values);
+executionService.startProcessInstanceBykey("scriptTaskExample", variables);
</programlisting>
In the output console, we can now see the script being executed:
<programlisting>
@@ -1148,58 +1162,58 @@
56 x 2 = 112
980 x 2 = 1960
67543 x 2 = 135086
-8762524 x 2 = 17525048
+8762524 x 2 = 17525048
</programlisting>
</para>
-
+
</section>
-
+
<section id="manualTask">
-
+
<title>Task: Manual task</title>
-
+
<para>
<mediaobject><imageobject><imagedata align="center" fileref="images/bpmn2.manual.task.png"/></imageobject></mediaobject>
- A manual task is a task that is performed by an external actor, but without the aid of
+ A manual task is a task that is performed by an external actor, but without the aid of
a BPM system or a service that is invoked. In the real world, examples are plenty:
- the installation of telephone system, sending of a letter using regular mail, calling
+ the installation of telephone system, sending of a letter using regular mail, calling
a customer by phone, etc.
<programlisting>
-<manualTask id="myManualTask" name="Call customer" />
+<manualTask id="myManualTask" name="Call customer" />
</programlisting>
</para>
-
+
<para>
The purpose of the manual task is more documentation/modeling-wise, as it has no meaning for
execution on a process engine. As such, the process engine will simply pass through
a manual task when it encounters one.
</para>
-
+
</section>
-
+
<section id="receiveTaskJava">
-
+
<title>Task: Java Receive task</title>
-
+
<para>
- A <emphasis role="bold">receive task</emphasis> is a task that waits for the arrival of
+ A <emphasis role="bold">receive task</emphasis> is a task that waits for the arrival of
an external message. Besides the obvious use case involving webservices, the specification
- is liberal in what to do in other environments. The web service use case is not yet
+ is liberal in what to do in other environments. The web service use case is not yet
implemented, but the receive task can already be used in a Java environment.
</para>
-
+
<para>
The receive task is depicted as a rounded rectangle (= task shape) with a little enveloppe
in the left top corner.
<mediaobject><imageobject><imagedata align="center" fileref="images/bpmn2.receive.task.java.png"/></imageobject></mediaobject>
</para>
-
+
<para>
In a Java environment, the receive task without any other attribute filled in besides
an id and (optionally) a name, behaves as a wait state. To introduce a wait state in your
business process, just add the following line:
<programlisting>
-<receiveTask id="receiveTask" name="wait" />
+<receiveTask id="receiveTask" name="wait" />
</programlisting>
Process execution will wait in such a receive task. The process can then be continued
using the familiar jBPM <emphasis role="bold">signal methods</emphasis>. Note that
@@ -1207,29 +1221,29 @@
meaning in BPMN 2.0.
<programlisting>
Execution execution = processInstance.findActiveExecutionIn("receiveTask");
-executionService.signalExecutionById(execution.getId());
+executionService.signalExecutionById(execution.getId());
</programlisting>
</para>
-
+
</section>
-
+
</section> <!-- End of basic constructs section -->
-
+
<section id="advancedConstructs">
-
+
<title>Advanced constructs</title>
-
+
<section id="embeddedSubProcess">
-
+
<title>Embedded sub-process</title>
-
+
<para>
- Subprocesses are in the first place a way of making a process "hierarchical", meaning that
- a modeller can create several 'levels' of detail. The top level view then explains the
- high-level way of doing things, while the lowest level focusses on the nitty gritty
+ Subprocesses are in the first place a way of making a process "hierarchical", meaning that
+ a modeller can create several 'levels' of detail. The top level view then explains the
+ high-level way of doing things, while the lowest level focusses on the nitty gritty
details.
</para>
-
+
<para>
Take for example the following diagram. In this model, only the high level steps are shown.
The actual implementation of the "Check credit" step is hidden behind a
@@ -1237,13 +1251,13 @@
of detail to discuss business processes with end-users.
<mediaobject><imageobject><imagedata align="center" fileref="images/bpmn2.collapsed.subprocess.png"/></imageobject></mediaobject>
</para>
-
+
<para>
The second major use case for sub-processes is that the sub-process "container"
- acts as a scope for events. When an event is fired from within the sub-process, the catch
+ acts as a scope for events. When an event is fired from within the sub-process, the catch
events on the boundary of the sub-process will be the first to receive this event.
</para>
-
+
<para>
A sub-process that is defined within a top-level process is called an <emphasis role="bold">
embeddable sub-process</emphasis>. All process data that is available in the parent
@@ -1259,11 +1273,11 @@
<receiveTask name="Receive order" id="receiveOrder" />
<sequenceFlow id="flow2" sourceRef="receiveOrder" targetRef="checkCreditSubProcess" />
<emphasis role="bold"><subProcess id="checkCreditSubProcess" name="Credit check"></emphasis>
-
+
...
<emphasis role="bold"></subProcess></emphasis>
-
+
<sequenceFlow id="flow9" sourceRef="checkCreditSubProcess" targetRef="theEnd" />
<endEvent id="theEnd" />
@@ -1273,7 +1287,7 @@
a top-level process (hence the three "..." within the XML example above. Sub-processes
are <emphasis role="bold">only allowed to have a none start event</emphasis>.
</para>
-
+
<para>
Conceptually an embedded sub-process works as follows: when an execution arrives
at the subprocess, a child execution is created. The child execution can then later create
@@ -1282,14 +1296,14 @@
within the subprocess. In that case, the parent execution is taken for further continuation
of the process.
</para>
- <para>
+ <para>
For example, in the following diagram, the "Third task"
will only be reached after both the "First task" and the "Second task"
are completed. Completing one of the tasks in the sub-process, will not trigger the
continuation of the sub-process, since one execution is still active within the sub-process.
<mediaobject><imageobject><imagedata align="center" fileref="images/bpmn2.subprocess.two.endevents.png"/></imageobject></mediaobject>
</para>
-
+
<para>
Sub-processes can have multiple start events. In that case, multiple parallel paths
will exist within the sub-process. The rules for sub-process completion are unchanged:
@@ -1297,58 +1311,58 @@
ended.
<mediaobject><imageobject><imagedata align="center" fileref="images/bpmn2.subprocess.parallel.paths.png"/></imageobject></mediaobject>
</para>
-
+
<para>
Nested sub-processes are also possible. This way, the process can be divided into several
levels of detail. There is no limitation on the levels of nesting.
<mediaobject><imageobject><imagedata align="center" fileref="images/bpmn2.subprocess.nested.png"/></imageobject></mediaobject>
</para>
-
+
<para>
Implementation note: According to the BPMN 2 specification, an activity without ougoing sequence
- flow implicitly ends the current execution. However currently, it is necessary for a correct functioning to
+ flow implicitly ends the current execution. However currently, it is necessary for a correct functioning to
specifically use an end event within the sub-process to end a certain path. This will
be enhanced in the future to be specification-compliant.
</para>
-
+
</section> <!-- End of embedded subprocess -->
-
+
<section id="Timer start event">
-
+
<title>Timer start event</title>
-
+
<para>
A timer start event is used to indicate that a process should be started when a given
time condition is met. This could be a specific point in time (eg. October 10th, 2010 at
- 5am), but also and more typically a recurring time (eg. every Friday at midnight).
- </para>
-
+ 5am), but also and more typically a recurring time (eg. every Friday at midnight).
+ </para>
+
<para>
A timer start event is visualized as a circle with the clock icon inside.
<mediaobject><imageobject><imagedata align="center" fileref="images/bpmn2.timer.start.event.png"/></imageobject></mediaobject>
</para>
-
+
<para>
Using a Timer Start event is done by adding a <emphasis role="bold">timerEventDefinition</emphasis>
element below the startEvent element:
<programlisting>
<startEvent name="Every Monday morning" id="myStart">
<emphasis role="bold"><timerEventDefinition/></emphasis>
-</startEvent>
+</startEvent>
</programlisting>
Following time definitions are possible:
<itemizedlist>
<listitem>
<emphasis role="bold">timeDate: </emphasis>specifies a fixed date when a process instance
must be created. The default format of the date specification is
- "dd/MM/yyyy hh:mm:ss". This can engine-wide be changed by setting the
+ "dd/MM/yyyy hh:mm:ss". This can engine-wide be changed by setting the
<emphasis role="bold">jbpm.duedatetime.format</emphasis> property in the configuration.
<programlisting>
<startEvent id="myStartEvent" >
<timerEventDefinition>
<emphasis role="bold"><timeDate>10/10/2099 00:00:00</timeDate></emphasis>
</timerEventDefinition>
-</startEvent>
+</startEvent>
</programlisting>
Note that using a fixed duedate makes the process only useable for a single time.
After the process instance is created, the timer start event will never fire again.
@@ -1358,17 +1372,17 @@
process instance will be created. Two types are possible
<para>
- <emphasis role="bold">Duration expression: </emphasis>
+ <emphasis role="bold">Duration expression: </emphasis>
<programlisting>
-quantity [business] {second | seconds | minute | minutes |
- hour | hours | day | days | week |
- weeks | month | months | year | years}
+quantity [business] {second | seconds | minute | minutes |
+ hour | hours | day | days | week |
+ weeks | month | months | year | years}
</programlisting>
- This is completely similar to a timer duration definition in JPDL. Note that the
+ This is completely similar to a timer duration definition in JPDL. Note that the
BPMN2 start timer event also understands "business time". This
allows for example to define a "business day" as an interval from
9am to 5pm. This way, the time from 5pm to 9am will not be taken in account when
- the time on which the event will fire is calculated.
+ the time on which the event will fire is calculated.
Please refer to the JPDL userguide for more details on how this business calendar can be customized.
The following example shows a timer start event that will start a new process
instance every five hours.
@@ -1377,44 +1391,44 @@
<timerEventDefinition>
<emphasis role="bold"><timeCycle>5 hours</timeCycle></emphasis>
</timerEventDefinition>
-</startEvent>
+</startEvent>
</programlisting>
</para>
<para>
<emphasis role="bold"><ulink url="http://en.wikipedia.org/wiki/CRON_expression">Cron expression:</ulink></emphasis>
- altough duration expressions cover already a great deal of recurring time definitions,
- sometimes they are not easy to use.
+ altough duration expressions cover already a great deal of recurring time definitions,
+ sometimes they are not easy to use.
When for example a process instance should be started every Friday night 23pm,
cron expressions allow a more natural way of defining such repeating occurrences.
</para>
<para>
The following example shows a timer start event that will start a new process
- instance every Friday at 23pm.
+ instance every Friday at 23pm.
<programlisting>
<startEvent id="myStartEvent" >
<timerEventDefinition>
<emphasis role="bold"><timeCycle>0 0 23 ? * FRI</timeCycle></emphasis>
</timerEventDefinition>
-</startEvent>
+</startEvent>
</programlisting>
</para>
</listitem>
</itemizedlist>
</para>
-
+
<para>
The timer start event implementation in jBPM also has following features:
<itemizedlist>
<listitem>
Process definitions that have a timer start event, can be started as if it also
- were a none start event. This means that calling for example
+ were a none start event. This means that calling for example
executionService.startProcessInstanceByKey(key) just works.
</listitem>
<listitem>
The timer start event is internally implemented as a scheduled job. This means
that a <emphasis role="bold">job executor</emphasis> has to be configured for
the timer start event to work. The advantage of this implementation is that the
- timer start event firing is transactional (eg. if a service tasks right after the
+ timer start event firing is transactional (eg. if a service tasks right after the
timer start event fails, the transaction will be rolled back and the timer start event
will be retried later) and able to cope with a server crash (ie. the when the server
comes back up, the timer start event will be picked up by the job executor just as if
@@ -1422,31 +1436,31 @@
</listitem>
<listitem>
When a new version of a process definition with a timer start event is deployed, the
- old timer start event job is removed from the system. This means that
+ old timer start event job is removed from the system. This means that
<emphasis role="bold">only the latest version of the process definition will be used</emphasis>
to create a new process instances.
</listitem>
- </itemizedlist>
+ </itemizedlist>
</para>
-
+
</section> <!-- end of Timer start event -->
-
+
<section id="intermediateEvents">
-
+
<title>Intermediate events</title>
-
+
<para>
An intermediate event is used to model something that happens during a process (ie. after
the process has started and before it is ended). Intermediate events are visualized as
a circle with a double border, with an icon indicating the event type within the circle.
</para>
-
+
<para>
There are several intermediate event types, such as a timer event, signal event, escalation
event, etc. Intermediate events can be either throwing or catching:
<itemizedlist>
<listitem>
- <emphasis role="bold">Throwing: </emphasis>when an execution arrives in the event, it
+ <emphasis role="bold">Throwing: </emphasis>when an execution arrives in the event, it
immediately fires a certain trigger (a signal, an error, etc.). Throwing events can
be graphically recognized by the icon that is filled in with black.
</listitem>
@@ -1457,19 +1471,19 @@
</listitem>
</itemizedlist>
</para>
-
+
</section> <!-- end of intermediate events -->
-
+
<section id="intermediateCatchTimer">
-
+
<title>Intermediate catch event: Timer </title>
-
+
<para>
An intermediate timer event is used to represent a <emphasis role="bold">delay</emphasis>
in the process. Straightfoward use cases are for example polling of data, executing
heavy logic only at night when nobody is working, etc.
</para>
-
+
<para>
Note that an intermediate timer only can be used as a catch event (throwing a timer event
makes no sense). The following diagram shows how the intermediate timer event is visualized.
@@ -1480,26 +1494,26 @@
<timerEventDefinition>
<timeCycle>1 hour</timeCycle>
</timerEventDefinition>
-</intermediateCatchEvent>
+</intermediateCatchEvent>
</programlisting>
There are two ways to specify the delay, using either a <emphasis role="bold">timeCycle
or a timeDate</emphasis>. In the example above, a timeCycle is used.
</para>
-
+
<para>
Following delay definitions are possible (similar to those for a Timer Start Event).
<itemizedlist>
<listitem>
<emphasis role="bold">timeDate: </emphasis>specifies a fixed date when the timer will
fire and the process continues. The default format of the date specification is
- "dd/MM/yyyy hh:mm:ss". This can engine-wide be changed by setting the
+ "dd/MM/yyyy hh:mm:ss". This can engine-wide be changed by setting the
<emphasis role="bold">jbpm.duedatetime.format</emphasis> property in the configuration.
<programlisting>
<intermediateCatchEvent id="myTimer" >
<timerEventDefinition>
<emphasis role="bold"><timeDate>10/10/2099 00:00:00</timeDate></emphasis>
</timerEventDefinition>
-</intermediateCatchEvent>
+</intermediateCatchEvent>
</programlisting>
</listitem>
<listitem>
@@ -1507,13 +1521,13 @@
time when the execution enters the timer event. Two types are possible
<para>
- <emphasis role="bold">Duration expression: </emphasis>
+ <emphasis role="bold">Duration expression: </emphasis>
<programlisting>
-quantity [business] {second | seconds | minute | minutes |
- hour | hours | day | days | week |
- weeks | month | months | year | years}
+quantity [business] {second | seconds | minute | minutes |
+ hour | hours | day | days | week |
+ weeks | month | months | year | years}
</programlisting>
- This is completely similar to a timer duration definition in JPDL. Note that the
+ This is completely similar to a timer duration definition in JPDL. Note that the
BPMN2 intermediate timer event also understands "business time". This
allows for example to define a "business day" as an interval from
9am to 5pm. Timers that are started at 4pm with a duration of 2 hours, will fire
@@ -1524,74 +1538,74 @@
<timerEventDefinition>
<emphasis role="bold"><timeCycle>5 hours</timeCycle></emphasis>
</timerEventDefinition>
-</intermediateCatchEvent>
+</intermediateCatchEvent>
</programlisting>
</para>
<para>
- <emphasis role="bold">Cron expression: </emphasis>altough duration expressions cover
- already a great deal of delay definitions, sometimes they are not easy to use. When
- for example the process should be delayed until Friday night 23pm such that the
- processes can be executed in the weekend, duration expressions are hard to use
- (you need something like "#{calculated_value} seconds", where you need
- to calculate the value first).
- </para>
- <para>
- <ulink url="http://en.wikipedia.org/wiki/CRON_expression">Cron expressions</ulink>
- allow to define delays in a way many people know (since cron expressions
- are used to define scheduled task on Unix machines). Note that a cron expression
- typically is used to define repetion. In this context however, the
- <emphasis role="bold">first point in time where the cron expression is satisfied</emphasis>
- is used to set the due date of the timer event (so no repetition). The following example
- shows how an intermediate timer event can be specified to continue the process
- the next friday night at 23pm.
- <programlisting>
+ <emphasis role="bold">Cron expression: </emphasis>altough duration expressions cover
+ already a great deal of delay definitions, sometimes they are not easy to use. When
+ for example the process should be delayed until Friday night 23pm such that the
+ processes can be executed in the weekend, duration expressions are hard to use
+ (you need something like "#{calculated_value} seconds", where you need
+ to calculate the value first).
+ </para>
+ <para>
+ <ulink url="http://en.wikipedia.org/wiki/CRON_expression">Cron expressions</ulink>
+ allow to define delays in a way many people know (since cron expressions
+ are used to define scheduled task on Unix machines). Note that a cron expression
+ typically is used to define repetion. In this context however, the
+ <emphasis role="bold">first point in time where the cron expression is satisfied</emphasis>
+ is used to set the due date of the timer event (so no repetition). The following example
+ shows how an intermediate timer event can be specified to continue the process
+ the next friday night at 23pm.
+ <programlisting>
<intermediateCatchEvent id="intermediateTimer" >
<timerEventDefinition>
<emphasis role="bold"><timeCycle>0 0 23 ? * FRI</timeCycle></emphasis>
</timerEventDefinition>
-</intermediateCatchEvent>
- </programlisting>
- </para>
+</intermediateCatchEvent>
+ </programlisting>
+ </para>
</listitem>
</itemizedlist>
</para>
-
+
</section> <!-- end of intermediate catch event -->
-
+
</section> <!-- End of advanced constructs -->
-
-
-
+
+
+
<section id="completeExample">
-
+
<title>Complete example (including console task forms)</title>
-
+
<para>
<emphasis role="bold">Prerequisites</emphasis>: to run the example, we assume that a working
- jBPM console has been installed on your JBoss server. If not, please run the 'demo.setup.jboss'
+ jBPM console has been installed on your JBoss server. If not, please run the 'demo.setup.jboss'
install script first.
</para>
-
+
<para>
The business process we're implementing looks as follows:
<mediaobject><imageobject><imagedata align="center" fileref="images/bpmn2.vacationrequest.example.png"/></imageobject></mediaobject>
- You might recognize this example, since we’ve also implemented it in
- JPDL as an example in our distribution.
- </para>
- <para>
- The business process is simple: an employee can start a new process and
- make a request for a certain amount of vacation days. After the request
- task has been completed, the manager will find a verification task in
- its tasklist. The Manager can now decide to accept or reject this
- request. Depending on the outcome (that’s the little rhombus on the
- outgoing sequence flow - it means there is a conditional expression on the sequence flow),
- a rejection message is send or the process ends. Do note that in fact we've used a shortcut
- here: instead of putting expressions on the outgoing sequence flow of the 'verify request'
- task, we've could have used an exclusive gateway after the user task to control the flow
- through the process. Also note that since we haven't implemented swimlanes yet (probably
- the next release), it's difficult to actually see who does what in the business process.
- </para>
-
+ You might recognize this example, since we’ve also implemented it in
+ JPDL as an example in our distribution.
+ </para>
+ <para>
+ The business process is simple: an employee can start a new process and
+ make a request for a certain amount of vacation days. After the request
+ task has been completed, the manager will find a verification task in
+ its tasklist. The Manager can now decide to accept or reject this
+ request. Depending on the outcome (that’s the little rhombus on the
+ outgoing sequence flow - it means there is a conditional expression on the sequence flow),
+ a rejection message is send or the process ends. Do note that in fact we've used a shortcut
+ here: instead of putting expressions on the outgoing sequence flow of the 'verify request'
+ task, we've could have used an exclusive gateway after the user task to control the flow
+ through the process. Also note that since we haven't implemented swimlanes yet (probably
+ the next release), it's difficult to actually see who does what in the business process.
+ </para>
+
<para>
The XML version of this process looks as follows:
<programlisting>
@@ -1657,18 +1671,18 @@
targetRef="theEnd" />
<endEvent id="theEnd" name="End" />
-</process>
+</process>
</programlisting>
- <emphasis role="bold">Note</emphasis>: this example is already installed when you've
+ <emphasis role="bold">Note</emphasis>: this example is already installed when you've
used the demo setup. Also note that we're using a Script Task here, to quickly write
something as output instead of sending a real message (the diagram is showing a Service
Task). Also note that we've taken some shortcuts here regarding task assignment (will
be fixed in the next release).
</para>
-
+
<para>
The constructs used in this implementation are all covered in the previous section.
- Also note that we're using the <emphasis role="bold">taskform functionality</emphasis>
+ Also note that we're using the <emphasis role="bold">taskform functionality</emphasis>
here, which is a custom jBPM extension for the <emphasis role="bold">rendering</emphasis>
element of a User task.
<programlisting>
@@ -1683,7 +1697,7 @@
<jbpm:form>org/jbpm/examples/bpmn/usertask/taskform/verify_request.ftl</jbpm:form>
</rendering>
</userTask>
- </programlisting>
+ </programlisting>
The mechanism regarding task forms for BPMN 2.0 is complete equivalent to that of JPDL.
The form itself is a <ulink url="http://freemarker.org/">Freemarker</ulink> template file
that needs to be incorporated in the deployment. For example, the 'verify_request.ftl' form
@@ -1693,30 +1707,30 @@
<body>
<form action="${form.action}" method="POST" enctype="multipart/form-data">
-
+
<h3>Your employee, <emphasis role="bold">${employee_name}</emphasis> would like to go on vacation</h3>
Number of days: <emphasis role="bold">${number_of_days}<</emphasis>br/>
-
+
<hr>
-
+
In case you reject, please provide a reason:<br/>
<emphasis role="bold"><input type="textarea" name="reason"/><br/></emphasis>
-
+
<emphasis role="bold"><input type="submit" name="verificationResult" value="OK">
<input type="submit" name="verificationResult" value="Not OK"></emphasis>
-
+
</form>
</body>
-</html>
+</html>
</programlisting>
- Note that <emphasis role="bold">process variables can be
+ Note that <emphasis role="bold">process variables can be
accessed using the ${my_process_variable} construct.</emphasis> Also note that named
- input controls (eg. input field, submit button) can be used to
- <emphasis role="bold">define new process variables</emphasis>.
+ input controls (eg. input field, submit button) can be used to
+ <emphasis role="bold">define new process variables</emphasis>.
For example, the text input of the following field will be stored as the process
variable 'reason'
<programlisting>
-<input type="textarea" name="reason"/>
+<input type="textarea" name="reason"/>
</programlisting>
Note that there are two submit buttons (which makes sense if you look at the 'OK' and 'Not OK'
sequence flows going out the 'request vacation' task. By pressing one of these buttons, the
@@ -1728,10 +1742,10 @@
<conditionExpression xsi:type="tFormalExpression">
<emphasis role="bold">${verificationResult == 'OK'}</emphasis>
</conditionExpression>
-</sequenceFlow>
+</sequenceFlow>
</programlisting>
</para>
-
+
<para>
The process can now be deployed. You can use the ant deploy task for this (see examples),
or you can point your jBPM configuration to the database of the console. To deploy
@@ -1741,38 +1755,38 @@
deployment.addResourceFromClasspath("org/jbpm/examples/bpmn/usertask/taskform/vacationrequest.bpmn.xml");
deployment.addResourceFromClasspath("org/jbpm/examples/bpmn/usertask/taskform/request_vacation.ftl");
deployment.addResourceFromClasspath("org/jbpm/examples/bpmn/usertask/taskform/verify_request.ftl");
-deployment.deploy();
+deployment.deploy();
</programlisting>
- You can now embed (or run on a standalone server) this business process, by using the
- familiar jBPM API operations. For example, process instances can now be started using the
+ You can now embed (or run on a standalone server) this business process, by using the
+ familiar jBPM API operations. For example, process instances can now be started using the
key (ie. the process id for BPMN 2.0):
<programlisting>
-ProcessInstance pi = executionService.startProcessInstanceByKey("vacationRequestProcess");
+ProcessInstance pi = executionService.startProcessInstanceByKey("vacationRequestProcess");
</programlisting>
Or tasks list can be retrieved:
<programlisting>
-Task requestTasktask = taskService.createTaskQuery().candidate("peter").uniqueResult();
+Task requestTasktask = taskService.createTaskQuery().candidate("peter").uniqueResult();
</programlisting>
</para>
-
+
<para>
When deploying to the jBPM console database, you should see our new business process popping up.
<mediaobject><imageobject><imagedata align="center" fileref="images/bpmn2.vacationrequest.example.console.01.png"/></imageobject></mediaobject>
-
+
After you start a new process, a new task should be available in the employee's tasklist.
When clicking on 'view', the task form will be displayed, requesting to fill in some
variables for further use in the process.
<mediaobject><imageobject><imagedata align="center" fileref="images/bpmn2.vacationrequest.example.console.02.png"/></imageobject></mediaobject>
-
+
After task completion, the manager will find a new verification task in his task list.
He can now accept or reject the vacation request, based on the input of the employee.
<mediaobject><imageobject><imagedata align="center" fileref="images/bpmn2.vacationrequest.example.console.03.png"/></imageobject></mediaobject>
-
+
Since the database schema remains unchanged when we added BPMN 2.0 on top of the jBPM PVM, all
existing reports can be applied to our new BPMN 2.0 processes.
<mediaobject><imageobject><imagedata align="center" fileref="images/bpmn2.vacationrequest.example.console.04.png"/></imageobject></mediaobject>
</para>
-
+
</section>
-
+
</chapter>
Modified: jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/bpmn/test/deployment/Bpmn2DeploymentTest.java
===================================================================
--- jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/bpmn/test/deployment/Bpmn2DeploymentTest.java 2010-10-16 13:44:02 UTC (rev 6764)
+++ jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/bpmn/test/deployment/Bpmn2DeploymentTest.java 2010-10-17 14:44:27 UTC (rev 6765)
@@ -35,8 +35,8 @@
* @author Joram Barrez
*/
public class Bpmn2DeploymentTest extends JbpmTestCase {
-
- private static final String TEST_PROCESS_ONLY_ID =
+
+ private static final String TEST_PROCESS_ONLY_ID =
"<definitions>" +
" <process id='myProcess' >" +
" <startEvent id='start'/>" +
@@ -44,8 +44,8 @@
" <endEvent id='end'/>" +
" </process>" +
"</definitions>";
-
- private static final String TEST_PROCESS_ONLY_NAME =
+
+ private static final String TEST_PROCESS_ONLY_NAME =
"<definitions>" +
" <process name='myProcess' >" +
" <startEvent id='start'/>" +
@@ -53,8 +53,8 @@
" <endEvent id='end'/>" +
" </process>" +
"</definitions>";
-
- private static final String TEST_PROCESS_ID_AND_NAME =
+
+ private static final String TEST_PROCESS_ID_AND_NAME =
"<definitions>" +
" <process id='myProcess' name='myFirstProcess'>" +
" <startEvent id='start'/>" +
@@ -62,84 +62,88 @@
" <endEvent id='end'/>" +
" </process>" +
"</definitions>";
-
+
public void testDeployProcessWithOnlyName() {
try {
deployBpmn2XmlString(TEST_PROCESS_ONLY_NAME);
fail();
} catch (JbpmException e) {
// Exception is to be expected
+ String newLine = System.getProperty("line.separator");
+ assertEquals(newLine + " error: attribute <process id=\"...\" is required " + newLine
+ + " error: Process has no or an empty id ", e.getMessage());
}
}
-
+
public void testDeployProcessWithOnlyId() {
deployBpmn2XmlString(TEST_PROCESS_ONLY_ID);
ProcessInstance processInstance = executionService.startProcessInstanceByKey("myProcess");
assertNotNull(processInstance);
assertProcessInstanceEnded(processInstance);
}
-
+
public void testDeployProcessWithIdAndName() {
deployBpmn2XmlString(TEST_PROCESS_ID_AND_NAME);
-
- ProcessInstance processInstance = executionService.startProcessInstanceByKey("myFirstProcess");
+
+ ProcessInstance processInstance = executionService.startProcessInstanceByKey("myProcess");
assertNotNull(processInstance);
assertProcessInstanceEnded(processInstance);
-
+
try {
- executionService.startProcessInstanceByKey("myProcess");
+ executionService.startProcessInstanceByKey("myFirstProcess");
fail();
} catch (JbpmException e) {
assertTrue(e.getMessage().contains("no process definition with key"));
// exception expected: when a key is given, the id can't be used as a key
}
}
-
+
/* ------------
* REDEPLOYMENT
* ------------
*/
-
+
public void testRedeployProcessWithOnlyId() {
deployBpmn2XmlString(TEST_PROCESS_ONLY_ID);
-
+
ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery().processDefinitionKey("myProcess");
List<ProcessDefinition> definitions = query.list();
assertEquals(1, definitions.size());
-
+
deployBpmn2XmlString(TEST_PROCESS_ONLY_ID);
query.orderAsc(ProcessDefinitionQuery.PROPERTY_VERSION);
definitions = query.list();
-
+
assertEquals(2, definitions.size());
assertEquals(1, definitions.get(0).getVersion());
assertEquals(2, definitions.get(1).getVersion());
-
+
// Check if the key is replaced with the name (query should give same result)
List<ProcessDefinition> definitionsByName = repositoryService.createProcessDefinitionQuery()
.processDefinitionName("myProcess").list();
CollectionAssertions.assertContainsSameElements(definitions, definitionsByName);
}
-
+
public void testRedeployProcessWithIdAndName() {
deployBpmn2XmlString(TEST_PROCESS_ID_AND_NAME);
-
- ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery().processDefinitionName("myProcess");
+
+ ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery()
+ .processDefinitionName("myFirstProcess");
List<ProcessDefinition> definitions = query.list();
assertEquals(1, definitions.size());
-
+
deployBpmn2XmlString(TEST_PROCESS_ID_AND_NAME);
query.orderAsc(ProcessDefinitionQuery.PROPERTY_VERSION);
definitions = query.list();
-
+
assertEquals(2, definitions.size());
assertEquals(1, definitions.get(0).getVersion());
assertEquals(2, definitions.get(1).getVersion());
-
+
// Check if the key is replaced with the name (query should give same result)
List<ProcessDefinition> definitionsByKey = repositoryService.createProcessDefinitionQuery()
- .processDefinitionKey("myFirstProcess").list();
+ .processDefinitionKey("myProcess").list();
CollectionAssertions.assertContainsSameElements(definitions, definitionsByKey);
}
-
+
}
Modified: jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/bpmn/test/startevent/TimerStartEventTest.java
===================================================================
--- jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/bpmn/test/startevent/TimerStartEventTest.java 2010-10-16 13:44:02 UTC (rev 6764)
+++ jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/bpmn/test/startevent/TimerStartEventTest.java 2010-10-17 14:44:27 UTC (rev 6765)
@@ -123,7 +123,7 @@
private static final String TIMER_START_TIMECYCLE_CRON_EXPR =
"<definitions xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>" +
- " <process id='timerStartTimeCycleCronExpression' name='timerStartCron'>" +
+ " <process id='timerStartTimeCycleCronExpression'>" +
" <startEvent id='theStart' >" +
" <timerEventDefinition >" +
" <timeCycle>0 0 22 * * ?</timeCycle>" + // every day at 22:00
13 years, 6 months
JBoss JBPM SVN: r6764 - in jbpm3/branches/jbpm-3.2-soa: core/src/main/resources and 2 other directories.
by do-not-reply@jboss.org
Author: alex.guizar(a)jboss.com
Date: 2010-10-16 09:44:02 -0400 (Sat, 16 Oct 2010)
New Revision: 6764
Removed:
jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/hibernate.properties.firebird.xml
jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/hibernate.properties.ingres.xml
jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/hibernate.properties.interbase.xml
jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/hibernate.properties.mckoi.xml
jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/hibernate.properties.sapdb.xml
Modified:
jbpm3/branches/jbpm-3.2-soa/core/scripts/antrun-config.xml
jbpm3/branches/jbpm-3.2-soa/db/scripts/antrun-jbpmschema.xml
jbpm3/branches/jbpm-3.2-soa/enterprise-jee5/src/main/java/org/jbpm/jms/JmsConnectorServiceFactory.java
Log:
remove configuration for databases not under continuous integration
Modified: jbpm3/branches/jbpm-3.2-soa/core/scripts/antrun-config.xml
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/scripts/antrun-config.xml 2010-10-16 13:21:11 UTC (rev 6763)
+++ jbpm3/branches/jbpm-3.2-soa/core/scripts/antrun-config.xml 2010-10-16 13:44:02 UTC (rev 6764)
@@ -63,16 +63,11 @@
<target name="gen-hibernate-config" description="generate hibernate configuration">
<cat-hibernate-config database="db2" />
<cat-hibernate-config database="derby" />
- <cat-hibernate-config database="firebird" />
<cat-hibernate-config database="hsqldb" />
- <cat-hibernate-config database="ingres" />
- <cat-hibernate-config database="interbase" />
- <cat-hibernate-config database="mckoi" />
<cat-hibernate-config database="mssql" />
<cat-hibernate-config database="mysql" />
<cat-hibernate-config database="oracle" />
<cat-hibernate-config database="postgresql" />
- <cat-hibernate-config database="sapdb" />
<cat-hibernate-config database="sybase" />
<copy file="${project.output.dir}/hibernate.cfg.${database}.xml"
Deleted: jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/hibernate.properties.firebird.xml
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/hibernate.properties.firebird.xml 2010-10-16 13:21:11 UTC (rev 6763)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/hibernate.properties.firebird.xml 2010-10-16 13:44:02 UTC (rev 6764)
@@ -1,12 +0,0 @@
-
- <!-- hibernate dialect -->
- <property name="hibernate.dialect">org.hibernate.dialect.FirebirdDialect</property>
-
- <!-- JDBC connection properties (begin) -->
- <!-- fetch driver from http://firebird.sourceforge.net/ -->
- <property name="hibernate.connection.driver_class">org.firebirdsql.jdbc.FBDriver</property>
- <property name="hibernate.connection.url">jdbc:firebirdsql:localhost:jbpmtest</property>
- <property name="hibernate.connection.username"></property>
- <property name="hibernate.connection.password"></property>
- <!-- JDBC connection properties (end) -->
-
Deleted: jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/hibernate.properties.ingres.xml
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/hibernate.properties.ingres.xml 2010-10-16 13:21:11 UTC (rev 6763)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/hibernate.properties.ingres.xml 2010-10-16 13:44:02 UTC (rev 6764)
@@ -1,12 +0,0 @@
-
- <!-- hibernate dialect -->
- <property name="hibernate.dialect">org.hibernate.dialect.IngresDialect</property>
-
- <!-- JDBC connection properties (begin) -->
- <!-- fetch driver from http://google.com -->
- <property name="hibernate.connection.driver_class"></property>
- <property name="hibernate.connection.url"></property>
- <property name="hibernate.connection.username"></property>
- <property name="hibernate.connection.password"></property>
- <!-- JDBC connection properties (end) -->
-
Deleted: jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/hibernate.properties.interbase.xml
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/hibernate.properties.interbase.xml 2010-10-16 13:21:11 UTC (rev 6763)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/hibernate.properties.interbase.xml 2010-10-16 13:44:02 UTC (rev 6764)
@@ -1,12 +0,0 @@
-
- <!-- hibernate dialect -->
- <property name="hibernate.dialect">org.hibernate.dialect.InterbaseDialect</property>
-
- <!-- JDBC connection properties (begin) -->
- <!-- fetch driver from http://google.com -->
- <property name="hibernate.connection.driver_class"></property>
- <property name="hibernate.connection.url"></property>
- <property name="hibernate.connection.username"></property>
- <property name="hibernate.connection.password"></property>
- <!-- JDBC connection properties (end) -->
-
Deleted: jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/hibernate.properties.mckoi.xml
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/hibernate.properties.mckoi.xml 2010-10-16 13:21:11 UTC (rev 6763)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/hibernate.properties.mckoi.xml 2010-10-16 13:44:02 UTC (rev 6764)
@@ -1,12 +0,0 @@
-
- <!-- hibernate dialect -->
- <property name="hibernate.dialect">org.hibernate.dialect.MckoiDialect</property>
-
- <!-- JDBC connection properties (begin) -->
- <!-- fetch driver from http://google.com -->
- <property name="hibernate.connection.driver_class"></property>
- <property name="hibernate.connection.url"></property>
- <property name="hibernate.connection.username"></property>
- <property name="hibernate.connection.password"></property>
- <!-- JDBC connection properties (end) -->
-
Deleted: jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/hibernate.properties.sapdb.xml
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/hibernate.properties.sapdb.xml 2010-10-16 13:21:11 UTC (rev 6763)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/hibernate.properties.sapdb.xml 2010-10-16 13:44:02 UTC (rev 6764)
@@ -1,12 +0,0 @@
-
- <!-- hibernate dialect -->
- <property name="hibernate.dialect">org.hibernate.dialect.SAPDBDialect</property>
-
- <!-- JDBC connection properties (begin) -->
- <!-- fetch driver from http://google.com -->
- <property name="hibernate.connection.driver_class"></property>
- <property name="hibernate.connection.url"></property>
- <property name="hibernate.connection.username"></property>
- <property name="hibernate.connection.password"></property>
- <!-- JDBC connection properties (end) -->
-
Modified: jbpm3/branches/jbpm-3.2-soa/db/scripts/antrun-jbpmschema.xml
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/db/scripts/antrun-jbpmschema.xml 2010-10-16 13:21:11 UTC (rev 6763)
+++ jbpm3/branches/jbpm-3.2-soa/db/scripts/antrun-jbpmschema.xml 2010-10-16 13:44:02 UTC (rev 6764)
@@ -22,21 +22,9 @@
<jbpmschema output="${project.output.dir}/jbpm.jpdl.derby.sql"
config="hibernate.cfg.derby.xml"
action="create" />
- <jbpmschema output="${project.output.dir}/jbpm.jpdl.firebird.sql"
- config="hibernate.cfg.firebird.xml"
- action="create" />
<jbpmschema output="${project.output.dir}/jbpm.jpdl.hsqldb.sql"
config="hibernate.cfg.hsqldb.xml"
action="create" />
- <jbpmschema output="${project.output.dir}/jbpm.jpdl.ingres.sql"
- config="hibernate.cfg.ingres.xml"
- action="create" />
- <jbpmschema output="${project.output.dir}/jbpm.jpdl.interbase.sql"
- config="hibernate.cfg.interbase.xml"
- action="create" />
- <jbpmschema output="${project.output.dir}/jbpm.jpdl.mckoi.sql"
- config="hibernate.cfg.mckoi.xml"
- action="create" />
<jbpmschema output="${project.output.dir}/jbpm.jpdl.mssql.sql"
config="hibernate.cfg.mssql.xml"
action="create" />
@@ -49,9 +37,6 @@
<jbpmschema output="${project.output.dir}/jbpm.jpdl.postgresql.sql"
config="hibernate.cfg.postgresql.xml"
action="create" />
- <jbpmschema output="${project.output.dir}/jbpm.jpdl.sapdb.sql"
- config="hibernate.cfg.sapdb.xml"
- action="create" />
<jbpmschema output="${project.output.dir}/jbpm.jpdl.sybase.sql"
config="hibernate.cfg.sybase.xml"
action="create"
Modified: jbpm3/branches/jbpm-3.2-soa/enterprise-jee5/src/main/java/org/jbpm/jms/JmsConnectorServiceFactory.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/enterprise-jee5/src/main/java/org/jbpm/jms/JmsConnectorServiceFactory.java 2010-10-16 13:21:11 UTC (rev 6763)
+++ jbpm3/branches/jbpm-3.2-soa/enterprise-jee5/src/main/java/org/jbpm/jms/JmsConnectorServiceFactory.java 2010-10-16 13:44:02 UTC (rev 6764)
@@ -28,6 +28,7 @@
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.JbpmException;
+import org.jbpm.ejb.JobListenerBean;
import org.jbpm.svc.Service;
import org.jbpm.svc.ServiceFactory;
import org.jbpm.util.JndiUtil;
13 years, 6 months
JBoss JBPM SVN: r6763 - in jbpm3/branches/jbpm-3.2-soa/core: scripts and 22 other directories.
by do-not-reply@jboss.org
Author: alex.guizar(a)jboss.com
Date: 2010-10-16 09:21:11 -0400 (Sat, 16 Oct 2010)
New Revision: 6763
Added:
jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/org/jbpm/job/Timer.calendar.hbm.xml
jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/context/exe/LongIdVariableDbTest.java
jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/context/exe/StringIdVariableDbTest.java
jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm1776/BusinessTimeSubstractionTest.java
jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2825/ProcessClassLoaderNoContextTest.java
jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2908/AlternateConfigurationAction.java
jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2958/
jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2958/TimerCalendarTest.java
jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/context/exe/jbpm.cfg.xml
jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/graph/
jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/graph/node/
jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/graph/node/jbpm.cfg.xml
jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2908/jbpm.cfg.xml
jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2958/
jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2958/gpd.xml
jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2958/jbpm.cfg.xml
jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2958/processdefinition.xml
jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2958/saturday-business-calendar.properties
jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2958/saturday-jbpm.cfg.xml
Removed:
jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/context/exe/CustomVariableLongIdDbTest.java
jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/context/exe/CustomVariableStringIdDbTest.java
jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm1776/JBPM1776Test.java
jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2825/JBPM2825Test.java
jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2908/ChangeJbpmConfigurationAction.java
jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2908/jbpm-no-auto.cfg.xml
jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2908/jbpm.cfg.xml
Modified:
jbpm3/branches/jbpm-3.2-soa/core/pom.xml
jbpm3/branches/jbpm-3.2-soa/core/scripts/antrun-config.xml
jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/JbpmConfiguration.java
jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/calendar/BusinessCalendar.java
jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/job/Timer.java
jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/persistence/db/DbPersistenceServiceFactory.java
jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/persistence/db/StaleObjectLogConfigurer.java
jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/scheduler/db/DbSchedulerService.java
jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/org/jbpm/calendar/jbpm.business.calendar.properties
jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/calendar/BusinessCalendarTest.java
jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/context/exe/CustomLongClass.java
jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/context/exe/CustomStringClass.java
jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/graph/node/JoinDbTest.java
jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2908/JBPM2908Test.java
jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/log4j.xml
jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2908/processdefinition1.xml
Log:
JBPM-2958 save business calendar resource used to create timer
Modified: jbpm3/branches/jbpm-3.2-soa/core/pom.xml
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/pom.xml 2010-10-16 02:10:32 UTC (rev 6762)
+++ jbpm3/branches/jbpm-3.2-soa/core/pom.xml 2010-10-16 13:21:11 UTC (rev 6763)
@@ -156,7 +156,7 @@
<executions>
<execution>
<id>gen-config</id>
- <phase>compile</phase>
+ <phase>process-resources</phase>
<goals>
<goal>run</goal>
</goals>
@@ -168,6 +168,21 @@
</tasks>
</configuration>
</execution>
+
+ <execution>
+ <id>gen-test-config</id>
+ <phase>process-test-resources</phase>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ <configuration>
+ <tasks>
+ <property name="project.output.dir" value="${project.build.outputDirectory}" />
+ <property name="project.test.output.dir" value="${project.build.testOutputDirectory}" />
+ <ant antfile="scripts/antrun-config.xml" target="gen-hibernate-test-config" />
+ </tasks>
+ </configuration>
+ </execution>
</executions>
</plugin>
</plugins>
@@ -195,85 +210,6 @@
</profile>
<!--
- Name: no-database
- Desc: Default Database Setup
- -->
- <profile>
- <id>no-database</id>
- <activation>
- <property>
- <name>!database</name>
- </property>
- </activation>
- <build>
- <plugins>
- <plugin>
- <artifactId>maven-antrun-plugin</artifactId>
- <executions>
- <execution>
- <id>no-hibernate-auto-create</id>
- <phase>process-test-resources</phase>
- <goals>
- <goal>run</goal>
- </goals>
- <configuration>
- <tasks>
- <property name="project.output.dir"
- value="${project.build.outputDirectory}" />
- <property name="project.test.output.dir"
- value="${project.build.testOutputDirectory}" />
- <ant antfile="scripts/antrun-config.xml"
- target="gen-hibernate-config-no-auto" />
- </tasks>
- </configuration>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
- </profile>
-
- <!--
- Name: hsqldb
- Desc: Hypersonic Database Setup
- -->
- <profile>
- <id>hsqldb</id>
- <activation>
- <property>
- <name>database</name>
- <value>hsqldb</value>
- </property>
- </activation>
- <build>
- <plugins>
- <plugin>
- <artifactId>maven-antrun-plugin</artifactId>
- <executions>
- <execution>
- <id>no-hibernate-auto-create</id>
- <phase>process-test-resources</phase>
- <goals>
- <goal>run</goal>
- </goals>
- <configuration>
- <tasks>
- <property name="project.output.dir"
- value="${project.build.outputDirectory}" />
- <property name="project.test.output.dir"
- value="${project.build.testOutputDirectory}" />
- <ant antfile="scripts/antrun-config.xml"
- target="gen-hibernate-config-no-auto" />
- </tasks>
- </configuration>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
- </profile>
-
- <!--
Name: db2
Desc: DB2 Test Exclusions
-->
Modified: jbpm3/branches/jbpm-3.2-soa/core/scripts/antrun-config.xml
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/scripts/antrun-config.xml 2010-10-16 02:10:32 UTC (rev 6762)
+++ jbpm3/branches/jbpm-3.2-soa/core/scripts/antrun-config.xml 2010-10-16 13:21:11 UTC (rev 6763)
@@ -11,7 +11,7 @@
<property name="project.output.dir" value="${basedir}/target/classes" />
<property name="project.test.output.dir" value="${basedir}/target/classes" />
- <macrodef name="macro-disable">
+ <macrodef name="comment-out">
<attribute name="file" />
<attribute name="section" />
<sequential>
@@ -23,19 +23,6 @@
</sequential>
</macrodef>
- <macrodef name="macro-enable">
- <attribute name="file" />
- <attribute name="section" />
- <sequential>
- <replace file="@{file}">
- <replacefilter token="<!-- @{section} (begin) ==="
- value="<!-- @{section} (begin) -->" />
- <replacefilter token="==== @{section} (end) -->"
- value="<!-- @{section} (end) -->" />
- </replace>
- </sequential>
- </macrodef>
-
<macrodef name="cat-hibernate-config">
<attribute name="database" />
<sequential>
@@ -92,10 +79,24 @@
tofile="${project.output.dir}/hibernate.cfg.xml" />
</target>
- <target name="gen-hibernate-config-no-auto">
+ <target name="gen-hibernate-test-config">
<copy file="${project.output.dir}/hibernate.cfg.xml"
- tofile="${project.test.output.dir}/hibernate-no-auto.cfg.xml" />
- <macro-disable file="${project.test.output.dir}/hibernate-no-auto.cfg.xml"
- section="Automatic schema creation" />
+ todir="${project.test.output.dir}/org/jbpm/graph/node" />
+ <replace file="${project.test.output.dir}/org/jbpm/graph/node/hibernate.cfg.xml"
+ token="Join.hbm.xml" value="Join.lock.hbm.xml" />
+ <comment-out file="${project.test.output.dir}/org/jbpm/graph/node/hibernate.cfg.xml"
+ section="Automatic schema creation" />
+
+ <copy file="${project.output.dir}/hibernate.cfg.xml"
+ todir="${project.test.output.dir}/org/jbpm/jbpm2908" />
+ <comment-out file="${project.test.output.dir}/org/jbpm/jbpm2908/hibernate.cfg.xml"
+ section="Automatic schema creation" />
+
+ <copy file="${project.output.dir}/hibernate.cfg.xml"
+ todir="${project.test.output.dir}/org/jbpm/jbpm2958" />
+ <replace file="${project.test.output.dir}/org/jbpm/jbpm2958/hibernate.cfg.xml"
+ token="Timer.hbm.xml" value="Timer.calendar.hbm.xml" />
+ <comment-out file="${project.test.output.dir}/org/jbpm/jbpm2958/hibernate.cfg.xml"
+ section="Automatic schema creation" />
</target>
</project>
Modified: jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/JbpmConfiguration.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/JbpmConfiguration.java 2010-10-16 02:10:32 UTC (rev 6762)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/JbpmConfiguration.java 2010-10-16 13:21:11 UTC (rev 6763)
@@ -41,7 +41,6 @@
import org.jbpm.instantiation.ProcessClassLoaderFactory;
import org.jbpm.job.executor.JobExecutor;
import org.jbpm.persistence.db.DbPersistenceServiceFactory;
-import org.jbpm.persistence.db.StaleObjectLogConfigurer;
import org.jbpm.svc.ServiceFactory;
import org.jbpm.svc.Services;
import org.jbpm.util.ClassLoaderUtil;
@@ -358,21 +357,9 @@
objectFactoryImpl.addObjectInfo(new ValueInfo("jbpmConfiguration", jbpmConfiguration));
objectFactoryImpl.addObjectInfo(new ValueInfo(OBJECT_NAME, jbpmConfiguration));
}
- // honor hide stale state exceptions setting
- if (getHideStaleObjectExceptions(objectFactory)) {
- StaleObjectLogConfigurer.hideStaleObjectExceptions();
- }
return jbpmConfiguration;
}
- private static boolean getHideStaleObjectExceptions(ObjectFactory objectFactory) {
- if (objectFactory.hasObject("jbpm.hide.stale.object.exceptions")) {
- Object hide = objectFactory.createObject("jbpm.hide.stale.object.exceptions");
- if (Boolean.FALSE.equals(hide)) return false;
- }
- return true;
- }
-
public static JbpmConfiguration parseInputStream(InputStream inputStream) {
ObjectFactory objectFactory;
if (inputStream != null) {
Modified: jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/calendar/BusinessCalendar.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/calendar/BusinessCalendar.java 2010-10-16 02:10:32 UTC (rev 6762)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/calendar/BusinessCalendar.java 2010-10-16 13:21:11 UTC (rev 6763)
@@ -30,7 +30,7 @@
import java.util.Map;
import java.util.Properties;
-import org.jbpm.JbpmConfiguration;
+import org.jbpm.JbpmConfiguration.Configs;
import org.jbpm.util.ClassLoaderUtil;
/**
@@ -40,47 +40,51 @@
private static final long serialVersionUID = 1L;
- private Day[] weekDays;
- private List holidays;
+ private final Day[] weekDays;
+ private final List holidays;
private static final Map propertiesByResource = new HashMap();
public static Properties getBusinessCalendarProperties() {
- String resource = JbpmConfiguration.Configs.getString("resource.business.calendar");
+ String calendarResource = Configs.getString("resource.business.calendar");
+ return getBusinessCalendarProperties(calendarResource);
+ }
+
+ private static Properties getBusinessCalendarProperties(String calendarResource) {
synchronized (propertiesByResource) {
- Properties properties = (Properties) propertiesByResource.get(resource);
+ Properties properties = (Properties) propertiesByResource.get(calendarResource);
if (properties == null) {
- properties = ClassLoaderUtil.getProperties(resource);
- propertiesByResource.put(resource, properties);
+ properties = ClassLoaderUtil.getProperties(calendarResource);
+ propertiesByResource.put(calendarResource, properties);
}
return properties;
}
}
public BusinessCalendar() {
- // do not load properties during creation time!
- // see http://community.jboss.org/message/404365
- // this(getBusinessCalendarProperties());
+ /*
+ * loading properties at construction time used to be bad, as business calendars were kept
+ * in static attributes of persistent classes, resulting in the default configuration being
+ * unduly loaded; however, business calendars are no longer static.
+ * see http://community.jboss.org/message/404365
+ */
+ this(getBusinessCalendarProperties());
}
+ public BusinessCalendar(String calendarResource) {
+ this(getBusinessCalendarProperties(calendarResource));
+ }
+
public BusinessCalendar(Properties calendarProperties) {
weekDays = Day.parseWeekDays(calendarProperties, this);
holidays = Holiday.parseHolidays(calendarProperties, this);
}
public Day[] getWeekDays() {
- if (weekDays == null) {
- // lazy load properties if not set during creation
- weekDays = Day.parseWeekDays(getBusinessCalendarProperties(), this);
- }
return weekDays;
}
public List getHolidays() {
- if (holidays == null) {
- // lazy load properties if not set during creation
- holidays = Holiday.parseHolidays(getBusinessCalendarProperties(), this);
- }
return holidays;
}
Modified: jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/job/Timer.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/job/Timer.java 2010-10-16 02:10:32 UTC (rev 6762)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/job/Timer.java 2010-10-16 13:21:11 UTC (rev 6763)
@@ -26,6 +26,7 @@
private String transitionName;
private Action action;
private GraphElement graphElement;
+ private String calendarResource;
public Timer() {
}
@@ -75,28 +76,23 @@
// if repeat is specified, reschedule the job
if (repeat != null) {
- // suppose that it took the timer runner thread a
- // very long time to execute the timers.
- // then the repeat action dueDate could already have passed.
- Duration interval = new Duration(repeat);
- long currentTime = System.currentTimeMillis();
+ // if a calendar resource is specified, use it to calculate repeat dates
+ // https://jira.jboss.org/browse/JBPM-2958
+ BusinessCalendar businessCalendar = calendarResource == null ? new BusinessCalendar()
+ : new BusinessCalendar(calendarResource);
- BusinessCalendar businessCalendar = new BusinessCalendar();
- Date repeatDate = getDueDate();
- do {
- repeatDate = businessCalendar.add(repeatDate, interval);
- } while (repeatDate.getTime() <= currentTime);
-
+ Date repeatDate = businessCalendar.add(getDueDate(), new Duration(repeat));
if (log.isDebugEnabled()) {
log.debug("scheduling " + this + " for repeat on " + repeatDate);
}
setDueDate(repeatDate);
// unlock timer so that:
- // (a) any job executor thread can acquire it next time
- // (b) the engine knows it is not executing and can be deleted
- // see https://jira.jboss.org/jira/browse/JBPM-2036
+ // (a) any job executor thread can acquire it the next time
+ // (b) the engine knows it is not executing and can be canceled
+ // https://jira.jboss.org/jira/browse/JBPM-2036
setLockOwner(null);
+
return false;
}
@@ -157,5 +153,19 @@
this.action = action;
}
+ /**
+ * Gets the business calendar resource used for calculating repeat dates.
+ */
+ public String getCalendarResource() {
+ return calendarResource;
+ }
+
+ /**
+ * Sets the business calendar resource to use for calculating repeat dates.
+ */
+ public void setCalendarResource(String calendarResource) {
+ this.calendarResource = calendarResource;
+ }
+
private static final Log log = LogFactory.getLog(Timer.class);
}
Modified: jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/persistence/db/DbPersistenceServiceFactory.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/persistence/db/DbPersistenceServiceFactory.java 2010-10-16 02:10:32 UTC (rev 6762)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/persistence/db/DbPersistenceServiceFactory.java 2010-10-16 13:21:11 UTC (rev 6763)
@@ -27,6 +27,7 @@
import org.apache.commons.logging.LogFactory;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.jbpm.JbpmConfiguration;
import org.jbpm.db.JbpmSchema;
@@ -130,7 +131,7 @@
boolean getScript() {
boolean script = false;
- String showSql = getConfiguration().getProperty("hibernate.show_sql");
+ String showSql = getConfiguration().getProperty(Environment.SHOW_SQL);
if ("true".equalsIgnoreCase(showSql)) {
script = true;
}
Modified: jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/persistence/db/StaleObjectLogConfigurer.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/persistence/db/StaleObjectLogConfigurer.java 2010-10-16 02:10:32 UTC (rev 6762)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/persistence/db/StaleObjectLogConfigurer.java 2010-10-16 13:21:11 UTC (rev 6763)
@@ -26,100 +26,21 @@
public class StaleObjectLogConfigurer {
- private static Log staleObjectExceptionsLog = LogFactory
- .getLog(StaleObjectLogConfigurer.class.getName() + ".staleObjectExceptions");
+ private static final Log log = LogFactory.getLog(StaleObjectLogConfigurer.class);
private StaleObjectLogConfigurer() {
// hide default constructor to prevent instantiation
}
public static Log getStaleObjectExceptionsLog() {
- return staleObjectExceptionsLog;
+ return log;
}
+ /**
+ * @deprecated to hide stale object exceptions, just set the log category threshold above
+ * ERROR.
+ */
public static void hideStaleObjectExceptions() {
- Log log = LogFactory.getLog(StaleObjectLogConfigurer.class);
-
- // check whether stale state exceptions are already hidden
- if (staleObjectExceptionsLog instanceof LogWrapper) {
- if (log.isDebugEnabled()) {
- log.debug("stale object exceptions already hidden from logging");
- }
- return;
- }
-
- log.info("stale object exceptions will not be logged");
- staleObjectExceptionsLog = new LogWrapper(staleObjectExceptionsLog);
+ // nothing to do here
}
-
- private static class LogWrapper implements Log {
-
- private final Log delegate;
-
- LogWrapper(Log delegate) {
- this.delegate = delegate;
- }
-
- public void debug(Object arg0, Throwable arg1) {
- }
-
- public void debug(Object arg0) {
- }
-
- public void error(Object arg0, Throwable arg1) {
- }
-
- public void error(Object arg0) {
- }
-
- public void info(Object arg0, Throwable arg1) {
- }
-
- public void info(Object arg0) {
- }
-
- public void trace(Object arg0, Throwable arg1) {
- }
-
- public void trace(Object arg0) {
- }
-
- public void warn(Object arg0, Throwable arg1) {
- }
-
- public void warn(Object arg0) {
- }
-
- public void fatal(Object arg0, Throwable arg1) {
- delegate.fatal(arg0, arg1);
- }
-
- public void fatal(Object arg0) {
- delegate.fatal(arg0);
- }
-
- public boolean isDebugEnabled() {
- return false;
- }
-
- public boolean isErrorEnabled() {
- return false;
- }
-
- public boolean isFatalEnabled() {
- return delegate.isFatalEnabled();
- }
-
- public boolean isInfoEnabled() {
- return false;
- }
-
- public boolean isTraceEnabled() {
- return false;
- }
-
- public boolean isWarnEnabled() {
- return false;
- }
- }
}
Modified: jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/scheduler/db/DbSchedulerService.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/scheduler/db/DbSchedulerService.java 2010-10-16 02:10:32 UTC (rev 6762)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/scheduler/db/DbSchedulerService.java 2010-10-16 13:21:11 UTC (rev 6763)
@@ -23,7 +23,7 @@
import org.jbpm.JbpmContext;
import org.jbpm.JbpmException;
-import org.jbpm.db.JobSession;
+import org.jbpm.configuration.ObjectFactory;
import org.jbpm.graph.exe.ProcessInstance;
import org.jbpm.graph.exe.Token;
import org.jbpm.job.Timer;
@@ -34,39 +34,45 @@
private static final long serialVersionUID = 1L;
- private final JobSession jobSession;
- private final JobExecutor jobExecutor;
+ private final JbpmContext jbpmContext;
private boolean hasProducedJobs;
public DbSchedulerService() {
- JbpmContext jbpmContext = JbpmContext.getCurrentJbpmContext();
+ jbpmContext = JbpmContext.getCurrentJbpmContext();
if (jbpmContext == null) throw new JbpmException("no active jbpm context");
-
- this.jobSession = jbpmContext.getJobSession();
- this.jobExecutor = jbpmContext.getJbpmConfiguration().getJobExecutor();
}
- public void createTimer(Timer timerJob) {
- jobSession.saveJob(timerJob);
+ public void createTimer(Timer timer) {
+ // save business calendar resource used to create timer
+ // https://jira.jboss.org/browse/JBPM-2958
+ ObjectFactory objectFactory = jbpmContext.getObjectFactory();
+ if (objectFactory.hasObject("resource.business.calendar")) {
+ timer.setCalendarResource((String) objectFactory.getObject("resource.business.calendar"));
+ }
+
+ jbpmContext.getJobSession().saveJob(timer);
hasProducedJobs = true;
}
public void deleteTimer(Timer timer) {
- jobSession.deleteJob(timer);
+ jbpmContext.getJobSession().deleteJob(timer);
}
public void deleteTimersByName(String timerName, Token token) {
- jobSession.deleteTimersByName(timerName, token);
+ jbpmContext.getJobSession().deleteTimersByName(timerName, token);
}
public void deleteTimersByProcessInstance(ProcessInstance processInstance) {
- jobSession.deleteJobsForProcessInstance(processInstance);
+ jbpmContext.getJobSession().deleteJobsForProcessInstance(processInstance);
}
public void close() {
- // if timers were produced
- if (hasProducedJobs && jobExecutor != null) {
- // notify job executor
+ // if no timers were produced, just return
+ if (!hasProducedJobs) return;
+
+ // notify job executor
+ JobExecutor jobExecutor = jbpmContext.getJbpmConfiguration().getJobExecutor();
+ if (jobExecutor != null) {
synchronized (jobExecutor) {
jobExecutor.notify();
}
Modified: jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/org/jbpm/calendar/jbpm.business.calendar.properties
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/org/jbpm/calendar/jbpm.business.calendar.properties 2010-10-16 02:10:32 UTC (rev 6762)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/org/jbpm/calendar/jbpm.business.calendar.properties 2010-10-16 13:21:11 UTC (rev 6763)
@@ -11,7 +11,7 @@
weekday.saturday=
weekday.sunday=
-day.format=dd/MM/yyyy
+day.format=MM/dd/yyyy
# holiday ::= <holiday-period>
# holiday-period ::= <start-day> [- <end-day>]
# start-day and end-day must be in the day.format
@@ -19,32 +19,31 @@
# new year's day
holiday.1= 01/01/2010
# birthday of martin luther king
-holiday.2= 18/01/2010
+holiday.2= 01/18/2010
# washington's birthday
-holiday.3= 15/02/2010
+holiday.3= 02/15/2010
# memorial day
-holiday.4= 31/05/2010
+holiday.4= 05/31/2010
# independence day
-holiday.5= 05/07/2010
+holiday.5= 07/05/2010
# labor day
-holiday.6= 06/09/2010
+holiday.6= 09/06/2010
# columbus day
-holiday.7= 11/10/2010
+holiday.7= 10/11/2010
# veterans day
holiday.8= 11/11/2010
# thanksgiving day
-holiday.9= 25/11/2010
+holiday.9= 11/25/2010
# day after thanksgiving
-holiday.10= 26/11/2010
+holiday.10= 11/26/2010
# christmas day
-holiday.11= 24/12/2010
+holiday.11= 12/24/2010
# typical workday excluding breaks
business.day.expressed.in.hours= 7.5
# 7.5 hours * 5 days a week
business.week.expressed.in.hours= 37.5
-# 253 business days / 12 months
+# 250 business days / 12 months
business.month.expressed.in.business.days= 21
-# 365 natural days - 105 weekend days - 7 holidays
-business.year.expressed.in.business.days= 253
-
+# 365 natural days - 104 weekend days - 11 holidays
+business.year.expressed.in.business.days= 250
Added: jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/org/jbpm/job/Timer.calendar.hbm.xml
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/org/jbpm/job/Timer.calendar.hbm.xml (rev 0)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/org/jbpm/job/Timer.calendar.hbm.xml 2010-10-16 13:21:11 UTC (rev 6763)
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+
+<!DOCTYPE hibernate-mapping PUBLIC
+ "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<hibernate-mapping auto-import="false" default-access="field">
+
+ <subclass name="org.jbpm.job.Timer"
+ discriminator-value="T"
+ extends="org.jbpm.job.Job">
+
+ <property name="name" column="NAME_" />
+ <property name="repeat" column="REPEAT_" />
+ <property name="transitionName" column="TRANSITIONNAME_" />
+
+ <many-to-one name="action"
+ column="ACTION_"
+ cascade="lock"
+ foreign-key="FK_JOB_ACTION"
+ index="IDX_JOB_ACTION"/>
+
+ <any name="graphElement" id-type="long" cascade="lock">
+ <column name="GRAPHELEMENTTYPE_"/>
+ <column name="GRAPHELEMENT_"/>
+ </any>
+
+ <property name="calendarResource" column="CALENDARRESOURCE_" />
+
+ </subclass>
+
+</hibernate-mapping>
Property changes on: jbpm3/branches/jbpm-3.2-soa/core/src/main/resources/org/jbpm/job/Timer.calendar.hbm.xml
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/calendar/BusinessCalendarTest.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/calendar/BusinessCalendarTest.java 2010-10-16 02:10:32 UTC (rev 6762)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/calendar/BusinessCalendarTest.java 2010-10-16 13:21:11 UTC (rev 6763)
@@ -291,12 +291,11 @@
public void testBusinessYearAddition() {
Calendar calendar = Calendar.getInstance();
- calendar.set(2010, Calendar.FEBRUARY, 8, 9, 30, 0);
+ calendar.set(2009, Calendar.DECEMBER, 28, 9, 30, 0);
calendar.set(Calendar.MILLISECOND, 0);
Date start = calendar.getTime();
- calendar.set(Calendar.YEAR, 2011);
- calendar.set(Calendar.DAY_OF_MONTH, 9);
+ calendar.set(Calendar.YEAR, 2010);
Date expected = calendar.getTime();
assertEquals(expected, businessCalendar.add(start, new Duration("1 business year")));
Modified: jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/context/exe/CustomLongClass.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/context/exe/CustomLongClass.java 2010-10-16 02:10:32 UTC (rev 6762)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/context/exe/CustomLongClass.java 2010-10-16 13:21:11 UTC (rev 6763)
@@ -22,13 +22,17 @@
package org.jbpm.context.exe;
public class CustomLongClass {
- long id = 0;
- public String name = null;
+
+ long id;
+ String name;
+
public CustomLongClass() {
}
+
public CustomLongClass(String name) {
this.name = name;
}
+
public String getName() {
return name;
}
Modified: jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/context/exe/CustomStringClass.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/context/exe/CustomStringClass.java 2010-10-16 02:10:32 UTC (rev 6762)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/context/exe/CustomStringClass.java 2010-10-16 13:21:11 UTC (rev 6763)
@@ -22,13 +22,17 @@
package org.jbpm.context.exe;
public class CustomStringClass {
- String id = null;
- public String name = null;
+
+ String id;
+ String name;
+
public CustomStringClass() {
}
+
public CustomStringClass(String name) {
this.name = name;
}
+
public String getName() {
return name;
}
Deleted: jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/context/exe/CustomVariableLongIdDbTest.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/context/exe/CustomVariableLongIdDbTest.java 2010-10-16 02:10:32 UTC (rev 6762)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/context/exe/CustomVariableLongIdDbTest.java 2010-10-16 13:21:11 UTC (rev 6763)
@@ -1,95 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2005, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jbpm.context.exe;
-
-import org.hibernate.cfg.Configuration;
-
-import org.jbpm.JbpmConfiguration;
-import org.jbpm.JbpmContext;
-import org.jbpm.context.def.ContextDefinition;
-import org.jbpm.db.AbstractDbTestCase;
-import org.jbpm.db.JbpmSchema;
-import org.jbpm.graph.def.ProcessDefinition;
-import org.jbpm.graph.exe.ProcessInstance;
-import org.jbpm.persistence.db.DbPersistenceServiceFactory;
-import org.jbpm.svc.Services;
-
-public class CustomVariableLongIdDbTest extends AbstractDbTestCase {
-
- protected JbpmConfiguration getJbpmConfiguration() {
- if (jbpmConfiguration == null) {
- // disable logging service to prevent logs from referencing custom object
- jbpmConfiguration = JbpmConfiguration.parseXmlString("<jbpm-configuration>"
- + "<jbpm-context>"
- + " <service name='persistence'"
- + " factory='org.jbpm.persistence.db.DbPersistenceServiceFactory' />"
- + " <service name='tx' factory='org.jbpm.tx.TxServiceFactory' />"
- + "</jbpm-context>"
- + "</jbpm-configuration>");
-
- JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
- try {
- DbPersistenceServiceFactory persistenceServiceFactory =
- (DbPersistenceServiceFactory) jbpmContext.getServiceFactory(Services.SERVICENAME_PERSISTENCE);
- Configuration configuration = persistenceServiceFactory.getConfiguration();
- configuration.addClass(CustomLongClass.class);
-
- JbpmSchema jbpmSchema = new JbpmSchema(configuration);
- jbpmSchema.createTable("JBPM_TEST_CUSTOMLONGID");
- }
- finally {
- jbpmContext.close();
- }
- }
- return jbpmConfiguration;
- }
-
- protected void tearDown() throws Exception {
- super.tearDown();
- jbpmConfiguration.close();
- }
-
- public void testCustomVariableClassWithLongId() {
- // create and save process definition
- ProcessDefinition processDefinition = new ProcessDefinition(getName());
- processDefinition.addDefinition(new ContextDefinition());
- deployProcessDefinition(processDefinition);
-
- // create process instance
- ProcessInstance processInstance = new ProcessInstance(processDefinition);
- // create custom object
- CustomLongClass customLongObject = new CustomLongClass("my stuff");
- processInstance.getContextInstance().setVariable("custom", customLongObject);
-
- // save process instance
- processInstance = saveAndReload(processInstance);
- // get custom object from variables
- customLongObject = (CustomLongClass) processInstance.getContextInstance()
- .getVariable("custom");
- assertNotNull(customLongObject);
- assertEquals("my stuff", customLongObject.getName());
-
- // delete custom object
- processInstance.getContextInstance().deleteVariable("custom");
- session.delete(customLongObject);
- }
-}
Deleted: jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/context/exe/CustomVariableStringIdDbTest.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/context/exe/CustomVariableStringIdDbTest.java 2010-10-16 02:10:32 UTC (rev 6762)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/context/exe/CustomVariableStringIdDbTest.java 2010-10-16 13:21:11 UTC (rev 6763)
@@ -1,95 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2005, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jbpm.context.exe;
-
-import org.hibernate.cfg.Configuration;
-
-import org.jbpm.JbpmConfiguration;
-import org.jbpm.JbpmContext;
-import org.jbpm.context.def.ContextDefinition;
-import org.jbpm.db.AbstractDbTestCase;
-import org.jbpm.db.JbpmSchema;
-import org.jbpm.graph.def.ProcessDefinition;
-import org.jbpm.graph.exe.ProcessInstance;
-import org.jbpm.persistence.db.DbPersistenceServiceFactory;
-import org.jbpm.svc.Services;
-
-public class CustomVariableStringIdDbTest extends AbstractDbTestCase {
-
- protected JbpmConfiguration getJbpmConfiguration() {
- if (jbpmConfiguration == null) {
- // disable logging service to prevent logs from referencing custom object
- jbpmConfiguration = JbpmConfiguration.parseXmlString("<jbpm-configuration>"
- + "<jbpm-context>"
- + " <service name='persistence'"
- + " factory='org.jbpm.persistence.db.DbPersistenceServiceFactory' />"
- + " <service name='tx' factory='org.jbpm.tx.TxServiceFactory' />"
- + "</jbpm-context>"
- + "</jbpm-configuration>");
-
- JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
- try {
- DbPersistenceServiceFactory persistenceServiceFactory =
- (DbPersistenceServiceFactory) jbpmContext.getServiceFactory(Services.SERVICENAME_PERSISTENCE);
- Configuration configuration = persistenceServiceFactory.getConfiguration();
- configuration.addClass(CustomStringClass.class);
-
- JbpmSchema jbpmSchema = new JbpmSchema(configuration);
- jbpmSchema.createTable("JBPM_TEST_CUSTOMSTRINGID");
- }
- finally {
- jbpmContext.close();
- }
- }
- return jbpmConfiguration;
- }
-
- protected void tearDown() throws Exception {
- super.tearDown();
- jbpmConfiguration.close();
- }
-
- public void testCustomVariableClassWithStringId() {
- // create and save process definition
- ProcessDefinition processDefinition = new ProcessDefinition(getName());
- processDefinition.addDefinition(new ContextDefinition());
- deployProcessDefinition(processDefinition);
-
- // create process instance
- ProcessInstance processInstance = new ProcessInstance(processDefinition);
- // create custom object
- CustomStringClass customStringObject = new CustomStringClass("my stuff");
- processInstance.getContextInstance().setVariable("custom", customStringObject);
-
- // save process instance
- processInstance = saveAndReload(processInstance);
- // get custom object from variables
- customStringObject = (CustomStringClass) processInstance.getContextInstance()
- .getVariable("custom");
- assertNotNull(customStringObject);
- assertEquals("my stuff", customStringObject.getName());
-
- // delete custom object
- processInstance.getContextInstance().deleteVariable("custom");
- session.delete(customStringObject);
- }
-}
Copied: jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/context/exe/LongIdVariableDbTest.java (from rev 6741, jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/context/exe/CustomVariableLongIdDbTest.java)
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/context/exe/LongIdVariableDbTest.java (rev 0)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/context/exe/LongIdVariableDbTest.java 2010-10-16 13:21:11 UTC (rev 6763)
@@ -0,0 +1,89 @@
+/*
+ * 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.context.exe;
+
+import org.hibernate.cfg.Configuration;
+
+import org.jbpm.JbpmConfiguration;
+import org.jbpm.JbpmContext;
+import org.jbpm.context.def.ContextDefinition;
+import org.jbpm.db.AbstractDbTestCase;
+import org.jbpm.db.JbpmSchema;
+import org.jbpm.graph.def.ProcessDefinition;
+import org.jbpm.graph.exe.ProcessInstance;
+import org.jbpm.persistence.db.DbPersistenceServiceFactory;
+import org.jbpm.svc.Services;
+
+public class LongIdVariableDbTest extends AbstractDbTestCase {
+
+ protected JbpmConfiguration getJbpmConfiguration() {
+ if (jbpmConfiguration == null) {
+ // disable logging service to prevent logs from referencing custom object
+ jbpmConfiguration = JbpmConfiguration.parseResource("org/jbpm/context/exe/jbpm.cfg.xml");
+
+ JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
+ try {
+ DbPersistenceServiceFactory persistenceServiceFactory =
+ (DbPersistenceServiceFactory) jbpmContext.getServiceFactory(Services.SERVICENAME_PERSISTENCE);
+ Configuration configuration = persistenceServiceFactory.getConfiguration();
+ configuration.addClass(CustomLongClass.class);
+
+ JbpmSchema jbpmSchema = new JbpmSchema(configuration);
+ jbpmSchema.createTable("JBPM_TEST_CUSTOMLONGID");
+ }
+ finally {
+ jbpmContext.close();
+ }
+ }
+ return jbpmConfiguration;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ jbpmConfiguration.close();
+ }
+
+ public void testCustomVariableClassWithLongId() {
+ // create and save process definition
+ ProcessDefinition processDefinition = new ProcessDefinition(getName());
+ processDefinition.addDefinition(new ContextDefinition());
+ deployProcessDefinition(processDefinition);
+
+ // create process instance
+ ProcessInstance processInstance = new ProcessInstance(processDefinition);
+ // create custom object
+ CustomLongClass customLongObject = new CustomLongClass("my stuff");
+ processInstance.getContextInstance().setVariable("custom", customLongObject);
+
+ // save process instance
+ processInstance = saveAndReload(processInstance);
+ // get custom object from variables
+ customLongObject = (CustomLongClass) processInstance.getContextInstance()
+ .getVariable("custom");
+ assertNotNull(customLongObject);
+ assertEquals("my stuff", customLongObject.getName());
+
+ // delete custom object
+ processInstance.getContextInstance().deleteVariable("custom");
+ session.delete(customLongObject);
+ }
+}
Copied: jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/context/exe/StringIdVariableDbTest.java (from rev 6741, jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/context/exe/CustomVariableStringIdDbTest.java)
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/context/exe/StringIdVariableDbTest.java (rev 0)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/context/exe/StringIdVariableDbTest.java 2010-10-16 13:21:11 UTC (rev 6763)
@@ -0,0 +1,89 @@
+/*
+ * 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.context.exe;
+
+import org.hibernate.cfg.Configuration;
+
+import org.jbpm.JbpmConfiguration;
+import org.jbpm.JbpmContext;
+import org.jbpm.context.def.ContextDefinition;
+import org.jbpm.db.AbstractDbTestCase;
+import org.jbpm.db.JbpmSchema;
+import org.jbpm.graph.def.ProcessDefinition;
+import org.jbpm.graph.exe.ProcessInstance;
+import org.jbpm.persistence.db.DbPersistenceServiceFactory;
+import org.jbpm.svc.Services;
+
+public class StringIdVariableDbTest extends AbstractDbTestCase {
+
+ protected JbpmConfiguration getJbpmConfiguration() {
+ if (jbpmConfiguration == null) {
+ // disable logging service to prevent logs from referencing custom object
+ jbpmConfiguration = JbpmConfiguration.parseResource("org/jbpm/context/exe/jbpm.cfg.xml");
+
+ JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
+ try {
+ DbPersistenceServiceFactory persistenceServiceFactory =
+ (DbPersistenceServiceFactory) jbpmContext.getServiceFactory(Services.SERVICENAME_PERSISTENCE);
+ Configuration configuration = persistenceServiceFactory.getConfiguration();
+ configuration.addClass(CustomStringClass.class);
+
+ JbpmSchema jbpmSchema = new JbpmSchema(configuration);
+ jbpmSchema.createTable("JBPM_TEST_CUSTOMSTRINGID");
+ }
+ finally {
+ jbpmContext.close();
+ }
+ }
+ return jbpmConfiguration;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ jbpmConfiguration.close();
+ }
+
+ public void testCustomVariableClassWithStringId() {
+ // create and save process definition
+ ProcessDefinition processDefinition = new ProcessDefinition(getName());
+ processDefinition.addDefinition(new ContextDefinition());
+ deployProcessDefinition(processDefinition);
+
+ // create process instance
+ ProcessInstance processInstance = new ProcessInstance(processDefinition);
+ // create custom object
+ CustomStringClass customStringObject = new CustomStringClass("my stuff");
+ processInstance.getContextInstance().setVariable("custom", customStringObject);
+
+ // save process instance
+ processInstance = saveAndReload(processInstance);
+ // get custom object from variables
+ customStringObject = (CustomStringClass) processInstance.getContextInstance()
+ .getVariable("custom");
+ assertNotNull(customStringObject);
+ assertEquals("my stuff", customStringObject.getName());
+
+ // delete custom object
+ processInstance.getContextInstance().deleteVariable("custom");
+ session.delete(customStringObject);
+ }
+}
Modified: jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/graph/node/JoinDbTest.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/graph/node/JoinDbTest.java 2010-10-16 02:10:32 UTC (rev 6762)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/graph/node/JoinDbTest.java 2010-10-16 13:21:11 UTC (rev 6763)
@@ -21,23 +21,10 @@
*/
package org.jbpm.graph.node;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.net.URI;
-import java.net.URL;
-import java.util.regex.Pattern;
-
import org.hibernate.LockMode;
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
-import org.jbpm.JbpmException;
import org.jbpm.db.AbstractDbTestCase;
import org.jbpm.db.JbpmSchema;
import org.jbpm.graph.def.ProcessDefinition;
@@ -53,28 +40,12 @@
protected JbpmConfiguration getJbpmConfiguration() {
if (jbpmConfiguration == null) {
- URL cfgResource = getClass().getClassLoader().getResource("hibernate.cfg.xml");
- try {
- InputStream cfgSource = cfgResource.openStream();
- OutputStream cfgSink = new FileOutputStream(new File(URI.create(cfgResource.toString())
- .resolve("hibernate.join.cfg.xml")));
+ jbpmConfiguration = JbpmConfiguration.parseResource("org/jbpm/graph/node/jbpm.cfg.xml");
- sed("Join\\.hbm\\.xml", "Join.lock.hbm.xml", cfgSource, cfgSink);
-
- cfgSource.close();
- cfgSink.close();
- }
- catch (IOException e) {
- throw new JbpmException("could not edit hibernate configuration", e);
- }
- jbpmConfiguration = JbpmConfiguration.parseXmlString("<jbpm-configuration>"
- + " <string name='resource.hibernate.cfg.xml' value='hibernate.join.cfg.xml' />"
- + "</jbpm-configuration>");
-
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
try {
- DbPersistenceServiceFactory persistenceServiceFactory = (DbPersistenceServiceFactory) jbpmContext
- .getServiceFactory(Services.SERVICENAME_PERSISTENCE);
+ DbPersistenceServiceFactory persistenceServiceFactory = (DbPersistenceServiceFactory)
+ jbpmContext.getServiceFactory(Services.SERVICENAME_PERSISTENCE);
JbpmSchema jbpmSchema = new JbpmSchema(persistenceServiceFactory.getConfiguration());
jbpmSchema.updateTable("JBPM_NODE");
}
@@ -90,18 +61,6 @@
jbpmConfiguration.close();
}
- private static void sed(String regex, String replacement, InputStream inStream,
- OutputStream outStream) throws IOException {
- BufferedReader reader = new BufferedReader(new InputStreamReader(inStream));
- PrintWriter writer = new PrintWriter(outStream);
- Pattern pattern = Pattern.compile(regex);
- for (String inLine; (inLine = reader.readLine()) != null;) {
- String outLine = pattern.matcher(inLine).replaceAll(replacement);
- writer.println(outLine);
- }
- writer.flush();
- }
-
public void testParentLockMode() {
ProcessDefinition processDefinition = ProcessDefinition.parseXmlString("<process-definition name='lock mode'>"
+ " <join name='read' lock='READ' />"
Copied: jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm1776/BusinessTimeSubstractionTest.java (from rev 6757, jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm1776/JBPM1776Test.java)
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm1776/BusinessTimeSubstractionTest.java (rev 0)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm1776/BusinessTimeSubstractionTest.java 2010-10-16 13:21:11 UTC (rev 6763)
@@ -0,0 +1,294 @@
+/*
+ * 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.jbpm1776;
+
+import java.util.Calendar;
+import java.util.Date;
+
+import org.jbpm.AbstractJbpmTestCase;
+import org.jbpm.calendar.BusinessCalendar;
+import org.jbpm.calendar.Duration;
+
+/**
+ * Business time subtraction delivers unexpected results.
+ *
+ * @see <a href="https://jira.jboss.org/browse/JBPM-1776">JBPM-1776</a>
+ * @author Alejandro Guizar
+ */
+public class BusinessTimeSubstractionTest extends AbstractJbpmTestCase {
+
+ static BusinessCalendar businessCalendar = new BusinessCalendar();
+
+ public void testNonBusinessSecondSubtraction() {
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(2005, Calendar.APRIL, 7, 10, 30, 0);
+ calendar.set(Calendar.MILLISECOND, 0);
+ Date start = calendar.getTime();
+
+ calendar.add(Calendar.SECOND, -20);
+ Date expected = calendar.getTime();
+
+ Date actual = businessCalendar.add(start, new Duration("-20 seconds"));
+ assertEquals(expected, actual);
+ }
+
+ public void testNonBusinessMinuteSubtraction() {
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(2005, Calendar.APRIL, 7, 11, 55, 0);
+ calendar.set(Calendar.MILLISECOND, 0);
+ Date start = calendar.getTime();
+
+ calendar.add(Calendar.MINUTE, -10);
+ Date expected = calendar.getTime();
+
+ assertEquals(expected, businessCalendar.add(start, new Duration("-10 minutes")));
+ }
+
+ public void testNonBusinessFractionalDurationSubtraction() {
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(2008, Calendar.FEBRUARY, 5, 6, 30, 45);
+ calendar.set(Calendar.MILLISECOND, 125);
+ Date start = calendar.getTime();
+
+ calendar.add(Calendar.HOUR, -7);
+ calendar.add(Calendar.MINUTE, -45);
+ Date expected = calendar.getTime();
+
+ assertEquals(expected, businessCalendar.add(start, new Duration("-7.75 hours")));
+ }
+
+ public void testNonBusinessDaySubtraction() {
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(2005, Calendar.FEBRUARY, 5, 6, 30, 45);
+ calendar.set(Calendar.MILLISECOND, 125);
+ Date start = calendar.getTime();
+
+ calendar.add(Calendar.DAY_OF_MONTH, -10);
+ Date expected = calendar.getTime();
+
+ assertEquals(expected, businessCalendar.add(start, new Duration("-10 days")));
+ }
+
+ public void testNonBusinessWeekSubtraction() {
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(2008, Calendar.FEBRUARY, 5, 6, 30, 45);
+ calendar.set(Calendar.MILLISECOND, 125);
+ Date start = calendar.getTime();
+
+ calendar.add(Calendar.WEEK_OF_YEAR, -5);
+ Date expected = calendar.getTime();
+
+ assertEquals(expected, businessCalendar.add(start, new Duration("-5 weeks")));
+ }
+
+ public void testNonBusinessMonthSubtraction() {
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(2008, Calendar.FEBRUARY, 5, 6, 30, 45);
+ calendar.set(Calendar.MILLISECOND, 125);
+ Date start = calendar.getTime();
+
+ calendar.add(Calendar.MONTH, -3);
+ Date expected = calendar.getTime();
+
+ assertEquals(expected, businessCalendar.add(start, new Duration("-3 months")));
+ }
+
+ public void testNonBusinessYearSubtraction() {
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(2008, Calendar.FEBRUARY, 5, 6, 30, 45);
+ calendar.set(Calendar.MILLISECOND, 125);
+ Date start = calendar.getTime();
+
+ calendar.add(Calendar.YEAR, -1);
+ Date expected = calendar.getTime();
+
+ assertEquals(expected, businessCalendar.add(start, new Duration("-1 year")));
+ }
+
+ public void testBusinessDurationSubtractionOverBusinessTime() {
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(2005, Calendar.APRIL, 7, 11, 55, 0);
+ calendar.set(Calendar.MILLISECOND, 0);
+ Date start = calendar.getTime();
+
+ calendar.add(Calendar.MINUTE, -1);
+ Date expected = calendar.getTime();
+
+ assertEquals(expected, businessCalendar.add(start, new Duration("-1 business minute")));
+ }
+
+ public void testBusinessDurationSubtractionOverLunchBreak() {
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(2005, Calendar.APRIL, 7, 12, 35, 0);
+ calendar.set(Calendar.MILLISECOND, 0);
+ Date start = calendar.getTime();
+
+ calendar.add(Calendar.MINUTE, -10);
+ // lunch break spans 30 minutes
+ calendar.add(Calendar.MINUTE, -30);
+ Date expected = calendar.getTime();
+
+ assertEquals(expected, businessCalendar.add(start, new Duration("-10 business minutes")));
+ }
+
+ public void testBusinessDurationSubtractionOverDayBreak() {
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(2005, Calendar.APRIL, 8, 9, 5, 0);
+ calendar.set(Calendar.MILLISECOND, 0);
+ Date start = calendar.getTime();
+
+ calendar.add(Calendar.MINUTE, -10);
+ // there are 16 hours between 17:00 and 9:00
+ calendar.add(Calendar.HOUR, -16);
+ Date expected = calendar.getTime();
+
+ assertEquals(expected, businessCalendar.add(start, new Duration("-10 business minutes")));
+ }
+
+ public void testBusinessDurationSubtractionOverHoliday() {
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(2010, Calendar.NOVEMBER, 12, 9, 5, 0);
+ calendar.set(Calendar.MILLISECOND, 0);
+ Date start = calendar.getTime();
+
+ calendar.add(Calendar.MINUTE, -10);
+ // there are 16 hours between 17:00 and 9:00
+ calendar.add(Calendar.HOUR, -16);
+ // holiday
+ calendar.add(Calendar.DAY_OF_MONTH, -1);
+ Date expected = calendar.getTime();
+
+ assertEquals(expected, businessCalendar.add(start, new Duration("-10 business minutes")));
+ }
+
+ public void testBusinessDurationSubtractionOverWeekend() {
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(2005, Calendar.APRIL, 11, 9, 5, 0);
+ calendar.set(Calendar.MILLISECOND, 0);
+ Date start = calendar.getTime();
+
+ calendar.add(Calendar.MINUTE, -10);
+ // there are 16 hours between 17:00 and 9:00
+ calendar.add(Calendar.HOUR, -16);
+ // weekend
+ calendar.add(Calendar.DAY_OF_MONTH, -2);
+ Date expected = calendar.getTime();
+
+ assertEquals(expected, businessCalendar.add(start, new Duration("-10 business minutes")));
+ }
+
+ public void testTwoBusinessHoursOverLunch() {
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(2005, Calendar.APRIL, 7, 13, 45, 0);
+ calendar.set(Calendar.MILLISECOND, 0);
+ Date start = calendar.getTime();
+
+ calendar.add(Calendar.HOUR, -2);
+ // lunch break spans 30 minutes
+ calendar.add(Calendar.MINUTE, -30);
+ Date expected = calendar.getTime();
+
+ assertEquals(expected, businessCalendar.add(start, new Duration("-2 business hours")));
+ }
+
+ public void testBusinessDurationSubtractionOutsideBusinessHours() {
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(2005, Calendar.APRIL, 8, 12, 15, 0);
+ calendar.set(Calendar.MILLISECOND, 0);
+ Date start = calendar.getTime();
+
+ calendar.add(Calendar.MINUTE, -30);
+ // lunch break ends at 12:30
+ calendar.add(Calendar.MINUTE, -15);
+ Date expected = calendar.getTime();
+
+ assertEquals(expected, businessCalendar.add(start, new Duration("-30 business minutes")));
+ }
+
+ public void testBusinessDurationSubtractionOutsideBusinessHoursOverWeekend() {
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(2005, Calendar.APRIL, 11, 12, 15, 0);
+ calendar.set(Calendar.MILLISECOND, 0);
+ Date start = calendar.getTime();
+
+ calendar.add(Calendar.HOUR, -5);
+ // lunch break ends at 12:30
+ calendar.add(Calendar.MINUTE, -15);
+ // there are 16 hours between 17:00 and 9:00
+ calendar.add(Calendar.HOUR, -16);
+ // weekend
+ calendar.add(Calendar.DAY_OF_MONTH, -2);
+ Date expected = calendar.getTime();
+
+ assertEquals(expected, businessCalendar.add(start, new Duration("-5 business hours")));
+ }
+
+ public void testBusinessDaySubtraction() {
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(2005, Calendar.FEBRUARY, 21, 9, 30, 0);
+ calendar.set(Calendar.MILLISECOND, 0);
+ Date start = calendar.getTime();
+
+ calendar.set(Calendar.DAY_OF_MONTH, 7);
+ Date expected = calendar.getTime();
+
+ assertEquals(expected, businessCalendar.add(start, new Duration("-10 business days")));
+ }
+
+ public void testBusinessWeekSubtraction() {
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(2005, Calendar.MARCH, 14, 9, 30, 0);
+ calendar.set(Calendar.MILLISECOND, 0);
+ Date start = calendar.getTime();
+
+ calendar.set(Calendar.MONTH, Calendar.FEBRUARY);
+ calendar.set(Calendar.DAY_OF_MONTH, 7);
+ Date expected = calendar.getTime();
+
+ assertEquals(expected, businessCalendar.add(start, new Duration("-5 business weeks")));
+ }
+
+ public void testBusinessMonthSubtraction() {
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(2010, Calendar.MAY, 4, 9, 30, 0);
+ calendar.set(Calendar.MILLISECOND, 0);
+ Date start = calendar.getTime();
+
+ calendar.set(Calendar.MONTH, Calendar.FEBRUARY);
+ calendar.set(Calendar.DAY_OF_MONTH, 3);
+ Date expected = calendar.getTime();
+
+ assertEquals(expected, businessCalendar.add(start, new Duration("-3 business months")));
+ }
+
+ public void testBusinessYearSubtraction() {
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(2010, Calendar.DECEMBER, 28, 9, 30, 0);
+ calendar.set(Calendar.MILLISECOND, 0);
+ Date start = calendar.getTime();
+
+ calendar.set(Calendar.YEAR, 2009);
+ Date expected = calendar.getTime();
+
+ assertEquals(expected, businessCalendar.add(start, new Duration("-1 business year")));
+ }
+}
Deleted: jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm1776/JBPM1776Test.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm1776/JBPM1776Test.java 2010-10-16 02:10:32 UTC (rev 6762)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm1776/JBPM1776Test.java 2010-10-16 13:21:11 UTC (rev 6763)
@@ -1,295 +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.jbpm1776;
-
-import java.util.Calendar;
-import java.util.Date;
-
-import org.jbpm.AbstractJbpmTestCase;
-import org.jbpm.calendar.BusinessCalendar;
-import org.jbpm.calendar.Duration;
-
-/**
- * Business time subtraction delivers unexpected results.
- *
- * @see <a href="https://jira.jboss.org/browse/JBPM-1776">JBPM-1776</a>
- * @author Alejandro Guizar
- */
-public class JBPM1776Test extends AbstractJbpmTestCase {
-
- static BusinessCalendar businessCalendar = new BusinessCalendar();
-
- public void testNonBusinessSecondSubtraction() {
- Calendar calendar = Calendar.getInstance();
- calendar.set(2005, Calendar.APRIL, 7, 10, 30, 0);
- calendar.set(Calendar.MILLISECOND, 0);
- Date start = calendar.getTime();
-
- calendar.add(Calendar.SECOND, -20);
- Date expected = calendar.getTime();
-
- Date actual = businessCalendar.add(start, new Duration("-20 seconds"));
- assertEquals(expected, actual);
- }
-
- public void testNonBusinessMinuteSubtraction() {
- Calendar calendar = Calendar.getInstance();
- calendar.set(2005, Calendar.APRIL, 7, 11, 55, 0);
- calendar.set(Calendar.MILLISECOND, 0);
- Date start = calendar.getTime();
-
- calendar.add(Calendar.MINUTE, -10);
- Date expected = calendar.getTime();
-
- assertEquals(expected, businessCalendar.add(start, new Duration("-10 minutes")));
- }
-
- public void testNonBusinessFractionalDurationSubtraction() {
- Calendar calendar = Calendar.getInstance();
- calendar.set(2008, Calendar.FEBRUARY, 5, 6, 30, 45);
- calendar.set(Calendar.MILLISECOND, 125);
- Date start = calendar.getTime();
-
- calendar.add(Calendar.HOUR, -7);
- calendar.add(Calendar.MINUTE, -45);
- Date expected = calendar.getTime();
-
- assertEquals(expected, businessCalendar.add(start, new Duration("-7.75 hours")));
- }
-
- public void testNonBusinessDaySubtraction() {
- Calendar calendar = Calendar.getInstance();
- calendar.set(2005, Calendar.FEBRUARY, 5, 6, 30, 45);
- calendar.set(Calendar.MILLISECOND, 125);
- Date start = calendar.getTime();
-
- calendar.add(Calendar.DAY_OF_MONTH, -10);
- Date expected = calendar.getTime();
-
- assertEquals(expected, businessCalendar.add(start, new Duration("-10 days")));
- }
-
- public void testNonBusinessWeekSubtraction() {
- Calendar calendar = Calendar.getInstance();
- calendar.set(2008, Calendar.FEBRUARY, 5, 6, 30, 45);
- calendar.set(Calendar.MILLISECOND, 125);
- Date start = calendar.getTime();
-
- calendar.add(Calendar.WEEK_OF_YEAR, -5);
- Date expected = calendar.getTime();
-
- assertEquals(expected, businessCalendar.add(start, new Duration("-5 weeks")));
- }
-
- public void testNonBusinessMonthSubtraction() {
- Calendar calendar = Calendar.getInstance();
- calendar.set(2008, Calendar.FEBRUARY, 5, 6, 30, 45);
- calendar.set(Calendar.MILLISECOND, 125);
- Date start = calendar.getTime();
-
- calendar.add(Calendar.MONTH, -3);
- Date expected = calendar.getTime();
-
- assertEquals(expected, businessCalendar.add(start, new Duration("-3 months")));
- }
-
- public void testNonBusinessYearSubtraction() {
- Calendar calendar = Calendar.getInstance();
- calendar.set(2008, Calendar.FEBRUARY, 5, 6, 30, 45);
- calendar.set(Calendar.MILLISECOND, 125);
- Date start = calendar.getTime();
-
- calendar.add(Calendar.YEAR, -1);
- Date expected = calendar.getTime();
-
- assertEquals(expected, businessCalendar.add(start, new Duration("-1 year")));
- }
-
- public void testBusinessDurationSubtractionOverBusinessTime() {
- Calendar calendar = Calendar.getInstance();
- calendar.set(2005, Calendar.APRIL, 7, 11, 55, 0);
- calendar.set(Calendar.MILLISECOND, 0);
- Date start = calendar.getTime();
-
- calendar.add(Calendar.MINUTE, -1);
- Date expected = calendar.getTime();
-
- assertEquals(expected, businessCalendar.add(start, new Duration("-1 business minute")));
- }
-
- public void testBusinessDurationSubtractionOverLunchBreak() {
- Calendar calendar = Calendar.getInstance();
- calendar.set(2005, Calendar.APRIL, 7, 12, 35, 0);
- calendar.set(Calendar.MILLISECOND, 0);
- Date start = calendar.getTime();
-
- calendar.add(Calendar.MINUTE, -10);
- // lunch break spans 30 minutes
- calendar.add(Calendar.MINUTE, -30);
- Date expected = calendar.getTime();
-
- assertEquals(expected, businessCalendar.add(start, new Duration("-10 business minutes")));
- }
-
- public void testBusinessDurationSubtractionOverDayBreak() {
- Calendar calendar = Calendar.getInstance();
- calendar.set(2005, Calendar.APRIL, 8, 9, 5, 0);
- calendar.set(Calendar.MILLISECOND, 0);
- Date start = calendar.getTime();
-
- calendar.add(Calendar.MINUTE, -10);
- // there are 16 hours between 17:00 and 9:00
- calendar.add(Calendar.HOUR, -16);
- Date expected = calendar.getTime();
-
- assertEquals(expected, businessCalendar.add(start, new Duration("-10 business minutes")));
- }
-
- public void testBusinessDurationSubtractionOverHoliday() {
- Calendar calendar = Calendar.getInstance();
- calendar.set(2010, Calendar.NOVEMBER, 12, 9, 5, 0);
- calendar.set(Calendar.MILLISECOND, 0);
- Date start = calendar.getTime();
-
- calendar.add(Calendar.MINUTE, -10);
- // there are 16 hours between 17:00 and 9:00
- calendar.add(Calendar.HOUR, -16);
- // holiday
- calendar.add(Calendar.DAY_OF_MONTH, -1);
- Date expected = calendar.getTime();
-
- assertEquals(expected, businessCalendar.add(start, new Duration("-10 business minutes")));
- }
-
- public void testBusinessDurationSubtractionOverWeekend() {
- Calendar calendar = Calendar.getInstance();
- calendar.set(2005, Calendar.APRIL, 11, 9, 5, 0);
- calendar.set(Calendar.MILLISECOND, 0);
- Date start = calendar.getTime();
-
- calendar.add(Calendar.MINUTE, -10);
- // there are 16 hours between 17:00 and 9:00
- calendar.add(Calendar.HOUR, -16);
- // weekend
- calendar.add(Calendar.DAY_OF_MONTH, -2);
- Date expected = calendar.getTime();
-
- assertEquals(expected, businessCalendar.add(start, new Duration("-10 business minutes")));
- }
-
- public void testTwoBusinessHoursOverLunch() {
- Calendar calendar = Calendar.getInstance();
- calendar.set(2005, Calendar.APRIL, 7, 13, 45, 0);
- calendar.set(Calendar.MILLISECOND, 0);
- Date start = calendar.getTime();
-
- calendar.add(Calendar.HOUR, -2);
- // lunch break spans 30 minutes
- calendar.add(Calendar.MINUTE, -30);
- Date expected = calendar.getTime();
-
- assertEquals(expected, businessCalendar.add(start, new Duration("-2 business hours")));
- }
-
- public void testBusinessDurationSubtractionOutsideBusinessHours() {
- Calendar calendar = Calendar.getInstance();
- calendar.set(2005, Calendar.APRIL, 8, 12, 15, 0);
- calendar.set(Calendar.MILLISECOND, 0);
- Date start = calendar.getTime();
-
- calendar.add(Calendar.MINUTE, -30);
- // lunch break ends at 12:30
- calendar.add(Calendar.MINUTE, -15);
- Date expected = calendar.getTime();
-
- assertEquals(expected, businessCalendar.add(start, new Duration("-30 business minutes")));
- }
-
- public void testBusinessDurationSubtractionOutsideBusinessHoursOverWeekend() {
- Calendar calendar = Calendar.getInstance();
- calendar.set(2005, Calendar.APRIL, 11, 12, 15, 0);
- calendar.set(Calendar.MILLISECOND, 0);
- Date start = calendar.getTime();
-
- calendar.add(Calendar.HOUR, -5);
- // lunch break ends at 12:30
- calendar.add(Calendar.MINUTE, -15);
- // there are 16 hours between 17:00 and 9:00
- calendar.add(Calendar.HOUR, -16);
- // weekend
- calendar.add(Calendar.DAY_OF_MONTH, -2);
- Date expected = calendar.getTime();
-
- assertEquals(expected, businessCalendar.add(start, new Duration("-5 business hours")));
- }
-
- public void testBusinessDaySubtraction() {
- Calendar calendar = Calendar.getInstance();
- calendar.set(2005, Calendar.FEBRUARY, 21, 9, 30, 0);
- calendar.set(Calendar.MILLISECOND, 0);
- Date start = calendar.getTime();
-
- calendar.set(Calendar.DAY_OF_MONTH, 7);
- Date expected = calendar.getTime();
-
- assertEquals(expected, businessCalendar.add(start, new Duration("-10 business days")));
- }
-
- public void testBusinessWeekSubtraction() {
- Calendar calendar = Calendar.getInstance();
- calendar.set(2005, Calendar.MARCH, 14, 9, 30, 0);
- calendar.set(Calendar.MILLISECOND, 0);
- Date start = calendar.getTime();
-
- calendar.set(Calendar.MONTH, Calendar.FEBRUARY);
- calendar.set(Calendar.DAY_OF_MONTH, 7);
- Date expected = calendar.getTime();
-
- assertEquals(expected, businessCalendar.add(start, new Duration("-5 business weeks")));
- }
-
- public void testBusinessMonthSubtraction() {
- Calendar calendar = Calendar.getInstance();
- calendar.set(2010, Calendar.MAY, 7, 9, 30, 0);
- calendar.set(Calendar.MILLISECOND, 0);
- Date start = calendar.getTime();
-
- calendar.set(Calendar.MONTH, Calendar.FEBRUARY);
- calendar.set(Calendar.DAY_OF_MONTH, 8);
- Date expected = calendar.getTime();
-
- assertEquals(expected, businessCalendar.add(start, new Duration("-3 business months")));
- }
-
- public void testBusinessYearSubtraction() {
- Calendar calendar = Calendar.getInstance();
- calendar.set(2011, Calendar.FEBRUARY, 9, 9, 30, 0);
- calendar.set(Calendar.MILLISECOND, 0);
- Date start = calendar.getTime();
-
- calendar.set(Calendar.YEAR, 2010);
- calendar.set(Calendar.DAY_OF_MONTH, 8);
- Date expected = calendar.getTime();
-
- assertEquals(expected, businessCalendar.add(start, new Duration("-1 business year")));
- }
-}
Deleted: jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2825/JBPM2825Test.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2825/JBPM2825Test.java 2010-10-16 02:10:32 UTC (rev 6762)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2825/JBPM2825Test.java 2010-10-16 13:21:11 UTC (rev 6763)
@@ -1,60 +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.jbpm2825;
-
-import org.jbpm.JbpmConfiguration;
-import org.jbpm.db.AbstractDbTestCase;
-import org.jbpm.file.def.FileDefinition;
-import org.jbpm.graph.def.ProcessDefinition;
-
-/**
- * @author Alejandro Guizar
- */
-public class JBPM2825Test extends AbstractDbTestCase {
-
- public void testProcessClassLoaderOutsideContext() {
- FileDefinition fileDefinition = new FileDefinition();
- byte[] magicNumber = {
- (byte) 0xCA, (byte) 0xFE, (byte) 0xBA, (byte) 0xBE
- };
- fileDefinition.addFile("classes/org/example/Undef", magicNumber);
-
- ProcessDefinition processDefinition = new ProcessDefinition(getName());
- processDefinition.addDefinition(fileDefinition);
- jbpmContext.deployProcessDefinition(processDefinition);
-
- ClassLoader procClassLoader = JbpmConfiguration.getProcessClassLoader(processDefinition);
- String undefClassName = "org.example.Undef";
-
- closeJbpmContext();
- try {
- Class.forName(undefClassName, false, procClassLoader);
- fail("expected class " + undefClassName + " to not be found");
- }
- catch (ClassNotFoundException e) {
- assertEquals(undefClassName, e.getMessage());
- }
- finally {
- createJbpmContext();
- }
- }
-}
Copied: jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2825/ProcessClassLoaderNoContextTest.java (from rev 6741, jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2825/JBPM2825Test.java)
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2825/ProcessClassLoaderNoContextTest.java (rev 0)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2825/ProcessClassLoaderNoContextTest.java 2010-10-16 13:21:11 UTC (rev 6763)
@@ -0,0 +1,65 @@
+/*
+ * 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.jbpm2825;
+
+import org.jbpm.JbpmConfiguration;
+import org.jbpm.db.AbstractDbTestCase;
+import org.jbpm.file.def.FileDefinition;
+import org.jbpm.graph.def.ProcessDefinition;
+import org.jbpm.instantiation.ProcessClassLoader;
+
+/**
+ * {@link ProcessClassLoader} throws {@link NullPointerException} when no current context is
+ * available.
+ *
+ * @see <a href="https://jira.jboss.org/browse/JBPM-2825">JBPM-2825</a>
+ * @author Alejandro Guizar
+ */
+public class ProcessClassLoaderNoContextTest extends AbstractDbTestCase {
+
+ public void testProcessClassLoaderNoContext() {
+ FileDefinition fileDefinition = new FileDefinition();
+ byte[] magicNumber = {
+ (byte) 0xCA, (byte) 0xFE, (byte) 0xBA, (byte) 0xBE
+ };
+ fileDefinition.addFile("classes/org/example/Undef", magicNumber);
+
+ ProcessDefinition processDefinition = new ProcessDefinition(getName());
+ processDefinition.addDefinition(fileDefinition);
+ jbpmContext.deployProcessDefinition(processDefinition);
+
+ ClassLoader procClassLoader = JbpmConfiguration.getProcessClassLoader(processDefinition);
+ String undefClassName = "org.example.Undef";
+
+ closeJbpmContext();
+ try {
+ Class.forName(undefClassName, false, procClassLoader);
+ fail("expected class " + undefClassName + " to not be found");
+ }
+ catch (ClassNotFoundException e) {
+ assertEquals(undefClassName, e.getMessage());
+ }
+ finally {
+ createJbpmContext();
+ }
+ }
+}
Copied: jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2908/AlternateConfigurationAction.java (from rev 6741, jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2908/ChangeJbpmConfigurationAction.java)
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2908/AlternateConfigurationAction.java (rev 0)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2908/AlternateConfigurationAction.java 2010-10-16 13:21:11 UTC (rev 6763)
@@ -0,0 +1,32 @@
+package org.jbpm.jbpm2908;
+
+import org.jbpm.JbpmConfiguration;
+import org.jbpm.JbpmContext;
+import org.jbpm.graph.def.ActionHandler;
+import org.jbpm.graph.exe.ExecutionContext;
+import org.jbpm.graph.exe.ProcessInstance;
+
+public class AlternateConfigurationAction implements ActionHandler {
+
+ private static final long serialVersionUID = 1L;
+
+ public void execute(ExecutionContext exeContext) throws Exception {
+ // load another configuration
+ JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseResource("org/jbpm/jbpm2908/jbpm.cfg.xml");
+ try {
+ JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
+ try {
+ // start instance
+ ProcessInstance processInstance = jbpmContext.newProcessInstance("process2");
+ processInstance.signal();
+ jbpmContext.save(processInstance);
+ }
+ finally {
+ jbpmContext.close();
+ }
+ }
+ finally {
+ jbpmConfiguration.close();
+ }
+ }
+}
Deleted: jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2908/ChangeJbpmConfigurationAction.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2908/ChangeJbpmConfigurationAction.java 2010-10-16 02:10:32 UTC (rev 6762)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2908/ChangeJbpmConfigurationAction.java 2010-10-16 13:21:11 UTC (rev 6763)
@@ -1,34 +0,0 @@
-package org.jbpm.jbpm2908;
-
-import org.jbpm.JbpmConfiguration;
-import org.jbpm.JbpmContext;
-import org.jbpm.graph.def.ActionHandler;
-import org.jbpm.graph.exe.ExecutionContext;
-import org.jbpm.graph.exe.ProcessInstance;
-
-public class ChangeJbpmConfigurationAction implements ActionHandler {
-
- private static final long serialVersionUID = 1L;
-
- public void execute(ExecutionContext exeContext) throws Exception {
- // load another configuration
- String dialect = (String) exeContext.getVariable("dialect");
- JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseResource(dialect.indexOf("HSQL") != -1 ?
- "org/jbpm/jbpm2908/jbpm-no-auto.cfg.xml" : "org/jbpm/jbpm2908/jbpm.cfg.xml");
- try {
- JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
- try {
- // start instance
- ProcessInstance processInstance = jbpmContext.newProcessInstance("process2");
- processInstance.signal();
- jbpmContext.save(processInstance);
- }
- finally {
- jbpmContext.close();
- }
- }
- finally {
- jbpmConfiguration.close();
- }
- }
-}
Modified: jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2908/JBPM2908Test.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2908/JBPM2908Test.java 2010-10-16 02:10:32 UTC (rev 6762)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2908/JBPM2908Test.java 2010-10-16 13:21:11 UTC (rev 6763)
@@ -44,8 +44,7 @@
// start instance
ProcessInstance processInstance = jbpmContext.newProcessInstanceForUpdate("process1");
- processInstance.getContextInstance().setVariable("dialect", getHibernateDialect());
processInstance.signal();
- assert processInstance.hasEnded() : processInstance;
+ assert processInstance.hasEnded() : "expected " + processInstance + " to have ended";
}
}
Added: jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2958/TimerCalendarTest.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2958/TimerCalendarTest.java (rev 0)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2958/TimerCalendarTest.java 2010-10-16 13:21:11 UTC (rev 6763)
@@ -0,0 +1,125 @@
+/*
+ * 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.jbpm2958;
+
+import java.util.Calendar;
+import java.util.Date;
+
+import org.jbpm.JbpmConfiguration;
+import org.jbpm.JbpmContext;
+import org.jbpm.db.AbstractDbTestCase;
+import org.jbpm.db.JbpmSchema;
+import org.jbpm.graph.def.ProcessDefinition;
+import org.jbpm.graph.exe.ProcessInstance;
+import org.jbpm.job.Timer;
+import org.jbpm.persistence.db.DbPersistenceServiceFactory;
+import org.jbpm.svc.Services;
+
+/**
+ * Timer should employ the very calendar that computed the first due date to calculate repeat
+ * dates.
+ *
+ * @see <a href="https://jira.jboss.org/browse/JBPM-2958">JBPM-2958</a>
+ * @author Alejandro Guizar
+ */
+public class TimerCalendarTest extends AbstractDbTestCase {
+
+ protected JbpmConfiguration getJbpmConfiguration() {
+ if (jbpmConfiguration == null) {
+ jbpmConfiguration = JbpmConfiguration.parseResource("org/jbpm/jbpm2958/saturday-jbpm.cfg.xml");
+
+ JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
+ try {
+ DbPersistenceServiceFactory persistenceServiceFactory = (DbPersistenceServiceFactory) jbpmContext.getServiceFactory(Services.SERVICENAME_PERSISTENCE);
+ JbpmSchema jbpmSchema = new JbpmSchema(persistenceServiceFactory.getConfiguration());
+ jbpmSchema.updateTable("JBPM_JOB");
+ }
+ finally {
+ jbpmContext.close();
+ }
+ }
+ return jbpmConfiguration;
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ ProcessDefinition processDefinition = ProcessDefinition.parseXmlResource("org/jbpm/jbpm2958/processdefinition.xml");
+ deployProcessDefinition(processDefinition);
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ jbpmConfiguration.close();
+ }
+
+ public void testTimerCalendarResource() {
+ // baseDate is a Friday, one hour before close of business
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(2010, Calendar.OCTOBER, 8, 16, 0, 0);
+ calendar.set(Calendar.MILLISECOND, 0);
+ Date baseDate = calendar.getTime();
+
+ // processInstance schedules a timer due on baseDate
+ // in jbpmConfiguration, Saturday is a work day
+ ProcessInstance processInstance = jbpmContext.newProcessInstanceForUpdate("jbpm2958");
+ processInstance.getContextInstance().setVariable("baseDate", baseDate);
+ processInstance.signal();
+
+ closeJbpmContext();
+ try {
+ // in standardConfiguration, Saturday is NOT a work day
+ JbpmConfiguration standardConfiguration = JbpmConfiguration.parseResource("org/jbpm/jbpm2958/jbpm.cfg.xml");
+ JbpmContext standardContext = standardConfiguration.createJbpmContext();
+ try {
+ Timer timer = (Timer) standardContext.getSession()
+ .createCriteria(Timer.class)
+ .uniqueResult();
+ timer.execute(standardContext);
+ }
+ catch (Exception e) {
+ standardContext.setRollbackOnly();
+ fail(e.getMessage());
+ }
+ finally {
+ standardContext.close();
+ standardConfiguration.close();
+ }
+ }
+ finally {
+ createJbpmContext();
+ }
+
+ calendar.add(Calendar.HOUR, 2);
+ // there are 16 hours between 17:00 and 9:00
+ calendar.add(Calendar.HOUR, 16);
+ // repeatDate is a Saturday
+ Date repeatDate = calendar.getTime();
+
+ Timer timer = (Timer) session.createCriteria(Timer.class).uniqueResult();
+ assertEquals(repeatDate, new Date(timer.getDueDate().getTime()));
+
+ processInstance = jbpmContext.loadProcessInstanceForUpdate(processInstance.getId());
+ processInstance.signal();
+ assert processInstance.hasEnded() : "expected " + processInstance + " to have ended";
+ }
+}
Property changes on: jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2958/TimerCalendarTest.java
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/log4j.xml
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/log4j.xml 2010-10-16 02:10:32 UTC (rev 6762)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/log4j.xml 2010-10-16 13:21:11 UTC (rev 6763)
@@ -37,13 +37,18 @@
<priority value="DEBUG" />
</category>
+ <!-- stale state errors -->
+ <category name="org.jbpm.persistence.db.StaleObjectLogConfigurer">
+ <priority value="OFF" />
+ </category>
+
<category name="org.hibernate">
<priority value="INFO" />
</category>
<!-- proxy narrowing warnings -->
<category name="org.hibernate.engine.StatefulPersistenceContext.ProxyWarnLog">
- <priority value="ERROR" />
+ <priority value="OFF" />
</category>
<!-- optimistic locking failures
Added: jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/context/exe/jbpm.cfg.xml
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/context/exe/jbpm.cfg.xml (rev 0)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/context/exe/jbpm.cfg.xml 2010-10-16 13:21:11 UTC (rev 6763)
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<jbpm-configuration>
+ <jbpm-context>
+ <service name="authentication" factory="org.jbpm.security.authentication.DefaultAuthenticationServiceFactory" />
+ <!-- disable logging service to prevent logs from referencing custom object -->
+ <service name="message" factory="org.jbpm.msg.db.DbMessageServiceFactory" />
+ <service name="persistence" factory="org.jbpm.persistence.db.DbPersistenceServiceFactory" />
+ <service name="scheduler" factory="org.jbpm.scheduler.db.DbSchedulerServiceFactory" />
+ <service name="tx" factory="org.jbpm.tx.TxServiceFactory" />
+ </jbpm-context>
+</jbpm-configuration>
\ No newline at end of file
Property changes on: jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/context/exe/jbpm.cfg.xml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/graph/node/jbpm.cfg.xml
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/graph/node/jbpm.cfg.xml (rev 0)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/graph/node/jbpm.cfg.xml 2010-10-16 13:21:11 UTC (rev 6763)
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<jbpm-configuration>
+ <string name='resource.hibernate.cfg.xml' value='org/jbpm/graph/node/hibernate.cfg.xml' />
+</jbpm-configuration>
Property changes on: jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/graph/node/jbpm.cfg.xml
___________________________________________________________________
Name: svn:eol-style
+ native
Deleted: jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2908/jbpm-no-auto.cfg.xml
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2908/jbpm-no-auto.cfg.xml 2010-10-16 02:10:32 UTC (rev 6762)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2908/jbpm-no-auto.cfg.xml 2010-10-16 13:21:11 UTC (rev 6763)
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<jbpm-configuration>
- <string name="resource.hibernate.cfg.xml" value="hibernate-no-auto.cfg.xml" />
-</jbpm-configuration>
Deleted: jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2908/jbpm.cfg.xml
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2908/jbpm.cfg.xml 2010-10-16 02:10:32 UTC (rev 6762)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2908/jbpm.cfg.xml 2010-10-16 13:21:11 UTC (rev 6763)
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<jbpm-configuration />
Copied: jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2908/jbpm.cfg.xml (from rev 6741, jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2908/jbpm-no-auto.cfg.xml)
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2908/jbpm.cfg.xml (rev 0)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2908/jbpm.cfg.xml 2010-10-16 13:21:11 UTC (rev 6763)
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jbpm-configuration>
+ <string name="resource.hibernate.cfg.xml" value="org/jbpm/jbpm2908/hibernate.cfg.xml" />
+</jbpm-configuration>
Modified: jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2908/processdefinition1.xml
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2908/processdefinition1.xml 2010-10-16 02:10:32 UTC (rev 6762)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2908/processdefinition1.xml 2010-10-16 13:21:11 UTC (rev 6763)
@@ -7,7 +7,7 @@
<node name="node1">
<event type="node-enter">
- <action class="org.jbpm.jbpm2908.ChangeJbpmConfigurationAction" />
+ <action class="org.jbpm.jbpm2908.AlternateConfigurationAction" />
</event>
<transition to="end" />
</node>
Added: jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2958/gpd.xml
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2958/gpd.xml (rev 0)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2958/gpd.xml 2010-10-16 13:21:11 UTC (rev 6763)
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<root-container name="jbpm2958" width="788" height="585">
+ <node name="start" x="96" y="48" width="121" height="37">
+ <edge>
+ <label x="5" y="-10"/>
+ </edge>
+ </node>
+ <node name="midway" x="96" y="120" width="121" height="37">
+ <edge>
+ <label x="5" y="-10"/>
+ </edge>
+ </node>
+ <node name="end" x="0" y="0" width="132" height="36"/>
+ <deployment serverName="" serverPort="" serverDeployer="">
+ <classesAndResources/>
+ <filesAndFolders>
+ <element value="/jbpm-jpdl/src/test/resources/org/jbpm/jbpm2958/gpd.xml"/>
+ <element value="/jbpm-jpdl/src/test/resources/org/jbpm/jbpm2958/processdefinition.xml"/>
+ </filesAndFolders>
+ </deployment>
+</root-container>
Property changes on: jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2958/gpd.xml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2958/jbpm.cfg.xml
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2958/jbpm.cfg.xml (rev 0)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2958/jbpm.cfg.xml 2010-10-16 13:21:11 UTC (rev 6763)
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+
+<jbpm-configuration>
+ <string name="resource.hibernate.cfg.xml" value="org/jbpm/jbpm2958/hibernate.cfg.xml" />
+</jbpm-configuration>
\ No newline at end of file
Property changes on: jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2958/jbpm.cfg.xml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2958/processdefinition.xml
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2958/processdefinition.xml (rev 0)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2958/processdefinition.xml 2010-10-16 13:21:11 UTC (rev 6763)
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<process-definition xmlns="urn:jbpm.org:jpdl-3.2" name="jbpm2958">
+ <start-state name="start">
+ <transition to="midway" />
+ </start-state>
+
+ <state name="midway">
+ <timer duedate="${baseDate}" repeat="2 business hours">
+ <action />
+ </timer>
+ <transition to="end" />
+ </state>
+
+ <end-state name="end" />
+</process-definition>
\ No newline at end of file
Property changes on: jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2958/processdefinition.xml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2958/saturday-business-calendar.properties
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2958/saturday-business-calendar.properties (rev 0)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2958/saturday-business-calendar.properties 2010-10-16 13:21:11 UTC (rev 6763)
@@ -0,0 +1,49 @@
+hour.format=HH:mm
+# weekday ::= [<daypart> [& <daypart>]*]
+# daypart ::= <start-hour>-<end-hour>
+# start-hour and end-hour must be in the hour.format
+# dayparts have to be ordered
+weekday.monday= 9:00-12:30 & 13:00-17:00
+weekday.tuesday= 9:00-12:30 & 13:00-17:00
+weekday.wednesday= 9:00-12:30 & 13:00-17:00
+weekday.thursday= 9:00-12:30 & 13:00-17:00
+weekday.friday= 9:00-12:30 & 13:00-17:00
+weekday.saturday= 9:00-13:00
+weekday.sunday=
+
+day.format=dd/MM/yyyy
+# holiday ::= <holiday-period>
+# holiday-period ::= <start-day> [- <end-day>]
+# start-day and end-day must be in the day.format
+# below are the u.s. official holidays
+# new year's day
+holiday.1= 01/01/2010
+# birthday of martin luther king
+holiday.2= 18/01/2010
+# washington's birthday
+holiday.3= 15/02/2010
+# memorial day
+holiday.4= 31/05/2010
+# independence day
+holiday.5= 05/07/2010
+# labor day
+holiday.6= 06/09/2010
+# columbus day
+holiday.7= 11/10/2010
+# veterans day
+holiday.8= 11/11/2010
+# thanksgiving day
+holiday.9= 25/11/2010
+# day after thanksgiving
+holiday.10= 26/11/2010
+# christmas day
+holiday.11= 24/12/2010
+
+# typical workday excluding breaks
+business.day.expressed.in.hours= 7.5
+# 7.5 hours * 5 days a week
+business.week.expressed.in.hours= 37.5
+# 253 business days / 12 months
+business.month.expressed.in.business.days= 20.75
+# 365 natural days - 105 weekend days - 7 holidays
+business.year.expressed.in.business.days= 249
Property changes on: jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2958/saturday-business-calendar.properties
___________________________________________________________________
Name: svn:eol-style
+ native
Added: jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2958/saturday-jbpm.cfg.xml
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2958/saturday-jbpm.cfg.xml (rev 0)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2958/saturday-jbpm.cfg.xml 2010-10-16 13:21:11 UTC (rev 6763)
@@ -0,0 +1,7 @@
+<?xml version="1.0"?>
+
+<jbpm-configuration>
+ <string name="resource.hibernate.cfg.xml" value="org/jbpm/jbpm2958/hibernate.cfg.xml" />
+ <string name="resource.business.calendar"
+ value="org/jbpm/jbpm2958/saturday-business-calendar.properties" />
+</jbpm-configuration>
\ No newline at end of file
Property changes on: jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2958/saturday-jbpm.cfg.xml
___________________________________________________________________
Name: svn:eol-style
+ native
13 years, 6 months
JBoss JBPM SVN: r6762 - in jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm: instantiation and 1 other directory.
by do-not-reply@jboss.org
Author: alex.guizar(a)jboss.com
Date: 2010-10-15 22:10:32 -0400 (Fri, 15 Oct 2010)
New Revision: 6762
Modified:
jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/graph/def/ProcessDefinition.java
jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/instantiation/SharedProcessClassLoaderFactory.java
Log:
JBPM-2954 consider negative process definition versions as unknown and hence incomparable
Modified: jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/graph/def/ProcessDefinition.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/graph/def/ProcessDefinition.java 2010-10-15 05:13:50 UTC (rev 6761)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/graph/def/ProcessDefinition.java 2010-10-16 02:10:32 UTC (rev 6762)
@@ -39,6 +39,7 @@
import org.xml.sax.InputSource;
import org.jbpm.JbpmConfiguration;
+import org.jbpm.JbpmContext;
import org.jbpm.JbpmException;
import org.jbpm.context.def.ContextDefinition;
import org.jbpm.file.def.FileDefinition;
@@ -188,6 +189,11 @@
// equals ///////////////////////////////////////////////////////////////////
+ /**
+ * Tells whether this process definition is equal to the given object. This method considers
+ * two process definitions equal if they are equal in name and version, the name is not null
+ * and the version is not negative.
+ */
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof ProcessDefinition)) return false;
@@ -195,11 +201,17 @@
ProcessDefinition other = (ProcessDefinition) o;
if (id != 0 && id == other.getId()) return true;
- return name != null && name.equals(other.getName()) && version == other.getVersion();
+ return name != null && version >= 0 && name.equals(other.getName())
+ && version == other.getVersion();
}
+ /**
+ * Computes the hash code for this process definition. Process definitions with a null name or
+ * a negative version will return their {@linkplain System#identityHashCode(Object) identity
+ * hash code}.
+ */
public int hashCode() {
- if (name == null) return super.hashCode();
+ if (name == null || version < 0) return System.identityHashCode(this);
int result = 224001527 + name.hashCode();
result = 1568661329 * result + version;
@@ -553,6 +565,14 @@
return version;
}
+ /**
+ * Sets the version of this process. Generally the version is assigned automatically upon
+ * {@linkplain JbpmContext#deployProcessDefinition(ProcessDefinition) deployment}.
+ *
+ * @param version the version to assign. Automatic versioning starts from 1. Any negative
+ * value is regarded as an unknown or <code>null</code> version. The meaning of version 0 is
+ * undefined.
+ */
public void setVersion(int version) {
this.version = version;
}
Modified: jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/instantiation/SharedProcessClassLoaderFactory.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/instantiation/SharedProcessClassLoaderFactory.java 2010-10-15 05:13:50 UTC (rev 6761)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/instantiation/SharedProcessClassLoaderFactory.java 2010-10-16 02:10:32 UTC (rev 6762)
@@ -33,8 +33,9 @@
import org.jbpm.util.ClassLoaderUtil;
/**
- * Refined process class loader factory that maintains a cache of the class loaders it returns. The
- * cache does not prevent class loaders from being discarded by the garbage collector.
+ * Factory that caches the class loaders it produces, in order to prevent duplicate class
+ * loaders from eating up the permanent generation space. The cache does not prevent class
+ * loaders from being discarded by the garbage collector.
*
* @author Alejandro Guizar
*/
@@ -54,29 +55,31 @@
}
public ClassLoader getProcessClassLoader(ProcessDefinition processDefinition) {
- // determine the key to lookup a cached class loader
- // observe that the given process definition may be transient
+ // use database identifier as key to lookup cached class loader
long id = processDefinition.getId();
- if (id == 0L) id = System.identityHashCode(processDefinition);
- Long key = new Long(id);
+ // if process definition is transient, use hash code as key
+ Long key = new Long(id == 0L ? processDefinition.hashCode() : id);
+
// consider that the context class loader changes among applications
ClassLoader parentClassLoader = ClassLoaderUtil.getClassLoader();
synchronized (classLoaderRefs) {
- // lookup the class loader reference
+ // lookup cached class loader
ClassLoader processClassLoader = getProcessClassLoader(key, parentClassLoader);
- // the reference may not exist or may have been cleared already
+ // if class loader is not cached,
if (processClassLoader == null) {
- // (re-)create the class loader and the reference
- processClassLoader = new ProcessClassLoader(parentClassLoader, processDefinition, jbpmConfiguration);
- // cache the reference
+ // (re-)create class loader
+ processClassLoader = new ProcessClassLoader(parentClassLoader, processDefinition,
+ jbpmConfiguration);
+ // add class loader to cache
putProcessClassLoader(key, processClassLoader);
}
return processClassLoader;
}
}
- private ClassLoader getProcessClassLoader(Long processDefinitionKey, ClassLoader parentClassLoader) {
+ private ClassLoader getProcessClassLoader(Long processDefinitionKey,
+ ClassLoader parentClassLoader) {
List referenceList = (List) classLoaderRefs.get(processDefinitionKey);
if (referenceList != null) {
for (Iterator i = referenceList.iterator(); i.hasNext();) {
13 years, 6 months
JBoss JBPM SVN: r6761 - in jbpm3/branches/jbpm-3.2-soa/core/src: test/java/org/jbpm/jbpm2959 and 1 other directories.
by do-not-reply@jboss.org
Author: alex.guizar(a)jboss.com
Date: 2010-10-15 01:13:50 -0400 (Fri, 15 Oct 2010)
New Revision: 6761
Modified:
jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/graph/action/Script.java
jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2959/JBPM2959Test.java
jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2959/processdefinition.xml
Log:
JBPM-2959 launch multiple process instances to produce the job insertion deadlock more quickly;
trim scripts to economize memory and database storage
Modified: jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/graph/action/Script.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/graph/action/Script.java 2010-10-14 18:09:32 UTC (rev 6760)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/main/java/org/jbpm/graph/action/Script.java 2010-10-15 05:13:50 UTC (rev 6761)
@@ -53,11 +53,11 @@
public void read(Element scriptElement, JpdlXmlReader jpdlReader) {
if (scriptElement.isTextOnly()) {
- expression = scriptElement.getText();
+ expression = scriptElement.getTextTrim();
}
else {
variableAccesses = new HashSet(jpdlReader.readVariableAccesses(scriptElement));
- expression = scriptElement.element("expression").getText();
+ expression = scriptElement.element("expression").getTextTrim();
}
}
Modified: jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2959/JBPM2959Test.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2959/JBPM2959Test.java 2010-10-14 18:09:32 UTC (rev 6760)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2959/JBPM2959Test.java 2010-10-15 05:13:50 UTC (rev 6761)
@@ -34,6 +34,8 @@
*/
public class JBPM2959Test extends AbstractDbTestCase {
+ private static final int INSTANCE_COUNT = 10;
+
protected void setUp() throws Exception {
super.setUp();
@@ -54,11 +56,18 @@
}
public void testDeadlockAtJobInsert() {
- ProcessInstance processInstance = jbpmContext.newProcessInstanceForUpdate("jbpm2959");
- processInstance.signal();
+ long[] processInstanceIds = new long[INSTANCE_COUNT];
+ for (int i = 0; i < processInstanceIds.length; i++) {
+ ProcessInstance processInstance = jbpmContext.newProcessInstanceForUpdate("jbpm2959");
+ processInstance.signal();
+ processInstanceIds[i] = processInstance.getId();
+ }
processJobs();
- processInstance = jbpmContext.loadProcessInstance(processInstance.getId());
- assert processInstance.hasEnded() : "expected " + processInstance + " to have ended";
+
+ for (int i = 0; i < processInstanceIds.length; i++) {
+ ProcessInstance processInstance = jbpmContext.loadProcessInstance(processInstanceIds[i]);
+ assert processInstance.hasEnded() : "expected " + processInstance + " to have ended";
+ }
}
}
Modified: jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2959/processdefinition.xml
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2959/processdefinition.xml 2010-10-14 18:09:32 UTC (rev 6760)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2959/processdefinition.xml 2010-10-15 05:13:50 UTC (rev 6761)
@@ -17,7 +17,7 @@
<decision name="Keep Going?">
<transition to="Sleep" name="Yes">
- <condition expression="${count < 10}" />
+ <condition expression="${count < 5}" />
<script>
executionContext.setVariable("count", count + 1);
</script>
13 years, 6 months
JBoss JBPM SVN: r6760 - in jbpm3/branches/jbpm-3.2-soa/core/src/test: java/org/jbpm/jbpm2959 and 3 other directories.
by do-not-reply@jboss.org
Author: alex.guizar(a)jboss.com
Date: 2010-10-14 14:09:32 -0400 (Thu, 14 Oct 2010)
New Revision: 6760
Added:
jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2959/
jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2959/JBPM2959Test.java
jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2959/
jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2959/gpd.xml
jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2959/processdefinition.xml
Modified:
jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/log4j.xml
Log:
JBPM-2959 check in provided test process
Added: jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2959/JBPM2959Test.java
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2959/JBPM2959Test.java (rev 0)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2959/JBPM2959Test.java 2010-10-14 18:09:32 UTC (rev 6760)
@@ -0,0 +1,64 @@
+/*
+ * 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.jbpm2959;
+
+import org.jbpm.db.AbstractDbTestCase;
+import org.jbpm.graph.def.ProcessDefinition;
+import org.jbpm.graph.exe.ProcessInstance;
+
+/**
+ * Backport the dispatcher thread from jBPM 4 to avoid race conditions with multiple JobExecutor
+ * threads.
+ *
+ * @see <a href="https://jira.jboss.org/browse/JBPM-2959">JBPM-2959</a>
+ * @author Alejandro Guizar
+ */
+public class JBPM2959Test extends AbstractDbTestCase {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // [JBPM-2115] multiple threads not supported on DB2 < 9.7
+ // multiple threads not be supported on HSQL
+ String dialect = getHibernateDialect();
+ if (dialect.indexOf("DB2") == -1 && dialect.indexOf("HSQL") == -1) {
+ jbpmConfiguration.getJobExecutor().setNbrOfThreads(4);
+ }
+
+ ProcessDefinition processDefinition = ProcessDefinition.parseXmlResource("org/jbpm/jbpm2959/processdefinition.xml");
+ deployProcessDefinition(processDefinition);
+ }
+
+ protected void tearDown() throws Exception {
+ jbpmConfiguration.getJobExecutor().setNbrOfThreads(1);
+ super.tearDown();
+ }
+
+ public void testDeadlockAtJobInsert() {
+ ProcessInstance processInstance = jbpmContext.newProcessInstanceForUpdate("jbpm2959");
+ processInstance.signal();
+
+ processJobs();
+ processInstance = jbpmContext.loadProcessInstance(processInstance.getId());
+ assert processInstance.hasEnded() : "expected " + processInstance + " to have ended";
+ }
+}
Property changes on: jbpm3/branches/jbpm-3.2-soa/core/src/test/java/org/jbpm/jbpm2959/JBPM2959Test.java
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/log4j.xml
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/log4j.xml 2010-10-13 05:11:34 UTC (rev 6759)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/log4j.xml 2010-10-14 18:09:32 UTC (rev 6760)
@@ -34,7 +34,7 @@
<!-- ================ -->
<category name="org.jbpm">
- <priority value="INFO" />
+ <priority value="DEBUG" />
</category>
<category name="org.hibernate">
Added: jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2959/gpd.xml
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2959/gpd.xml (rev 0)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2959/gpd.xml 2010-10-14 18:09:32 UTC (rev 6760)
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<root-container name="jbpm2959" width="756" height="575">
+ <node name="Start" x="84" y="48" width="132" height="36">
+ <edge>
+ <label x="5" y="-10"/>
+ </edge>
+ </node>
+ <node name="Sleep" x="84" y="192" width="132" height="36">
+ <edge>
+ <label x="5" y="-10"/>
+ <bendpoint w1="-114" h1="-1" w2="-114" h2="71"/>
+ <bendpoint w1="-114" h1="-73" w2="-114" h2="-1"/>
+ </edge>
+ </node>
+ <node name="Keep Going?" x="84" y="120" width="132" height="36">
+ <edge>
+ <label x="5" y="-10"/>
+ </edge>
+ <edge>
+ <label x="-8" y="-22"/>
+ </edge>
+ </node>
+ <node name="End" x="288" y="120" width="132" height="36"/>
+ <deployment serverName="localhost" serverPort="8180" serverDeployer="/jbpm-console/app/upload">
+ <classesAndResources/>
+ <filesAndFolders/>
+ </deployment>
+</root-container>
Property changes on: jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2959/gpd.xml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2959/processdefinition.xml
===================================================================
--- jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2959/processdefinition.xml (rev 0)
+++ jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2959/processdefinition.xml 2010-10-14 18:09:32 UTC (rev 6760)
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<process-definition xmlns="urn:jbpm.org:jpdl-3.2" name="jbpm2959">
+
+ <start-state name="Start">
+ <transition to="Keep Going?" >
+ <script>
+ executionContext.setVariable("count", 0);
+ </script>
+ </transition>
+ </start-state>
+
+ <state name="Sleep">
+ <timer duedate="1 second" name="sleep_timer_1" transition="Done" />
+ <transition to="Keep Going?" name="Done" />
+ </state>
+
+ <decision name="Keep Going?">
+ <transition to="Sleep" name="Yes">
+ <condition expression="${count < 10}" />
+ <script>
+ executionContext.setVariable("count", count + 1);
+ </script>
+ </transition>
+ <transition to="End" name="No" />
+ </decision>
+
+ <end-state name="End" />
+
+</process-definition>
\ No newline at end of file
Property changes on: jbpm3/branches/jbpm-3.2-soa/core/src/test/resources/org/jbpm/jbpm2959/processdefinition.xml
___________________________________________________________________
Name: svn:eol-style
+ native
13 years, 6 months