Merge V1.4 to HEAD

- Ignored Enterprise-specific changes
   svn merge svn://svn.alfresco.com:3691/alfresco/BRANCHES/V1.4@3701 svn://svn.alfresco.com:3691/alfresco/BRANCHES/V1.4@3703 .
   svn merge svn://svn.alfresco.com:3691/alfresco/BRANCHES/V1.4@3704 svn://svn.alfresco.com:3691/alfresco/BRANCHES/V1.4@3705 .
   svn merge svn://svn.alfresco.com:3691/alfresco/BRANCHES/V1.4@3707 svn://svn.alfresco.com:3691/alfresco/BRANCHES/V1.4@3876 .
   svn revert root\projects\web-client\source\web\jsp\admin\admin-console.jsp


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@3879 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2006-09-21 23:35:51 +00:00
parent 89f39cd176
commit d2bce74f0b
103 changed files with 3569 additions and 1172 deletions

View File

@@ -31,20 +31,24 @@ import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
import org.alfresco.service.cmr.workflow.WorkflowPath;
import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.service.cmr.workflow.WorkflowTask;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
/**
* Simple workflow action executor
*
* @author Roy Wetherall
* @author David Caruana
*/
public class StartWorkflowActionExecuter extends ActionExecuterAbstractBase
{
public static final String NAME = "start-workflow";
public static final String PARAM_WORKFLOW_NAME = "workflowName";
public static final String PARAM_END_START_TASK = "endStartTask";
public static final String PARAM_START_TASK_TRANSITION = "startTaskTransition";
// action dependencies
private NamespaceService namespaceService;
@@ -94,7 +98,9 @@ public class StartWorkflowActionExecuter extends ActionExecuterAbstractBase
protected void addParameterDefinitions(List<ParameterDefinition> paramList)
{
paramList.add(new ParameterDefinitionImpl(PARAM_WORKFLOW_NAME, DataTypeDefinition.TEXT, false, getParamDisplayLabel(PARAM_WORKFLOW_NAME)));
// TODO: Start Task Template parameter
paramList.add(new ParameterDefinitionImpl(PARAM_END_START_TASK, DataTypeDefinition.BOOLEAN, false, getParamDisplayLabel(PARAM_END_START_TASK)));
paramList.add(new ParameterDefinitionImpl(PARAM_START_TASK_TRANSITION, DataTypeDefinition.TEXT, false, getParamDisplayLabel(PARAM_START_TASK_TRANSITION)));
// TODO: start task node parameter
}
@@ -127,9 +133,31 @@ public class StartWorkflowActionExecuter extends ActionExecuterAbstractBase
workflowParameters.put(qname, value);
}
}
// provide a default context, if one is not specified
Serializable context = workflowParameters.get(WorkflowModel.PROP_CONTEXT);
if (context == null)
{
workflowParameters.put(WorkflowModel.PROP_CONTEXT, childAssoc.getParentRef());
}
// start the workflow
workflowService.startWorkflow(def.id, workflowParameters);
WorkflowPath path = workflowService.startWorkflow(def.id, workflowParameters);
// determine whether to auto-end the start task
Boolean endStartTask = (Boolean)ruleAction.getParameterValue(PARAM_END_START_TASK);
String startTaskTransition = (String)ruleAction.getParameterValue(PARAM_START_TASK_TRANSITION);
endStartTask = (endStartTask == null) ? true : false;
startTaskTransition = (startTaskTransition == null) ? "" : startTaskTransition;
// auto-end the start task with the provided transition (if one)
if (endStartTask)
{
List<WorkflowTask> tasks = workflowService.getTasksForWorkflowPath(path.id);
for (WorkflowTask task : tasks)
{
workflowService.endTask(task.id, startTaskTransition);
}
}
}
}

View File

