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:
N Smith
2011-09-25 17:13:56 +00:00
parent 74b9ff5845
commit eb3404c462
10 changed files with 164 additions and 116 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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