mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
ALF-10197, Added the ability to auto-complete Start Tasks in Activiti. If a start task extends the bpm:activitiStartTask type or implements the bpm:endAutomatically aspect then the task will be ended as soon as the workflow instance is started.
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@30750 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -335,6 +335,18 @@
|
|||||||
|
|
||||||
</type>
|
</type>
|
||||||
|
|
||||||
|
<!-- -->
|
||||||
|
<!-- Default Activiti Start Task -->
|
||||||
|
<!-- Ends automatically when workflow starts -->
|
||||||
|
<!-- -->
|
||||||
|
|
||||||
|
<type name="bpm:activitiStartTask">
|
||||||
|
<parent>bpm:startTask</parent>
|
||||||
|
<mandatory-aspects>
|
||||||
|
<aspect>bpm:endAutomatically</aspect>
|
||||||
|
</mandatory-aspects>
|
||||||
|
</type>
|
||||||
|
|
||||||
<!-- -->
|
<!-- -->
|
||||||
<!-- Workflow Definition -->
|
<!-- Workflow Definition -->
|
||||||
<!-- -->
|
<!-- -->
|
||||||
@@ -490,6 +502,11 @@
|
|||||||
|
|
||||||
</aspect>
|
</aspect>
|
||||||
|
|
||||||
</aspects>
|
<!-- -->
|
||||||
|
<!-- Amy start task implementing this marker aspect is automatically ended as soon as the workflow starts -->
|
||||||
|
<!-- Note this only applies to the Activiti Workflow Engine -->
|
||||||
|
<!-- -->
|
||||||
|
|
||||||
|
<aspect name="bpm:endAutomatically" />
|
||||||
|
</aspects>
|
||||||
</model>
|
</model>
|
@@ -24,6 +24,7 @@ import org.alfresco.repo.tenant.TenantService;
|
|||||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||||
import org.alfresco.service.cmr.workflow.WorkflowException;
|
import org.alfresco.service.cmr.workflow.WorkflowException;
|
||||||
import org.alfresco.service.namespace.NamespaceService;
|
import org.alfresco.service.namespace.NamespaceService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Nick Smith
|
* @author Nick Smith
|
||||||
@@ -58,7 +59,8 @@ public abstract class AlfrescoBpmEngine extends BPMEngine
|
|||||||
throw new WorkflowException("NamespaceService not specified");
|
throw new WorkflowException("NamespaceService not specified");
|
||||||
}
|
}
|
||||||
WorkflowQNameConverter qNameConverter = new WorkflowQNameConverter(namespaceService);
|
WorkflowQNameConverter qNameConverter = new WorkflowQNameConverter(namespaceService);
|
||||||
this.factory = new WorkflowObjectFactory(qNameConverter, tenantService, messageService, dictionaryService, getEngineId());
|
QName defaultStartTaskType = getDefaultStartTaskType();
|
||||||
|
this.factory = new WorkflowObjectFactory(qNameConverter, tenantService, messageService, dictionaryService, getEngineId(), defaultStartTaskType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -114,4 +116,6 @@ public abstract class AlfrescoBpmEngine extends BPMEngine
|
|||||||
{
|
{
|
||||||
this.authorityManager = authorityManager;
|
this.authorityManager = authorityManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract QName getDefaultStartTaskType();
|
||||||
}
|
}
|
||||||
|
@@ -73,6 +73,12 @@ public interface WorkflowModel
|
|||||||
// Activiti Task Constants
|
// Activiti Task Constants
|
||||||
static final QName TYPE_ACTIVTI_TASK = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "activitiOutcomeTask");
|
static final QName TYPE_ACTIVTI_TASK = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "activitiOutcomeTask");
|
||||||
static final QName PROP_OUTCOME_PROPERTY_NAME= QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "outcomePropertyName");
|
static final QName PROP_OUTCOME_PROPERTY_NAME= QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "outcomePropertyName");
|
||||||
|
|
||||||
|
// Activiti Start Task Constants
|
||||||
|
static final QName TYPE_ACTIVTI_START_TASK = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "activitiStartTask");
|
||||||
|
|
||||||
|
// Activiti Start Task Constants
|
||||||
|
static final QName ASPECT_END_AUTOMATICALLY= QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "endAutomatically");
|
||||||
|
|
||||||
// workflow package
|
// workflow package
|
||||||
static final QName ASPECT_WORKFLOW_PACKAGE = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowPackage");
|
static final QName ASPECT_WORKFLOW_PACKAGE = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowPackage");
|
||||||
|
@@ -62,18 +62,20 @@ public class WorkflowObjectFactory
|
|||||||
private final MessageService messageService;
|
private final MessageService messageService;
|
||||||
private final DictionaryService dictionaryService;
|
private final DictionaryService dictionaryService;
|
||||||
private final String engineId;
|
private final String engineId;
|
||||||
|
private final QName defaultStartTaskType;
|
||||||
|
|
||||||
public WorkflowObjectFactory(WorkflowQNameConverter qNameConverter,
|
public WorkflowObjectFactory(WorkflowQNameConverter qNameConverter,
|
||||||
TenantService tenantService,
|
TenantService tenantService,
|
||||||
MessageService messageService,
|
MessageService messageService,
|
||||||
DictionaryService dictionaryService,
|
DictionaryService dictionaryService,
|
||||||
String engineId)
|
String engineId, QName defaultStartTaskType)
|
||||||
{
|
{
|
||||||
this.tenantService = tenantService;
|
this.tenantService = tenantService;
|
||||||
this.messageService = messageService;
|
this.messageService = messageService;
|
||||||
this.dictionaryService = dictionaryService;
|
this.dictionaryService = dictionaryService;
|
||||||
this.engineId = engineId;
|
this.engineId = engineId;
|
||||||
this.qNameConverter = qNameConverter;
|
this.qNameConverter = qNameConverter;
|
||||||
|
this.defaultStartTaskType = defaultStartTaskType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String buildGlobalId(String localId)
|
public String buildGlobalId(String localId)
|
||||||
@@ -390,7 +392,7 @@ public class WorkflowObjectFactory
|
|||||||
}
|
}
|
||||||
if (typeDef == null)
|
if (typeDef == null)
|
||||||
{
|
{
|
||||||
QName defaultTypeName = isStart? WorkflowModel.TYPE_START_TASK : WorkflowModel.TYPE_WORKFLOW_TASK;
|
QName defaultTypeName = isStart? defaultStartTaskType : WorkflowModel.TYPE_WORKFLOW_TASK;
|
||||||
typeDef = dictionaryService.getType(defaultTypeName);
|
typeDef = dictionaryService.getType(defaultTypeName);
|
||||||
if (typeDef == null)
|
if (typeDef == null)
|
||||||
{
|
{
|
||||||
|
@@ -357,14 +357,31 @@ public class ActivitiTypeConverter
|
|||||||
taskDef, taskDef.getId(), defaultTitle, defaultDescription, state, path, properties);
|
taskDef, taskDef.getId(), defaultTitle, defaultDescription, state, path, properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WorkflowTask getVirtualStartTask(String executionId, boolean inProgress)
|
public WorkflowTask getVirtualStartTask(String processInstanceId, Boolean inProgress)
|
||||||
{
|
{
|
||||||
Execution execution = runtimeService.createExecutionQuery().executionId(executionId).singleResult();
|
ProcessInstance processInstance = activitiUtil.getProcessInstance(processInstanceId);
|
||||||
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
|
if(processInstance != null)
|
||||||
.processInstanceId(execution.getProcessInstanceId())
|
{
|
||||||
.singleResult();
|
if(null == inProgress)
|
||||||
|
{
|
||||||
String id = ActivitiConstants.START_TASK_PREFIX + execution.getProcessInstanceId();
|
inProgress = isStartTaskActive(processInstanceId);
|
||||||
|
}
|
||||||
|
return getVirtualStartTask(processInstance, inProgress);
|
||||||
|
}
|
||||||
|
HistoricProcessInstance historicProcessInstance = activitiUtil.getHistoricProcessInstance(processInstanceId);
|
||||||
|
return getVirtualStartTask(historicProcessInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isStartTaskActive(String processInstanceId)
|
||||||
|
{
|
||||||
|
Object endDate = runtimeService.getVariable(processInstanceId, ActivitiConstants.PROP_START_TASK_END_DATE);
|
||||||
|
return endDate == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private WorkflowTask getVirtualStartTask(ProcessInstance processInstance, boolean inProgress)
|
||||||
|
{
|
||||||
|
String processInstanceId = processInstance.getId();
|
||||||
|
String id = ActivitiConstants.START_TASK_PREFIX + processInstanceId;
|
||||||
|
|
||||||
WorkflowTaskState state = null;
|
WorkflowTaskState state = null;
|
||||||
if(inProgress)
|
if(inProgress)
|
||||||
@@ -376,7 +393,7 @@ public class ActivitiTypeConverter
|
|||||||
state = WorkflowTaskState.COMPLETED;
|
state = WorkflowTaskState.COMPLETED;
|
||||||
}
|
}
|
||||||
|
|
||||||
WorkflowPath path = convert(execution);
|
WorkflowPath path = convert((Execution)processInstance);
|
||||||
|
|
||||||
// Convert start-event to start-task Node
|
// Convert start-event to start-task Node
|
||||||
ReadOnlyProcessDefinition procDef = activitiUtil.getDeployedProcessDefinition(processInstance.getProcessDefinitionId());
|
ReadOnlyProcessDefinition procDef = activitiUtil.getDeployedProcessDefinition(processInstance.getProcessDefinitionId());
|
||||||
@@ -393,7 +410,7 @@ public class ActivitiTypeConverter
|
|||||||
// Add properties based on HistoricProcessInstance
|
// Add properties based on HistoricProcessInstance
|
||||||
HistoricProcessInstance historicProcessInstance = historyService
|
HistoricProcessInstance historicProcessInstance = historyService
|
||||||
.createHistoricProcessInstanceQuery()
|
.createHistoricProcessInstanceQuery()
|
||||||
.processInstanceId(execution.getProcessInstanceId())
|
.processInstanceId(processInstance.getId())
|
||||||
.singleResult();
|
.singleResult();
|
||||||
|
|
||||||
Map<QName, Serializable> properties = propertyConverter.getStartTaskProperties(historicProcessInstance, taskDefId, !inProgress);
|
Map<QName, Serializable> properties = propertyConverter.getStartTaskProperties(historicProcessInstance, taskDefId, !inProgress);
|
||||||
@@ -406,7 +423,7 @@ public class ActivitiTypeConverter
|
|||||||
taskDef, taskDef.getId(), defaultTitle, defaultDescription, state, path, properties);
|
taskDef, taskDef.getId(), defaultTitle, defaultDescription, state, path, properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WorkflowTask getVirtualStartTask(HistoricProcessInstance historicProcessInstance)
|
private WorkflowTask getVirtualStartTask(HistoricProcessInstance historicProcessInstance)
|
||||||
{
|
{
|
||||||
if(historicProcessInstance == null)
|
if(historicProcessInstance == null)
|
||||||
{
|
{
|
||||||
@@ -416,18 +433,9 @@ public class ActivitiTypeConverter
|
|||||||
String processInstanceId = historicProcessInstance.getId();
|
String processInstanceId = historicProcessInstance.getId();
|
||||||
String id = ActivitiConstants.START_TASK_PREFIX + processInstanceId;
|
String id = ActivitiConstants.START_TASK_PREFIX + processInstanceId;
|
||||||
|
|
||||||
WorkflowTaskState state = null;
|
// Since the process instance is complete the Start Task must be complete!
|
||||||
|
WorkflowTaskState state = WorkflowTaskState.COMPLETED;
|
||||||
boolean completed = historicProcessInstance.getEndTime() != null;
|
|
||||||
if(completed)
|
|
||||||
{
|
|
||||||
state = WorkflowTaskState.COMPLETED;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
state = WorkflowTaskState.IN_PROGRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We use the process-instance ID as execution-id. It's ended anyway
|
// We use the process-instance ID as execution-id. It's ended anyway
|
||||||
WorkflowPath path = buildCompletedPath(processInstanceId, processInstanceId);
|
WorkflowPath path = buildCompletedPath(processInstanceId, processInstanceId);
|
||||||
if(path == null)
|
if(path == null)
|
||||||
@@ -442,6 +450,7 @@ public class ActivitiTypeConverter
|
|||||||
String taskDefId = activitiUtil.getStartFormKey(historicProcessInstance.getProcessDefinitionId());
|
String taskDefId = activitiUtil.getStartFormKey(historicProcessInstance.getProcessDefinitionId());
|
||||||
WorkflowTaskDefinition taskDef = factory.createTaskDefinition(taskDefId, startNode, taskDefId, true);
|
WorkflowTaskDefinition taskDef = factory.createTaskDefinition(taskDefId, startNode, taskDefId, true);
|
||||||
|
|
||||||
|
boolean completed = historicProcessInstance.getEndTime() != null;
|
||||||
Map<QName, Serializable> properties = propertyConverter.getStartTaskProperties(historicProcessInstance, taskDefId, completed);
|
Map<QName, Serializable> properties = propertyConverter.getStartTaskProperties(historicProcessInstance, taskDefId, completed);
|
||||||
|
|
||||||
// TODO: Figure out what name/description should be used for the start-task, start event's name?
|
// TODO: Figure out what name/description should be used for the start-task, start event's name?
|
||||||
|
@@ -33,6 +33,7 @@ import java.util.LinkedList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.activiti.engine.ActivitiException;
|
import org.activiti.engine.ActivitiException;
|
||||||
import org.activiti.engine.FormService;
|
import org.activiti.engine.FormService;
|
||||||
@@ -81,6 +82,7 @@ import org.alfresco.repo.workflow.WorkflowModel;
|
|||||||
import org.alfresco.repo.workflow.WorkflowNodeConverter;
|
import org.alfresco.repo.workflow.WorkflowNodeConverter;
|
||||||
import org.alfresco.repo.workflow.WorkflowObjectFactory;
|
import org.alfresco.repo.workflow.WorkflowObjectFactory;
|
||||||
import org.alfresco.repo.workflow.activiti.properties.ActivitiPropertyConverter;
|
import org.alfresco.repo.workflow.activiti.properties.ActivitiPropertyConverter;
|
||||||
|
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.service.cmr.repository.NodeService;
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
import org.alfresco.service.cmr.repository.StoreRef;
|
import org.alfresco.service.cmr.repository.StoreRef;
|
||||||
@@ -689,46 +691,42 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
|
|||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public List<WorkflowTask> getTasksForWorkflowPath(String pathId)
|
public List<WorkflowTask> getTasksForWorkflowPath(String pathId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Extract the Activiti ID from the path
|
// Extract the Activiti ID from the path
|
||||||
String executionId = getExecutionIdFromPath(pathId);
|
String executionId = getExecutionIdFromPath(pathId);
|
||||||
if(executionId == null)
|
if (executionId == null)
|
||||||
{
|
{
|
||||||
throw new WorkflowException(messageService.getMessage(ERR_GET_WORKFLOW_TOKEN_INVALID, pathId));
|
throw new WorkflowException(messageService.getMessage(ERR_GET_WORKFLOW_TOKEN_INVALID, pathId));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the execution exists
|
// Check if the execution exists
|
||||||
Execution execution = runtimeService.createExecutionQuery().executionId(executionId).singleResult();
|
Execution execution = runtimeService.createExecutionQuery().executionId(executionId).singleResult();
|
||||||
if(execution == null)
|
if (execution == null)
|
||||||
{
|
{
|
||||||
throw new WorkflowException(messageService.getMessage(ERR_GET_WORKFLOW_TOKEN_NULL, pathId));
|
throw new WorkflowException(messageService.getMessage(ERR_GET_WORKFLOW_TOKEN_NULL, pathId));
|
||||||
}
|
}
|
||||||
|
|
||||||
List<WorkflowTask> resultList = new ArrayList<WorkflowTask>();
|
// Check if workflow's start task has been completed. If not, return
|
||||||
|
// the virtual task
|
||||||
// Check if workflow's start task has been completed. If not, return the virtual task
|
// Otherwise, just return the runtime Activiti tasks
|
||||||
// Otherwise, just return the runtime activiti tasks
|
String processInstanceId = execution.getProcessInstanceId();
|
||||||
Date startTaskEndDate = (Date) runtimeService.getVariable(execution.getProcessInstanceId(),
|
ArrayList<WorkflowTask> resultList = new ArrayList<WorkflowTask>();
|
||||||
ActivitiConstants.PROP_START_TASK_END_DATE);
|
if (typeConverter.isStartTaskActive(processInstanceId))
|
||||||
boolean startTaskEnded = (startTaskEndDate != null);
|
{
|
||||||
|
resultList.add(typeConverter.getVirtualStartTask(processInstanceId, true));
|
||||||
if(startTaskEnded)
|
}
|
||||||
{
|
else
|
||||||
List<Task> tasks = taskService.createTaskQuery().executionId(executionId).list();
|
{
|
||||||
for(Task task : tasks)
|
List<Task> tasks = taskService.createTaskQuery().executionId(executionId).list();
|
||||||
{
|
for (Task task : tasks)
|
||||||
resultList.add(typeConverter.convert(task));
|
{
|
||||||
}
|
resultList.add(typeConverter.convert(task));
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
return resultList;
|
||||||
resultList.add(typeConverter.getVirtualStartTask(executionId, true));
|
|
||||||
}
|
|
||||||
return resultList;
|
|
||||||
}
|
}
|
||||||
catch (ActivitiException ae)
|
catch (ActivitiException ae)
|
||||||
{
|
{
|
||||||
@@ -736,7 +734,7 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
|
|||||||
throw new WorkflowException(msg, ae);
|
throw new WorkflowException(msg, ae);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getExecutionIdFromPath(String workflowPath)
|
protected String getExecutionIdFromPath(String workflowPath)
|
||||||
{
|
{
|
||||||
if(workflowPath != null)
|
if(workflowPath != null)
|
||||||
@@ -1017,7 +1015,9 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return typeConverter.convert((Execution)instance);
|
WorkflowPath path = typeConverter.convert((Execution)instance);
|
||||||
|
endStartTaskAutomatically(path, instance);
|
||||||
|
return path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (ActivitiException ae)
|
catch (ActivitiException ae)
|
||||||
@@ -1026,6 +1026,23 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
|
|||||||
throw new WorkflowException(msg, ae);
|
throw new WorkflowException(msg, ae);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param path
|
||||||
|
* @param instance
|
||||||
|
*/
|
||||||
|
private void endStartTaskAutomatically(WorkflowPath path, ProcessInstance instance)
|
||||||
|
{
|
||||||
|
// Check if StartTask Needs to be ended automatically
|
||||||
|
WorkflowDefinition definition = path.getInstance().getDefinition();
|
||||||
|
TypeDefinition metadata = definition.getStartTaskDefinition().getMetadata();
|
||||||
|
Set<QName> aspects = metadata.getDefaultAspectNames();
|
||||||
|
if(aspects.contains(WorkflowModel.ASPECT_END_AUTOMATICALLY))
|
||||||
|
{
|
||||||
|
String taskId = ActivitiConstants.START_TASK_PREFIX + instance.getId();
|
||||||
|
endStartTask(taskId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
@@ -1296,7 +1313,7 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
|
|||||||
// Check if the task is a virtual start task
|
// Check if the task is a virtual start task
|
||||||
if(localTaskId.startsWith(ActivitiConstants.START_TASK_PREFIX))
|
if(localTaskId.startsWith(ActivitiConstants.START_TASK_PREFIX))
|
||||||
{
|
{
|
||||||
return endStartTask(taskId, localTaskId, transition);
|
return endStartTask(localTaskId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return endNormalTask(taskId, localTaskId, transition);
|
return endNormalTask(taskId, localTaskId, transition);
|
||||||
@@ -1356,11 +1373,15 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
|
|||||||
propertyConverter.updateTask(task, updates, null, null);
|
propertyConverter.updateTask(task, updates, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private WorkflowTask endStartTask(String taskId, String localTaskId, String transition)
|
private WorkflowTask endStartTask(String localTaskId)
|
||||||
{
|
{
|
||||||
// We don't end a task, we set a variable on the process-instance
|
// We don't end a task, we set a variable on the process-instance
|
||||||
// to indicate that it's started
|
// to indicate that it's started
|
||||||
String processInstanceId = localTaskId.replace(ActivitiConstants.START_TASK_PREFIX, "");
|
String processInstanceId = localTaskId.replace(ActivitiConstants.START_TASK_PREFIX, "");
|
||||||
|
if(false == typeConverter.isStartTaskActive(processInstanceId))
|
||||||
|
{
|
||||||
|
return typeConverter.getVirtualStartTask(processInstanceId, false);
|
||||||
|
}
|
||||||
|
|
||||||
// Set start task end date on the process
|
// Set start task end date on the process
|
||||||
runtimeService.setVariable(processInstanceId, ActivitiConstants.PROP_START_TASK_END_DATE, new Date());
|
runtimeService.setVariable(processInstanceId, ActivitiConstants.PROP_START_TASK_END_DATE, new Date());
|
||||||
@@ -1379,22 +1400,10 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
|
|||||||
runtimeService.signal(processInstanceId);
|
runtimeService.signal(processInstanceId);
|
||||||
|
|
||||||
// It's possible the process has ended after signalling the receive task
|
// It's possible the process has ended after signalling the receive task
|
||||||
processInstance = activitiUtil.getProcessInstance(processInstanceId);
|
|
||||||
if (processInstance != null)
|
|
||||||
{
|
|
||||||
return typeConverter.getVirtualStartTask(processInstanceId, false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return typeConverter.getVirtualStartTask(activitiUtil.getHistoricProcessInstance(processInstanceId));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
// Return virtual start task for the execution, it's safe to use the
|
||||||
{
|
// processInstanceId
|
||||||
// Return virtual start task for the execution, it's safe to use the processInstanceId
|
return typeConverter.getVirtualStartTask(processInstanceId, false);
|
||||||
return typeConverter.getVirtualStartTask(processInstanceId, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1515,7 +1524,7 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
|
|||||||
if(localId.startsWith(ActivitiConstants.START_TASK_PREFIX))
|
if(localId.startsWith(ActivitiConstants.START_TASK_PREFIX))
|
||||||
{
|
{
|
||||||
String processInstanceId = localId.replace(ActivitiConstants.START_TASK_PREFIX ,"");
|
String processInstanceId = localId.replace(ActivitiConstants.START_TASK_PREFIX ,"");
|
||||||
return getVirtualStartTaskForProcessInstance(processInstanceId);
|
return typeConverter.getVirtualStartTask(processInstanceId, null);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1884,8 +1893,7 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
|
|||||||
// Only return start-task when a process or task id is set
|
// Only return start-task when a process or task id is set
|
||||||
if(processInstanceId != null)
|
if(processInstanceId != null)
|
||||||
{
|
{
|
||||||
// Extract processInstanceId
|
WorkflowTask workflowTask = typeConverter.getVirtualStartTask(processInstanceId, null);
|
||||||
WorkflowTask workflowTask = getVirtualStartTaskForProcessInstance(processInstanceId);
|
|
||||||
if(workflowTask != null)
|
if(workflowTask != null)
|
||||||
{
|
{
|
||||||
boolean startTaskMatches = isStartTaskMatching(workflowTask, query);
|
boolean startTaskMatches = isStartTaskMatching(workflowTask, query);
|
||||||
@@ -2033,32 +2041,7 @@ public class ActivitiWorkflowEngine extends BPMEngine implements WorkflowEngine
|
|||||||
public WorkflowTask getStartTask(String workflowInstanceId)
|
public WorkflowTask getStartTask(String workflowInstanceId)
|
||||||
{
|
{
|
||||||
String instanceId = createLocalId(workflowInstanceId);
|
String instanceId = createLocalId(workflowInstanceId);
|
||||||
return getVirtualStartTaskForProcessInstance(instanceId);
|
return typeConverter.getVirtualStartTask(instanceId, null);
|
||||||
}
|
|
||||||
|
|
||||||
public WorkflowTask getVirtualStartTaskForProcessInstance(String processInstanceId)
|
|
||||||
{
|
|
||||||
|
|
||||||
ProcessInstance runningInstance = runtimeService.createProcessInstanceQuery()
|
|
||||||
.processInstanceId(processInstanceId)
|
|
||||||
.singleResult();
|
|
||||||
|
|
||||||
if(runningInstance != null)
|
|
||||||
{
|
|
||||||
// Check the process instance variable to see if start-task has been completed
|
|
||||||
Date startTaskEndDate = (Date) runtimeService.getVariable(runningInstance.getProcessInstanceId(),
|
|
||||||
ActivitiConstants.PROP_START_TASK_END_DATE);
|
|
||||||
boolean startTaskEnded = (startTaskEndDate != null);
|
|
||||||
return typeConverter.getVirtualStartTask(runningInstance.getId(), !startTaskEnded);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HistoricProcessInstance hpi = historyService.createHistoricProcessInstanceQuery()
|
|
||||||
.processInstanceId(processInstanceId)
|
|
||||||
.singleResult();
|
|
||||||
|
|
||||||
return typeConverter.getVirtualStartTask(hpi);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -26,6 +26,7 @@ import org.alfresco.repo.tenant.TenantService;
|
|||||||
import org.alfresco.repo.workflow.BPMEngineRegistry;
|
import org.alfresco.repo.workflow.BPMEngineRegistry;
|
||||||
import org.alfresco.repo.workflow.DefaultWorkflowPropertyHandler;
|
import org.alfresco.repo.workflow.DefaultWorkflowPropertyHandler;
|
||||||
import org.alfresco.repo.workflow.WorkflowAuthorityManager;
|
import org.alfresco.repo.workflow.WorkflowAuthorityManager;
|
||||||
|
import org.alfresco.repo.workflow.WorkflowModel;
|
||||||
import org.alfresco.repo.workflow.WorkflowObjectFactory;
|
import org.alfresco.repo.workflow.WorkflowObjectFactory;
|
||||||
import org.alfresco.repo.workflow.WorkflowPropertyHandlerRegistry;
|
import org.alfresco.repo.workflow.WorkflowPropertyHandlerRegistry;
|
||||||
import org.alfresco.repo.workflow.WorkflowQNameConverter;
|
import org.alfresco.repo.workflow.WorkflowQNameConverter;
|
||||||
@@ -37,6 +38,7 @@ import org.alfresco.service.cmr.search.SearchService;
|
|||||||
import org.alfresco.service.cmr.security.PersonService;
|
import org.alfresco.service.cmr.security.PersonService;
|
||||||
import org.alfresco.service.cmr.workflow.WorkflowException;
|
import org.alfresco.service.cmr.workflow.WorkflowException;
|
||||||
import org.alfresco.service.namespace.NamespaceService;
|
import org.alfresco.service.namespace.NamespaceService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
import org.springframework.beans.factory.FactoryBean;
|
import org.springframework.beans.factory.FactoryBean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -90,7 +92,8 @@ public class ActivitiWorkflowManagerFactory implements FactoryBean<ActivitiWorkf
|
|||||||
WorkflowPropertyHandlerRegistry handlerRegistry = new WorkflowPropertyHandlerRegistry(defaultPropertyHandler, qNameConverter);
|
WorkflowPropertyHandlerRegistry handlerRegistry = new WorkflowPropertyHandlerRegistry(defaultPropertyHandler, qNameConverter);
|
||||||
|
|
||||||
WorkflowAuthorityManager authorityManager = new WorkflowAuthorityManager(authorityDAO);
|
WorkflowAuthorityManager authorityManager = new WorkflowAuthorityManager(authorityDAO);
|
||||||
WorkflowObjectFactory factory = new WorkflowObjectFactory(qNameConverter, tenantService, messageService, dictionaryService, engineId);
|
QName defaultStartTaskType = WorkflowModel.TYPE_ACTIVTI_START_TASK;
|
||||||
|
WorkflowObjectFactory factory = new WorkflowObjectFactory(qNameConverter, tenantService, messageService, dictionaryService, engineId, defaultStartTaskType);
|
||||||
ActivitiUtil activitiUtil = new ActivitiUtil(processEngine);
|
ActivitiUtil activitiUtil = new ActivitiUtil(processEngine);
|
||||||
ActivitiPropertyConverter propertyConverter = new ActivitiPropertyConverter(activitiUtil, factory, handlerRegistry, authorityManager, messageService, nodeConverter);
|
ActivitiPropertyConverter propertyConverter = new ActivitiPropertyConverter(activitiUtil, factory, handlerRegistry, authorityManager, messageService, nodeConverter);
|
||||||
ActivitiTypeConverter typeConverter = new ActivitiTypeConverter(processEngine, factory, propertyConverter);
|
ActivitiTypeConverter typeConverter = new ActivitiTypeConverter(processEngine, factory, propertyConverter);
|
||||||
|
@@ -81,6 +81,26 @@ public class ActivitiWorkflowServiceIntegrationTest extends AbstractWorkflowServ
|
|||||||
assertEquals("Approve", outcome);
|
assertEquals("Approve", outcome);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testStartTaskEndsAutomatically()
|
||||||
|
{
|
||||||
|
// Deploy the test workflow definition which uses the
|
||||||
|
// default Start Task type, so it should end automatically.
|
||||||
|
WorkflowDefinition definition = deployDefinition(getTestDefinitionPath());
|
||||||
|
|
||||||
|
// Start the Workflow
|
||||||
|
WorkflowPath path = workflowService.startWorkflow(definition.getId(), null);
|
||||||
|
String instanceId = path.getInstance().getId();
|
||||||
|
|
||||||
|
// Check the Start Task is completed.
|
||||||
|
WorkflowTask startTask = workflowService.getStartTask(instanceId);
|
||||||
|
assertEquals(WorkflowTaskState.COMPLETED, startTask.getState());
|
||||||
|
|
||||||
|
List<WorkflowTask> tasks = workflowService.getTasksForWorkflowPath(path.getId());
|
||||||
|
assertEquals(1, tasks.size());
|
||||||
|
String taskName = tasks.get(0).getName();
|
||||||
|
assertEquals("bpm_foo_task", taskName);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void checkTaskQueryStartTaskCompleted(String workflowInstanceId, WorkflowTask startTask)
|
protected void checkTaskQueryStartTaskCompleted(String workflowInstanceId, WorkflowTask startTask)
|
||||||
{
|
{
|
||||||
|
@@ -852,12 +852,10 @@ public class ActivitiPropertyConverter
|
|||||||
*/
|
*/
|
||||||
private List<QName> getMissingMandatoryTaskProperties(DelegateTask task)
|
private List<QName> getMissingMandatoryTaskProperties(DelegateTask task)
|
||||||
{
|
{
|
||||||
|
|
||||||
TypeDefinition typeDefinition = typeManager.getFullTaskDefinition(task);
|
TypeDefinition typeDefinition = typeManager.getFullTaskDefinition(task);
|
||||||
// retrieve properties of task
|
// retrieve properties of task
|
||||||
Map<QName, Serializable> existingValues = getTaskProperties(task, typeDefinition, false);
|
Map<QName, Serializable> existingValues = getTaskProperties(task, typeDefinition, false);
|
||||||
|
|
||||||
// retrieve definition of task
|
|
||||||
Map<QName, PropertyDefinition> propertyDefs = typeDefinition.getProperties();
|
Map<QName, PropertyDefinition> propertyDefs = typeDefinition.getProperties();
|
||||||
Map<QName, AssociationDefinition> assocDefs = typeDefinition.getAssociations();
|
Map<QName, AssociationDefinition> assocDefs = typeDefinition.getAssociations();
|
||||||
|
|
||||||
|
@@ -3417,7 +3417,7 @@ public class JBPMEngine extends AlfrescoBpmEngine implements WorkflowEngine
|
|||||||
{
|
{
|
||||||
if (node instanceof HibernateProxy)
|
if (node instanceof HibernateProxy)
|
||||||
{
|
{
|
||||||
Node realNode = (Node)((HibernateProxy)node).getHibernateLazyInitializer().getImplementation();
|
Node realNode = (Node)((HibernateProxy)node).getHibernateLazyInitializer().getImplementation();
|
||||||
return realNode;
|
return realNode;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -3426,4 +3426,10 @@ public class JBPMEngine extends AlfrescoBpmEngine implements WorkflowEngine
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected QName getDefaultStartTaskType()
|
||||||
|
{
|
||||||
|
return WorkflowModel.TYPE_START_TASK;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user