@@ -31,9 +31,9 @@ import org.alfresco.util.BaseSpringTest;
import org.alfresco.util.GUID;
/**
* Add features action execution test
* Start Advanced Workflow action execution test
*
* @author Roy Wetherall
* @author David Caruana
*/
public class StartWorkflowActionExecuterTest extends BaseSpringTest
{
@@ -78,9 +78,10 @@ public class StartWorkflowActionExecuterTest extends BaseSpringTest
// Execute the action
ActionImpl action = new ActionImpl(null, GUID.generate(), StartWorkflowActionExecuter.NAME, null);
action.setParameterValue(StartWorkflowActionExecuter.PARAM_WORKFLOW_NAME, "jbpm$wf:review");
action.setParameterValue(WorkflowModel.PROP_REVIEW_DUE_DATE.toPrefixString(namespaceService), new Date());
action.setParameterValue(WorkflowModel.PROP_WORKFLOW_DUE_DATE.toPrefixString(namespaceService), new Date());
NodeRef reviewer = personService.getPerson("admin");
action.setParameterValue(WorkflowModel.ASSOC_REVIEWER.toPrefixString(namespaceService), reviewer);
action.setParameterValue(WorkflowModel.ASSOC_ASSIGNEE.toPrefixString(namespaceService), reviewer);
executer.execute(action, this.nodeRef);
}
}

View File

@@ -118,6 +118,14 @@ public interface WorkflowComponent
*/
public List<WorkflowInstance> getActiveWorkflows(String workflowDefinitionId);
/**
* Gets a specific workflow instances
*
* @param workflowId the id of the workflow to retrieve
* @return the workflow instance
*/
public WorkflowInstance getWorkflowById(String workflowId);
/**
* Gets all Paths for the specified Workflow instance
*

View File

@@ -16,12 +16,15 @@
*/
package org.alfresco.repo.workflow;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import javax.transaction.UserTransaction;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.dictionary.DictionaryBootstrap;
import org.alfresco.repo.dictionary.DictionaryDAO;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.service.cmr.view.ImporterException;
import org.alfresco.service.cmr.workflow.WorkflowDeployment;
@@ -56,7 +59,10 @@ public class WorkflowDeployer implements ApplicationListener
private TransactionService transactionService;
private WorkflowService workflowService;
private AuthenticationComponent authenticationComponent;
private DictionaryDAO dictionaryDAO;
private List<Properties> workflowDefinitions;
private List<String> models = new ArrayList<String>();
private List<String> resourceBundles = new ArrayList<String>();
/**
@@ -89,6 +95,16 @@ public class WorkflowDeployer implements ApplicationListener
this.authenticationComponent = authenticationComponent;
}
/**
* Sets the Dictionary DAO
*
* @param dictionaryDAO
*/
public void setDictionaryDAO(DictionaryDAO dictionaryDAO)
{
this.dictionaryDAO = dictionaryDAO;
}
/**
* Sets the Workflow Definitions
*
@@ -99,6 +115,26 @@ public class WorkflowDeployer implements ApplicationListener
this.workflowDefinitions = workflowDefinitions;
}
/**
* Sets the initial list of Workflow models to bootstrap with
*
* @param modelResources the model names
*/
public void setModels(List<String> modelResources)
{
this.models = modelResources;
}
/**
* Sets the initial list of Workflow reosurce bundles to bootstrap with
*
* @param modelResources the model names
*/
public void setLabels(List<String> labels)
{
this.resourceBundles = labels;
}
/**
* Deploy the Workflow Definitions
*/
@@ -124,6 +160,16 @@ public class WorkflowDeployer implements ApplicationListener
{
userTransaction.begin();
// bootstrap the workflow models and labels
if (models != null && resourceBundles != null)
{
DictionaryBootstrap dictionaryBootstrap = new DictionaryBootstrap();
dictionaryBootstrap.setDictionaryDAO(dictionaryDAO);
dictionaryBootstrap.setModels(models);
dictionaryBootstrap.setLabels(resourceBundles);
dictionaryBootstrap.bootstrap();
}
// bootstrap the workflow definitions
if (workflowDefinitions != null)
{

View File

@@ -45,26 +45,23 @@ public interface WorkflowModel
// workflow task contstants
static final QName TYPE_WORKFLOW_TASK = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowTask");
static final QName PROP_CONTEXT = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "context");
static final QName PROP_DESCRIPTION = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "description");
static final QName PROP_OUTCOME = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "outcome");
static final QName PROP_PACKAGE_ACTION_GROUP = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "packageActionGroup");
static final QName PROP_PACKAGE_ITEM_ACTION_GROUP = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "packageItemActionGroup");
static final QName ASSOC_PACKAGE = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "package");
// workflow task contstants
static final QName TYPE_START_TASK = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "startTask");
static final QName PROP_WORKFLOW_DESCRIPTION = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowDescription");
static final QName PROP_WORKFLOW_PRIORITY = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowPriority");
static final QName PROP_WORKFLOW_DUE_DATE = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowDueDate");
static final QName ASSOC_ASSIGNEE = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "assignee");
// workflow package
static final QName ASPECT_WORKFLOW_PACKAGE = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowPackage");
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");
//
// Workflow Models
//
// review & approve
static final QName TYPE_SUBMITREVIEW_TASK = QName.createQName(NamespaceService.WORKFLOW_MODEL_1_0_URI, "submitReviewTask");
static final QName PROP_REVIEW_PRIORITY = QName.createQName(NamespaceService.WORKFLOW_MODEL_1_0_URI, "reviewPriority");
static final QName PROP_REVIEW_DUE_DATE = QName.createQName(NamespaceService.WORKFLOW_MODEL_1_0_URI, "reviewDueDate");
static final QName ASSOC_REVIEWER = QName.createQName(NamespaceService.WORKFLOW_MODEL_1_0_URI, "reviewer");
}

