mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Heinous merge from HEAD. Seems to basically work. Be on guard however.
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/WCM-DEV2/root@4137 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -23,6 +23,7 @@ import java.util.Map;
|
||||
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.repository.ScriptService;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowException;
|
||||
import org.dom4j.Element;
|
||||
import org.jbpm.context.def.VariableAccess;
|
||||
import org.jbpm.context.exe.ContextInstance;
|
||||
@@ -36,7 +37,7 @@ import org.xml.sax.InputSource;
|
||||
* A jBPM Action Handler for executing Alfresco Script
|
||||
*
|
||||
* The configuration of this action is as follows:
|
||||
* <script language="javascript">
|
||||
* <script>
|
||||
* <expression>
|
||||
* the script to execute
|
||||
* </expression>
|
||||
@@ -72,6 +73,12 @@ public class AlfrescoJavaScript extends JBPMSpringActionHandler
|
||||
@SuppressWarnings("unchecked")
|
||||
public void execute(ExecutionContext executionContext) throws Exception
|
||||
{
|
||||
// validate script
|
||||
if (script == null)
|
||||
{
|
||||
throw new WorkflowException("Script has not been provided");
|
||||
}
|
||||
|
||||
// extract action configuration
|
||||
String expression = null;
|
||||
List<VariableAccess> variableAccesses = null;
|
||||
@@ -96,7 +103,12 @@ public class AlfrescoJavaScript extends JBPMSpringActionHandler
|
||||
else
|
||||
{
|
||||
variableAccesses = jpdlReader.readVariableAccesses(script);
|
||||
expression = script.element("expression").getTextTrim();
|
||||
Element expressionElement = script.element("expression");
|
||||
if (expressionElement == null)
|
||||
{
|
||||
throw new WorkflowException("Script expression has not been provided");
|
||||
}
|
||||
expression = expressionElement.getTextTrim();
|
||||
}
|
||||
|
||||
// construct script arguments and execute
|
||||
|
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* 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 junit.framework.TestCase;
|
||||
|
||||
import org.jbpm.JbpmConfiguration;
|
||||
import org.jbpm.JbpmContext;
|
||||
import org.jbpm.db.GraphSession;
|
||||
import org.jbpm.db.TaskMgmtSession;
|
||||
import org.jbpm.graph.def.ProcessDefinition;
|
||||
import org.jbpm.graph.exe.ProcessInstance;
|
||||
import org.jbpm.graph.exe.Token;
|
||||
import org.jbpm.taskmgmt.exe.TaskInstance;
|
||||
|
||||
|
||||
/**
|
||||
* Unit Test for reproducing constraint violation during JBPM process deletion
|
||||
*
|
||||
* http://jira.jboss.com/jira/browse/JBPM-757
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
|
||||
public class JBPMDeleteProcessTest extends TestCase {
|
||||
|
||||
static JbpmConfiguration jbpmConfiguration = null;
|
||||
static long processId = -1L;
|
||||
static String currentTokenPath = null;
|
||||
|
||||
static {
|
||||
jbpmConfiguration = JbpmConfiguration.parseXmlString(
|
||||
"<jbpm-configuration>" +
|
||||
" <jbpm-context>" +
|
||||
" <service name='persistence' " +
|
||||
" factory='org.jbpm.persistence.db.DbPersistenceServiceFactory' />" +
|
||||
" </jbpm-context>" +
|
||||
" <string name='resource.hibernate.cfg.xml' " +
|
||||
" value='jbpmresources/hibernate.cfg.xml' />" +
|
||||
" <string name='resource.business.calendar' " +
|
||||
" value='org/jbpm/calendar/jbpm.business.calendar.properties' />" +
|
||||
" <string name='resource.default.modules' " +
|
||||
" value='org/jbpm/graph/def/jbpm.default.modules.properties' />" +
|
||||
" <string name='resource.converter' " +
|
||||
" value='org/jbpm/db/hibernate/jbpm.converter.properties' />" +
|
||||
" <string name='resource.action.types' " +
|
||||
" value='org/jbpm/graph/action/action.types.xml' />" +
|
||||
" <string name='resource.node.types' " +
|
||||
" value='org/jbpm/graph/node/node.types.xml' />" +
|
||||
" <string name='resource.varmapping' " +
|
||||
" value='org/jbpm/context/exe/jbpm.varmapping.xml' />" +
|
||||
"</jbpm-configuration>"
|
||||
);
|
||||
}
|
||||
|
||||
public void setUp() {
|
||||
jbpmConfiguration.createSchema();
|
||||
}
|
||||
|
||||
public void tearDown() {
|
||||
jbpmConfiguration.dropSchema();
|
||||
}
|
||||
|
||||
public void testDelete() {
|
||||
deployProcessDefinition();
|
||||
|
||||
startProcess();
|
||||
step2TaskEnd();
|
||||
deleteProcess();
|
||||
}
|
||||
|
||||
public void deployProcessDefinition() {
|
||||
ProcessDefinition processDefinition = ProcessDefinition.parseXmlString
|
||||
(
|
||||
"<process-definition name='deletetest'>" +
|
||||
" <start-state name='start'> " +
|
||||
" <task name='startTask'> " +
|
||||
" <controller> " +
|
||||
" <variable name='var1' access='write'/> " +
|
||||
" </controller> " +
|
||||
" </task> " +
|
||||
" <transition name='' to='step2'/> " +
|
||||
" </start-state> " +
|
||||
" <task-node name='step2'> " +
|
||||
" <task name='step2Task'/> " +
|
||||
" <transition name='' to='step3'/> " +
|
||||
" </task-node>" +
|
||||
" <task-node name='step3'> " +
|
||||
" <task name='step3Task'/> " +
|
||||
" <transition name='' to='end'/> " +
|
||||
" </task-node> " +
|
||||
" <end-state name='end' />" +
|
||||
"</process-definition>"
|
||||
);
|
||||
|
||||
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
|
||||
try {
|
||||
jbpmContext.deployProcessDefinition(processDefinition);
|
||||
} finally {
|
||||
jbpmContext.close();
|
||||
}
|
||||
}
|
||||
|
||||
public void startProcess() {
|
||||
|
||||
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
|
||||
try {
|
||||
|
||||
GraphSession graphSession = jbpmContext.getGraphSession();
|
||||
|
||||
ProcessDefinition processDefinition = graphSession.findLatestProcessDefinition("deletetest");
|
||||
ProcessInstance processInstance = new ProcessInstance(processDefinition);
|
||||
processId = processInstance.getId();
|
||||
|
||||
TaskInstance taskInstance = processInstance.getTaskMgmtInstance().createStartTaskInstance();
|
||||
taskInstance.setVariableLocally("var1", "var1Value");
|
||||
taskInstance.end();
|
||||
Token token = taskInstance.getToken();
|
||||
currentTokenPath = token.getFullName();
|
||||
|
||||
jbpmContext.save(processInstance);
|
||||
} finally {
|
||||
jbpmContext.close();
|
||||
}
|
||||
}
|
||||
|
||||
public void step2TaskEnd() {
|
||||
|
||||
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
|
||||
try {
|
||||
|
||||
GraphSession graphSession = jbpmContext.getGraphSession();
|
||||
ProcessInstance processInstance = graphSession.loadProcessInstance(processId);
|
||||
Token token = processInstance.findToken(currentTokenPath);
|
||||
TaskMgmtSession taskSession = jbpmContext.getTaskMgmtSession();
|
||||
List tasks = taskSession.findTaskInstancesByToken(token.getId());
|
||||
TaskInstance taskInstance = (TaskInstance)tasks.get(0);
|
||||
|
||||
//
|
||||
// Uncomment the following line to force constraint violation
|
||||
//
|
||||
// taskInstance.setVariableLocally("var1", "var1TaskValue");
|
||||
|
||||
taskInstance.setVariableLocally("var2", "var2UpdatedValue");
|
||||
taskInstance.end();
|
||||
token = taskInstance.getToken();
|
||||
currentTokenPath = token.getFullName();
|
||||
|
||||
jbpmContext.save(processInstance);
|
||||
} finally {
|
||||
jbpmContext.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void deleteProcess()
|
||||
{
|
||||
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
|
||||
try {
|
||||
|
||||
GraphSession graphSession = jbpmContext.getGraphSession();
|
||||
ProcessInstance processInstance = graphSession.loadProcessInstance(processId);
|
||||
graphSession.deleteProcessInstance(processInstance, true, true, true);
|
||||
} finally {
|
||||
jbpmContext.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -59,6 +59,7 @@ import org.alfresco.service.cmr.workflow.WorkflowTask;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTaskDefinition;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTransition;
|
||||
import org.alfresco.service.namespace.NamespaceException;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.hibernate.Query;
|
||||
@@ -259,8 +260,7 @@ public class JBPMEngine extends BPMEngine
|
||||
{
|
||||
// retrieve process definition
|
||||
GraphSession graphSession = context.getGraphSession();
|
||||
ProcessDefinition processDefinition = graphSession.loadProcessDefinition(getJbpmId(workflowDefinitionId));
|
||||
// NOTE: if not found, should throw an exception
|
||||
ProcessDefinition processDefinition = getProcessDefinition(graphSession, workflowDefinitionId);
|
||||
|
||||
// undeploy
|
||||
// NOTE: jBPM deletes all "in-flight" processes too
|
||||
@@ -331,7 +331,7 @@ public class JBPMEngine extends BPMEngine
|
||||
{
|
||||
GraphSession graphSession = context.getGraphSession();
|
||||
ProcessDefinition processDef = graphSession.findLatestProcessDefinition(createLocalId(workflowName));
|
||||
return createWorkflowDefinition(processDef);
|
||||
return processDef == null ? null : createWorkflowDefinition(processDef);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -341,6 +341,23 @@ public class JBPMEngine extends BPMEngine
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a jBPM process definition
|
||||
*
|
||||
* @param graphSession jBPM graph session
|
||||
* @param workflowDefinitionId workflow definition id
|
||||
* @return process definition
|
||||
*/
|
||||
private ProcessDefinition getProcessDefinition(GraphSession graphSession, String workflowDefinitionId)
|
||||
{
|
||||
ProcessDefinition processDefinition = graphSession.getProcessDefinition(getJbpmId(workflowDefinitionId));
|
||||
if (processDefinition == null)
|
||||
{
|
||||
throw new WorkflowException("Workflow definition '" + workflowDefinitionId + "' does not exist");
|
||||
}
|
||||
return processDefinition;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Workflow Instance Management...
|
||||
@@ -366,7 +383,7 @@ public class JBPMEngine extends BPMEngine
|
||||
|
||||
// construct a new process
|
||||
GraphSession graphSession = context.getGraphSession();
|
||||
ProcessDefinition processDefinition = graphSession.loadProcessDefinition(getJbpmId(workflowDefinitionId));
|
||||
ProcessDefinition processDefinition = getProcessDefinition(graphSession, workflowDefinitionId);
|
||||
ProcessInstance processInstance = new ProcessInstance(processDefinition);
|
||||
|
||||
// assign initial process context
|
||||
@@ -398,7 +415,7 @@ public class JBPMEngine extends BPMEngine
|
||||
throw new WorkflowException("Failed to start workflow " + workflowDefinitionId, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.workflow.WorkflowComponent#getActiveWorkflows(java.lang.String)
|
||||
*/
|
||||
@@ -432,6 +449,46 @@ public class JBPMEngine extends BPMEngine
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.workflow.WorkflowComponent#getWorkflowById(java.lang.String)
|
||||
*/
|
||||
public WorkflowInstance getWorkflowById(final String workflowId)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (WorkflowInstance) jbpmTemplate.execute(new JbpmCallback()
|
||||
{
|
||||
public Object doInJbpm(JbpmContext context)
|
||||
{
|
||||
// retrieve workflow
|
||||
GraphSession graphSession = context.getGraphSession();
|
||||
ProcessInstance processInstance = graphSession.getProcessInstance(getJbpmId(workflowId));
|
||||
return processInstance == null ? null : createWorkflowInstance(processInstance);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch(JbpmException e)
|
||||
{
|
||||
throw new WorkflowException("Failed to retrieve workflow instance '" + workflowId + "'", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a jBPM Process Instance
|
||||
* @param graphSession jBPM graph session
|
||||
* @param workflowId workflow id
|
||||
* @return process instance
|
||||
*/
|
||||
private ProcessInstance getProcessInstance(GraphSession graphSession, String workflowId)
|
||||
{
|
||||
ProcessInstance processInstance = graphSession.getProcessInstance(getJbpmId(workflowId));
|
||||
if (processInstance == null)
|
||||
{
|
||||
throw new WorkflowException("Workflow instance '" + workflowId + "' does not exist");
|
||||
}
|
||||
return processInstance;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.workflow.WorkflowComponent#getWorkflowPaths(java.lang.String)
|
||||
*/
|
||||
@@ -446,7 +503,7 @@ public class JBPMEngine extends BPMEngine
|
||||
{
|
||||
// retrieve process instance
|
||||
GraphSession graphSession = context.getGraphSession();
|
||||
ProcessInstance processInstance = graphSession.loadProcessInstance(getJbpmId(workflowId));
|
||||
ProcessInstance processInstance = getProcessInstance(graphSession, workflowId);
|
||||
|
||||
// convert jBPM tokens to workflow posisitons
|
||||
List<Token> tokens = processInstance.findAllTokens();
|
||||
@@ -479,16 +536,21 @@ public class JBPMEngine extends BPMEngine
|
||||
{
|
||||
return (WorkflowInstance) jbpmTemplate.execute(new JbpmCallback()
|
||||
{
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object doInJbpm(JbpmContext context)
|
||||
{
|
||||
// retrieve and cancel process instance
|
||||
GraphSession graphSession = context.getGraphSession();
|
||||
ProcessInstance processInstance = graphSession.loadProcessInstance(getJbpmId(workflowId));
|
||||
processInstance.end();
|
||||
|
||||
// save the process instance along with the task instance
|
||||
context.save(processInstance);
|
||||
return createWorkflowInstance(processInstance);
|
||||
ProcessInstance processInstance = getProcessInstance(graphSession, workflowId);
|
||||
// TODO: Determine if this is the most appropriate way to cancel workflow...
|
||||
// It might be useful to record point at which it was cancelled etc
|
||||
WorkflowInstance workflowInstance = createWorkflowInstance(processInstance);
|
||||
|
||||
// delete the process instance
|
||||
graphSession.deleteProcessInstance(processInstance, true, true, true);
|
||||
workflowInstance.active = false;
|
||||
workflowInstance.endDate = new Date();
|
||||
return workflowInstance;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -681,6 +743,22 @@ public class JBPMEngine extends BPMEngine
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a jBPM Task Instance
|
||||
* @param taskSession jBPM task session
|
||||
* @param taskId task id
|
||||
* @return task instance
|
||||
*/
|
||||
private TaskInstance getTaskInstance(TaskMgmtSession taskSession, String taskId)
|
||||
{
|
||||
TaskInstance taskInstance = taskSession.getTaskInstance(getJbpmId(taskId));
|
||||
if (taskInstance == null)
|
||||
{
|
||||
throw new WorkflowException("Task instance '" + taskId + "' does not exist");
|
||||
}
|
||||
return taskInstance;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.workflow.TaskComponent#updateTask(java.lang.String, java.util.Map, java.util.Map, java.util.Map)
|
||||
*/
|
||||
@@ -694,7 +772,7 @@ public class JBPMEngine extends BPMEngine
|
||||
{
|
||||
// retrieve task
|
||||
TaskMgmtSession taskSession = context.getTaskMgmtSession();
|
||||
TaskInstance taskInstance = taskSession.loadTaskInstance(getJbpmId(taskId));
|
||||
TaskInstance taskInstance = getTaskInstance(taskSession, taskId);
|
||||
|
||||
// create properties to set on task instance
|
||||
Map<QName, Serializable> newProperties = properties;
|
||||
@@ -705,7 +783,7 @@ public class JBPMEngine extends BPMEngine
|
||||
|
||||
if (add != null || remove != null)
|
||||
{
|
||||
Map<QName, Serializable> existingProperties = getTaskProperties(taskInstance);
|
||||
Map<QName, Serializable> existingProperties = getTaskProperties(taskInstance, false);
|
||||
|
||||
if (add != null)
|
||||
{
|
||||
@@ -814,8 +892,8 @@ public class JBPMEngine extends BPMEngine
|
||||
{
|
||||
// retrieve task
|
||||
TaskMgmtSession taskSession = context.getTaskMgmtSession();
|
||||
TaskInstance taskInstance = taskSession.loadTaskInstance(getJbpmId(taskId));
|
||||
|
||||
TaskInstance taskInstance = getTaskInstance(taskSession, taskId);
|
||||
|
||||
// signal the transition on the task
|
||||
if (transition == null)
|
||||
{
|
||||
@@ -860,8 +938,8 @@ public class JBPMEngine extends BPMEngine
|
||||
{
|
||||
// retrieve task
|
||||
TaskMgmtSession taskSession = context.getTaskMgmtSession();
|
||||
TaskInstance taskInstance = taskSession.loadTaskInstance(getJbpmId(taskId));
|
||||
return createWorkflowTask(taskInstance);
|
||||
TaskInstance taskInstance = taskSession.getTaskInstance(getJbpmId(taskId));
|
||||
return taskInstance == null ? null : createWorkflowTask(taskInstance);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -992,7 +1070,7 @@ public class JBPMEngine extends BPMEngine
|
||||
TypeDefinition typeDef = dictionaryService.getType(typeName);
|
||||
if (typeDef == null)
|
||||
{
|
||||
typeDef = dictionaryService.getType(WorkflowModel.TYPE_WORKFLOW_TASK);
|
||||
typeDef = dictionaryService.getType(task.getStartState() == null ? WorkflowModel.TYPE_WORKFLOW_TASK : WorkflowModel.TYPE_START_TASK);
|
||||
if (typeDef == null)
|
||||
{
|
||||
throw new WorkflowException("Failed to find type definition '" + WorkflowModel.TYPE_WORKFLOW_TASK + "'");
|
||||
@@ -1072,7 +1150,7 @@ public class JBPMEngine extends BPMEngine
|
||||
}
|
||||
|
||||
// retrieve jBPM token for workflow position
|
||||
ProcessInstance processInstance = session.loadProcessInstance(getJbpmId(path[0]));
|
||||
ProcessInstance processInstance = getProcessInstance(session, path[0]);
|
||||
String tokenId = path[1].replace(WORKFLOW_TOKEN_SEPERATOR, "/");
|
||||
Token token = processInstance.findToken(tokenId);
|
||||
if (token == null)
|
||||
@@ -1090,43 +1168,55 @@ public class JBPMEngine extends BPMEngine
|
||||
* @param properties properties to set
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Map<QName, Serializable> getTaskProperties(TaskInstance instance)
|
||||
protected Map<QName, Serializable> getTaskProperties(TaskInstance instance, boolean localProperties)
|
||||
{
|
||||
// retrieve type definition for task
|
||||
TypeDefinition taskDef = getAnonymousTaskDefinition(getTaskDefinition(instance.getTask()));
|
||||
Map<QName, PropertyDefinition> taskProperties = taskDef.getProperties();
|
||||
Map<QName, AssociationDefinition> taskAssocs = taskDef.getAssociations();
|
||||
|
||||
// map arbitrary task variables
|
||||
Map<QName, Serializable> properties = new HashMap<QName, Serializable>(10);
|
||||
Map<String, Object> vars = instance.getVariablesLocally();
|
||||
Map<String, Object> vars = (localProperties ? instance.getVariablesLocally() : instance.getVariables());
|
||||
|
||||
for (Entry<String, Object> entry : vars.entrySet())
|
||||
{
|
||||
String key = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
QName qname = mapNameToQName(key);
|
||||
|
||||
//
|
||||
// perform data conversions
|
||||
//
|
||||
|
||||
// Convert Nodes to NodeRefs
|
||||
if (value instanceof JBPMNode)
|
||||
// add variable, only if part of task definition or locally defined on task
|
||||
if (taskProperties.containsKey(qname) || taskAssocs.containsKey(qname) || instance.hasVariableLocally(key))
|
||||
{
|
||||
value = ((JBPMNode)value).getNodeRef();
|
||||
Object value = entry.getValue();
|
||||
|
||||
//
|
||||
// perform data conversions
|
||||
//
|
||||
|
||||
// Convert Nodes to NodeRefs
|
||||
if (value instanceof JBPMNode)
|
||||
{
|
||||
value = ((JBPMNode)value).getNodeRef();
|
||||
}
|
||||
else if (value instanceof JBPMNodeList)
|
||||
{
|
||||
JBPMNodeList nodes = (JBPMNodeList)value;
|
||||
List<NodeRef> nodeRefs = new ArrayList<NodeRef>(nodes.size());
|
||||
for (JBPMNode node : nodes)
|
||||
{
|
||||
nodeRefs.add(node.getNodeRef());
|
||||
}
|
||||
value = (Serializable)nodeRefs;
|
||||
}
|
||||
|
||||
// place task variable in map to return
|
||||
properties.put(qname, (Serializable)value);
|
||||
}
|
||||
else if (value instanceof JBPMNodeList)
|
||||
{
|
||||
JBPMNodeList nodes = (JBPMNodeList)value;
|
||||
List<NodeRef> nodeRefs = new ArrayList<NodeRef>(nodes.size());
|
||||
for (JBPMNode node : nodes)
|
||||
{
|
||||
nodeRefs.add(node.getNodeRef());
|
||||
}
|
||||
value = (Serializable)nodeRefs;
|
||||
}
|
||||
|
||||
// place task variable in map to return
|
||||
QName qname = QName.createQName(key, this.namespaceService);
|
||||
properties.put(qname, (Serializable)value);
|
||||
}
|
||||
|
||||
// map jBPM task instance fields to properties
|
||||
properties.put(WorkflowModel.PROP_TASK_ID, instance.getId());
|
||||
properties.put(WorkflowModel.PROP_DESCRIPTION, instance.getDescription());
|
||||
properties.put(WorkflowModel.PROP_START_DATE, instance.getStart());
|
||||
properties.put(WorkflowModel.PROP_DUE_DATE, instance.getDueDate());
|
||||
properties.put(WorkflowModel.PROP_COMPLETION_DATE, instance.getEnd());
|
||||
@@ -1207,6 +1297,15 @@ public class JBPMEngine extends BPMEngine
|
||||
}
|
||||
|
||||
// map property to specific jBPM task instance field
|
||||
if (key.equals(WorkflowModel.PROP_DESCRIPTION))
|
||||
{
|
||||
if (value != null && !(value instanceof String))
|
||||
{
|
||||
throw new WorkflowException("Task description '" + value + "' is invalid");
|
||||
}
|
||||
instance.setDescription((String)value);
|
||||
continue;
|
||||
}
|
||||
if (key.equals(WorkflowModel.PROP_DUE_DATE))
|
||||
{
|
||||
if (value != null && !(value instanceof Date))
|
||||
@@ -1269,6 +1368,39 @@ public class JBPMEngine extends BPMEngine
|
||||
instance.setPooledActors(pooledActors);
|
||||
continue;
|
||||
}
|
||||
else if (key.equals(WorkflowModel.ASSOC_PACKAGE))
|
||||
{
|
||||
// Attach workflow definition & instance id to Workflow Package in Repository
|
||||
String name = mapQNameToName(key);
|
||||
JBPMNode existingWorkflowPackage = (JBPMNode)instance.getVariable(name);
|
||||
|
||||
// first check if provided workflow package has already been associated with another workflow instance
|
||||
if (existingWorkflowPackage != null && value != null)
|
||||
{
|
||||
NodeRef newPackageNodeRef = ((JBPMNode)value).getNodeRef();
|
||||
ProcessInstance processInstance = instance.getToken().getProcessInstance();
|
||||
String packageInstanceId = (String)nodeService.getProperty(newPackageNodeRef, WorkflowModel.PROP_WORKFLOW_INSTANCE_ID);
|
||||
if (packageInstanceId != null && packageInstanceId.length() > 0 && (processInstance.getId() == getJbpmId(packageInstanceId)))
|
||||
{
|
||||
String workflowInstanceId = createGlobalId(new Long(processInstance.getId()).toString());
|
||||
throw new WorkflowException("Cannot associate workflow package '" + newPackageNodeRef + "' with workflow instance '" + workflowInstanceId + "' as it's already associated with workflow instance '" + packageInstanceId + "'");
|
||||
}
|
||||
}
|
||||
|
||||
// initialise workflow package
|
||||
if (existingWorkflowPackage == null && value != null)
|
||||
{
|
||||
// initialise workflow package
|
||||
NodeRef newPackageNodeRef = ((JBPMNode)value).getNodeRef();
|
||||
ProcessInstance processInstance = instance.getToken().getProcessInstance();
|
||||
WorkflowInstance workflowInstance = createWorkflowInstance(processInstance);
|
||||
nodeService.setProperty(newPackageNodeRef, WorkflowModel.PROP_WORKFLOW_DEFINITION_ID, workflowInstance.definition.id);
|
||||
nodeService.setProperty(newPackageNodeRef, WorkflowModel.PROP_WORKFLOW_DEFINITION_NAME, workflowInstance.definition.name);
|
||||
nodeService.setProperty(newPackageNodeRef, WorkflowModel.PROP_WORKFLOW_INSTANCE_ID, workflowInstance.id);
|
||||
}
|
||||
|
||||
// NOTE: Fall-through to allow setting of Workflow Package on Task Instance
|
||||
}
|
||||
}
|
||||
|
||||
// untyped value, perform minimal conversion
|
||||
@@ -1283,7 +1415,7 @@ public class JBPMEngine extends BPMEngine
|
||||
|
||||
// no specific mapping to jBPM task has been established, so place into
|
||||
// the generic task variable bag
|
||||
String name = key.toPrefixString(this.namespaceService);
|
||||
String name = mapQNameToName(key);
|
||||
instance.setVariableLocally(name, value);
|
||||
}
|
||||
}
|
||||
@@ -1295,7 +1427,7 @@ public class JBPMEngine extends BPMEngine
|
||||
*/
|
||||
protected void setDefaultTaskProperties(TaskInstance instance)
|
||||
{
|
||||
Map<QName, Serializable> existingValues = null;
|
||||
Map<QName, Serializable> existingValues = getTaskProperties(instance, true);
|
||||
Map<QName, Serializable> defaultValues = new HashMap<QName, Serializable>();
|
||||
|
||||
// construct an anonymous type that flattens all mandatory aspects
|
||||
@@ -1308,10 +1440,6 @@ public class JBPMEngine extends BPMEngine
|
||||
String defaultValue = entry.getValue().getDefaultValue();
|
||||
if (defaultValue != null)
|
||||
{
|
||||
if (existingValues == null)
|
||||
{
|
||||
existingValues = getTaskProperties(instance);
|
||||
}
|
||||
if (existingValues.get(entry.getKey()) == null)
|
||||
{
|
||||
defaultValues.put(entry.getKey(), defaultValue);
|
||||
@@ -1319,6 +1447,22 @@ public class JBPMEngine extends BPMEngine
|
||||
}
|
||||
}
|
||||
|
||||
// special case for task description default value
|
||||
String description = (String)existingValues.get(WorkflowModel.PROP_DESCRIPTION);
|
||||
if (description == null || description.length() == 0)
|
||||
{
|
||||
description = (String)instance.getContextInstance().getVariable(mapQNameToName(WorkflowModel.PROP_WORKFLOW_DESCRIPTION));
|
||||
if (description != null && description.length() > 0)
|
||||
{
|
||||
defaultValues.put(WorkflowModel.PROP_DESCRIPTION, description);
|
||||
}
|
||||
else
|
||||
{
|
||||
WorkflowTask task = createWorkflowTask(instance);
|
||||
defaultValues.put(WorkflowModel.PROP_DESCRIPTION, task.title);
|
||||
}
|
||||
}
|
||||
|
||||
// assign the default values to the task
|
||||
if (defaultValues.size() > 0)
|
||||
{
|
||||
@@ -1327,16 +1471,62 @@ public class JBPMEngine extends BPMEngine
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Task Outcome based on specified Transition
|
||||
* Sets default description for the Task
|
||||
*
|
||||
* @param instance task instance
|
||||
* @param transition transition
|
||||
*/
|
||||
protected void setTaskOutcome(TaskInstance instance, Transition transition)
|
||||
public void setDefaultStartTaskDescription(TaskInstance instance)
|
||||
{
|
||||
Map<QName, Serializable> outcome = new HashMap<QName, Serializable>();
|
||||
outcome.put(WorkflowModel.PROP_OUTCOME, transition.getName());
|
||||
setTaskProperties(instance, outcome);
|
||||
String description = instance.getTask().getDescription();
|
||||
if (description == null || description.length() == 0)
|
||||
{
|
||||
description = (String)instance.getContextInstance().getVariable(mapQNameToName(WorkflowModel.PROP_WORKFLOW_DESCRIPTION));
|
||||
if (description != null && description.length() > 0)
|
||||
{
|
||||
Map<QName, Serializable> defaultValues = new HashMap<QName, Serializable>();
|
||||
defaultValues.put(WorkflowModel.PROP_DESCRIPTION, description);
|
||||
setTaskProperties(instance, defaultValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise Workflow Instance properties
|
||||
*
|
||||
* @param startTask start task instance
|
||||
*/
|
||||
protected void setDefaultWorkflowProperties(TaskInstance startTask)
|
||||
{
|
||||
Map<QName, Serializable> taskProperties = getTaskProperties(startTask, true);
|
||||
|
||||
ContextInstance processContext = startTask.getContextInstance();
|
||||
String workflowDescriptionName = mapQNameToName(WorkflowModel.PROP_WORKFLOW_DESCRIPTION);
|
||||
if (!processContext.hasVariable(workflowDescriptionName))
|
||||
{
|
||||
processContext.setVariable(workflowDescriptionName, taskProperties.get(WorkflowModel.PROP_WORKFLOW_DESCRIPTION));
|
||||
}
|
||||
String workflowDueDateName = mapQNameToName(WorkflowModel.PROP_WORKFLOW_DUE_DATE);
|
||||
if (!processContext.hasVariable(workflowDueDateName))
|
||||
{
|
||||
processContext.setVariable(workflowDueDateName, taskProperties.get(WorkflowModel.PROP_WORKFLOW_DUE_DATE));
|
||||
}
|
||||
String workflowPriorityName = mapQNameToName(WorkflowModel.PROP_WORKFLOW_PRIORITY);
|
||||
if (!processContext.hasVariable(workflowPriorityName))
|
||||
{
|
||||
processContext.setVariable(workflowPriorityName, taskProperties.get(WorkflowModel.PROP_WORKFLOW_PRIORITY));
|
||||
}
|
||||
String workflowPackageName = mapQNameToName(WorkflowModel.ASSOC_PACKAGE);
|
||||
if (!processContext.hasVariable(workflowPackageName))
|
||||
{
|
||||
Serializable packageNodeRef = taskProperties.get(WorkflowModel.ASSOC_PACKAGE);
|
||||
processContext.setVariable(workflowPackageName, convertNodeRefs(packageNodeRef instanceof List, packageNodeRef));
|
||||
}
|
||||
String workflowContextName = mapQNameToName(WorkflowModel.PROP_CONTEXT);
|
||||
if (!processContext.hasVariable(workflowContextName))
|
||||
{
|
||||
Serializable contextRef = taskProperties.get(WorkflowModel.PROP_CONTEXT);
|
||||
processContext.setVariable(workflowContextName, convertNodeRefs(contextRef instanceof List, contextRef));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1403,6 +1593,39 @@ public class JBPMEngine extends BPMEngine
|
||||
return authority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map jBPM variable name to QName
|
||||
*
|
||||
* @param name jBPM variable name
|
||||
* @return qname
|
||||
*/
|
||||
private QName mapNameToQName(String name)
|
||||
{
|
||||
QName qname = null;
|
||||
String qnameStr = name.replaceFirst("_", ":");
|
||||
try
|
||||
{
|
||||
qname = QName.createQName(qnameStr, this.namespaceService);
|
||||
}
|
||||
catch(NamespaceException e)
|
||||
{
|
||||
qname = QName.createQName(name, this.namespaceService);
|
||||
}
|
||||
return qname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map QName to jBPM variable name
|
||||
*
|
||||
* @param name QName
|
||||
* @return jBPM variable name
|
||||
*/
|
||||
private String mapQNameToName(QName name)
|
||||
{
|
||||
String nameStr = name.toPrefixString(this.namespaceService);
|
||||
return nameStr.replace(':', '_');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an I18N Label for a workflow item
|
||||
*
|
||||
@@ -1516,6 +1739,7 @@ public class JBPMEngine extends BPMEngine
|
||||
{
|
||||
WorkflowInstance workflowInstance = new WorkflowInstance();
|
||||
workflowInstance.id = createGlobalId(new Long(instance.getId()).toString());
|
||||
workflowInstance.description = (String)instance.getContextInstance().getVariable(mapQNameToName(WorkflowModel.PROP_WORKFLOW_DESCRIPTION));
|
||||
workflowInstance.definition = createWorkflowDefinition(instance.getProcessDefinition());
|
||||
workflowInstance.active = !instance.hasEnded();
|
||||
JBPMNode initiator = (JBPMNode)instance.getContextInstance().getVariable("initiator");
|
||||
@@ -1523,6 +1747,16 @@ public class JBPMEngine extends BPMEngine
|
||||
{
|
||||
workflowInstance.initiator = initiator.getNodeRef();
|
||||
}
|
||||
JBPMNode context = (JBPMNode)instance.getContextInstance().getVariable(mapQNameToName(WorkflowModel.PROP_CONTEXT));
|
||||
if (context != null)
|
||||
{
|
||||
workflowInstance.context = context.getNodeRef();
|
||||
}
|
||||
JBPMNode workflowPackage = (JBPMNode)instance.getContextInstance().getVariable(mapQNameToName(WorkflowModel.ASSOC_PACKAGE));
|
||||
if (workflowPackage != null)
|
||||
{
|
||||
workflowInstance.workflowPackage = workflowPackage.getNodeRef();
|
||||
}
|
||||
workflowInstance.startDate = instance.getStart();
|
||||
workflowInstance.endDate = instance.getEnd();
|
||||
return workflowInstance;
|
||||
@@ -1566,7 +1800,7 @@ public class JBPMEngine extends BPMEngine
|
||||
workflowTask.path = createWorkflowPath(task.getToken());
|
||||
workflowTask.state = getWorkflowTaskState(task);
|
||||
workflowTask.definition = createWorkflowTaskDefinition(task.getTask());
|
||||
workflowTask.properties = getTaskProperties(task);
|
||||
workflowTask.properties = getTaskProperties(task, false);
|
||||
workflowTask.title = getLabel(processName + ".task." + workflowTask.name, TITLE_LABEL, null);
|
||||
if (workflowTask.title == null)
|
||||
{
|
||||
|
@@ -152,6 +152,21 @@ public class JBPMEngineTest extends BaseSpringTest
|
||||
}
|
||||
|
||||
|
||||
public void testGetWorkflowInstance()
|
||||
{
|
||||
WorkflowDefinition workflowDef = getTestDefinition();
|
||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, null);
|
||||
assertNotNull(path);
|
||||
assertTrue(path.id.endsWith("-@"));
|
||||
assertNotNull(path.node);
|
||||
assertNotNull(path.instance);
|
||||
assertEquals(workflowDef.id, path.instance.definition.id);
|
||||
WorkflowInstance instance = workflowComponent.getWorkflowById(path.instance.id);
|
||||
assertNotNull(instance);
|
||||
assertEquals(path.instance.id, instance.id);
|
||||
}
|
||||
|
||||
|
||||
public void testStartWorkflowParameters()
|
||||
{
|
||||
WorkflowDefinition workflowDef = getTestDefinition();
|
||||
@@ -303,20 +318,27 @@ public class JBPMEngineTest extends BaseSpringTest
|
||||
|
||||
public void testCancelWorkflowInstance()
|
||||
{
|
||||
WorkflowDefinition workflowDef = getTestDefinition();
|
||||
WorkflowDefinition workflowDef = getTestDefinition();
|
||||
workflowComponent.startWorkflow(workflowDef.id, null);
|
||||
List<WorkflowInstance> instances1 = workflowComponent.getActiveWorkflows(workflowDef.id);
|
||||
assertNotNull(instances1);
|
||||
assertEquals(1, instances1.size());
|
||||
List<WorkflowTask> tasks = taskComponent.getAssignedTasks("admin", WorkflowTaskState.IN_PROGRESS);
|
||||
assertNotNull(tasks);
|
||||
assertTrue(tasks.size() > 0);
|
||||
WorkflowInstance cancelledInstance = workflowComponent.cancelWorkflow(instances1.get(0).id);
|
||||
assertNotNull(cancelledInstance);
|
||||
assertFalse(cancelledInstance.active);
|
||||
List<WorkflowInstance> instances2 = workflowComponent.getActiveWorkflows(workflowDef.id);
|
||||
assertNotNull(instances2);
|
||||
assertEquals(0, instances2.size());
|
||||
List<WorkflowTask> tasks1 = taskComponent.getAssignedTasks("admin", WorkflowTaskState.IN_PROGRESS);
|
||||
assertNotNull(tasks1);
|
||||
tasks1 = filterTasksByWorkflowInstance(tasks1, cancelledInstance.id);
|
||||
assertEquals(0, tasks1.size());
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void testSignal()
|
||||
{
|
||||
WorkflowDefinition workflowDef = getTestDefinition();
|
||||
@@ -335,7 +357,6 @@ public class JBPMEngineTest extends BaseSpringTest
|
||||
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "testNode"), testNodeRef);
|
||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, parameters);
|
||||
assertNotNull(path);
|
||||
assertNotNull(path);
|
||||
List<WorkflowTask> tasks = workflowComponent.getTasksForWorkflowPath(path.id);
|
||||
assertNotNull(tasks);
|
||||
assertEquals(1, tasks.size());
|
||||
@@ -361,7 +382,6 @@ public class JBPMEngineTest extends BaseSpringTest
|
||||
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "testNode"), testNodeRef);
|
||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, parameters);
|
||||
assertNotNull(path);
|
||||
assertNotNull(path);
|
||||
List<WorkflowTask> tasks1 = workflowComponent.getTasksForWorkflowPath(path.id);
|
||||
assertNotNull(tasks1);
|
||||
assertEquals(1, tasks1.size());
|
||||
|
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* 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 org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
||||
import org.alfresco.repo.transaction.TransactionListener;
|
||||
import org.alfresco.util.GUID;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jbpm.JbpmConfiguration;
|
||||
import org.jbpm.JbpmContext;
|
||||
import org.jbpm.graph.def.ProcessDefinition;
|
||||
import org.springmodules.workflow.jbpm31.JbpmTemplate;
|
||||
|
||||
|
||||
/**
|
||||
* JBPM Template that manages JBPM Context at the Alfresco Transaction level
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class JBPMTransactionTemplate extends JbpmTemplate
|
||||
implements TransactionListener
|
||||
{
|
||||
// Logging support
|
||||
private static Log logger = LogFactory.getLog("org.alfresco.repo.workflow");
|
||||
|
||||
/** Id used in equals and hash */
|
||||
private String id = GUID.generate();
|
||||
|
||||
// JBPM Template Keys
|
||||
private static final String JBPM_CONTEXT_KEY = JBPMTransactionTemplate.class.getName() + ".context";
|
||||
|
||||
/** Use local or transaction bound JBPM Context */
|
||||
private boolean localContext = true;
|
||||
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
public JBPMTransactionTemplate()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
public JBPMTransactionTemplate(JbpmConfiguration jbpmConfiguration, ProcessDefinition processDefinition)
|
||||
{
|
||||
super(jbpmConfiguration, processDefinition);
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
public JBPMTransactionTemplate(JbpmConfiguration jbpmConfiguration)
|
||||
{
|
||||
super(jbpmConfiguration);
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
JBPMTransactionTemplate.super.afterPropertiesSet();
|
||||
}
|
||||
finally
|
||||
{
|
||||
localContext = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springmodules.workflow.jbpm31.JbpmTemplate#getContext()
|
||||
*/
|
||||
@Override
|
||||
protected JbpmContext getContext()
|
||||
{
|
||||
if (localContext)
|
||||
{
|
||||
return super.getContext();
|
||||
}
|
||||
else
|
||||
{
|
||||
JbpmContext context = (JbpmContext)AlfrescoTransactionSupport.getResource(JBPM_CONTEXT_KEY);
|
||||
if (context == null)
|
||||
{
|
||||
context = super.getContext();
|
||||
AlfrescoTransactionSupport.bindResource(JBPM_CONTEXT_KEY, context);
|
||||
AlfrescoTransactionSupport.bindListener(this);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Attached JBPM Context to transaction " + AlfrescoTransactionSupport.getTransactionId());
|
||||
}
|
||||
return context;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springmodules.workflow.jbpm31.JbpmTemplate#releaseContext(org.jbpm.JbpmContext)
|
||||
*/
|
||||
@Override
|
||||
protected void releaseContext(JbpmContext jbpmContext)
|
||||
{
|
||||
if (localContext)
|
||||
{
|
||||
jbpmContext.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
// NOTE: Defer release to end of transaction
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.transaction.TransactionListener#flush()
|
||||
*/
|
||||
public void flush()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.transaction.TransactionListener#beforeCommit(boolean)
|
||||
*/
|
||||
public void beforeCommit(boolean readOnly)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.transaction.TransactionListener#beforeCompletion()
|
||||
*/
|
||||
public void beforeCompletion()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.transaction.TransactionListener#afterCommit()
|
||||
*/
|
||||
public void afterCommit()
|
||||
{
|
||||
JbpmContext context = (JbpmContext)AlfrescoTransactionSupport.getResource(JBPM_CONTEXT_KEY);
|
||||
if (context != null)
|
||||
{
|
||||
super.releaseContext(context);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Detached (commit) JBPM Context from transaction " + AlfrescoTransactionSupport.getTransactionId());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.transaction.TransactionListener#afterRollback()
|
||||
*/
|
||||
public void afterRollback()
|
||||
{
|
||||
JbpmContext context = (JbpmContext)AlfrescoTransactionSupport.getResource(JBPM_CONTEXT_KEY);
|
||||
if (context != null)
|
||||
{
|
||||
super.releaseContext(context);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Detached (rollback) JBPM Context from transaction " + AlfrescoTransactionSupport.getTransactionId());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return this.id.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof JBPMTransactionTemplate)
|
||||
{
|
||||
JBPMTransactionTemplate that = (JBPMTransactionTemplate) obj;
|
||||
return (this.id.equals(that.id));
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -69,7 +69,7 @@ public class NodeListConverterTest extends BaseSpringTest
|
||||
taskComponent = registry.getTaskComponent("jbpm");
|
||||
|
||||
// deploy latest review and approve process definition
|
||||
ClassPathResource processDef = new ClassPathResource("org/alfresco/repo/workflow/jbpm/review_and_approve_processdefinition.xml");
|
||||
ClassPathResource processDef = new ClassPathResource("alfresco/workflow/review_processdefinition.xml");
|
||||
WorkflowDeployment deployment = workflowComponent.deployDefinition(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML);
|
||||
testWorkflowDef = deployment.definition;
|
||||
assertNotNull(testWorkflowDef);
|
||||
|
@@ -69,7 +69,7 @@ public class ReviewAndApproveTest extends BaseSpringTest
|
||||
taskComponent = registry.getTaskComponent("jbpm");
|
||||
|
||||
// deploy latest review and approve process definition
|
||||
ClassPathResource processDef = new ClassPathResource("org/alfresco/repo/workflow/jbpm/review_and_approve_processdefinition.xml");
|
||||
ClassPathResource processDef = new ClassPathResource("alfresco/workflow/review_processdefinition.xml");
|
||||
WorkflowDeployment deployment = workflowComponent.deployDefinition(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML);
|
||||
testWorkflowDef = deployment.definition;
|
||||
assertNotNull(testWorkflowDef);
|
||||
@@ -97,9 +97,10 @@ public class ReviewAndApproveTest extends BaseSpringTest
|
||||
Map<QName, Serializable> params = new HashMap<QName, Serializable>();
|
||||
params.put(WorkflowModel.ASSOC_PACKAGE, testNodeRef);
|
||||
Date reviewDueDate = new Date();
|
||||
params.put(QName.createQName("http://www.alfresco.org/model/workflow/1.0", "reviewDueDate"), reviewDueDate);
|
||||
params.put(WorkflowModel.PROP_WORKFLOW_DUE_DATE, reviewDueDate);
|
||||
NodeRef reviewer = personService.getPerson("admin");
|
||||
params.put(QName.createQName("http://www.alfresco.org/model/workflow/1.0", "reviewer"), reviewer);
|
||||
params.put(WorkflowModel.ASSOC_ASSIGNEE, reviewer);
|
||||
params.put(WorkflowModel.PROP_WORKFLOW_DESCRIPTION, "Test review");
|
||||
|
||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, params);
|
||||
assertNotNull(path);
|
||||
@@ -113,6 +114,8 @@ public class ReviewAndApproveTest extends BaseSpringTest
|
||||
assertNotNull(endedTask);
|
||||
assertTrue(endedTask.properties.containsKey(WorkflowModel.PROP_OUTCOME));
|
||||
assertEquals("", endedTask.properties.get(WorkflowModel.PROP_OUTCOME));
|
||||
assertEquals("Test review", endedTask.properties.get(WorkflowModel.PROP_DESCRIPTION));
|
||||
assertEquals("Test review", endedTask.path.instance.description);
|
||||
|
||||
List<WorkflowTask> assignedTasks = taskComponent.getAssignedTasks("admin", WorkflowTaskState.IN_PROGRESS);
|
||||
assertNotNull(assignedTasks);
|
||||
@@ -134,9 +137,9 @@ public class ReviewAndApproveTest extends BaseSpringTest
|
||||
params.put(WorkflowModel.ASSOC_PACKAGE, testNodeRef);
|
||||
params.put(WorkflowModel.PROP_COMPLETED_ITEMS, (Serializable)nodeRefs);
|
||||
Date reviewDueDate = new Date();
|
||||
params.put(QName.createQName("http://www.alfresco.org/model/workflow/1.0", "reviewDueDate"), reviewDueDate);
|
||||
params.put(WorkflowModel.PROP_WORKFLOW_DUE_DATE, reviewDueDate);
|
||||
NodeRef reviewer = personService.getPerson("admin");
|
||||
params.put(QName.createQName("http://www.alfresco.org/model/workflow/1.0", "reviewer"), reviewer);
|
||||
params.put(WorkflowModel.ASSOC_ASSIGNEE, reviewer);
|
||||
|
||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, params);
|
||||
assertNotNull(path);
|
||||
|
@@ -16,7 +16,13 @@
|
||||
*/
|
||||
package org.alfresco.repo.workflow.jbpm;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.repo.workflow.WorkflowModel;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowException;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.jbpm.graph.def.Transition;
|
||||
import org.jbpm.graph.exe.ExecutionContext;
|
||||
import org.jbpm.taskmgmt.exe.TaskInstance;
|
||||
@@ -96,14 +102,30 @@ public class WorkflowTaskInstance extends TaskInstance
|
||||
@Override
|
||||
public void end(Transition transition)
|
||||
{
|
||||
// NOTE: Set the outcome first, so it's available during the submission of
|
||||
// Set task properties on completion of task
|
||||
// NOTE: Set properties first, so they're available during the submission of
|
||||
// task variables to the process context
|
||||
Map<QName, Serializable> taskProperties = new HashMap<QName, Serializable>();
|
||||
Transition outcome = (transition == null) ? token.getNode().getDefaultLeavingTransition() : transition;
|
||||
if (outcome != null)
|
||||
{
|
||||
getJBPMEngine().setTaskOutcome(this, outcome);
|
||||
taskProperties.put(WorkflowModel.PROP_OUTCOME, outcome.getName());
|
||||
}
|
||||
taskProperties.put(WorkflowModel.PROP_STATUS, "Completed");
|
||||
getJBPMEngine().setTaskProperties(this, taskProperties);
|
||||
|
||||
// perform transition
|
||||
super.end(transition);
|
||||
|
||||
if (getTask().getStartState() != null)
|
||||
{
|
||||
// if ending a start task, push start task properties to process context, if not
|
||||
// already done
|
||||
getJBPMEngine().setDefaultWorkflowProperties(this);
|
||||
|
||||
// set task description
|
||||
getJBPMEngine().setDefaultStartTaskDescription(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,57 +1,65 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<process-definition xmlns="urn:jbpm.org:jpdl-3.1" name="test_script">
|
||||
<swimlane name="initiator"></swimlane>
|
||||
<swimlane name="initiator"></swimlane>
|
||||
|
||||
<start-state name="start">
|
||||
<task name="submit" swimlane="initiator">
|
||||
<event type="task-assign">
|
||||
<start-state name="start">
|
||||
<task name="submit" swimlane="initiator">
|
||||
<event type="task-assign">
|
||||
<script>
|
||||
System.out.println("taskInstance.create: " + taskInstance.create);
|
||||
System.out.println("taskInstance.description: " + taskInstance.description);
|
||||
</script>
|
||||
</event>
|
||||
<controller>
|
||||
<variable name="testNode" access="write,required" />
|
||||
<variable name="bpm_workflowDescription" access="write" />
|
||||
</controller>
|
||||
</task>
|
||||
<transition name="" to="doit" />
|
||||
</start-state>
|
||||
|
||||
<node name="doit">
|
||||
<event type="node-enter">
|
||||
<script>
|
||||
System.out.println("taskInstance.create: " + taskInstance.create);
|
||||
<expression>
|
||||
System.out.println("testNode.created: " + testNode.properties{"cm:created"});
|
||||
System.out.println("test node " + testNode.name + " contains " + testNode.children.length + " children");
|
||||
</expression>
|
||||
<variable name="testNode" access="read" />
|
||||
</script>
|
||||
</event>
|
||||
<controller>
|
||||
<variable name="testNode" access="write,required" />
|
||||
</controller>
|
||||
</task>
|
||||
<transition name="" to="doit"/>
|
||||
</start-state>
|
||||
|
||||
<node name="doit">
|
||||
<event type="node-enter">
|
||||
<script>
|
||||
<expression>
|
||||
System.out.println("testNode.created: " + testNode.properties{"cm:created"});
|
||||
System.out.println("test node " + testNode.name + " contains " + testNode.children.length + " children");
|
||||
</expression>
|
||||
<variable name="testNode" access="read"/>
|
||||
</script>
|
||||
</event>
|
||||
<event type="node-enter">
|
||||
<action class="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript">
|
||||
<script>
|
||||
<!-- following line fails as it attempts to convert properties of children to javascript objects -->
|
||||
<!-- except the beanshell line above has already pre-created the children without the javascript scope -->
|
||||
<!-- object -->
|
||||
<!-- var result = "testNode.created: " + testNode.properties["cm:created"] + ", testNode.children.length: " + testNode.children[0].properties["cm:name"]; -->
|
||||
<expression>
|
||||
var result = "testNode.created: " + testNode.properties["cm:created"] + ", testNode.children.length: " + testNode.children.length;
|
||||
result;
|
||||
</expression>
|
||||
<variable name="testNode" access="read"/>
|
||||
<variable name="alfrescoScriptResult" access="write"/>
|
||||
</script>
|
||||
</action>
|
||||
</event>
|
||||
<transition name="" to="end"/>
|
||||
</node>
|
||||
|
||||
<end-state name="end">
|
||||
<event type="node-enter">
|
||||
<script>
|
||||
System.out.println("javascript: " + alfrescoScriptResult);
|
||||
</script>
|
||||
</event>
|
||||
</end-state>
|
||||
|
||||
</event>
|
||||
<event type="node-enter">
|
||||
<action
|
||||
class="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript">
|
||||
<script>
|
||||
<!-- following line fails as it attempts to convert properties of children to javascript objects -->
|
||||
<!-- except the beanshell line above has already pre-created the children without the javascript scope -->
|
||||
<!-- object -->
|
||||
<!-- var result = "testNode.created: " + testNode.properties["cm:created"] + ", testNode.children.length: " + testNode.children[0].properties["cm:name"]; -->
|
||||
<expression>
|
||||
var result = "testNode.created: " + theTestNode.properties["cm:created"] + ", theTestNode.children.length: " + theTestNode.children.length;
|
||||
if (logger.isLoggingEnabled())
|
||||
{
|
||||
logger.log(result);
|
||||
}
|
||||
result;
|
||||
</expression>
|
||||
<variable name="testNode" access="read" mapped-name="theTestNode" />
|
||||
<variable name="alfrescoScriptResult" access="write" />
|
||||
</script>
|
||||
</action>
|
||||
</event>
|
||||
<transition name="" to="end" />
|
||||
</node>
|
||||
|
||||
<end-state name="end">
|
||||
<event type="node-enter">
|
||||
<script>
|
||||
System.out.println("javascript: " + alfrescoScriptResult);
|
||||
System.out.println("bpm_workflowDescription: " + bpm_workflowDescription);
|
||||
</script>
|
||||
</event>
|
||||
</end-state>
|
||||
|
||||
</process-definition>
|
||||
|
Reference in New Issue
Block a user