Merged V1.4 to HEAD

svn merge svn://svn.alfresco.com:3691/alfresco/BRANCHES/V1.4@3925 svn://svn.alfresco.com:3691/alfresco/BRANCHES/V1.4@3965 .


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@3966 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2006-09-29 07:45:33 +00:00
parent d4947ef511
commit cf29ca2343
51 changed files with 2076 additions and 1985 deletions

View File

@@ -60,6 +60,7 @@ public interface WorkflowModel
// workflow package
static final QName ASPECT_WORKFLOW_PACKAGE = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowPackage");
static final QName PROP_IS_SYSTEM_PACKAGE = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "isSystemPackage");
static final QName PROP_WORKFLOW_DEFINITION_ID = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowDefinitionId");
static final QName PROP_WORKFLOW_DEFINITION_NAME = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowDefinitionName");
static final QName PROP_WORKFLOW_INSTANCE_ID = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowInstanceId");

View File

@@ -40,6 +40,16 @@ public interface WorkflowPackageComponent
*/
public NodeRef createPackage(NodeRef container);
/**
* Deletes a Workflow Package
*
* The workflow package aspect is removed, and if the container was previously created by the workflow
* service (i.e. not provided from elsewhere), it will be deleted.
*
* @param container
*/
public void deletePackage(NodeRef container);
// TODO: Further support for finding packages via meta-data of WorkflowPackage aspect
/**

View File

@@ -89,6 +89,7 @@ public class WorkflowPackageImpl implements WorkflowPackageComponent
public NodeRef createPackage(NodeRef container)
{
// create a container, if one is not specified
boolean isSystemPackage = false;
if (container == null)
{
// create simple folder in workflow system folder
@@ -112,6 +113,7 @@ public class WorkflowPackageImpl implements WorkflowPackageComponent
QName qname = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, containerName);
ChildAssociationRef childRef = nodeService.createNode(packages, ContentModel.ASSOC_CONTAINS, qname, ContentModel.TYPE_SYSTEM_FOLDER);
container = childRef.getChildRef();
isSystemPackage = true;
}
// attach workflow package
@@ -120,11 +122,31 @@ public class WorkflowPackageImpl implements WorkflowPackageComponent
throw new WorkflowException("Container '" + container + "' is already a workflow package.");
}
nodeService.addAspect(container, WorkflowModel.ASPECT_WORKFLOW_PACKAGE, null);
nodeService.setProperty(container, WorkflowModel.PROP_IS_SYSTEM_PACKAGE, isSystemPackage);
// return container
return container;
}
/* (non-Javadoc)
* @see org.alfresco.repo.workflow.WorkflowPackageComponent#deletePackage(org.alfresco.service.cmr.repository.NodeRef)
*/
public void deletePackage(NodeRef container)
{
if (container != null && nodeService.exists(container) && nodeService.hasAspect(container, WorkflowModel.ASPECT_WORKFLOW_PACKAGE))
{
Boolean isSystemPackage = (Boolean)nodeService.getProperty(container, WorkflowModel.PROP_IS_SYSTEM_PACKAGE);
if (isSystemPackage != null && isSystemPackage.booleanValue())
{
nodeService.deleteNode(container);
}
else
{
nodeService.removeAspect(container, WorkflowModel.ASPECT_WORKFLOW_PACKAGE);
}
}
}
/* (non-Javadoc)
* @see org.alfresco.repo.workflow.WorkflowPackageComponent#getWorkflowIdsForContent(org.alfresco.service.cmr.repository.NodeRef, boolean)
*/
@@ -150,7 +172,6 @@ public class WorkflowPackageImpl implements WorkflowPackageComponent
}
return workflowIds;
}
/**
* Gets the system workflow container for storing workflow related items
@@ -170,7 +191,6 @@ public class WorkflowPackageImpl implements WorkflowPackageComponent
}
return systemWorkflowContainer;
}
/**
* Finds the system workflow container
@@ -193,7 +213,6 @@ public class WorkflowPackageImpl implements WorkflowPackageComponent
return systemWorkflowContainer;
}
/**
* Finds the system container
*
@@ -214,7 +233,6 @@ public class WorkflowPackageImpl implements WorkflowPackageComponent
}
return nodeRefs.get(0);
}
/**
* Creates the System Workflow Container

View File

@@ -210,6 +210,8 @@ public class WorkflowServiceImpl implements WorkflowService
*/
public WorkflowInstance cancelWorkflow(String workflowId)
{
WorkflowInstance instance = getWorkflowById(workflowId);
workflowPackageComponent.deletePackage(instance.workflowPackage);
String engineId = BPMEngineRegistry.getEngineId(workflowId);
WorkflowComponent component = getWorkflowComponent(engineId);
return component.cancelWorkflow(workflowId);
@@ -319,7 +321,7 @@ public class WorkflowServiceImpl implements WorkflowService
String engineId = BPMEngineRegistry.getEngineId(workflowId);
WorkflowComponent component = getWorkflowComponent(engineId);
WorkflowInstance instance = component.getWorkflowById(workflowId);
if (instance.active == active)
if (instance != null && instance.active == active)
{
workflowInstances.add(instance);
}

View File

@@ -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();
}
}
}

View File