View File

@@ -16,6 +16,8 @@
*/
package org.alfresco.repo.workflow;
import java.util.List;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -38,6 +40,14 @@ public interface WorkflowPackageComponent
*/
public NodeRef createPackage(NodeRef container);
// TODO: Support for finding packages via meta-data of WorkflowPackage aspect
// TODO: Further support for finding packages via meta-data of WorkflowPackage aspect
/**
* Gets the Workflows that act upon the specified Repository content.
*
* @param packageItem the repository content item to get workflows for
* @return list of workflows which act upon the specified content
*/
public List<String> getWorkflowIdsForContent(NodeRef packageItem);
}

View File

@@ -21,8 +21,6 @@ import java.util.List;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.importer.ImporterBootstrap;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
@@ -31,6 +29,7 @@ import org.alfresco.service.cmr.workflow.WorkflowException;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.GUID;
import org.alfresco.util.ParameterCheck;
/**
@@ -41,14 +40,13 @@ import org.alfresco.util.GUID;
*/
public class WorkflowPackageImpl implements WorkflowPackageComponent
{
private final static String PACKAGE_FOLDER = "Workflow Packages";
private final static String PACKAGE_FOLDER = "packages";
// service dependencies
private ImporterBootstrap bootstrap;
private SearchService searchService;
private NodeService nodeService;
private NamespaceService namespaceService;
private FileFolderService fileFolderService;
private NodeRef systemWorkflowContainer = null;
@@ -60,14 +58,6 @@ public class WorkflowPackageImpl implements WorkflowPackageComponent
this.bootstrap = bootstrap;
}
/**
* @param fileFolderService file folder service
*/
public void setFileFolderService(FileFolderService fileFolderService)
{
this.fileFolderService = fileFolderService;
}
/**
* @param searchService search service
*/
@@ -105,11 +95,23 @@ public class WorkflowPackageImpl implements WorkflowPackageComponent
NodeRef system = getSystemWorkflowContainer();
// TODO: Consider structuring this folder, if number of children becomes an issue
List<String> folders = new ArrayList<String>();
folders.add(PACKAGE_FOLDER);
folders.add(GUID.generate());
FileInfo containerFolder = fileFolderService.makeFolders(system, folders, ContentModel.TYPE_FOLDER);
container = containerFolder.getNodeRef();
NodeRef packages = null;
List<NodeRef> results = searchService.selectNodes(system, "./" + NamespaceService.CONTENT_MODEL_PREFIX + ":" + PACKAGE_FOLDER, null, namespaceService, false);
if (results.size() > 0)
{
packages = results.get(0);
}
else
{
QName qname = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, PACKAGE_FOLDER);
ChildAssociationRef childRef = nodeService.createNode(system, ContentModel.ASSOC_CHILDREN, qname, ContentModel.TYPE_SYSTEM_FOLDER);
packages = childRef.getChildRef();
}
String containerName = "pkg_" + GUID.generate();
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();
}
// attach workflow package
@@ -123,6 +125,32 @@ public class WorkflowPackageImpl implements WorkflowPackageComponent
return container;
}
/* (non-Javadoc)
* @see org.alfresco.repo.workflow.WorkflowPackageComponent#getWorkflowIdsForContent(org.alfresco.service.cmr.repository.NodeRef, boolean)
*/
public List<String> getWorkflowIdsForContent(NodeRef packageItem)
{
ParameterCheck.mandatory("packageItem", packageItem);
List<String> workflowIds = new ArrayList<String>();
if (nodeService.exists(packageItem))
{
List<ChildAssociationRef> packageItemParents = nodeService.getParentAssocs(packageItem);
for (ChildAssociationRef packageItemParent : packageItemParents)
{
NodeRef parentRef = packageItemParent.getParentRef();
if (nodeService.hasAspect(parentRef, WorkflowModel.ASPECT_WORKFLOW_PACKAGE))
{
String workflowInstance = (String)nodeService.getProperty(parentRef, WorkflowModel.PROP_WORKFLOW_INSTANCE_ID);
if (workflowInstance != null && workflowInstance.length() > 0)
{
workflowIds.add(workflowInstance);
}
}
}
}
return workflowIds;
}
/**
* Gets the system workflow container for storing workflow related items
@@ -201,10 +229,10 @@ public class WorkflowPackageImpl implements WorkflowPackageComponent
{
String name = bootstrap.getConfiguration().getProperty("system.workflow_container.childname");
QName qname = QName.createQName(name, namespaceService);
ChildAssociationRef childRef = nodeService.createNode(systemContainer, ContentModel.ASSOC_CHILDREN, qname, ContentModel.TYPE_FOLDER);
ChildAssociationRef childRef = nodeService.createNode(systemContainer, ContentModel.ASSOC_CHILDREN, qname, ContentModel.TYPE_CONTAINER);
systemWorkflowContainer = childRef.getChildRef();
}
return systemWorkflowContainer;
}
}

View File

@@ -185,6 +185,16 @@ public class WorkflowServiceImpl implements WorkflowService
return component.getActiveWorkflows(workflowDefinitionId);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.workflow.WorkflowService#getWorkflowById(java.lang.String)
*/
public WorkflowInstance getWorkflowById(String workflowId)
{
String engineId = BPMEngineRegistry.getEngineId(workflowId);
WorkflowComponent component = getWorkflowComponent(engineId);
return component.getWorkflowById(workflowId);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.workflow.WorkflowService#getWorkflowPaths(java.lang.String)
*/
@@ -296,6 +306,27 @@ public class WorkflowServiceImpl implements WorkflowService
{
return workflowPackageComponent.createPackage(container);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.workflow.WorkflowService#getWorkflowsForContent(org.alfresco.service.cmr.repository.NodeRef, boolean)
*/
public List<WorkflowInstance> getWorkflowsForContent(NodeRef packageItem, boolean active)
{
List<String> workflowIds = workflowPackageComponent.getWorkflowIdsForContent(packageItem);
List<WorkflowInstance> workflowInstances = new ArrayList<WorkflowInstance>(workflowIds.size());
for (String workflowId : workflowIds)
{
String engineId = BPMEngineRegistry.getEngineId(workflowId);
WorkflowComponent component = getWorkflowComponent(engineId);
WorkflowInstance instance = component.getWorkflowById(workflowId);
if (instance.active == active)
{
workflowInstances.add(instance);
}
}
return workflowInstances;
}
/**
* Gets the Workflow Component registered against the specified BPM Engine Id

View File

@@ -16,15 +16,24 @@
*/
package org.alfresco.repo.workflow;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
import org.alfresco.service.cmr.workflow.WorkflowInstance;
import org.alfresco.service.cmr.workflow.WorkflowPath;
import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.BaseSpringTest;
@@ -43,7 +52,7 @@ public class WorkflowServiceImplTest extends BaseSpringTest
{
workflowService = (WorkflowService)applicationContext.getBean(ServiceRegistry.WORKFLOW_SERVICE.getLocalName());
nodeService = (NodeService)applicationContext.getBean(ServiceRegistry.NODE_SERVICE.getLocalName());
// authenticate
AuthenticationComponent auth = (AuthenticationComponent) applicationContext.getBean("authenticationComponent");
auth.setSystemUserAsCurrentUser();
@@ -77,4 +86,44 @@ public class WorkflowServiceImplTest extends BaseSpringTest
assertTrue(nodeService.hasAspect(nodeRef, WorkflowModel.ASPECT_WORKFLOW_PACKAGE));
}
public void testAssociateWorkflowPackage()
{
// create workflow package
NodeRef rootRef = nodeService.getRootNode(new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "spacesStore"));
NodeRef nodeRef = workflowService.createPackage(null);
assertNotNull(nodeRef);
assertTrue(nodeService.hasAspect(nodeRef, WorkflowModel.ASPECT_WORKFLOW_PACKAGE));
ChildAssociationRef childAssoc = nodeService.createNode(rootRef, ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_PREFIX, "test"), ContentModel.TYPE_CONTENT, null);
nodeService.addChild(nodeRef, childAssoc.getChildRef(), ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_PREFIX, "test"));
// start workflow
List<WorkflowDefinition> workflowDefs = workflowService.getDefinitions();
assertNotNull(workflowDefs);
assertTrue(workflowDefs.size() > 0);
WorkflowDefinition workflowDef = workflowDefs.get(0);
Map<QName, Serializable> parameters = new HashMap<QName, Serializable>();
parameters.put(WorkflowModel.ASSOC_PACKAGE, nodeRef);
WorkflowPath path = workflowService.startWorkflow(workflowDef.id, parameters);
assertNotNull(path);
assertTrue(path.active);
assertNotNull(path.node);
assertNotNull(path.instance);
assertEquals(workflowDef.id, path.instance.definition.id);
String workflowDefId = (String)nodeService.getProperty(nodeRef, WorkflowModel.PROP_WORKFLOW_DEFINITION_ID);
assertEquals(workflowDefId, workflowDef.id);
String workflowDefName = (String)nodeService.getProperty(nodeRef, WorkflowModel.PROP_WORKFLOW_DEFINITION_NAME);
assertEquals(workflowDefName, workflowDef.name);
String workflowInstanceId = (String)nodeService.getProperty(nodeRef, WorkflowModel.PROP_WORKFLOW_INSTANCE_ID);
assertEquals(workflowInstanceId, path.instance.id);
// get workflows for content
List<WorkflowInstance> instances = workflowService.getWorkflowsForContent(childAssoc.getChildRef(), true);
assertNotNull(instances);
assertEquals(1, instances.size());
assertEquals(instances.get(0).id, path.instance.id);
List<WorkflowInstance> completedInstances = workflowService.getWorkflowsForContent(childAssoc.getChildRef(), false);
assertNotNull(completedInstances);
assertEquals(0, completedInstances.size());
}
}

