diff --git a/config/alfresco/application-context.xml b/config/alfresco/application-context.xml
index 5cb650346c..6e9163edc6 100644
--- a/config/alfresco/application-context.xml
+++ b/config/alfresco/application-context.xml
@@ -22,6 +22,7 @@
+
diff --git a/config/alfresco/hibernate-context.xml b/config/alfresco/hibernate-context.xml
index fc2befda7b..b656dfaf0e 100644
--- a/config/alfresco/hibernate-context.xml
+++ b/config/alfresco/hibernate-context.xml
@@ -32,11 +32,107 @@
+
+
+
+
org/alfresco/repo/domain/hibernate/Node.hbm.xml
org/alfresco/repo/domain/hibernate/Store.hbm.xml
org/alfresco/repo/domain/hibernate/VersionCount.hbm.xml
org/alfresco/repo/domain/hibernate/AppliedPatch.hbm.xml
org/alfresco/repo/domain/hibernate/Permission.hbm.xml
+
+
+
+
+
+
+
+ org/jbpm/graph/action/Script.hbm.xml
+ org/jbpm/db/hibernate.queries.hbm.xml
+ org/jbpm/graph/def/ProcessDefinition.hbm.xml
+ org/jbpm/graph/def/Node.hbm.xml
+ org/jbpm/graph/def/Transition.hbm.xml
+ org/jbpm/graph/def/Event.hbm.xml
+ org/jbpm/graph/def/Action.hbm.xml
+ org/jbpm/graph/def/SuperState.hbm.xml
+ org/jbpm/graph/def/ExceptionHandler.hbm.xml
+ org/jbpm/instantiation/Delegation.hbm.xml
+ org/jbpm/graph/node/StartState.hbm.xml
+ org/jbpm/graph/node/EndState.hbm.xml
+ org/jbpm/graph/node/ProcessState.hbm.xml
+ org/jbpm/graph/node/Decision.hbm.xml
+ org/jbpm/graph/node/Fork.hbm.xml
+ org/jbpm/graph/node/Join.hbm.xml
+ org/jbpm/graph/node/State.hbm.xml
+ org/jbpm/graph/node/TaskNode.hbm.xml
+ org/jbpm/context/def/ContextDefinition.hbm.xml
+ org/jbpm/context/def/VariableAccess.hbm.xml
+ org/jbpm/taskmgmt/def/TaskMgmtDefinition.hbm.xml
+ org/jbpm/taskmgmt/def/Swimlane.hbm.xml
+ org/jbpm/taskmgmt/def/Task.hbm.xml
+ org/jbpm/taskmgmt/def/TaskController.hbm.xml
+ org/jbpm/module/def/ModuleDefinition.hbm.xml
+ org/jbpm/bytes/ByteArray.hbm.xml
+ org/jbpm/file/def/FileDefinition.hbm.xml
+ org/jbpm/scheduler/def/CreateTimerAction.hbm.xml
+ org/jbpm/scheduler/def/CancelTimerAction.hbm.xml
+ org/jbpm/graph/exe/Comment.hbm.xml
+ org/jbpm/graph/exe/ProcessInstance.hbm.xml
+ org/jbpm/graph/exe/Token.hbm.xml
+ org/jbpm/graph/exe/RuntimeAction.hbm.xml
+ org/jbpm/module/exe/ModuleInstance.hbm.xml
+ org/jbpm/context/exe/ContextInstance.hbm.xml
+ org/jbpm/context/exe/TokenVariableMap.hbm.xml
+ org/jbpm/context/exe/VariableInstance.hbm.xml
+ org/jbpm/context/exe/variableinstance/ByteArrayInstance.hbm.xml
+ org/jbpm/context/exe/variableinstance/DateInstance.hbm.xml
+ org/jbpm/context/exe/variableinstance/DoubleInstance.hbm.xml
+ org/jbpm/context/exe/variableinstance/HibernateLongInstance.hbm.xml
+ org/jbpm/context/exe/variableinstance/HibernateStringInstance.hbm.xml
+ org/jbpm/context/exe/variableinstance/LongInstance.hbm.xml
+ org/jbpm/context/exe/variableinstance/NullInstance.hbm.xml
+ org/jbpm/context/exe/variableinstance/StringInstance.hbm.xml
+ org/jbpm/msg/Message.hbm.xml
+ org/jbpm/msg/db/TextMessage.hbm.xml
+ org/jbpm/command/ExecuteActionCommand.hbm.xml
+ org/jbpm/command/ExecuteNodeCommand.hbm.xml
+ org/jbpm/command/SignalCommand.hbm.xml
+ org/jbpm/command/TaskInstanceEndCommand.hbm.xml
+ org/jbpm/taskmgmt/exe/TaskMgmtInstance.hbm.xml
+ org/jbpm/taskmgmt/exe/TaskInstance.hbm.xml
+ org/jbpm/taskmgmt/exe/PooledActor.hbm.xml
+ org/jbpm/taskmgmt/exe/SwimlaneInstance.hbm.xml
+ org/jbpm/scheduler/exe/Timer.hbm.xml
+ org/jbpm/logging/log/ProcessLog.hbm.xml
+ org/jbpm/logging/log/MessageLog.hbm.xml
+ org/jbpm/logging/log/CompositeLog.hbm.xml
+ org/jbpm/graph/log/ActionLog.hbm.xml
+ org/jbpm/graph/log/NodeLog.hbm.xml
+ org/jbpm/graph/log/ProcessInstanceCreateLog.hbm.xml
+ org/jbpm/graph/log/ProcessInstanceEndLog.hbm.xml
+ org/jbpm/graph/log/SignalLog.hbm.xml
+ org/jbpm/graph/log/TokenCreateLog.hbm.xml
+ org/jbpm/graph/log/TokenEndLog.hbm.xml
+ org/jbpm/graph/log/TransitionLog.hbm.xml
+ org/jbpm/context/log/VariableLog.hbm.xml
+ org/jbpm/context/log/VariableCreateLog.hbm.xml
+ org/jbpm/context/log/VariableDeleteLog.hbm.xml
+ org/jbpm/context/log/VariableUpdateLog.hbm.xml
+ org/jbpm/context/log/variableinstance/ByteArrayUpdateLog.hbm.xml
+ org/jbpm/context/log/variableinstance/DateUpdateLog.hbm.xml
+ org/jbpm/context/log/variableinstance/DoubleUpdateLog.hbm.xml
+ org/jbpm/context/log/variableinstance/HibernateLongUpdateLog.hbm.xml
+ org/jbpm/context/log/variableinstance/HibernateStringUpdateLog.hbm.xml
+ org/jbpm/context/log/variableinstance/LongUpdateLog.hbm.xml
+ org/jbpm/context/log/variableinstance/StringUpdateLog.hbm.xml
+ org/jbpm/taskmgmt/log/TaskLog.hbm.xml
+ org/jbpm/taskmgmt/log/TaskCreateLog.hbm.xml
+ org/jbpm/taskmgmt/log/TaskAssignLog.hbm.xml
+ org/jbpm/taskmgmt/log/TaskEndLog.hbm.xml
+ org/jbpm/taskmgmt/log/SwimlaneLog.hbm.xml
+ org/jbpm/taskmgmt/log/SwimlaneCreateLog.hbm.xml
+ org/jbpm/taskmgmt/log/SwimlaneAssignLog.hbm.xml
diff --git a/config/alfresco/workflow-context.xml b/config/alfresco/workflow-context.xml
new file mode 100644
index 0000000000..44b2a55ebf
--- /dev/null
+++ b/config/alfresco/workflow-context.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/java/org/alfresco/repo/workflow/jbpm/JBPMSpringTest.java b/source/java/org/alfresco/repo/workflow/jbpm/JBPMSpringTest.java
new file mode 100644
index 0000000000..e49b18b9ad
--- /dev/null
+++ b/source/java/org/alfresco/repo/workflow/jbpm/JBPMSpringTest.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2005 Alfresco, Inc.
+ *
+ * Licensed under the Mozilla Public License version 1.1
+ * with a permitted attribution clause. You may obtain a
+ * copy of the License at
+ *
+ * http://www.alfresco.org/legal/license.txt
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the
+ * License.
+ */
+package org.alfresco.repo.workflow.jbpm;
+
+import java.util.List;
+
+import org.alfresco.util.BaseSpringTest;
+import org.jbpm.JbpmContext;
+import org.jbpm.db.GraphSession;
+import org.jbpm.graph.def.ProcessDefinition;
+import org.jbpm.graph.exe.ProcessInstance;
+import org.jbpm.graph.exe.Token;
+import org.springmodules.workflow.jbpm31.JbpmCallback;
+import org.springmodules.workflow.jbpm31.JbpmTemplate;
+
+
+/**
+ * Test Usage of jBPM within Alfresco Spring Context
+ *
+ * @author davidc
+ */
+public class JBPMSpringTest extends BaseSpringTest
+{
+ private JbpmTemplate jbpmTemplate;
+
+
+ @Override
+ protected void onSetUpInTransaction() throws Exception
+ {
+ jbpmTemplate = (JbpmTemplate)applicationContext.getBean("jbpmTemplate");
+ }
+
+
+ public void testHelloWorld()
+ throws Exception
+ {
+ // Between the 3 method calls below, all data is passed via the
+ // database. Here, in this unit test, these 3 methods are executed
+ // right after each other because we want to test a complete process
+ // scenario. But in reality, these methods represent different
+ // requests to a server.
+
+ // Since we start with a clean, empty in-memory database, we have to
+ // deploy the process first. In reality, this is done once by the
+ // process developer.
+ deployProcessDefinition();
+
+ // Suppose we want to start a process instance (=process execution)
+ // when a user submits a form in a web application...
+ processInstanceIsCreatedWhenUserSubmitsWebappForm();
+
+ // Then, later, upon the arrival of an asynchronous message the
+ // execution must continue.
+ theProcessInstanceContinuesWhenAnAsyncMessageIsReceived();
+ }
+
+ public void testStep0()
+ throws Exception
+ {
+ deployProcessDefinition();
+ setComplete();
+ }
+
+ public void testStep1()
+ throws Exception
+ {
+ processInstanceIsCreatedWhenUserSubmitsWebappForm();
+ setComplete();
+ }
+
+ public void testStep2()
+ throws Exception
+ {
+ theProcessInstanceContinuesWhenAnAsyncMessageIsReceived();
+ setComplete();
+ }
+
+ private void deployProcessDefinition()
+ {
+ // This test shows a process definition and one execution
+ // of the process definition. The process definition has
+ // 3 nodes: an unnamed start-state, a state 's' and an
+ // end-state named 'end'.
+ final ProcessDefinition processDefinition = ProcessDefinition.parseXmlString(
+ "" +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ " " +
+ ""
+ );
+
+ jbpmTemplate.execute(new JbpmCallback()
+ {
+ public Object doInJbpm(JbpmContext context)
+ {
+ context.deployProcessDefinition(processDefinition);
+ return null;
+ }
+ });
+ }
+
+ private void processInstanceIsCreatedWhenUserSubmitsWebappForm()
+ {
+ jbpmTemplate.execute(new JbpmCallback()
+ {
+ public Object doInJbpm(JbpmContext context)
+ {
+ GraphSession graphSession = context.getGraphSession();
+ ProcessDefinition processDefinition = graphSession.findLatestProcessDefinition("hello world");
+
+ // With the processDefinition that we retrieved from the database, we
+ // can create an execution of the process definition just like in the
+ // hello world example (which was without persistence).
+ ProcessInstance processInstance = new ProcessInstance(processDefinition);
+
+ Token token = processInstance.getRootToken();
+ assertEquals("start", token.getNode().getName());
+ // Let's start the process execution
+ token.signal();
+ // Now the process is in the state 's'.
+ assertEquals("s", token.getNode().getName());
+
+ context.save(processInstance);
+ return null;
+ }
+ });
+ }
+
+ private void theProcessInstanceContinuesWhenAnAsyncMessageIsReceived()
+ {
+ jbpmTemplate.execute(new JbpmCallback()
+ {
+ public Object doInJbpm(JbpmContext context)
+ {
+ GraphSession graphSession = context.getGraphSession();
+
+ // First, we need to get the process instance back out of the database.
+ // There are several options to know what process instance we are dealing
+ // with here. The easiest in this simple test case is just to look for
+ // the full list of process instances. That should give us only one
+ // result. So let's look up the process definition.
+ ProcessDefinition processDefinition = graphSession.findLatestProcessDefinition("hello world");
+
+ // Now, we search for all process instances of this process definition.
+ List processInstances = graphSession.findProcessInstances(processDefinition.getId());
+
+ // Because we know that in the context of this unit test, there is
+ // only one execution. In real life, the processInstanceId can be
+ // extracted from the content of the message that arrived or from
+ // the user making a choice.
+ ProcessInstance processInstance = (ProcessInstance) processInstances.get(0);
+
+ // Now we can continue the execution. Note that the processInstance
+ // delegates signals to the main path of execution (=the root token).
+ processInstance.signal();
+
+ // After this signal, we know the process execution should have
+ // arrived in the end-state.
+ assertTrue(processInstance.hasEnded());
+
+ // Now we can update the state of the execution in the database
+ context.save(processInstance);
+ return null;
+ }
+ });
+ }
+
+}
+