@@ -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;
@@ -67,7 +68,6 @@ import org.hibernate.proxy.HibernateProxy;
import org.jbpm.JbpmContext;
import org.jbpm.JbpmException;
import org.jbpm.context.exe.ContextInstance;
import org.jbpm.context.exe.TokenVariableMap;
import org.jbpm.db.GraphSession;
import org.jbpm.db.TaskMgmtSession;
import org.jbpm.graph.def.Node;
@@ -260,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
@@ -332,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);
}
});
}
@@ -342,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...
@@ -367,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
@@ -399,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)
*/
@@ -447,7 +463,7 @@ public class JBPMEngine extends BPMEngine
// retrieve workflow
GraphSession graphSession = context.getGraphSession();
ProcessInstance processInstance = graphSession.getProcessInstance(getJbpmId(workflowId));
return createWorkflowInstance(processInstance);
return processInstance == null ? null : createWorkflowInstance(processInstance);
}
});
}
@@ -457,6 +473,22 @@ public class JBPMEngine extends BPMEngine
}
}
/**
* 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)
*/
@@ -471,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();
@@ -509,37 +541,10 @@ public class JBPMEngine extends BPMEngine
{
// retrieve and cancel process instance
GraphSession graphSession = context.getGraphSession();
ProcessInstance processInstance = graphSession.loadProcessInstance(getJbpmId(workflowId));
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);
//
// TODO: remove - workaround for JBPM variable mapping constraint exception
//
Collection<TaskInstance> tasks = processInstance.getTaskMgmtInstance().getTaskInstances();
for (TaskInstance task : tasks)
{
Map<String, Serializable> taskVariables = task.getVariablesLocally();
for (String varName : taskVariables.keySet())
{
task.deleteVariableLocally(varName);
}
}
ContextInstance processContext = processInstance.getContextInstance();
Map<Token, TokenVariableMap> tokenVarMaps = processContext.getTokenVariableMaps();
for (Map.Entry<Token, TokenVariableMap> mapEntry : tokenVarMaps.entrySet())
{
TokenVariableMap tokenVarMap = mapEntry.getValue();
Map<String, Serializable> variables = tokenVarMap.getVariables();
for (String name : variables.keySet())
{
tokenVarMap.deleteVariable(name);
}
}
//
// end TODO
//
// delete the process instance
graphSession.deleteProcessInstance(processInstance, true, true, true);
@@ -738,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)
*/
@@ -751,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;
@@ -871,13 +892,8 @@ public class JBPMEngine extends BPMEngine
{
// retrieve task
TaskMgmtSession taskSession = context.getTaskMgmtSession();
TaskInstance taskInstance = taskSession.loadTaskInstance(getJbpmId(taskId));
TaskInstance taskInstance = getTaskInstance(taskSession, taskId);
// set status to complete
Map<QName, Serializable> taskProperties = new HashMap<QName, Serializable>();
taskProperties.put(WorkflowModel.PROP_STATUS, "Completed");
setTaskProperties(taskInstance, taskProperties);
// signal the transition on the task
if (transition == null)
{
@@ -922,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);
}
});
}
@@ -1134,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)
@@ -1166,8 +1182,7 @@ public class JBPMEngine extends BPMEngine
for (Entry<String, Object> entry : vars.entrySet())
{
String key = entry.getKey();
String name = key.replace("_", ":");
QName qname = QName.createQName(name, this.namespaceService);
QName qname = mapNameToQName(key);
// add variable, only if part of task definition or locally defined on task
if (taskProperties.containsKey(qname) || taskAssocs.containsKey(qname) || instance.hasVariableLocally(key))
@@ -1356,8 +1371,7 @@ public class JBPMEngine extends BPMEngine
else if (key.equals(WorkflowModel.ASSOC_PACKAGE))
{
// Attach workflow definition & instance id to Workflow Package in Repository
String name = key.toPrefixString(this.namespaceService);
name = name.replace(':', '_');
String name = mapQNameToName(key);
JBPMNode existingWorkflowPackage = (JBPMNode)instance.getVariable(name);
// first check if provided workflow package has already been associated with another workflow instance
@@ -1401,8 +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);
name = name.replace(':', '_');
String name = mapQNameToName(key);
instance.setVariableLocally(name, value);
}
}
@@ -1414,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
@@ -1427,10 +1440,6 @@ public class JBPMEngine extends BPMEngine
String defaultValue = entry.getValue().getDefaultValue();
if (defaultValue != null)
{
if (existingValues == null)
{
existingValues = getTaskProperties(instance, true);
}
if (existingValues.get(entry.getKey()) == null)
{
defaultValues.put(entry.getKey(), defaultValue);
@@ -1442,7 +1451,7 @@ public class JBPMEngine extends BPMEngine
String description = (String)existingValues.get(WorkflowModel.PROP_DESCRIPTION);
if (description == null || description.length() == 0)
{
description = (String)instance.getContextInstance().getVariable("bpm_workflowDescription");
description = (String)instance.getContextInstance().getVariable(mapQNameToName(WorkflowModel.PROP_WORKFLOW_DESCRIPTION));
if (description != null && description.length() > 0)
{
defaultValues.put(WorkflowModel.PROP_DESCRIPTION, description);
@@ -1453,7 +1462,7 @@ public class JBPMEngine extends BPMEngine
defaultValues.put(WorkflowModel.PROP_DESCRIPTION, task.title);
}
}
// assign the default values to the task
if (defaultValues.size() > 0)
{
@@ -1462,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));
}
}
/**
@@ -1538,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
*
@@ -1651,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");
@@ -1658,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;

View File

@@ -100,6 +100,7 @@ public class ReviewAndApproveTest extends BaseSpringTest
params.put(WorkflowModel.PROP_WORKFLOW_DUE_DATE, reviewDueDate);
NodeRef reviewer = personService.getPerson("admin");
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);

View File

@@ -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);
}
}
}

View File

@@ -57,7 +57,7 @@
<event type="node-enter">
<script>
System.out.println("javascript: " + alfrescoScriptResult);
System.out.println("bpm_workflowDescription: " + bpm_description);
System.out.println("bpm_workflowDescription: " + bpm_workflowDescription);
</script>
</event>
</end-state>