View File

@@ -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

View File

@@ -67,6 +67,7 @@ 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;
@@ -432,6 +433,30 @@ 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 createWorkflowInstance(processInstance);
}
});
}
catch(JbpmException e)
{
throw new WorkflowException("Failed to retrieve workflow instance '" + workflowId + "'", e);
}
}
/* (non-Javadoc)
* @see org.alfresco.repo.workflow.WorkflowComponent#getWorkflowPaths(java.lang.String)
*/
@@ -479,16 +504,48 @@ 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();
// 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);
// save the process instance along with the task instance
context.save(processInstance);
return 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);
workflowInstance.active = false;
workflowInstance.endDate = new Date();
return workflowInstance;
}
});
}
@@ -705,7 +762,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)
{
@@ -815,6 +872,11 @@ public class JBPMEngine extends BPMEngine
// retrieve task
TaskMgmtSession taskSession = context.getTaskMgmtSession();
TaskInstance taskInstance = taskSession.loadTaskInstance(getJbpmId(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)
@@ -992,7 +1054,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 + "'");
@@ -1090,43 +1152,56 @@ 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();
String name = key.replace("_", ":");
QName qname = QName.createQName(name, this.namespaceService);
//
// 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 +1282,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 +1353,40 @@ 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 = key.toPrefixString(this.namespaceService);
name = name.replace(':', '_');
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
@@ -1284,6 +1402,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(':', '_');
instance.setVariableLocally(name, value);
}
}
@@ -1310,7 +1429,7 @@ public class JBPMEngine extends BPMEngine
{
if (existingValues == null)
{
existingValues = getTaskProperties(instance);
existingValues = getTaskProperties(instance, true);
}
if (existingValues.get(entry.getKey()) == null)
{
@@ -1319,6 +1438,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("bpm_workflowDescription");
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)
{
@@ -1566,7 +1701,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)
{

View File

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

View File

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

View File

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

View File

@@ -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,9 @@ 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);
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.id, params);
assertNotNull(path);
@@ -134,9 +134,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);

View File

@@ -1,70 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<process-definition xmlns="urn:jbpm.org:jpdl-3.1" name="wf:adhoc">
<swimlane name="initiator"/>
<start-state name="start">
<task name="wf:submitAdhocTask" swimlane="initiator">
<controller>
<variable name="assignee" access="write" mapped-name="wf:assignee"/>
<variable name="adhocduedate" access="write" mapped-name="wf:adhocDueDate"/>
<variable name="adhocpriority" access="write" mapped-name="wf:adhocPriority"/>
<variable name="adhocdescription" access="write" mapped-name="wf:adhocDescription"/>
<variable name="notify" access="write" mapped-name="wf:notifyMe"/>
<variable name="workflowpackage" access="write" mapped-name="bpm:package"/>
<variable name="workflowcontext" access="write" mapped-name="bpm:context"/>
</controller>
</task>
<transition name="" to="adhoc"/>
</start-state>
<swimlane name="assignee">
<assignment actor-id="#{assignee.properties['cm:userName']}"/>
</swimlane>
<task-node name="adhoc">
<event type="task-create">
<script>
taskInstance.dueDate = adhocduedate;
taskInstance.priority = adhocpriority;
</script>
</event>
<task name="wf:adhocTask" swimlane="assignee">
<controller>
<variable name="adhocdescription" access="read" mapped-name="wf:adhocDescription"/>
<variable name="workflowpackage" access="read" mapped-name="bpm:package"/>
<variable name="workflowcontext" access="read" mapped-name="bpm:context"/>
</controller>
</task>
<transition name="" to="completed">
<action class="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript">
<script>
if (notify)
{
var mail = actions.create("mail");
mail.parameters.to = initiator.properties["cm:email"];
mail.parameters.subject = "Adhoc Task " + adhocdescription;
mail.parameters.from = assignee.properties["cm:email"];
mail.parameters.text = "It's done";
mail.execute(workflowpackage);
}
</script>
</action>
</transition>
</task-node>
<task-node name="completed">
<task name="wf:completedAdhocTask" swimlane="initiator">
<controller>
<variable name="adhocdescription" access="read" mapped-name="wf:adhocDescription"/>
<variable name="workflowpackage" access="read" mapped-name="bpm:package"/>
<variable name="workflowcontext" access="read" mapped-name="bpm:context"/>
</controller>
</task>
<transition name="" to="end"/>
</task-node>
<end-state name="end"/>
</process-definition>

View File

@@ -1,63 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<process-definition xmlns="urn:jbpm.org:jpdl-3.1" name="wf:review">
<swimlane name="initiator"/>
<start-state name="start">
<task name="wf:submitReviewTask" swimlane="initiator">
<controller>
<variable name="reviewer" access="write" mapped-name="wf:reviewer"/>
<variable name="reviewduedate" access="write" mapped-name="wf:reviewDueDate"/>
<variable name="reviewpriority" access="write" mapped-name="wf:reviewPriority"/>
<variable name="package" access="write" mapped-name="bpm:package"/>
<variable name="context" access="write" mapped-name="bpm:context"/>
</controller>
</task>
<transition name="" to="review"/>
</start-state>
<swimlane name="reviewer">
<assignment actor-id="#{reviewer.properties['cm:userName']}"/>
</swimlane>
<task-node name="review">
<task name="wf:reviewTask" swimlane="reviewer">
<event type="task-create">
<script>
taskInstance.dueDate = reviewduedate;
taskInstance.priority = reviewpriority;
</script>
</event>
<controller>
<variable name="package" access="read,required" mapped-name="bpm:package"/>
<variable name="context" access="read,required" mapped-name="bpm:context"/>
</controller>
</task>
<transition name="reject" to="rejected"/>
<transition name="approve" to="approved"/>
</task-node>
<task-node name="rejected">
<task name="wf:rejectedTask" swimlane="initiator">
<controller>
<variable name="package" access="read,required" mapped-name="bpm:package"/>
<variable name="context" access="read,required" mapped-name="bpm:context"/>
</controller>
</task>
<transition name="" to="end"/>
</task-node>
<task-node name="approved">
<task name="wf:approvedTask" swimlane="initiator">
<controller>
<variable name="package" access="read,required" mapped-name="bpm:package"/>
<variable name="context" access="read,required" mapped-name="bpm:context"/>
</controller>
</task>
<transition name="" to="end"/>
</task-node>
<end-state name="end"/>
</process-definition>

View File

@@ -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_description);
</script>
</event>
</end-state>
</process-definition>