mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merged HEAD-QA to HEAD (4.2) (including moving test classes into separate folders)
51903 to 54309 git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@54310 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -0,0 +1,279 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.workflow;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.alfresco.repo.tenant.TenantAdminService;
|
||||
import org.alfresco.repo.tenant.TenantContextHolder;
|
||||
import org.alfresco.repo.tenant.TenantService;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.security.PersonService;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowDeployment;
|
||||
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.cmr.workflow.WorkflowTaskQuery;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.ApplicationContextHelper;
|
||||
import org.alfresco.util.BaseSpringTest;
|
||||
import org.alfresco.util.GUID;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
/**
|
||||
* @author Nick Smith
|
||||
* @since 4.0
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractMultitenantWorkflowTest extends BaseSpringTest
|
||||
{
|
||||
protected static final String XML = MimetypeMap.MIMETYPE_XML;
|
||||
|
||||
public static final String DEFAULT_ADMIN_PW = "admin";
|
||||
private final static QName ADHOC_TASK = QName.createQName(NamespaceService.WORKFLOW_MODEL_1_0_URI, "adhocTask");
|
||||
|
||||
private final String tenant1 = "wfMTTest1"+GUID.generate();
|
||||
private final String tenant2 = "wfMTTest2"+GUID.generate();
|
||||
|
||||
private TenantAdminService tenantAdminService;
|
||||
|
||||
protected TenantService tenantService;
|
||||
|
||||
protected ServiceRegistry serviceRegistry;
|
||||
|
||||
protected WorkflowService workflowService;
|
||||
protected PersonService personService;
|
||||
|
||||
protected String user1;
|
||||
protected String user2;
|
||||
|
||||
private WorkflowTestHelper wfTestHelper;
|
||||
|
||||
@Test
|
||||
public void xtestDeployWorkflow() throws Exception
|
||||
{
|
||||
// Run as User1 so tenant domain 1
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(user1);
|
||||
TenantContextHolder.setTenantDomain(tenant1);
|
||||
|
||||
List<WorkflowDefinition> allDefs = workflowService.getAllDefinitions();
|
||||
int allDefsSize = allDefs.size();
|
||||
List<WorkflowDefinition> defs = workflowService.getDefinitions();
|
||||
int defsSize = defs.size();
|
||||
|
||||
String definitionKey = getTestDefinitionKey();
|
||||
// Deploy to tenant1.
|
||||
WorkflowDefinition definition = workflowService.getDefinitionByName(definitionKey);
|
||||
assertNull(definition);
|
||||
|
||||
// Check definition was successfully deployed on tenant1.
|
||||
definition = deployDefinition(getTestDefinitionPath());
|
||||
assertNotNull(definition);
|
||||
assertEquals(definitionKey, definition.getName());
|
||||
assertNotNull(workflowService.getDefinitionById(definition.getId()));
|
||||
assertNotNull(workflowService.getDefinitionByName(definitionKey));
|
||||
|
||||
assertEquals(defsSize + 1, workflowService.getDefinitions().size());
|
||||
assertEquals(allDefsSize + 1, workflowService.getAllDefinitions().size());
|
||||
|
||||
// Switch to tenant2.
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(user2);
|
||||
TenantContextHolder.setTenantDomain(tenant2);
|
||||
|
||||
// Check definition not visible on tenant2.
|
||||
try
|
||||
{
|
||||
assertNull(workflowService.getDefinitionById(definition.getId()));
|
||||
fail("Should throw Exception here!");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
assertNull(workflowService.getDefinitionByName(definitionKey));
|
||||
|
||||
assertEquals(defsSize, workflowService.getDefinitions().size());
|
||||
assertEquals(allDefsSize, workflowService.getAllDefinitions().size());
|
||||
|
||||
// Check can deploy same definition to tenant2.
|
||||
assertNotNull(deployDefinition(getTestDefinitionPath()));
|
||||
|
||||
// Switch back to tenant1.
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(user1);
|
||||
TenantContextHolder.setTenantDomain(tenant1);
|
||||
|
||||
// Check the definition hasn't changed
|
||||
WorkflowDefinition definitionByName = workflowService.getDefinitionByName(definitionKey);
|
||||
assertEquals(definition.getId(), definitionByName.getId());
|
||||
}
|
||||
|
||||
public void testQueryTasks() throws Exception
|
||||
{
|
||||
WorkflowTaskQuery query = new WorkflowTaskQuery();
|
||||
|
||||
query.setTaskName(ADHOC_TASK);
|
||||
|
||||
// Run as User1 so tenant domain 1
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(user1);
|
||||
TenantContextHolder.setTenantDomain(tenant1);
|
||||
|
||||
// Check no tasks to start with
|
||||
List<WorkflowTask> tasks = workflowService.queryTasks(query);
|
||||
assertEquals(0, tasks.size());
|
||||
|
||||
String adhocKey = getAdhocDefinitionKey();
|
||||
WorkflowDefinition adhocDef1= workflowService.getDefinitionByName(adhocKey);
|
||||
//Check Adhoc definition exists
|
||||
assertNotNull(adhocDef1);
|
||||
|
||||
//Start Adhoc workflow on tenant1.
|
||||
NodeRef assignee1 = personService.getPerson(user1);
|
||||
NodeRef pckg1 = workflowService.createPackage(null);
|
||||
Map<QName, Serializable> parameters1 = new HashMap<QName, Serializable>();
|
||||
parameters1.put(WorkflowModel.ASSOC_PACKAGE, pckg1);
|
||||
parameters1.put(WorkflowModel.ASSOC_ASSIGNEE, assignee1);
|
||||
WorkflowPath path = workflowService.startWorkflow(adhocDef1.getId(), parameters1);
|
||||
|
||||
// End start task
|
||||
String instanceId = path.getInstance().getId();
|
||||
WorkflowTask startTask = workflowService.getStartTask(instanceId);
|
||||
workflowService.endTask(startTask.getId(), null);
|
||||
|
||||
// Should have found the new task.
|
||||
tasks = workflowService.queryTasks(query);
|
||||
assertEquals(1, tasks.size());
|
||||
|
||||
//Switch to tenant2
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(user2);
|
||||
TenantContextHolder.setTenantDomain(tenant2);
|
||||
|
||||
// Tenant2 should not find the task
|
||||
tasks = workflowService.queryTasks(query);
|
||||
assertEquals(0, tasks.size());
|
||||
|
||||
//Start Adhoc workflow on tenant2.
|
||||
WorkflowDefinition adhocDef2 = workflowService.getDefinitionByName(adhocKey);
|
||||
NodeRef assignee2 = personService.getPerson(user2);
|
||||
NodeRef pckg2 = workflowService.createPackage(null);
|
||||
Map<QName, Serializable> parameters2 = new HashMap<QName, Serializable>();
|
||||
parameters2.put(WorkflowModel.ASSOC_PACKAGE, pckg2);
|
||||
parameters2.put(WorkflowModel.ASSOC_ASSIGNEE, assignee2);
|
||||
WorkflowPath path2 = workflowService.startWorkflow(adhocDef2.getId(), parameters2);
|
||||
String path2Id = path2.getId();
|
||||
|
||||
// End start task
|
||||
String instanceId2 = path2.getInstance().getId();
|
||||
WorkflowTask startTask2 = workflowService.getStartTask(instanceId2);
|
||||
workflowService.endTask(startTask2.getId(), null);
|
||||
|
||||
// Tenant2 should find the new task
|
||||
tasks = workflowService.queryTasks(query);
|
||||
assertEquals(1, tasks.size());
|
||||
assertEquals(path2Id, tasks.get(0).getPath().getId());
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected void onSetUpBeforeTransaction() throws Exception
|
||||
{
|
||||
super.onSetUpBeforeTransaction();
|
||||
this.serviceRegistry = (ServiceRegistry) applicationContext.getBean(ServiceRegistry.SERVICE_REGISTRY);
|
||||
this.tenantService= (TenantService) applicationContext.getBean("tenantService");
|
||||
this.tenantAdminService= (TenantAdminService) applicationContext.getBean("tenantAdminService");
|
||||
|
||||
this.workflowService = serviceRegistry.getWorkflowService();
|
||||
this.personService = serviceRegistry.getPersonService();
|
||||
|
||||
WorkflowAdminServiceImpl workflowAdminService = (WorkflowAdminServiceImpl)applicationContext.getBean(WorkflowAdminServiceImpl.NAME);
|
||||
this.wfTestHelper = new WorkflowTestHelper(workflowAdminService, getEngine(), true);
|
||||
|
||||
AuthenticationUtil.clearCurrentSecurityContext();
|
||||
this.user1 = createTenant(tenant1);
|
||||
this.user2 = createTenant(tenant2);
|
||||
}
|
||||
|
||||
private String createTenant(final String tenantDomain)
|
||||
{
|
||||
// create tenants (if not already created)
|
||||
return AuthenticationUtil.runAsSystem(new RunAsWork<String>()
|
||||
{
|
||||
public String doWork() throws Exception
|
||||
{
|
||||
if (! tenantAdminService.existsTenant(tenantDomain))
|
||||
{
|
||||
tenantAdminService.createTenant(tenantDomain, (DEFAULT_ADMIN_PW+" "+tenantDomain).toCharArray(), null); // use default root dir
|
||||
}
|
||||
return tenantService.getDomainUser(AuthenticationUtil.getAdminUserName(), tenantDomain);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected void onTearDown() throws Exception
|
||||
{
|
||||
wfTestHelper.tearDown();
|
||||
|
||||
super.onTearDown();
|
||||
WorkflowSuiteContextShutdownTest.closeContext();
|
||||
}
|
||||
|
||||
protected WorkflowDefinition deployDefinition(String resource)
|
||||
{
|
||||
InputStream input = getInputStream(resource);
|
||||
WorkflowDeployment deployment = workflowService.deployDefinition(getEngine(), input, XML);
|
||||
WorkflowDefinition definition = deployment.getDefinition();
|
||||
return definition;
|
||||
}
|
||||
|
||||
protected InputStream getInputStream(String resource)
|
||||
{
|
||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||
return classLoader.getResourceAsStream(resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected String[] getConfigLocations()
|
||||
{
|
||||
return new String[] {ApplicationContextHelper.CONFIG_LOCATIONS[0],
|
||||
"classpath:tenant/mt-*context.xml"};
|
||||
}
|
||||
|
||||
protected abstract String getTestDefinitionPath();
|
||||
protected abstract String getTestDefinitionKey();
|
||||
protected abstract String getAdhocDefinitionKey();
|
||||
protected abstract String getEngine();
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.workflow;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.action.ActionImpl;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
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.security.PersonService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.BaseSpringTest;
|
||||
import org.alfresco.util.GUID;
|
||||
|
||||
/**
|
||||
* Start Advanced Workflow action execution test
|
||||
*
|
||||
* @author David Caruana
|
||||
*/
|
||||
public class StartWorkflowActionExecuterTest extends BaseSpringTest
|
||||
{
|
||||
private NodeService nodeService;
|
||||
private NamespaceService namespaceService;
|
||||
private PersonService personService;
|
||||
private NodeRef rootNodeRef;
|
||||
private NodeRef nodeRef;
|
||||
private StartWorkflowActionExecuter executer;
|
||||
|
||||
|
||||
/**
|
||||
* Called at the begining of all tests
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected void onSetUpInTransaction() throws Exception
|
||||
{
|
||||
this.nodeService = (NodeService)this.applicationContext.getBean("nodeService");
|
||||
this.namespaceService = (NamespaceService)this.applicationContext.getBean("namespaceService");
|
||||
this.personService = (PersonService)this.applicationContext.getBean("personService");
|
||||
|
||||
AuthenticationComponent authenticationComponent = (AuthenticationComponent)applicationContext.getBean("authenticationComponent");
|
||||
authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName());
|
||||
|
||||
// Create the store and get the root node
|
||||
rootNodeRef = nodeService.getRootNode(new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "SpacesStore"));
|
||||
this.nodeRef = this.nodeService.createNode(
|
||||
this.rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName("{test}testnode"),
|
||||
ContentModel.TYPE_CONTENT).getChildRef();
|
||||
|
||||
// Get the executer instance
|
||||
this.executer = (StartWorkflowActionExecuter)this.applicationContext.getBean(StartWorkflowActionExecuter.NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test execution
|
||||
*/
|
||||
public void testExecution()
|
||||
{
|
||||
// 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_WORKFLOW_DUE_DATE.toPrefixString(namespaceService), new Date());
|
||||
NodeRef reviewer = personService.getPerson(AuthenticationUtil.getAdminUserName());
|
||||
action.setParameterValue(WorkflowModel.ASSOC_ASSIGNEE.toPrefixString(namespaceService), reviewer);
|
||||
executer.execute(action, this.nodeRef);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.workflow;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.alfresco.repo.workflow.jbpm.WorkflowTaskInstance;
|
||||
import org.alfresco.util.ApplicationContextHelper;
|
||||
|
||||
public class WorkflowSuiteContextShutdownTest extends TestCase
|
||||
{
|
||||
public void testDummy() { /*Do Nothing */ }
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception
|
||||
{
|
||||
System.err.println("Workflow test suite has completed, shutting down the ApplicationContext...");
|
||||
closeContext();
|
||||
|
||||
System.err.println("Workflow test suite shutdown has finished");
|
||||
}
|
||||
|
||||
public static void closeContext() throws NoSuchFieldException, IllegalAccessException, InterruptedException
|
||||
{
|
||||
ApplicationContextHelper.closeApplicationContext();
|
||||
|
||||
// Null out the static Workflow engine field
|
||||
Field engineField = WorkflowTaskInstance.class.getDeclaredField("jbpmEngine");
|
||||
engineField.setAccessible(true);
|
||||
engineField.set(null, null);
|
||||
|
||||
Thread.yield();
|
||||
Thread.sleep(25);
|
||||
Thread.yield();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.workflow;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Nick Smith
|
||||
* @since 4.0
|
||||
*
|
||||
*/
|
||||
public class WorkflowTestHelper
|
||||
{
|
||||
private final WorkflowAdminServiceImpl workflowAdminService;
|
||||
private final String engineId;
|
||||
private final Set<String> enabledEngines;
|
||||
private final Set<String> visibleEngines;
|
||||
|
||||
public WorkflowTestHelper(WorkflowAdminServiceImpl workflowAdminService, String engineId, boolean enableEngineOnly)
|
||||
{
|
||||
this.workflowAdminService = workflowAdminService;
|
||||
this.engineId = engineId;
|
||||
this.enabledEngines = workflowAdminService.getEnabledEngines();
|
||||
this.visibleEngines = workflowAdminService.getVisibleEngines();
|
||||
if(enableEngineOnly)
|
||||
{
|
||||
enableThisEngineOnly();
|
||||
}
|
||||
}
|
||||
|
||||
public void enableThisEngineOnly()
|
||||
{
|
||||
workflowAdminService.setEnabledEngines(Arrays.asList(engineId));
|
||||
workflowAdminService.setVisibleEngines(Arrays.asList(engineId));
|
||||
}
|
||||
|
||||
public void tearDown()
|
||||
{
|
||||
workflowAdminService.setEnabledEngines(enabledEngines);
|
||||
workflowAdminService.setVisibleEngines(visibleEngines);
|
||||
}
|
||||
|
||||
public void setVisible(boolean isVisible)
|
||||
{
|
||||
workflowAdminService.setEngineVisibility(engineId, isVisible);
|
||||
}
|
||||
|
||||
public void setEnabled(boolean isEnabled)
|
||||
{
|
||||
workflowAdminService.setEngineEnabled(engineId, isEnabled);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.workflow;
|
||||
|
||||
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
import org.alfresco.repo.workflow.activiti.ActivitiMultitenantWorkflowTest;
|
||||
import org.alfresco.repo.workflow.activiti.ActivitiSpringTransactionTest;
|
||||
import org.alfresco.repo.workflow.activiti.ActivitiTimerExecutionTest;
|
||||
import org.alfresco.repo.workflow.activiti.ActivitiWorkflowServiceIntegrationTest;
|
||||
import org.alfresco.repo.workflow.jbpm.AlfrescoJavaScriptIntegrationTest;
|
||||
import org.alfresco.repo.workflow.jbpm.JBPMEngineTest;
|
||||
import org.alfresco.repo.workflow.jbpm.JBPMSpringTest;
|
||||
import org.alfresco.repo.workflow.jbpm.JbpmMultitenantWorkflowTest;
|
||||
import org.alfresco.repo.workflow.jbpm.JbpmWorkflowServiceIntegrationTest;
|
||||
import org.alfresco.repo.workflow.jbpm.ReviewAndApproveTest;
|
||||
import org.alfresco.util.ApplicationContextHelper;
|
||||
|
||||
/**
|
||||
* Workflow test suite
|
||||
*/
|
||||
public class WorkflowTestSuite extends TestSuite
|
||||
{
|
||||
/**
|
||||
* Creates the test suite
|
||||
*
|
||||
* @return the test suite
|
||||
*/
|
||||
public static Test suite()
|
||||
{
|
||||
TestSuite suite = new TestSuite();
|
||||
|
||||
// Ensure that the default context is available
|
||||
ApplicationContextHelper.getApplicationContext();
|
||||
|
||||
// Add the JBPM tests to be run
|
||||
suite.addTestSuite( StartWorkflowActionExecuterTest.class );
|
||||
suite.addTestSuite( JbpmWorkflowServiceIntegrationTest.class );
|
||||
suite.addTestSuite( ReviewAndApproveTest.class );
|
||||
suite.addTestSuite( JBPMSpringTest.class );
|
||||
suite.addTestSuite( JBPMEngineTest.class );
|
||||
suite.addTestSuite( AlfrescoJavaScriptIntegrationTest.class );
|
||||
// Add the Activiti tests to be run
|
||||
suite.addTestSuite( ActivitiWorkflowServiceIntegrationTest.class );
|
||||
suite.addTestSuite( ActivitiSpringTransactionTest.class );
|
||||
suite.addTestSuite( ActivitiTimerExecutionTest.class );
|
||||
|
||||
// This test will force the application context properly, which avoids
|
||||
// periodic wierd build failures
|
||||
suite.addTestSuite( WorkflowSuiteContextShutdownTest.class );
|
||||
|
||||
// These tests use a different Spring config.
|
||||
suite.addTestSuite( ActivitiMultitenantWorkflowTest.class );
|
||||
|
||||
suite.addTestSuite( JbpmMultitenantWorkflowTest.class );
|
||||
|
||||
// Note the following workflow tests are not included in this sutie:
|
||||
// ActivitiTaskComponentTest
|
||||
// ActivitiWorkflowComponentTest
|
||||
// ActivitiWorkflowRestApiTest
|
||||
// JbpmWorkflowRestApiTest
|
||||
return suite;
|
||||
}
|
||||
}
|
@@ -0,0 +1,428 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.workflow.activiti;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.activiti.engine.HistoryService;
|
||||
import org.activiti.engine.ManagementService;
|
||||
import org.activiti.engine.ProcessEngine;
|
||||
import org.activiti.engine.RepositoryService;
|
||||
import org.activiti.engine.RuntimeService;
|
||||
import org.activiti.engine.TaskService;
|
||||
import org.activiti.engine.repository.ProcessDefinition;
|
||||
import org.activiti.engine.runtime.ProcessInstance;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.i18n.MessageService;
|
||||
import org.alfresco.repo.model.Repository;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authority.AuthorityDAO;
|
||||
import org.alfresco.repo.workflow.WorkflowModel;
|
||||
import org.alfresco.repo.workflow.activiti.variable.ScriptNodeVariableType;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
||||
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.search.SearchService;
|
||||
import org.alfresco.service.cmr.security.AccessStatus;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.cmr.security.PersonService;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowDeployment;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.transaction.TransactionConfiguration;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* @author Nick Smith
|
||||
* @author Frederik Heremans
|
||||
* @since 3.4.e
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations={"classpath:test-database-context.xml",
|
||||
"classpath:activiti/test-activiti-component-context.xml",
|
||||
"classpath:alfresco/activiti-context.xml"})
|
||||
@TransactionConfiguration(transactionManager="transactionManager", defaultRollback=true)
|
||||
@Transactional
|
||||
public class AbstractActivitiComponentTest
|
||||
{
|
||||
protected static final String TEST_GROUP = "GROUP_testGroup";
|
||||
protected static final String TEST_USER = "testUser";
|
||||
protected static final String TEST_TASK_DEF = "activiti/testTransaction.bpmn20.xml";
|
||||
protected static final String TEST_TASK_KEY = "testTask";
|
||||
protected static final String TEST_ADHOC_DEF = "activiti/testAdhoc.bpmn20.xml";
|
||||
protected static final String TEST_SIGNALLING_DEF = "activiti/testSignalling.bpmn20.xml";
|
||||
protected static final String TEST_REVIEW_DEF = "activiti/testReview.bpmn20.xml";
|
||||
protected static final String TEST_ADHOC_KEY = "testAdhoc";
|
||||
protected static final String TEST_JOB_KEY = "testAdhoc";
|
||||
protected static final String TEST_JOB_DEF = "activiti/testJob.bpmn20.xml";
|
||||
protected static final String TEST_DIAGRAM_DEF = "activiti/testDiagram.bpmn20.xml";
|
||||
|
||||
protected static final String XML = MimetypeMap.MIMETYPE_XML;
|
||||
|
||||
@Autowired
|
||||
protected ProcessEngine processEngine;
|
||||
|
||||
@Resource(name="activitiWorkflowEngine")
|
||||
protected ActivitiWorkflowEngine workflowEngine;
|
||||
@Resource(name="activitiRuntimeService")
|
||||
protected RuntimeService runtime;
|
||||
@Resource(name="activitiRepositoryService")
|
||||
protected RepositoryService repo;
|
||||
@Resource(name="activitiTaskService")
|
||||
protected TaskService taskService;
|
||||
@Resource(name="activitiHistoryService")
|
||||
protected HistoryService historyService;
|
||||
@Resource(name="activitiManagementService")
|
||||
protected ManagementService managementService;
|
||||
|
||||
@Resource
|
||||
protected MessageService messageService;
|
||||
|
||||
@Resource(name="NamespaceService")
|
||||
protected NamespaceService namespaceService;
|
||||
|
||||
@Resource(name="DictionaryService")
|
||||
protected DictionaryService dictionaryService;
|
||||
|
||||
@Resource(name="NodeService")
|
||||
protected NodeService nodeService;
|
||||
|
||||
@Resource(name="searchService")
|
||||
protected SearchService unprotectedSearchService;
|
||||
|
||||
@Resource
|
||||
protected PermissionService permissionService;
|
||||
|
||||
@Resource(name="PersonService")
|
||||
protected PersonService personService;
|
||||
|
||||
@Resource
|
||||
protected AuthorityDAO authorityDAO;
|
||||
|
||||
@Resource
|
||||
protected ServiceRegistry serviceRegistry;
|
||||
|
||||
protected static final NodeRef rootNode = new NodeRef("workspace://root/");
|
||||
protected static final NodeRef companyHomeNode = new NodeRef("workspace://companyHome/");
|
||||
protected static final NodeRef adminPersonNode = new NodeRef("workspace://admin/");
|
||||
protected static final NodeRef adminHomeNode = new NodeRef("workspace://admin-home/");
|
||||
protected static final NodeRef testUserNode = new NodeRef("workspace://testUser/");
|
||||
protected static final NodeRef testGroupNode = new NodeRef("workspace://testGroup/");
|
||||
protected static final NodeRef testWorkflowPackage = new NodeRef("workspace://testPackage/");
|
||||
protected static final NodeRef testWorkflowContext = new NodeRef("workspace://testContext/");
|
||||
|
||||
protected WorkflowDefinition deployTestTaskDefinition()
|
||||
{
|
||||
return deployDefinition(TEST_TASK_DEF);
|
||||
}
|
||||
|
||||
protected WorkflowDefinition deployTestAdhocDefinition()
|
||||
{
|
||||
return deployDefinition(TEST_ADHOC_DEF);
|
||||
}
|
||||
|
||||
protected WorkflowDefinition deployTestSignallingDefinition()
|
||||
{
|
||||
return deployDefinition(TEST_SIGNALLING_DEF);
|
||||
}
|
||||
|
||||
protected WorkflowDefinition deployTestJobDefinition()
|
||||
{
|
||||
return deployDefinition(TEST_JOB_DEF);
|
||||
}
|
||||
|
||||
protected WorkflowDefinition deployTestDiagramDefinition()
|
||||
{
|
||||
return deployDefinition(TEST_DIAGRAM_DEF);
|
||||
}
|
||||
|
||||
protected WorkflowDefinition deployDefinition(String resource)
|
||||
{
|
||||
InputStream input = getInputStream(resource);
|
||||
WorkflowDeployment deployment = workflowEngine.deployDefinition(input, XML);
|
||||
WorkflowDefinition definition = deployment.getDefinition();
|
||||
return definition;
|
||||
}
|
||||
|
||||
protected InputStream getInputStream(String resource)
|
||||
{
|
||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||
InputStream input= classLoader.getResourceAsStream(resource);
|
||||
return input;
|
||||
}
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
mockNamespaceService();
|
||||
mockDictionaryService();
|
||||
mockNodeService();
|
||||
mockSearchService();
|
||||
mockPermissionService();
|
||||
mockPersonService();
|
||||
mockAuthorityDAO();
|
||||
mockServiceRegistry();
|
||||
|
||||
Repository repoHelper = mock(Repository.class);
|
||||
when(repoHelper.getCompanyHome()).thenReturn(companyHomeNode);
|
||||
workflowEngine.setRepositoryHelper(repoHelper);
|
||||
|
||||
// Also add custom type
|
||||
// TODO: Should come from configuration
|
||||
ScriptNodeVariableType variableType = new ScriptNodeVariableType();
|
||||
variableType.setServiceRegistry(serviceRegistry);
|
||||
|
||||
// ((ProcessEngineImpl)processEngine).getProcessEngineConfiguration().getVariableTypes().addType(variableType, 1);
|
||||
|
||||
// Use util to set current user to admin
|
||||
AuthenticationUtil.setFullyAuthenticatedUser("admin");
|
||||
|
||||
workflowEngine.afterPropertiesSet();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private void mockServiceRegistry()
|
||||
{
|
||||
// Set all services on the mocked Serviceregistry, injected by spring
|
||||
when(serviceRegistry.getNodeService()).thenReturn(nodeService);
|
||||
when(serviceRegistry.getDictionaryService()).thenReturn(dictionaryService);
|
||||
when(serviceRegistry.getPermissionService()).thenReturn(permissionService);
|
||||
}
|
||||
|
||||
private void mockAuthorityDAO()
|
||||
{
|
||||
when(authorityDAO.authorityExists(TEST_USER)).thenReturn(true);
|
||||
when(authorityDAO.authorityExists(TEST_GROUP)).thenReturn(true);
|
||||
|
||||
// We will return dummy node refs to authorities testUser and testGroup
|
||||
when(authorityDAO.getAuthorityNodeRefOrNull(TEST_USER)).thenReturn(testUserNode);
|
||||
when(authorityDAO.getAuthorityNodeRefOrNull(TEST_GROUP)).thenReturn(testGroupNode);
|
||||
}
|
||||
|
||||
private void mockPersonService()
|
||||
{
|
||||
// Checking if admin exists
|
||||
when(personService.personExists("admin")).thenReturn(true);
|
||||
|
||||
// Return reference to Admin person
|
||||
when(personService.getPerson("admin")).thenReturn(adminPersonNode);
|
||||
|
||||
// Check if test-user exists
|
||||
when(personService.personExists(TEST_USER)).thenReturn(true);
|
||||
when(personService.getPerson(TEST_USER)).thenReturn(testUserNode);
|
||||
}
|
||||
|
||||
private void mockPermissionService()
|
||||
{
|
||||
// Allow permission on all nodes
|
||||
when(permissionService.hasPermission((NodeRef) any(), anyString())).thenReturn(AccessStatus.ALLOWED);
|
||||
}
|
||||
|
||||
private void mockNodeService()
|
||||
{
|
||||
// Return root store
|
||||
when(nodeService.getRootNode(new StoreRef("workspace://SpacesStore"))).thenReturn(rootNode);
|
||||
|
||||
// Return company home and it's type
|
||||
when(nodeService.exists(companyHomeNode)).thenReturn(true);
|
||||
when(nodeService.getType((NodeRef) any())).thenReturn(QName.createQName("cm:folder"));
|
||||
|
||||
// Return admin's home property
|
||||
when(nodeService.getProperty(adminPersonNode, ContentModel.PROP_HOMEFOLDER)).thenReturn(adminHomeNode);
|
||||
|
||||
// Return testUser and testGroup types
|
||||
when(nodeService.getType(testUserNode)).thenReturn(ContentModel.TYPE_PERSON);
|
||||
when(nodeService.getType(testGroupNode)).thenReturn(ContentModel.TYPE_AUTHORITY);
|
||||
}
|
||||
|
||||
private void mockSearchService()
|
||||
{
|
||||
// When searching for company home, return single node
|
||||
when(unprotectedSearchService.selectNodes(rootNode, "spaces.company_home.childname", null, namespaceService, false)).thenReturn(Arrays.asList(companyHomeNode));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
private void mockDictionaryService()
|
||||
{
|
||||
Mockito.reset(dictionaryService);
|
||||
when(dictionaryService.getType((QName)any())).thenAnswer(new Answer<TypeDefinition>()
|
||||
{
|
||||
@Override
|
||||
public TypeDefinition answer(InvocationOnMock invocation) throws Throwable
|
||||
{
|
||||
QName name = (QName) invocation.getArguments()[0];
|
||||
TypeDefinition type = mock(TypeDefinition.class);
|
||||
|
||||
when(type.getName()).thenReturn(name);
|
||||
return type;
|
||||
}
|
||||
});
|
||||
|
||||
when(dictionaryService.getAnonymousType((QName)any())).thenAnswer(new Answer<TypeDefinition>()
|
||||
{
|
||||
@Override
|
||||
public TypeDefinition answer(InvocationOnMock invocation) throws Throwable
|
||||
{
|
||||
QName name = (QName) invocation.getArguments()[0];
|
||||
TypeDefinition type = mock(TypeDefinition.class);
|
||||
|
||||
when(type.getName()).thenReturn(name);
|
||||
|
||||
// Add a default value
|
||||
Map<QName, PropertyDefinition> props = new HashMap<QName, PropertyDefinition>();
|
||||
QName qname = QName.createQName("http://test", "myProp");
|
||||
|
||||
|
||||
DataTypeDefinition qNameDef = mock(DataTypeDefinition.class);
|
||||
when(qNameDef.getName()).thenReturn(DataTypeDefinition.QNAME);
|
||||
when(qNameDef.getJavaClassName()).thenReturn(QName.class.getName());
|
||||
|
||||
// Create dummy property type
|
||||
DataTypeDefinition def = mock(DataTypeDefinition.class);
|
||||
when(def.getName()).thenReturn(DataTypeDefinition.TEXT);
|
||||
when(def.getJavaClassName()).thenReturn(String.class.getName());
|
||||
|
||||
// Create dummy property definition
|
||||
PropertyDefinition prop = mock(PropertyDefinition.class);
|
||||
when(prop.getName()).thenReturn(qname);
|
||||
when(prop.getDefaultValue()).thenReturn("Default value");
|
||||
when(prop.getDataType()).thenReturn(def);
|
||||
|
||||
// Also add description
|
||||
PropertyDefinition description = mock(PropertyDefinition.class);
|
||||
when(description.getName()).thenReturn(WorkflowModel.PROP_DESCRIPTION);
|
||||
when(description.getDataType()).thenReturn(def);
|
||||
|
||||
// Add outcome property name
|
||||
PropertyDefinition outcomePropertyName = mock(PropertyDefinition.class);
|
||||
when(outcomePropertyName.getName()).thenReturn(WorkflowModel.PROP_OUTCOME_PROPERTY_NAME);
|
||||
when(outcomePropertyName.getDataType()).thenReturn(qNameDef);
|
||||
when(outcomePropertyName.getDefaultValue()).thenReturn("{http://test}testOutcome");
|
||||
|
||||
// Add outcome property
|
||||
PropertyDefinition outcomeProperty = mock(PropertyDefinition.class);
|
||||
when(outcomeProperty.getName()).thenReturn(QName.createQName("http://test", "testOutcome"));
|
||||
when(outcomeProperty.getDataType()).thenReturn(def);
|
||||
|
||||
props.put(qname, prop);
|
||||
props.put(WorkflowModel.PROP_DESCRIPTION, description);
|
||||
props.put(WorkflowModel.PROP_OUTCOME_PROPERTY_NAME, outcomePropertyName);
|
||||
props.put(QName.createQName("http://test", "testOutcome"), outcomeProperty);
|
||||
|
||||
when(type.getProperties()).thenReturn(props);
|
||||
return type;
|
||||
}
|
||||
});
|
||||
|
||||
// Mock type inheritance for person nodes
|
||||
when(dictionaryService.isSubClass(ContentModel.TYPE_PERSON, ContentModel.TYPE_PERSON)).thenReturn(true);
|
||||
}
|
||||
|
||||
private void mockNamespaceService()
|
||||
{
|
||||
namespaceService.registerNamespace(NamespaceService.BPM_MODEL_PREFIX, NamespaceService.BPM_MODEL_1_0_URI);
|
||||
namespaceService.registerNamespace(NamespaceService.DEFAULT_PREFIX, NamespaceService.DEFAULT_URI);
|
||||
namespaceService.registerNamespace(NamespaceService.WORKFLOW_MODEL_PREFIX, NamespaceService.WORKFLOW_MODEL_1_0_URI);
|
||||
namespaceService.registerNamespace("test", "http://test");
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown()
|
||||
{
|
||||
List<ProcessDefinition> defs = repo.createProcessDefinitionQuery()
|
||||
.processDefinitionKey(TEST_TASK_KEY)
|
||||
.list();
|
||||
HashSet<String> deployments = new HashSet<String>(defs.size());
|
||||
for (ProcessDefinition def : defs)
|
||||
{
|
||||
deployments.add(def.getDeploymentId());
|
||||
}
|
||||
for (String deployment : deployments)
|
||||
{
|
||||
List<ProcessDefinition> definitions = repo.createProcessDefinitionQuery()
|
||||
.deploymentId(deployment)
|
||||
.list();
|
||||
for (ProcessDefinition def : definitions)
|
||||
{
|
||||
killInstances(def);
|
||||
}
|
||||
repo.deleteDeployment(deployment);
|
||||
}
|
||||
}
|
||||
|
||||
public String mapQNameToName(QName name)
|
||||
{
|
||||
// NOTE: Map names using old conversion scheme (i.e. : -> _) as well as
|
||||
// new scheme (i.e. } -> _)
|
||||
// NOTE: Use new scheme
|
||||
String nameStr = name.toPrefixString(this.namespaceService);
|
||||
if (nameStr.indexOf('_') != -1 && nameStr.indexOf('_') < nameStr.indexOf(':'))
|
||||
{
|
||||
return nameStr.replace(':', '}');
|
||||
}
|
||||
return nameStr.replace(':', '_');
|
||||
}
|
||||
|
||||
|
||||
private void killInstances(ProcessDefinition def)
|
||||
{
|
||||
List<ProcessInstance> instances = runtime.createProcessInstanceQuery()
|
||||
.processDefinitionId(def.getId())
|
||||
.list();
|
||||
for (ProcessInstance instance : instances)
|
||||
{
|
||||
runtime.deleteProcessInstance(instance.getId(), "For test");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.workflow.activiti;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.workflow.AbstractMultitenantWorkflowTest;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowDeployment;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
|
||||
/**
|
||||
* @author Nick Smith
|
||||
* @since 4.0
|
||||
*
|
||||
*/
|
||||
public class ActivitiMultitenantWorkflowTest extends AbstractMultitenantWorkflowTest
|
||||
{
|
||||
private static final String CALLACTIVITY_SUBPROCESS_LOCATION = "activiti/test-callactivity-subprocess.bpmn20.xml";
|
||||
private static final String CALLACTIVITY_MAINPROCESS_LOCATION = "activiti/test-callactivity-main.bpmn20.xml";
|
||||
|
||||
|
||||
@Override
|
||||
protected String getEngine()
|
||||
{
|
||||
return ActivitiConstants.ENGINE_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTestDefinitionPath()
|
||||
{
|
||||
return "activiti/testTransaction.bpmn20.xml";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTestDefinitionKey()
|
||||
{
|
||||
return "activiti$testTask";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getAdhocDefinitionKey()
|
||||
{
|
||||
return "activiti$activitiAdhoc";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ALF-15939: Call-activity should be multi-tenant aware.
|
||||
*/
|
||||
public void testSubProcessCallActivity() throws Exception
|
||||
{
|
||||
// Run as User1 so tenant domain 1
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(user1);
|
||||
|
||||
// Deploy called sub-process on tenant domain 1
|
||||
InputStream input = getInputStream(CALLACTIVITY_SUBPROCESS_LOCATION);
|
||||
WorkflowDeployment deployment = workflowService.deployDefinition(getEngine(), input, XML);
|
||||
|
||||
// Deploy called main-process on tenant domain 1
|
||||
input = getInputStream(CALLACTIVITY_MAINPROCESS_LOCATION);
|
||||
deployment = workflowService.deployDefinition(getEngine(), input, XML);
|
||||
WorkflowDefinition mainProcessDefinition = deployment.getDefinition();
|
||||
|
||||
// Start a process, which immediately tries to call the sub-process before returning control to thread
|
||||
try {
|
||||
workflowService.startWorkflow(mainProcessDefinition.getId(), new HashMap<QName, Serializable>());
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
fail("No exception was expected while running process, but got: " + e.toString());
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.workflow.activiti;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.activiti.engine.ProcessEngine;
|
||||
import org.activiti.engine.ProcessEngineConfiguration;
|
||||
import org.activiti.engine.RepositoryService;
|
||||
import org.activiti.engine.RuntimeService;
|
||||
import org.activiti.engine.repository.Deployment;
|
||||
import org.activiti.engine.runtime.ProcessInstance;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
/**
|
||||
* @author Nick Smith
|
||||
* @since 3.4.e
|
||||
*/
|
||||
public class ActivitiSmokeTest extends TestCase
|
||||
{
|
||||
public void testDeploy() throws Exception
|
||||
{
|
||||
ProcessEngine engine = buildProcessEngine();
|
||||
|
||||
RepositoryService repoService = engine.getRepositoryService();
|
||||
|
||||
Deployment deployment = deployDefinition(repoService);
|
||||
|
||||
assertNotNull(deployment);
|
||||
|
||||
RuntimeService runtimeService = engine.getRuntimeService();
|
||||
try
|
||||
{
|
||||
ProcessInstance instance = runtimeService.startProcessInstanceByKey("testTask");
|
||||
assertNotNull(instance);
|
||||
|
||||
String instanceId = instance.getId();
|
||||
ProcessInstance instanceInDb = findProcessInstance(runtimeService, instanceId);
|
||||
assertNotNull(instanceInDb);
|
||||
runtimeService.deleteProcessInstance(instanceId, "");
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
// List<Deployment> deployments = repoService.createDeploymentQuery().list();
|
||||
// for (Deployment deployment2 : deployments)
|
||||
// {
|
||||
// repoService.deleteDeployment(deployment2.getId());
|
||||
// }
|
||||
|
||||
repoService.deleteDeployment(deployment.getId());
|
||||
}
|
||||
}
|
||||
|
||||
private Deployment deployDefinition(RepositoryService repoService) throws IOException
|
||||
{
|
||||
ClassPathResource resource = new ClassPathResource("org/alfresco/repo/workflow/activiti/testTransaction.bpmn20.xml");
|
||||
Deployment deployment = repoService.createDeployment()
|
||||
.addInputStream(resource.getFilename(), resource.getInputStream())
|
||||
.deploy();
|
||||
return deployment;
|
||||
}
|
||||
|
||||
private ProcessEngine buildProcessEngine()
|
||||
{
|
||||
String properties = "org/alfresco/repo/workflow/activiti/activiti.cfg.xml";
|
||||
ProcessEngine engine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource(properties).buildProcessEngine();
|
||||
return engine;
|
||||
}
|
||||
|
||||
private ProcessInstance findProcessInstance(RuntimeService runtimeService, String instanceId)
|
||||
{
|
||||
ProcessInstance instanceInDb = runtimeService.createProcessInstanceQuery()
|
||||
.processInstanceId(instanceId)
|
||||
.singleResult();
|
||||
return instanceInDb;
|
||||
}
|
||||
}
|
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.workflow.activiti;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.activiti.engine.ActivitiException;
|
||||
import org.activiti.engine.RepositoryService;
|
||||
import org.activiti.engine.RuntimeService;
|
||||
import org.activiti.engine.repository.Deployment;
|
||||
import org.activiti.engine.runtime.ProcessInstance;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
||||
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.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.util.ApplicationContextHelper;
|
||||
import org.apache.commons.lang.ArrayUtils;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
/**
|
||||
* @author Nick Smith
|
||||
* @since 3.4.e
|
||||
*/
|
||||
public class ActivitiSpringTest extends TestCase
|
||||
{
|
||||
private static final QName PROP_CHECK_VALUE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "check_value");
|
||||
private static final String PROC_DEF_KEY = "testTask";
|
||||
private static final String ACTIVITI_CONTEXT = "classpath:alfresco/activiti-context.xml";
|
||||
private static final QName ASPECT = ContentModel.ASPECT_ATTACHABLE;
|
||||
|
||||
private RuntimeService runtime;
|
||||
private RepositoryService repo;
|
||||
private Deployment deployment;
|
||||
private AuthenticationComponent authenticationComponent;
|
||||
private NodeService nodeService;
|
||||
private RetryingTransactionHelper txnHelper;
|
||||
private NodeRef workingNodeRef;
|
||||
|
||||
public void testSmoke() throws Exception
|
||||
{
|
||||
assertNotNull(runtime);
|
||||
|
||||
ProcessInstance instance = runtime.startProcessInstanceByKey(PROC_DEF_KEY);
|
||||
assertNotNull(instance);
|
||||
|
||||
String instanceId = instance.getId();
|
||||
ProcessInstance instanceInDb = findProcessInstance(instanceId);
|
||||
assertNotNull(instanceInDb);
|
||||
runtime.deleteProcessInstance(instance.getId(), "");
|
||||
assertNotNull(instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a process and then trigger a rollback by throwing an exception in Alfresco NodeService.
|
||||
* Check that the process instance was rolled back.
|
||||
*/
|
||||
public void testRollbackFromAlfresco()
|
||||
{
|
||||
RetryingTransactionCallback<String> callback = new RetryingTransactionCallback<String>()
|
||||
{
|
||||
public String execute() throws Throwable
|
||||
{
|
||||
ProcessInstance instance = runtime.startProcessInstanceByKey(PROC_DEF_KEY);
|
||||
String id = instance.getId();
|
||||
try
|
||||
{
|
||||
blowUp();
|
||||
}
|
||||
catch (InvalidNodeRefException e)
|
||||
{
|
||||
// Expected, but absorbed
|
||||
}
|
||||
return id;
|
||||
}
|
||||
};
|
||||
String id = txnHelper.doInTransaction(callback);
|
||||
ProcessInstance instance = findProcessInstance(id);
|
||||
if (instance != null)
|
||||
{
|
||||
runtime.deleteProcessInstance(id, "For test");
|
||||
fail("The process instance creation should have been rolled back!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a process and then trigger a rollback by throwing an exception in Alfresco NodeService.
|
||||
* Check that the process instance was rolled back.
|
||||
*/
|
||||
public void testRollbackFromActiviti()
|
||||
{
|
||||
RetryingTransactionCallback<Void> callback = new RetryingTransactionCallback<Void>()
|
||||
{
|
||||
public Void execute() throws Throwable
|
||||
{
|
||||
nodeService.addAspect(workingNodeRef, ASPECT, null);
|
||||
assertTrue("The node should have the aspect!", nodeService.hasAspect(workingNodeRef, ASPECT));
|
||||
try
|
||||
{
|
||||
runtime.signal("Fake Id");
|
||||
fail("Should throw an Exception here!");
|
||||
}
|
||||
catch (ActivitiException e)
|
||||
{
|
||||
// Expected, but absorbed
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
txnHelper.doInTransaction(callback);
|
||||
assertFalse("The node should not have the aspect!", nodeService.hasAspect(workingNodeRef, ASPECT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks nesting of two transactions with <code>requiresNew == true</code>
|
||||
*/
|
||||
public void testNestedWithoutPropogation()
|
||||
{
|
||||
RetryingTransactionCallback<Void> callback = new RetryingTransactionCallback<Void>()
|
||||
{
|
||||
public Void execute() throws Throwable
|
||||
{
|
||||
ProcessInstance instance = runtime.startProcessInstanceByKey(PROC_DEF_KEY);
|
||||
final String id = instance.getId();
|
||||
|
||||
ProcessInstance instanceInDb = findProcessInstance(id);
|
||||
assertNotNull("Can't read process instance in same transaction!", instanceInDb);
|
||||
RetryingTransactionCallback<Void> callbackInner = new RetryingTransactionCallback<Void>()
|
||||
{
|
||||
public Void execute() throws Throwable
|
||||
{
|
||||
ProcessInstance instanceInDb2 = findProcessInstance(id);
|
||||
assertNull("Should not be able to read process instance in inner transaction!", instanceInDb2);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
try
|
||||
{
|
||||
txnHelper.doInTransaction(callbackInner, false, true);
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
runtime.deleteProcessInstance(id, "FOr test");
|
||||
}
|
||||
}
|
||||
};
|
||||
txnHelper.doInTransaction(callback);
|
||||
}
|
||||
|
||||
private Long blowUp()
|
||||
{
|
||||
NodeRef invalidNodeRef = new NodeRef(workingNodeRef.getStoreRef(), "BOGUS");
|
||||
nodeService.setProperty(invalidNodeRef, PROP_CHECK_VALUE, null);
|
||||
fail("Expected to generate an InvalidNodeRefException");
|
||||
return null;
|
||||
}
|
||||
|
||||
private ProcessInstance findProcessInstance(String instanceId)
|
||||
{
|
||||
return runtime.createProcessInstanceQuery()
|
||||
.processInstanceId(instanceId)
|
||||
.singleResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected void setUp() throws Exception
|
||||
{
|
||||
ConfigurableApplicationContext appContext = loadContext();
|
||||
this.repo = (RepositoryService) appContext.getBean("activitiRepositoryService");
|
||||
this.runtime = (RuntimeService) appContext.getBean("activitiRuntimeService");
|
||||
|
||||
ServiceRegistry serviceRegistry = (ServiceRegistry) appContext.getBean(ServiceRegistry.SERVICE_REGISTRY);
|
||||
authenticationComponent = (AuthenticationComponent) appContext.getBean("authenticationComponent");
|
||||
TransactionService transactionService = serviceRegistry.getTransactionService();
|
||||
nodeService = serviceRegistry.getNodeService();
|
||||
txnHelper = transactionService.getRetryingTransactionHelper();
|
||||
|
||||
// authenticate
|
||||
authenticationComponent.setSystemUserAsCurrentUser();
|
||||
|
||||
StoreRef storeRef = nodeService.createStore(
|
||||
StoreRef.PROTOCOL_WORKSPACE,
|
||||
"test-" + getName() + "-" + System.currentTimeMillis());
|
||||
NodeRef rootNodeRef = nodeService.getRootNode(storeRef);
|
||||
// Create a node to work on
|
||||
workingNodeRef = nodeService.createNode(
|
||||
rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, getName()),
|
||||
ContentModel.TYPE_CMOBJECT).getChildRef();
|
||||
|
||||
String resource = "org/alfresco/repo/workflow/activiti/testTransaction.bpmn20.xml";
|
||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||
InputStream input= classLoader.getResourceAsStream(resource);
|
||||
this.deployment = repo.createDeployment()
|
||||
.addInputStream(resource, input)
|
||||
.deploy();
|
||||
}
|
||||
|
||||
private String[] getConfigLocations()
|
||||
{
|
||||
String[] defaultLocations = ApplicationContextHelper.CONFIG_LOCATIONS;
|
||||
Object[] locations = ArrayUtils.add(defaultLocations, ACTIVITI_CONTEXT);
|
||||
return (String[]) locations;
|
||||
}
|
||||
|
||||
private ConfigurableApplicationContext loadContext() throws Exception
|
||||
{
|
||||
String[] locations = getConfigLocations();
|
||||
return new ClassPathXmlApplicationContext(locations);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected void tearDown() throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
repo.deleteDeployment(deployment.getId());
|
||||
authenticationComponent.clearCurrentSecurityContext();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// Do Nothing }
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.workflow.activiti;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.activiti.engine.ActivitiException;
|
||||
import org.activiti.engine.RepositoryService;
|
||||
import org.activiti.engine.RuntimeService;
|
||||
import org.activiti.engine.repository.Deployment;
|
||||
import org.activiti.engine.runtime.ProcessInstance;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
||||
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.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.util.ApplicationContextHelper;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
/**
|
||||
* @author Nick Smith
|
||||
* @since 3.4.e
|
||||
*/
|
||||
public class ActivitiSpringTransactionTest extends TestCase
|
||||
{
|
||||
private static final QName PROP_CHECK_VALUE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "check_value");
|
||||
private static final String PROC_DEF_KEY = "testTask";
|
||||
private static final QName ASPECT = ContentModel.ASPECT_ATTACHABLE;
|
||||
|
||||
private RuntimeService runtime;
|
||||
private RepositoryService repo;
|
||||
private Deployment deployment;
|
||||
private AuthenticationComponent authenticationComponent;
|
||||
private NodeService nodeService;
|
||||
private RetryingTransactionHelper txnHelper;
|
||||
private NodeRef workingNodeRef;
|
||||
|
||||
public void testSmoke() throws Exception
|
||||
{
|
||||
assertNotNull(runtime);
|
||||
|
||||
ProcessInstance instance = runtime.startProcessInstanceByKey(PROC_DEF_KEY);
|
||||
assertNotNull(instance);
|
||||
|
||||
String instanceId = instance.getId();
|
||||
ProcessInstance instanceInDb = findProcessInstance(instanceId);
|
||||
assertNotNull(instanceInDb);
|
||||
runtime.deleteProcessInstance(instance.getId(), "");
|
||||
assertNotNull(instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a process and then trigger a rollback by throwing an exception in Alfresco NodeService.
|
||||
* Check that the process instance was rolled back.
|
||||
*/
|
||||
public void testRollbackFromAlfresco()
|
||||
{
|
||||
RetryingTransactionCallback<String> callback = new RetryingTransactionCallback<String>()
|
||||
{
|
||||
public String execute() throws Throwable
|
||||
{
|
||||
ProcessInstance instance = runtime.startProcessInstanceByKey(PROC_DEF_KEY);
|
||||
String id = instance.getId();
|
||||
try
|
||||
{
|
||||
blowUp();
|
||||
}
|
||||
catch (InvalidNodeRefException e)
|
||||
{
|
||||
// Expected, but absorbed
|
||||
}
|
||||
return id;
|
||||
}
|
||||
};
|
||||
String id = txnHelper.doInTransaction(callback);
|
||||
ProcessInstance instance = findProcessInstance(id);
|
||||
if (instance != null)
|
||||
{
|
||||
runtime.deleteProcessInstance(id, "For test");
|
||||
fail("The process instance creation should have been rolled back!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a process and then trigger a rollback by throwing an exception in Alfresco NodeService.
|
||||
* Check that the process instance was rolled back.
|
||||
*/
|
||||
public void testRollbackFromActiviti()
|
||||
{
|
||||
RetryingTransactionCallback<Void> callback = new RetryingTransactionCallback<Void>()
|
||||
{
|
||||
public Void execute() throws Throwable
|
||||
{
|
||||
nodeService.addAspect(workingNodeRef, ASPECT, null);
|
||||
assertTrue("The node should have the aspect!", nodeService.hasAspect(workingNodeRef, ASPECT));
|
||||
try
|
||||
{
|
||||
runtime.signal("Fake Id");
|
||||
fail("Should throw an Exception here!");
|
||||
}
|
||||
catch (ActivitiException e)
|
||||
{
|
||||
// Expected, but absorbed
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
txnHelper.doInTransaction(callback);
|
||||
assertFalse("The node should not have the aspect!", nodeService.hasAspect(workingNodeRef, ASPECT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks nesting of two transactions with <code>requiresNew == true</code>
|
||||
*/
|
||||
public void testNestedWithoutPropogation()
|
||||
{
|
||||
RetryingTransactionCallback<Void> callback = new RetryingTransactionCallback<Void>()
|
||||
{
|
||||
public Void execute() throws Throwable
|
||||
{
|
||||
ProcessInstance instance = runtime.startProcessInstanceByKey(PROC_DEF_KEY);
|
||||
final String id = instance.getId();
|
||||
|
||||
ProcessInstance instanceInDb = findProcessInstance(id);
|
||||
assertNotNull("Can't read process instance in same transaction!", instanceInDb);
|
||||
RetryingTransactionCallback<Void> callbackInner = new RetryingTransactionCallback<Void>()
|
||||
{
|
||||
public Void execute() throws Throwable
|
||||
{
|
||||
ProcessInstance instanceInDb2 = findProcessInstance(id);
|
||||
assertNull("Should not be able to read process instance in inner transaction!", instanceInDb2);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
try
|
||||
{
|
||||
txnHelper.doInTransaction(callbackInner, false, true);
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
runtime.deleteProcessInstance(id, "FOr test");
|
||||
}
|
||||
}
|
||||
};
|
||||
txnHelper.doInTransaction(callback);
|
||||
}
|
||||
|
||||
private Long blowUp()
|
||||
{
|
||||
NodeRef invalidNodeRef = new NodeRef(workingNodeRef.getStoreRef(), "BOGUS");
|
||||
nodeService.setProperty(invalidNodeRef, PROP_CHECK_VALUE, null);
|
||||
fail("Expected to generate an InvalidNodeRefException");
|
||||
return null;
|
||||
}
|
||||
|
||||
private ProcessInstance findProcessInstance(String instanceId)
|
||||
{
|
||||
return runtime.createProcessInstanceQuery()
|
||||
.processInstanceId(instanceId)
|
||||
.singleResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected void setUp() throws Exception
|
||||
{
|
||||
ApplicationContext appContext = ApplicationContextHelper.getApplicationContext();
|
||||
this.repo = (RepositoryService) appContext.getBean("activitiRepositoryService");
|
||||
this.runtime = (RuntimeService) appContext.getBean("activitiRuntimeService");
|
||||
|
||||
ServiceRegistry serviceRegistry = (ServiceRegistry) appContext.getBean(ServiceRegistry.SERVICE_REGISTRY);
|
||||
authenticationComponent = (AuthenticationComponent) appContext.getBean("authenticationComponent");
|
||||
TransactionService transactionService = serviceRegistry.getTransactionService();
|
||||
nodeService = serviceRegistry.getNodeService();
|
||||
txnHelper = transactionService.getRetryingTransactionHelper();
|
||||
|
||||
// authenticate
|
||||
authenticationComponent.setSystemUserAsCurrentUser();
|
||||
|
||||
StoreRef storeRef = nodeService.createStore(
|
||||
StoreRef.PROTOCOL_WORKSPACE,
|
||||
"test-" + getName() + "-" + System.currentTimeMillis());
|
||||
NodeRef rootNodeRef = nodeService.getRootNode(storeRef);
|
||||
// Create a node to work on
|
||||
workingNodeRef = nodeService.createNode(
|
||||
rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, getName()),
|
||||
ContentModel.TYPE_CMOBJECT).getChildRef();
|
||||
|
||||
String resource = "activiti/testTransaction.bpmn20.xml";
|
||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||
InputStream input= classLoader.getResourceAsStream(resource);
|
||||
this.deployment = repo.createDeployment()
|
||||
.addInputStream(resource, input)
|
||||
.deploy();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected void tearDown() throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
repo.deleteDeployment(deployment.getId(), true);
|
||||
authenticationComponent.clearCurrentSecurityContext();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// Do Nothing }
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,944 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.workflow.activiti;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.activiti.engine.history.HistoricDetail;
|
||||
import org.activiti.engine.history.HistoricTaskInstance;
|
||||
import org.activiti.engine.history.HistoricVariableUpdate;
|
||||
import org.activiti.engine.task.Task;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.workflow.BPMEngineRegistry;
|
||||
import org.alfresco.repo.workflow.WorkflowModel;
|
||||
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowException;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowPath;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTask;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTaskQuery;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Nick Smith
|
||||
* @author Frederik Heremans
|
||||
* @since 3.4.e
|
||||
*/
|
||||
public class ActivitiTaskComponentTest extends AbstractActivitiComponentTest
|
||||
{
|
||||
private WorkflowDefinition workflowDef;
|
||||
|
||||
@Test
|
||||
public void testGetStartTask()
|
||||
{
|
||||
try
|
||||
{
|
||||
workflowEngine.getStartTask("Foo");
|
||||
fail("Should blow up if Id is wrong format!");
|
||||
}
|
||||
catch(WorkflowException e)
|
||||
{
|
||||
// Do Nothing
|
||||
}
|
||||
|
||||
WorkflowTask result = workflowEngine.getStartTask(ActivitiConstants.ENGINE_ID + "$Foo");
|
||||
assertNull("Should not find any result for fake (but valid) Id.", result);
|
||||
|
||||
Map<QName, Serializable> params = new HashMap<QName, Serializable>();
|
||||
String comment = "Start task description";
|
||||
params.put(WorkflowModel.PROP_COMMENT, comment);
|
||||
params.put(WorkflowModel.PROP_PRIORITY, 1 );
|
||||
Date dueDate = new Date();
|
||||
params.put(WorkflowModel.PROP_DUE_DATE, dueDate );
|
||||
|
||||
WorkflowPath path = workflowEngine.startWorkflow(workflowDef.getId(), params);
|
||||
String instanceId = path.getInstance().getId();
|
||||
WorkflowTask task = workflowEngine.getStartTask(instanceId);
|
||||
assertNotNull("Task shoudl exist!", task);
|
||||
|
||||
String localId = ActivitiConstants.START_TASK_PREFIX+BPMEngineRegistry.getLocalId(instanceId);
|
||||
String taskId = BPMEngineRegistry.createGlobalId(ActivitiConstants.ENGINE_ID, localId);
|
||||
assertEquals("Start Task Id is wrong", taskId, task.getId());
|
||||
|
||||
assertEquals("The start task path is wrong!", path.getId(), task.getPath().getId());
|
||||
TypeDefinition definition = task.getDefinition().getMetadata();
|
||||
assertNotNull(definition);
|
||||
String name = definition.getName().toPrefixString(namespaceService).replace(':', '_');
|
||||
assertEquals("bpm_foo", name);
|
||||
|
||||
assertEquals(name, task.getName());
|
||||
assertEquals(name, task.getTitle());
|
||||
assertEquals(name, task.getDescription());
|
||||
assertEquals(WorkflowTaskState.IN_PROGRESS, task.getState());
|
||||
assertEquals(name, task.getDescription());
|
||||
|
||||
// Check start task properties populated.
|
||||
Map<QName, Serializable> properties = task.getProperties();
|
||||
assertEquals(comment, properties.get(WorkflowModel.PROP_COMMENT));
|
||||
assertEquals(1, properties.get(WorkflowModel.PROP_PRIORITY));
|
||||
assertEquals(dueDate, properties.get(WorkflowModel.PROP_DUE_DATE));
|
||||
|
||||
// Check start task after task is completed.
|
||||
task = workflowEngine.endTask(task.getId(), null);
|
||||
|
||||
assertEquals("Start Task Id is wrong", taskId, task.getId());
|
||||
|
||||
assertEquals("The start task path is wrong!", path.getId(), task.getPath().getId());
|
||||
definition = task.getDefinition().getMetadata();
|
||||
assertNotNull(definition);
|
||||
name = definition.getName().toPrefixString(namespaceService).replace(':', '_');
|
||||
assertEquals("bpm_foo", name);
|
||||
|
||||
assertEquals(name, task.getName());
|
||||
assertEquals(name, task.getTitle());
|
||||
assertEquals(name, task.getDescription());
|
||||
assertEquals(WorkflowTaskState.COMPLETED, task.getState());
|
||||
assertEquals(name, task.getDescription());
|
||||
|
||||
// Check start task properties populated.
|
||||
properties = task.getProperties();
|
||||
assertEquals(comment, properties.get(WorkflowModel.PROP_COMMENT));
|
||||
assertEquals(1, properties.get(WorkflowModel.PROP_PRIORITY));
|
||||
assertEquals(dueDate, properties.get(WorkflowModel.PROP_DUE_DATE));
|
||||
|
||||
// Check start task for historic process.
|
||||
workflowEngine.cancelWorkflow(instanceId);
|
||||
task = workflowEngine.getStartTask(instanceId);
|
||||
|
||||
assertNull(task);
|
||||
|
||||
|
||||
// assertEquals("Start Task Id is wrong", taskId, task.getId());
|
||||
//
|
||||
// assertEquals("The start task path is wrong!", path.getId(), task.getPath().getId());
|
||||
// definition = task.getDefinition().getMetadata();
|
||||
// assertNotNull(definition);
|
||||
// name = definition.getName().toPrefixString(namespaceService).replace(':', '_');
|
||||
// assertEquals("bpm_foo", name);
|
||||
//
|
||||
// assertEquals(name, task.getName());
|
||||
// assertEquals(name, task.getTitle());
|
||||
// assertEquals(name, task.getDescription());
|
||||
// assertEquals(WorkflowTaskState.COMPLETED, task.getState());
|
||||
// assertEquals(name, task.getDescription());
|
||||
//
|
||||
// // Check start task properties populated.
|
||||
// properties = task.getProperties();
|
||||
// assertEquals(comment, properties.get(WorkflowModel.PROP_COMMENT));
|
||||
// assertEquals(1, properties.get(WorkflowModel.PROP_PRIORITY));
|
||||
// assertEquals(dueDate, properties.get(WorkflowModel.PROP_DUE_DATE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTaskById() throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
workflowEngine.getTaskById("Foo");
|
||||
fail("Should blow up if Id is wrong format!");
|
||||
}
|
||||
catch(WorkflowException e)
|
||||
{
|
||||
// Do Nothing
|
||||
}
|
||||
|
||||
WorkflowTask result = workflowEngine.getTaskById(ActivitiConstants.ENGINE_ID + "$Foo");
|
||||
assertNull("Should not find any result for fake (but valid) Id.", result);
|
||||
|
||||
WorkflowPath path = workflowEngine.startWorkflow(workflowDef.getId(), new HashMap<QName, Serializable>());
|
||||
Task task = taskService.createTaskQuery()
|
||||
.executionId(BPMEngineRegistry.getLocalId(path.getId()))
|
||||
.singleResult();
|
||||
assertNotNull("Task shoudl exist!", task);
|
||||
|
||||
String taskId = BPMEngineRegistry.createGlobalId(ActivitiConstants.ENGINE_ID, task.getId());
|
||||
WorkflowTask wfTask = workflowEngine.getTaskById(taskId);
|
||||
assertNotNull(wfTask);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetStartTaskById() throws Exception
|
||||
{
|
||||
|
||||
WorkflowTask result = workflowEngine.getTaskById(ActivitiConstants.ENGINE_ID + "$Foo");
|
||||
assertNull("Should not find any result for fake (but valid) Id.", result);
|
||||
|
||||
WorkflowPath path = workflowEngine.startWorkflow(workflowDef.getId(), new HashMap<QName, Serializable>());
|
||||
|
||||
Task task = taskService.createTaskQuery()
|
||||
.executionId(BPMEngineRegistry.getLocalId(path.getId()))
|
||||
.singleResult();
|
||||
|
||||
// A start task should be available for the process instance
|
||||
String startTaskId = ActivitiConstants.START_TASK_PREFIX + task.getProcessInstanceId();
|
||||
|
||||
String taskId = createGlobalId(startTaskId);
|
||||
WorkflowTask wfTask = workflowEngine.getTaskById(taskId);
|
||||
assertNotNull(wfTask);
|
||||
assertEquals(createGlobalId(task.getProcessInstanceId()), wfTask.getPath().getId());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testGetFinishedTaskById() throws Exception
|
||||
{
|
||||
WorkflowPath path = workflowEngine.startWorkflow(workflowDef.getId(), new HashMap<QName, Serializable>());
|
||||
|
||||
// Finish the start-task
|
||||
WorkflowTask startTask = workflowEngine.getStartTask(path.getInstance().getId());
|
||||
workflowEngine.endTask(startTask.getId(), null);
|
||||
|
||||
// Set some task properties on the first task, different types
|
||||
List<WorkflowTask> tasks = workflowEngine.getTasksForWorkflowPath(path.getId());
|
||||
String finishedTaskId = tasks.get(0).getId();
|
||||
|
||||
Map<QName, Serializable> props = new HashMap<QName, Serializable>();
|
||||
props.put(WorkflowModel.PROP_DESCRIPTION, "Task description");
|
||||
props.put(WorkflowModel.PROP_PRIORITY, 1234);
|
||||
props.put(QName.createQName("myprop1"), "Property value");
|
||||
props.put(QName.createQName("myprop2"), Boolean.TRUE);
|
||||
props.put(QName.createQName("myprop3"), 12345);
|
||||
props.put(QName.createQName("myprop4"), 45678L);
|
||||
|
||||
workflowEngine.updateTask(finishedTaskId, props, null, null);
|
||||
|
||||
// Finish the first task, this task will be used in this test
|
||||
workflowEngine.endTask(finishedTaskId, null);
|
||||
|
||||
// Get the finished task
|
||||
WorkflowTask finishedTask = workflowEngine.getTaskById(finishedTaskId);
|
||||
assertNotNull(finishedTask);
|
||||
|
||||
Assert.assertEquals("Task description", finishedTask.getDescription());
|
||||
|
||||
Assert.assertEquals(finishedTaskId, finishedTask.getId());
|
||||
Assert.assertEquals("bpm_foo_task", finishedTask.getName());
|
||||
Assert.assertEquals("Task", finishedTask.getTitle());
|
||||
Assert.assertEquals(WorkflowTaskState.COMPLETED, finishedTask.getState());
|
||||
|
||||
// Check if typeDefinition (formKey) is preserved on finished tasks
|
||||
Assert.assertEquals("task name", finishedTask.getDefinition().getId(), "bpm_foo_task");
|
||||
|
||||
// Check workflowpath
|
||||
Assert.assertEquals(path.getId(), finishedTask.getPath().getId());
|
||||
Assert.assertEquals(path.getInstance().getId(), finishedTask.getPath().getInstance().getId());
|
||||
|
||||
// Check variables
|
||||
Assert.assertEquals("Property value", finishedTask.getProperties().get(QName.createQName("myprop1")));
|
||||
Assert.assertEquals(Boolean.TRUE, finishedTask.getProperties().get(QName.createQName("myprop2")));
|
||||
Assert.assertEquals(12345, finishedTask.getProperties().get(QName.createQName("myprop3")));
|
||||
Assert.assertEquals(45678L, finishedTask.getProperties().get(QName.createQName("myprop4")));
|
||||
|
||||
// Check pooled actors, should be one user and one group
|
||||
List<NodeRef> pooledActors = (List<NodeRef>) finishedTask.getProperties().get(WorkflowModel.ASSOC_POOLED_ACTORS);
|
||||
Assert.assertNotNull(pooledActors);
|
||||
Assert.assertEquals(2, pooledActors.size());
|
||||
Assert.assertTrue(pooledActors.contains(testGroupNode));
|
||||
Assert.assertTrue(pooledActors.contains(testUserNode));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEndTask() throws Exception
|
||||
{
|
||||
WorkflowPath path = workflowEngine.startWorkflow(workflowDef.getId(), new HashMap<QName, Serializable>());
|
||||
|
||||
Task task = taskService.createTaskQuery()
|
||||
.executionId(BPMEngineRegistry.getLocalId(path.getId()))
|
||||
.singleResult();
|
||||
|
||||
assertNotNull("Task should exist!", task);
|
||||
|
||||
String globalTaskId = createGlobalId(task.getId());
|
||||
// Set a custom property on the task, this will be flushed
|
||||
// to process-instance once task is completed
|
||||
Map<QName, Serializable> props = new HashMap<QName, Serializable>();
|
||||
props.put(QName.createQName("http://test", "myVar"), "test123");
|
||||
|
||||
workflowEngine.updateTask(globalTaskId, props, null, null);
|
||||
|
||||
// Now end the task
|
||||
workflowEngine.endTask(globalTaskId, null);
|
||||
|
||||
// Check if process-instance now contains the variable of the finished task
|
||||
List<HistoricDetail> updates = historyService.createHistoricDetailQuery()
|
||||
.variableUpdates()
|
||||
.processInstanceId(task.getProcessInstanceId())
|
||||
.list();
|
||||
|
||||
boolean found = false;
|
||||
for(HistoricDetail detail : updates)
|
||||
{
|
||||
HistoricVariableUpdate update = (HistoricVariableUpdate) detail;
|
||||
if (update.getVariableName().equals("test_myVar"))
|
||||
{
|
||||
Assert.assertEquals("test123", update.getValue());
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
Assert.assertTrue("Task variables are not flushed to process-instance", found);
|
||||
|
||||
// Check task assignee, should be currently logged in user
|
||||
HistoricTaskInstance hti = historyService.createHistoricTaskInstanceQuery().taskId(task.getId()).singleResult();
|
||||
assertNotNull(hti);
|
||||
assertEquals("admin", hti.getAssignee());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAssignedTasks() throws Exception
|
||||
{
|
||||
performGetAssignedTasks(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAssignedTasksLazyInitialization() throws Exception
|
||||
{
|
||||
// Lazy tasks should behave in exactly the same way, transparent for the user
|
||||
performGetAssignedTasks(true);
|
||||
}
|
||||
|
||||
protected void performGetAssignedTasks(boolean lazyInitialization) throws Exception
|
||||
{
|
||||
HashMap<QName, Serializable> props = new HashMap<QName, Serializable>();
|
||||
props.put(WorkflowModel.PROP_WORKFLOW_DUE_DATE, new Date());
|
||||
WorkflowPath path = workflowEngine.startWorkflow(workflowDef.getId(), props);
|
||||
|
||||
// Get start task
|
||||
WorkflowTask startTask = workflowEngine.getStartTask(path.getInstance().getId());
|
||||
assertNotNull(startTask);
|
||||
|
||||
// Finish the start task
|
||||
workflowEngine.endTask(startTask.getId(), null);
|
||||
|
||||
// No task should be assigned yet
|
||||
Assert.assertEquals(0, workflowEngine.getAssignedTasks("testUser", WorkflowTaskState.IN_PROGRESS, lazyInitialization).size());
|
||||
|
||||
// Get pooled task and assign
|
||||
List<WorkflowTask> tasks = workflowEngine.getTasksForWorkflowPath(path.getId());
|
||||
assertNotNull(tasks);
|
||||
Assert.assertEquals(1, tasks.size());
|
||||
|
||||
workflowEngine.updateTask(tasks.get(0).getId(), Collections.singletonMap(ContentModel.PROP_OWNER, (Serializable)"testUser"), null, null);
|
||||
|
||||
// A task should be assigned to the testUser
|
||||
tasks = workflowEngine.getAssignedTasks("testUser", WorkflowTaskState.IN_PROGRESS, lazyInitialization);
|
||||
assertNotNull(tasks);
|
||||
Assert.assertEquals(1, tasks.size());
|
||||
|
||||
// Check task
|
||||
WorkflowTask task = tasks.get(0);
|
||||
assertEquals("Task", task.getDescription());
|
||||
assertEquals("Task", task.getTitle());
|
||||
assertEquals(WorkflowTaskState.IN_PROGRESS, task.getState());
|
||||
assertEquals("testUser", task.getProperties().get(ContentModel.PROP_OWNER));
|
||||
assertEquals(props.get(WorkflowModel.PROP_DUE_DATE), task.getProperties().get(WorkflowModel.PROP_DUE_DATE));
|
||||
assertNotNull(task.getProperties().get(WorkflowModel.PROP_START_DATE));
|
||||
|
||||
// Complete the task as "testUser"
|
||||
AuthenticationUtil.setFullyAuthenticatedUser("testUser");
|
||||
workflowEngine.endTask(task.getId(), ActivitiConstants.DEFAULT_TRANSITION_NAME);
|
||||
|
||||
// NO active task should be assigned to the testUser
|
||||
tasks = workflowEngine.getAssignedTasks("testUser", WorkflowTaskState.IN_PROGRESS, lazyInitialization);
|
||||
assertNotNull(tasks);
|
||||
Assert.assertEquals(0, tasks.size());
|
||||
|
||||
// One completed task should be assigned to the testUser
|
||||
tasks = workflowEngine.getAssignedTasks("testUser", WorkflowTaskState.COMPLETED, lazyInitialization);
|
||||
assertNotNull(tasks);
|
||||
Assert.assertEquals(1, tasks.size());
|
||||
|
||||
// Check completed task
|
||||
task = tasks.get(0);
|
||||
assertEquals("Task", task.getDescription());
|
||||
assertEquals("Task", task.getTitle());
|
||||
assertEquals(WorkflowTaskState.COMPLETED, task.getState());
|
||||
assertEquals("testUser", task.getProperties().get(ContentModel.PROP_OWNER));
|
||||
assertEquals(props.get(WorkflowModel.PROP_DUE_DATE), task.getProperties().get(WorkflowModel.PROP_DUE_DATE));
|
||||
assertNotNull(task.getProperties().get(WorkflowModel.PROP_START_DATE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPooledTasks() throws Exception
|
||||
{
|
||||
performGetPooledTasksTest(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPooledTasksLazyInitialization() throws Exception
|
||||
{
|
||||
// Lazy tasks should behave in exactly the same way, transparent for the user
|
||||
performGetPooledTasksTest(true);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void performGetPooledTasksTest(boolean lazy)
|
||||
{
|
||||
// The first task in the TestTaskDefinition has candidate group 'testGroup'
|
||||
// and candidate-user 'testUser'
|
||||
WorkflowPath path = workflowEngine.startWorkflow(workflowDef.getId(), new HashMap<QName, Serializable>());
|
||||
|
||||
// Get start task
|
||||
WorkflowTask startTask = workflowEngine.getStartTask(path.getInstance().getId());
|
||||
assertNotNull(startTask);
|
||||
|
||||
// Finish the start task
|
||||
workflowEngine.endTask(startTask.getId(), null);
|
||||
|
||||
List<WorkflowTask> tasks = workflowEngine.getTasksForWorkflowPath(path.getId());
|
||||
assertNotNull(tasks);
|
||||
Assert.assertEquals(1, tasks.size());
|
||||
|
||||
// Check if the ASSOC_POOLED_ACTORS is set on the task, to be sure
|
||||
// pooled actors are used on task
|
||||
WorkflowTask theTask = tasks.get(0);
|
||||
|
||||
Serializable pooledActors = theTask.getProperties().get(WorkflowModel.ASSOC_POOLED_ACTORS);
|
||||
assertNotNull(pooledActors);
|
||||
|
||||
// Group and user should be present
|
||||
List<NodeRef> pooledActorNodes = (List<NodeRef>) pooledActors;
|
||||
Assert.assertEquals(2, pooledActorNodes.size());
|
||||
Assert.assertTrue(pooledActorNodes.contains(testUserNode));
|
||||
Assert.assertTrue(pooledActorNodes.contains(testGroupNode));
|
||||
|
||||
// The task should be found when pooled tasks are requested
|
||||
List<WorkflowTask> pooledUserTasks = workflowEngine.getPooledTasks(Arrays.asList(TEST_USER), lazy);
|
||||
assertNotNull(pooledUserTasks);
|
||||
Assert.assertEquals(1, pooledUserTasks.size());
|
||||
Assert.assertEquals(theTask.getId(), pooledUserTasks.get(0).getId());
|
||||
|
||||
// The task should be found when pooled taskes are requested
|
||||
List<WorkflowTask> pooledGroupTasks = workflowEngine.getPooledTasks(Arrays.asList(TEST_GROUP), lazy);
|
||||
assertNotNull(pooledGroupTasks);
|
||||
Assert.assertEquals(1, pooledGroupTasks.size());
|
||||
Assert.assertEquals(theTask.getId(), pooledGroupTasks.get(0).getId());
|
||||
|
||||
// Only a single task should be found when task is both pooled for testUser and testGroup
|
||||
List<WorkflowTask> pooledTasks = workflowEngine.getPooledTasks(Arrays.asList(TEST_USER, TEST_GROUP), lazy);
|
||||
assertNotNull(pooledTasks);
|
||||
Assert.assertEquals(1, pooledTasks.size());
|
||||
Assert.assertEquals(theTask.getId(), pooledTasks.get(0).getId());
|
||||
|
||||
// No tasks should be found
|
||||
List<WorkflowTask> unexistingPooledTasks = workflowEngine.getPooledTasks(Arrays.asList("unexisting"), lazy);
|
||||
assertNotNull(unexistingPooledTasks);
|
||||
Assert.assertEquals(0, unexistingPooledTasks.size());
|
||||
|
||||
// If one authority matches, task should be returned
|
||||
pooledGroupTasks = workflowEngine.getPooledTasks(Arrays.asList("unexistinggroup",TEST_GROUP), lazy);
|
||||
assertNotNull(pooledGroupTasks);
|
||||
Assert.assertEquals(1, pooledGroupTasks.size());
|
||||
Assert.assertEquals(theTask.getId(), pooledGroupTasks.get(0).getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueryTasksInProgress() throws Exception
|
||||
{
|
||||
// Testing all query functionality for WorkflowTaskState.IN_PROGRESS
|
||||
WorkflowPath path = workflowEngine.startWorkflow(workflowDef.getId(), new HashMap<QName, Serializable>());
|
||||
|
||||
Task task = taskService.createTaskQuery()
|
||||
.executionId(BPMEngineRegistry.getLocalId(path.getId()))
|
||||
.singleResult();
|
||||
assertNotNull("Task should exist!", task);
|
||||
|
||||
String globalTaskId = createGlobalId(task.getId());
|
||||
|
||||
// Test query by taskId
|
||||
WorkflowTaskQuery taskQuery = createWorkflowTaskQuery(WorkflowTaskState.IN_PROGRESS);
|
||||
taskQuery.setTaskId(globalTaskId);
|
||||
|
||||
List<WorkflowTask> tasks = workflowEngine.queryTasks(taskQuery);
|
||||
Assert.assertNotNull(tasks);
|
||||
Assert.assertEquals(1, tasks.size());
|
||||
Assert.assertEquals(globalTaskId, tasks.get(0).getId());
|
||||
|
||||
// Test query by nonexistent taskId
|
||||
taskQuery = createWorkflowTaskQuery(WorkflowTaskState.IN_PROGRESS);
|
||||
taskQuery.setTaskId(createGlobalId("nonexistentTask"));
|
||||
|
||||
tasks = workflowEngine.queryTasks(taskQuery);
|
||||
Assert.assertNotNull(tasks);
|
||||
Assert.assertEquals(0, tasks.size());
|
||||
|
||||
// Test query by process ID
|
||||
taskQuery = createWorkflowTaskQuery(WorkflowTaskState.IN_PROGRESS);
|
||||
taskQuery.setProcessId(createGlobalId(task.getProcessInstanceId()));
|
||||
|
||||
tasks = workflowEngine.queryTasks(taskQuery);
|
||||
Assert.assertNotNull(tasks);
|
||||
Assert.assertEquals(1, tasks.size());
|
||||
Assert.assertEquals(globalTaskId, tasks.get(0).getId());
|
||||
|
||||
// Test query by nonexistent processId
|
||||
taskQuery = createWorkflowTaskQuery(WorkflowTaskState.IN_PROGRESS);
|
||||
taskQuery.setProcessId(createGlobalId("nonexistentProcess"));
|
||||
|
||||
tasks = workflowEngine.queryTasks(taskQuery);
|
||||
Assert.assertNotNull(tasks);
|
||||
Assert.assertEquals(0, tasks.size());
|
||||
|
||||
// Test query by actor ID
|
||||
taskQuery = createWorkflowTaskQuery(WorkflowTaskState.IN_PROGRESS);
|
||||
taskQuery.setActorId(TEST_USER);
|
||||
tasks = workflowEngine.queryTasks(taskQuery);
|
||||
|
||||
// No tasks should be assigned to testUser
|
||||
Assert.assertNotNull(tasks);
|
||||
Assert.assertEquals(0, tasks.size());
|
||||
|
||||
// Assign the task
|
||||
taskService.setAssignee(task.getId(), TEST_USER);
|
||||
taskQuery = createWorkflowTaskQuery(WorkflowTaskState.IN_PROGRESS);
|
||||
taskQuery.setActorId(TEST_USER);
|
||||
tasks = workflowEngine.queryTasks(taskQuery);
|
||||
// Task is assigned to testUser
|
||||
Assert.assertNotNull(tasks);
|
||||
Assert.assertEquals(1, tasks.size());
|
||||
Assert.assertEquals(globalTaskId, tasks.get(0).getId());
|
||||
|
||||
// Test by nonexistent actor ID
|
||||
taskQuery = createWorkflowTaskQuery(WorkflowTaskState.IN_PROGRESS);
|
||||
taskQuery.setActorId("nonexistentUser");
|
||||
tasks = workflowEngine.queryTasks(taskQuery);
|
||||
|
||||
Assert.assertNotNull(tasks);
|
||||
Assert.assertEquals(0, tasks.size());
|
||||
|
||||
// Test query by process-name
|
||||
taskQuery = createWorkflowTaskQuery(WorkflowTaskState.IN_PROGRESS);
|
||||
taskQuery.setWorkflowDefinitionName("testTask");
|
||||
tasks = workflowEngine.queryTasks(taskQuery);
|
||||
|
||||
Assert.assertNotNull(tasks);
|
||||
Assert.assertEquals(1, tasks.size());
|
||||
|
||||
taskQuery.setWorkflowDefinitionName("unexistingTaskName");
|
||||
tasks = workflowEngine.queryTasks(taskQuery);
|
||||
Assert.assertNotNull(tasks);
|
||||
Assert.assertEquals(0, tasks.size());
|
||||
|
||||
// Test query by task-name
|
||||
taskQuery = createWorkflowTaskQuery(WorkflowTaskState.IN_PROGRESS);
|
||||
taskQuery.setTaskName(QName.createQName("bpm_foo_task"));
|
||||
tasks = workflowEngine.queryTasks(taskQuery);
|
||||
|
||||
Assert.assertNotNull(tasks);
|
||||
Assert.assertEquals(1, tasks.size());
|
||||
|
||||
taskQuery.setTaskName(QName.createQName("unexisting_task_name"));
|
||||
tasks = workflowEngine.queryTasks(taskQuery);
|
||||
Assert.assertNotNull(tasks);
|
||||
Assert.assertEquals(0, tasks.size());
|
||||
|
||||
// Test querying task variables, using all possible (and allowed) types of variables
|
||||
Map<String, Object> variables = new HashMap<String, Object>();
|
||||
variables.put("longVar", 928374L);
|
||||
variables.put("shortVar", (short) 123);
|
||||
variables.put("integerVar", 1234);
|
||||
variables.put("stringVar", "stringValue");
|
||||
variables.put("booleanVar", true);
|
||||
Date date = Calendar.getInstance().getTime();
|
||||
variables.put("dateVar", date);
|
||||
variables.put("nullVar", null);
|
||||
ActivitiScriptNode scriptNode = new ActivitiScriptNode(testGroupNode, serviceRegistry);
|
||||
variables.put("scriptNodeVar", scriptNode);
|
||||
|
||||
taskService.setVariablesLocal(task.getId(), variables);
|
||||
|
||||
// Query long variable
|
||||
checkTaskVariableTaskPresent(WorkflowTaskState.IN_PROGRESS, QName.createQName("longVar"), 928374L, globalTaskId);
|
||||
checkTaskVariableNoMatch(WorkflowTaskState.IN_PROGRESS, QName.createQName("longVar"), 444444L);
|
||||
|
||||
// Query short variable
|
||||
checkTaskVariableTaskPresent(WorkflowTaskState.IN_PROGRESS, QName.createQName("shortVar"), (short) 123, globalTaskId);
|
||||
checkTaskVariableNoMatch(WorkflowTaskState.IN_PROGRESS, QName.createQName("shortVar"), (short) 456);
|
||||
|
||||
// Query integer variable
|
||||
checkTaskVariableTaskPresent(WorkflowTaskState.IN_PROGRESS, QName.createQName("integerVar"), 1234, globalTaskId);
|
||||
checkTaskVariableNoMatch(WorkflowTaskState.IN_PROGRESS, QName.createQName("integerVar"), 5678);
|
||||
|
||||
// Query string variable
|
||||
checkTaskVariableTaskPresent(WorkflowTaskState.IN_PROGRESS, QName.createQName("stringVar"), "stringValue", globalTaskId);
|
||||
checkTaskVariableNoMatch(WorkflowTaskState.IN_PROGRESS, QName.createQName("stringVar"), "noMatchString");
|
||||
|
||||
// Query string variable
|
||||
checkTaskVariableTaskPresent(WorkflowTaskState.IN_PROGRESS, QName.createQName("booleanVar"), true, globalTaskId);
|
||||
checkTaskVariableNoMatch(WorkflowTaskState.IN_PROGRESS, QName.createQName("booleanVar"), false);
|
||||
|
||||
// Query date variable
|
||||
checkTaskVariableTaskPresent(WorkflowTaskState.IN_PROGRESS, QName.createQName("dateVar"), date, globalTaskId);
|
||||
Calendar otherDate = Calendar.getInstance();
|
||||
otherDate.add(Calendar.YEAR, 1);
|
||||
checkTaskVariableNoMatch(WorkflowTaskState.IN_PROGRESS, QName.createQName("dateVar"), otherDate.getTime());
|
||||
|
||||
// Query null variable
|
||||
checkTaskVariableTaskPresent(WorkflowTaskState.IN_PROGRESS, QName.createQName("nullVar"), null, globalTaskId);
|
||||
checkTaskVariableNoMatch(WorkflowTaskState.IN_PROGRESS, QName.createQName("nullVar"), "notNull");
|
||||
|
||||
// Query script-node variable
|
||||
checkTaskVariableTaskPresent(WorkflowTaskState.IN_PROGRESS, QName.createQName("scriptNodeVar"), scriptNode, globalTaskId);
|
||||
ActivitiScriptNode otherNode = new ActivitiScriptNode(testUserNode, serviceRegistry);
|
||||
checkTaskVariableNoMatch(WorkflowTaskState.IN_PROGRESS, QName.createQName("scriptNodeVar"), otherNode);
|
||||
|
||||
|
||||
// Query task based on process variable
|
||||
runtime.setVariable(task.getExecutionId(), "processVar", "testing");
|
||||
taskQuery = createWorkflowTaskQuery(WorkflowTaskState.IN_PROGRESS);
|
||||
Map<QName, Object> props = new HashMap<QName, Object>();
|
||||
props.put(QName.createQName("processVar"), "testing");
|
||||
taskQuery.setProcessCustomProps(props);
|
||||
|
||||
tasks = workflowEngine.queryTasks(taskQuery);
|
||||
assertNotNull(tasks);
|
||||
assertEquals(1, tasks.size());
|
||||
|
||||
props.put(QName.createQName("processVar"), "notmatching");
|
||||
|
||||
tasks = workflowEngine.queryTasks(taskQuery);
|
||||
assertNotNull(tasks);
|
||||
assertEquals(0, tasks.size());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testQueryTasksCompleted() throws Exception
|
||||
{
|
||||
// Testing all query functionality for WorkflowTaskState.COMPLETED
|
||||
WorkflowPath path = workflowEngine.startWorkflow(workflowDef.getId(), new HashMap<QName, Serializable>());
|
||||
|
||||
Task task = taskService.createTaskQuery()
|
||||
.executionId(BPMEngineRegistry.getLocalId(path.getId()))
|
||||
.singleResult();
|
||||
|
||||
taskService.setVariableLocal(task.getId(), "taskVar", "theValue");
|
||||
assertNotNull("Task should exist!", task);
|
||||
String globalTaskId = createGlobalId(task.getId());
|
||||
|
||||
// Set the actor
|
||||
taskService.setAssignee(task.getId(), TEST_USER);
|
||||
|
||||
// Set process prop
|
||||
runtime.setVariable(task.getExecutionId(), "processVar", "testing");
|
||||
|
||||
// End the task as TEST_USER
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(TEST_USER);
|
||||
workflowEngine.endTask(globalTaskId, null);
|
||||
AuthenticationUtil.setFullyAuthenticatedUser("admin");
|
||||
|
||||
// Test query by taskId
|
||||
WorkflowTaskQuery taskQuery = createWorkflowTaskQuery(WorkflowTaskState.COMPLETED);
|
||||
taskQuery.setActive(Boolean.FALSE); // Set to false, since workflow this task is in, has finished
|
||||
taskQuery.setTaskId(globalTaskId);
|
||||
|
||||
List<WorkflowTask> tasks = workflowEngine.queryTasks(taskQuery);
|
||||
Assert.assertNotNull(tasks);
|
||||
Assert.assertEquals(1, tasks.size());
|
||||
Assert.assertEquals(globalTaskId, tasks.get(0).getId());
|
||||
|
||||
// Test query by nonexistent task ID
|
||||
taskQuery = createWorkflowTaskQuery(WorkflowTaskState.COMPLETED);
|
||||
taskQuery.setTaskId(createGlobalId("nonexistantTask"));
|
||||
|
||||
tasks = workflowEngine.queryTasks(taskQuery);
|
||||
Assert.assertNotNull(tasks);
|
||||
Assert.assertEquals(0, tasks.size());
|
||||
|
||||
// Test query by process ID, this should also return the start-task
|
||||
taskQuery = createWorkflowTaskQuery(WorkflowTaskState.COMPLETED);
|
||||
taskQuery.setProcessId(createGlobalId(task.getProcessInstanceId()));
|
||||
taskQuery.setActive(Boolean.FALSE);
|
||||
|
||||
tasks = workflowEngine.queryTasks(taskQuery);
|
||||
Assert.assertNotNull(tasks);
|
||||
Assert.assertEquals(2, tasks.size());
|
||||
|
||||
boolean taskFound = false;
|
||||
boolean startTaskFound = false;
|
||||
for (WorkflowTask wfTask : tasks)
|
||||
{
|
||||
if (wfTask.getId().equals(globalTaskId))
|
||||
{
|
||||
taskFound = true;
|
||||
}
|
||||
if (wfTask.getId().contains(ActivitiConstants.START_TASK_PREFIX))
|
||||
{
|
||||
startTaskFound = true;
|
||||
}
|
||||
}
|
||||
Assert.assertTrue("Task should have been returned", taskFound);
|
||||
Assert.assertTrue("Start-task should have been returned", startTaskFound);
|
||||
|
||||
// Test query by nonexistent process ID
|
||||
taskQuery = createWorkflowTaskQuery(WorkflowTaskState.COMPLETED);
|
||||
taskQuery.setProcessId(createGlobalId("nonexistantProcess"));
|
||||
|
||||
tasks = workflowEngine.queryTasks(taskQuery);
|
||||
Assert.assertNotNull(tasks);
|
||||
Assert.assertEquals(0, tasks.size());
|
||||
|
||||
// Test query by actor
|
||||
taskQuery = createWorkflowTaskQuery(WorkflowTaskState.COMPLETED);
|
||||
taskQuery.setActorId(TEST_USER);
|
||||
taskQuery.setActive(Boolean.FALSE);
|
||||
|
||||
tasks = workflowEngine.queryTasks(taskQuery);
|
||||
Assert.assertNotNull(tasks);
|
||||
Assert.assertEquals(1, tasks.size());
|
||||
|
||||
// Test by nonexistent actor
|
||||
taskQuery = createWorkflowTaskQuery(WorkflowTaskState.COMPLETED);
|
||||
taskQuery.setActorId("unexistingUser");
|
||||
|
||||
tasks = workflowEngine.queryTasks(taskQuery);
|
||||
Assert.assertNotNull(tasks);
|
||||
Assert.assertEquals(0, tasks.size());
|
||||
|
||||
// Test query by process-name
|
||||
taskQuery = createWorkflowTaskQuery(WorkflowTaskState.COMPLETED);
|
||||
taskQuery.setWorkflowDefinitionName("testTask");
|
||||
taskQuery.setActive(Boolean.FALSE);
|
||||
tasks = workflowEngine.queryTasks(taskQuery);
|
||||
|
||||
Assert.assertNotNull(tasks);
|
||||
Assert.assertEquals(1, tasks.size());
|
||||
|
||||
taskQuery.setWorkflowDefinitionName("unexistingTaskName");
|
||||
tasks = workflowEngine.queryTasks(taskQuery);
|
||||
Assert.assertNotNull(tasks);
|
||||
Assert.assertEquals(0, tasks.size());
|
||||
|
||||
// Query task based on task variable
|
||||
taskQuery = createWorkflowTaskQuery(WorkflowTaskState.COMPLETED);
|
||||
Map<QName, Object> props = new HashMap<QName, Object>();
|
||||
props.put(QName.createQName("taskVar"), "theValue");
|
||||
taskQuery.setActive(false);
|
||||
taskQuery.setTaskCustomProps(props);
|
||||
|
||||
tasks = workflowEngine.queryTasks(taskQuery);
|
||||
assertNotNull(tasks);
|
||||
assertEquals(1, tasks.size());
|
||||
|
||||
props.put(QName.createQName("processVar"), "notmatching");
|
||||
|
||||
tasks = workflowEngine.queryTasks(taskQuery);
|
||||
assertNotNull(tasks);
|
||||
assertEquals(0, tasks.size());
|
||||
|
||||
// Query task based on process variable
|
||||
taskQuery = createWorkflowTaskQuery(WorkflowTaskState.COMPLETED);
|
||||
props = new HashMap<QName, Object>();
|
||||
props.put(QName.createQName("processVar"), "testing");
|
||||
taskQuery.setActive(false);
|
||||
taskQuery.setProcessCustomProps(props);
|
||||
|
||||
tasks = workflowEngine.queryTasks(taskQuery);
|
||||
assertNotNull(tasks);
|
||||
assertEquals(1, tasks.size());
|
||||
|
||||
props.put(QName.createQName("processVar"), "notmatching");
|
||||
|
||||
tasks = workflowEngine.queryTasks(taskQuery);
|
||||
assertNotNull(tasks);
|
||||
assertEquals(0, tasks.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueryUsingNodeRef() {
|
||||
NodeRef nodeRef = new NodeRef("workspace:///someRef");
|
||||
|
||||
QName nodeRefPropQname = QName.createQName("testProp");
|
||||
HashMap<QName, Serializable> props = new HashMap<QName, Serializable>();
|
||||
props.put(nodeRefPropQname, nodeRef);
|
||||
|
||||
// Start the workflow-path
|
||||
workflowEngine.startWorkflow(workflowDef.getId(), props);
|
||||
|
||||
// Test querying with a value of type NodeRef
|
||||
WorkflowTaskQuery taskQuery = createWorkflowTaskQuery(WorkflowTaskState.IN_PROGRESS);
|
||||
HashMap<QName, Object> queryParams = new HashMap<QName, Object>();
|
||||
queryParams.put(nodeRefPropQname, nodeRef);
|
||||
taskQuery.setProcessCustomProps(queryParams);
|
||||
|
||||
List<WorkflowTask> tasks = workflowEngine.queryTasks(taskQuery);
|
||||
assertNotNull(tasks);
|
||||
assertEquals(1, tasks.size());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testUpdateTask() {
|
||||
NodeRef nodeRef = new NodeRef("workspace:///someRef");
|
||||
NodeRef anotherRef = new NodeRef("workspace:///anotherRef");
|
||||
|
||||
QName propQname = QName.createQName("testProp");
|
||||
QName nodeRefPropQname = QName.createQName("testAssoc");
|
||||
QName singleNodeRefPropQname = QName.createQName("testAssocSingleValue");
|
||||
HashMap<QName, Serializable> props = new HashMap<QName, Serializable>();
|
||||
|
||||
// Start the workflow-path
|
||||
WorkflowPath path = workflowEngine.startWorkflow(workflowDef.getId(), props);
|
||||
WorkflowTask startTask = workflowEngine.getStartTask(path.getInstance().getId());
|
||||
|
||||
// End the start-task
|
||||
workflowEngine.endTask(startTask.getId(), null);
|
||||
|
||||
// Get the task to update
|
||||
WorkflowTaskQuery taskQuery = createWorkflowTaskQuery(WorkflowTaskState.IN_PROGRESS);
|
||||
taskQuery.setProcessId(path.getInstance().getId());
|
||||
|
||||
List<WorkflowTask> tasks = workflowEngine.queryTasks(taskQuery);
|
||||
WorkflowTask task = tasks.get(0);
|
||||
|
||||
// Test altering plain properties
|
||||
props = new HashMap<QName, Serializable>();
|
||||
props.put(propQname, "54321");
|
||||
props.put(singleNodeRefPropQname, nodeRef);
|
||||
workflowEngine.updateTask(task.getId(), props, null, null);
|
||||
|
||||
tasks = workflowEngine.queryTasks(taskQuery);
|
||||
task = tasks.get(0);
|
||||
assertEquals("54321", task.getProperties().get(propQname));
|
||||
|
||||
// Test adding association
|
||||
HashMap<QName, List<NodeRef>> toAdd = new HashMap<QName, List<NodeRef>>();
|
||||
toAdd.put(nodeRefPropQname, Arrays.asList(anotherRef, nodeRef));
|
||||
|
||||
workflowEngine.updateTask(task.getId(), null, toAdd, null);
|
||||
|
||||
tasks = workflowEngine.queryTasks(taskQuery);
|
||||
task = tasks.get(0);
|
||||
assertEquals(2, ((List<NodeRef>)task.getProperties().get(nodeRefPropQname)).size());
|
||||
|
||||
// Test removing association
|
||||
HashMap<QName, List<NodeRef>> toRemove = new HashMap<QName, List<NodeRef>>();
|
||||
toRemove.put(nodeRefPropQname, Arrays.asList(nodeRef));
|
||||
|
||||
workflowEngine.updateTask(task.getId(), null, null, toRemove);
|
||||
|
||||
tasks = workflowEngine.queryTasks(taskQuery);
|
||||
task = tasks.get(0);
|
||||
assertEquals(1, ((List<NodeRef>)task.getProperties().get(nodeRefPropQname)).size());
|
||||
assertEquals(anotherRef, ((List<NodeRef>)task.getProperties().get(nodeRefPropQname)).get(0));
|
||||
|
||||
// Test changing single-valued association
|
||||
toAdd = new HashMap<QName, List<NodeRef>>();
|
||||
toRemove = new HashMap<QName, List<NodeRef>>();
|
||||
|
||||
toRemove.put(singleNodeRefPropQname, Arrays.asList(nodeRef));
|
||||
toAdd.put(singleNodeRefPropQname, Arrays.asList(anotherRef));
|
||||
|
||||
workflowEngine.updateTask(task.getId(), null, toAdd, toRemove);
|
||||
tasks = workflowEngine.queryTasks(taskQuery);
|
||||
task = tasks.get(0);
|
||||
|
||||
assertEquals(anotherRef, task.getProperties().get(singleNodeRefPropQname));
|
||||
|
||||
// Test clearing single-valued association
|
||||
toRemove = new HashMap<QName, List<NodeRef>>();
|
||||
|
||||
toRemove.put(singleNodeRefPropQname, Arrays.asList(anotherRef));
|
||||
|
||||
workflowEngine.updateTask(task.getId(), null, null, toRemove);
|
||||
tasks = workflowEngine.queryTasks(taskQuery);
|
||||
task = tasks.get(0);
|
||||
|
||||
// Association value should be empty now
|
||||
assertNull(task.getProperties().get(singleNodeRefPropQname));
|
||||
}
|
||||
|
||||
private void checkTaskVariableTaskPresent(WorkflowTaskState state,
|
||||
QName varName, Object varValue, String expectedTask)
|
||||
{
|
||||
WorkflowTaskQuery taskQuery = createWorkflowTaskQuery(state);
|
||||
Map<QName, Object> customProperties = new HashMap<QName, Object>();
|
||||
customProperties.put(varName, varValue);
|
||||
taskQuery.setTaskCustomProps(customProperties);
|
||||
|
||||
assertTaskPresent(taskQuery, expectedTask);
|
||||
}
|
||||
|
||||
private void checkTaskVariableNoMatch(WorkflowTaskState state,
|
||||
QName varName, Object varValue)
|
||||
{
|
||||
WorkflowTaskQuery taskQuery = createWorkflowTaskQuery(state);
|
||||
Map<QName, Object> customProperties = new HashMap<QName, Object>();
|
||||
customProperties.put(varName, varValue);
|
||||
taskQuery.setTaskCustomProps(customProperties);
|
||||
|
||||
assertNoTaskPresent(taskQuery);
|
||||
}
|
||||
|
||||
private WorkflowTaskQuery createWorkflowTaskQuery(WorkflowTaskState state)
|
||||
{
|
||||
WorkflowTaskQuery taskQuery = new WorkflowTaskQuery();
|
||||
taskQuery.setTaskState(state);
|
||||
return taskQuery;
|
||||
}
|
||||
|
||||
|
||||
private void assertTaskPresent(WorkflowTaskQuery taskQuery,
|
||||
String taskId)
|
||||
{
|
||||
List<WorkflowTask> tasks = workflowEngine.queryTasks(taskQuery);
|
||||
Assert.assertNotNull(tasks);
|
||||
Assert.assertEquals(1, tasks.size());
|
||||
Assert.assertEquals(taskId, tasks.get(0).getId());
|
||||
}
|
||||
|
||||
private void assertNoTaskPresent(WorkflowTaskQuery taskQuery)
|
||||
{
|
||||
List<WorkflowTask> tasks = workflowEngine.queryTasks(taskQuery);
|
||||
Assert.assertNotNull(tasks);
|
||||
Assert.assertEquals(0, tasks.size());
|
||||
}
|
||||
|
||||
private String createGlobalId(String id)
|
||||
{
|
||||
return BPMEngineRegistry.createGlobalId(ActivitiConstants.ENGINE_ID, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
super.setUp();
|
||||
this.workflowDef = deployTestTaskDefinition();
|
||||
}
|
||||
}
|
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.workflow.activiti;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.activiti.engine.ProcessEngine;
|
||||
import org.activiti.engine.impl.persistence.entity.TimerEntity;
|
||||
import org.activiti.engine.repository.ProcessDefinition;
|
||||
import org.activiti.engine.runtime.Job;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||
import org.alfresco.repo.security.person.TestPersonManager;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.repo.workflow.BPMEngineRegistry;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.security.MutableAuthenticationService;
|
||||
import org.alfresco.service.cmr.security.PersonService;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowDeployment;
|
||||
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.cmr.workflow.WorkflowTask;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.BaseSpringTest;
|
||||
import org.alfresco.util.GUID;
|
||||
|
||||
/**
|
||||
* Test to verify timer execution autentication and transaction behaviour.
|
||||
*
|
||||
* @author Frederik Heremans
|
||||
* @since 3.4.e
|
||||
*/
|
||||
public class ActivitiTimerExecutionTest extends BaseSpringTest
|
||||
{
|
||||
|
||||
private static final String USER1 = "User1" + GUID.generate();
|
||||
|
||||
private RetryingTransactionHelper transactionHelper;
|
||||
|
||||
private WorkflowService workflowService;
|
||||
|
||||
private AuthenticationComponent authenticationComponent;
|
||||
|
||||
private NodeService nodeService;
|
||||
|
||||
private ProcessEngine activitiProcessEngine;
|
||||
|
||||
private TestPersonManager personManager;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public void testTimerExecutionAuthentication() throws Exception
|
||||
{
|
||||
this.setComplete();
|
||||
this.endTransaction();
|
||||
|
||||
try
|
||||
{
|
||||
WorkflowInstance taskAssigneeWorkflowInstance = transactionHelper
|
||||
.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<WorkflowInstance>()
|
||||
{
|
||||
public WorkflowInstance execute() throws Throwable
|
||||
{
|
||||
// Create test person
|
||||
personManager.createPerson(USER1);
|
||||
|
||||
WorkflowDefinition definition = deployDefinition("activiti/testTimerTransaction.bpmn20.xml");
|
||||
|
||||
// Start the test timer transaction process, with 'error' = false, expecting a timer job
|
||||
// to be executed without an error, with task timer is assigned to assigned to USER1
|
||||
Map<QName, Serializable> params = new HashMap<QName, Serializable>();
|
||||
params.put(QName.createQName("error"), Boolean.FALSE);
|
||||
params.put(QName.createQName("theTaskAssignee"), USER1);
|
||||
|
||||
WorkflowPath path = workflowService.startWorkflow(definition.getId(), params);
|
||||
// End start-task
|
||||
workflowService.endTask(workflowService.getStartTask(path.getInstance().getId()).getId(), null);
|
||||
|
||||
return path.getInstance();
|
||||
}
|
||||
});
|
||||
|
||||
// No timers should be available after a while they should have been executed, otherwise test fails
|
||||
waitForTimersToBeExecuted(taskAssigneeWorkflowInstance.getId());
|
||||
|
||||
// Test assigned task
|
||||
WorkflowPath path = workflowService.getWorkflowPaths(taskAssigneeWorkflowInstance.getId()).get(0);
|
||||
|
||||
// Check if job executed without exception, process should be waiting in "waitTask"
|
||||
List<WorkflowTask> tasks = workflowService.getTasksForWorkflowPath(path.getId());
|
||||
assertNotNull(tasks);
|
||||
assertEquals(1, tasks.size());
|
||||
assertEquals("waitTask", tasks.get(0).getDefinition().getNode().getName());
|
||||
|
||||
// Check if timer was executed as task assignee, was set while executing timer
|
||||
Map<QName, Serializable> pathProps = workflowService.getPathProperties(path.getId());
|
||||
assertEquals(USER1, pathProps.get(QName.createQName("timerExecutedAs")));
|
||||
}
|
||||
finally
|
||||
{
|
||||
cleanUp();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public void testTimerExecutionTransactionRollback() throws Exception
|
||||
{
|
||||
this.setComplete();
|
||||
this.endTransaction();
|
||||
|
||||
try
|
||||
{
|
||||
WorkflowInstance workflowInstance = transactionHelper
|
||||
.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<WorkflowInstance>()
|
||||
{
|
||||
public WorkflowInstance execute() throws Throwable
|
||||
{
|
||||
// Create test person
|
||||
personManager.createPerson(USER1);
|
||||
|
||||
WorkflowDefinition definition = deployDefinition("activiti/testTimerTransaction.bpmn20.xml");
|
||||
|
||||
// Start the test timer transaction process, with 'error' = false, expecting a timer job
|
||||
// to be executed without an error, with task timer is assigned to assigned to USER1
|
||||
Map<QName, Serializable> params = new HashMap<QName, Serializable>();
|
||||
params.put(QName.createQName("error"), Boolean.TRUE);
|
||||
params.put(QName.createQName("theTaskAssignee"), USER1);
|
||||
|
||||
WorkflowPath path = workflowService.startWorkflow(definition.getId(), params);
|
||||
// End start-task
|
||||
workflowService.endTask(workflowService.getStartTask(path.getInstance().getId()).getId(), null);
|
||||
|
||||
return path.getInstance();
|
||||
}
|
||||
});
|
||||
|
||||
String processInstanceId = BPMEngineRegistry.getLocalId(workflowInstance.getId());
|
||||
|
||||
// Check the timer, should have "error" set in it
|
||||
TimerEntity timer = (TimerEntity) activitiProcessEngine.getManagementService()
|
||||
.createJobQuery().timers()
|
||||
.processInstanceId(processInstanceId).singleResult();
|
||||
|
||||
int numberOfRetries = 5;
|
||||
for (int i = 0; i < numberOfRetries; i++)
|
||||
{
|
||||
if (timer.getExceptionMessage() != null && timer.getRetries() == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
Thread.sleep(1000);
|
||||
timer = (TimerEntity) activitiProcessEngine.getManagementService()
|
||||
.createJobQuery().timers()
|
||||
.processInstanceId(processInstanceId).singleResult();
|
||||
}
|
||||
assertNotNull("Job should have exception message set", timer.getExceptionMessage());
|
||||
assertEquals(0, timer.getRetries());
|
||||
|
||||
// Check if exception is the one we deliberately caused
|
||||
String fullExceptionStacktrace = activitiProcessEngine.getManagementService().getJobExceptionStacktrace(timer.getId());
|
||||
assertTrue(fullExceptionStacktrace.contains("Activiti engine rocks!"));
|
||||
|
||||
// Check if alfresco-changes that were performed are rolled back
|
||||
NodeRef personNode = personManager.get(USER1);
|
||||
NodeRef userHomeNode = (NodeRef)nodeService.getProperty(personNode, ContentModel.PROP_HOMEFOLDER);
|
||||
|
||||
String homeFolderName = (String) nodeService.getProperty(userHomeNode, ContentModel.PROP_NAME);
|
||||
assertNotSame("User home changed", homeFolderName);
|
||||
}
|
||||
finally
|
||||
{
|
||||
cleanUp();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the deployment, cascading all related processes/history
|
||||
*/
|
||||
private void cleanUp()
|
||||
{
|
||||
transactionHelper .doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>()
|
||||
{
|
||||
public Void execute() throws Throwable
|
||||
{
|
||||
try
|
||||
{
|
||||
personManager.clearPeople();
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Make sure process-definition is still deleted, even when clearing people fails.
|
||||
ProcessDefinition procDef = activitiProcessEngine.getRepositoryService()
|
||||
.createProcessDefinitionQuery()
|
||||
.processDefinitionKey("testTimerTransaction")
|
||||
.latestVersion()
|
||||
.singleResult();
|
||||
|
||||
if (procDef != null)
|
||||
{
|
||||
activitiProcessEngine.getRepositoryService().deleteDeployment(procDef.getDeploymentId(), true);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected void onSetUpInTransaction() throws Exception
|
||||
{
|
||||
ServiceRegistry registry = (ServiceRegistry) applicationContext.getBean(ServiceRegistry.SERVICE_REGISTRY);
|
||||
this.workflowService = registry.getWorkflowService();
|
||||
this.authenticationComponent = (AuthenticationComponent) applicationContext.getBean("authenticationComponent");
|
||||
this.nodeService = registry.getNodeService();
|
||||
|
||||
this.transactionHelper = (RetryingTransactionHelper) this.applicationContext
|
||||
.getBean("retryingTransactionHelper");
|
||||
|
||||
this.activitiProcessEngine = (ProcessEngine) this.applicationContext.getBean("activitiProcessEngine");
|
||||
|
||||
MutableAuthenticationService authenticationService = registry.getAuthenticationService();
|
||||
PersonService personService = registry.getPersonService();
|
||||
|
||||
this.personManager = new TestPersonManager(authenticationService, personService, nodeService);
|
||||
|
||||
authenticationComponent.setSystemUserAsCurrentUser();
|
||||
}
|
||||
|
||||
private void waitForTimersToBeExecuted(String workflowInstanceId) throws Exception
|
||||
{
|
||||
String processInstanceId = BPMEngineRegistry.getLocalId(workflowInstanceId);
|
||||
// Job-executor should finish the job, no timers should be available for WF
|
||||
List<Job> timers = activitiProcessEngine.getManagementService().createJobQuery()
|
||||
.timers()
|
||||
.processInstanceId(processInstanceId)
|
||||
.list();
|
||||
|
||||
int numberOfRetries = 5;
|
||||
for (int i=0; i< numberOfRetries; i++)
|
||||
{
|
||||
if (timers.size() == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
Thread.sleep(1000);
|
||||
timers = activitiProcessEngine.getManagementService().createJobQuery()
|
||||
.timers()
|
||||
.processInstanceId(processInstanceId)
|
||||
.list();
|
||||
}
|
||||
|
||||
if(timers.size() > 0) {
|
||||
fail("There are still timers available for the process: " + processInstanceId);
|
||||
}
|
||||
}
|
||||
|
||||
protected WorkflowDefinition deployDefinition(String resource)
|
||||
{
|
||||
InputStream input = getInputStream(resource);
|
||||
WorkflowDeployment deployment = workflowService.deployDefinition(ActivitiConstants.ENGINE_ID, input, MimetypeMap.MIMETYPE_XML);
|
||||
WorkflowDefinition definition = deployment.getDefinition();
|
||||
return definition;
|
||||
}
|
||||
|
||||
private InputStream getInputStream(String resource)
|
||||
{
|
||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||
InputStream input= classLoader.getResourceAsStream(resource);
|
||||
return input;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,779 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.workflow.activiti;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertFalse;
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
import static junit.framework.Assert.assertNull;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
import static junit.framework.Assert.fail;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.activiti.engine.history.HistoricProcessInstance;
|
||||
import org.activiti.engine.impl.util.ClockUtil;
|
||||
import org.activiti.engine.repository.ProcessDefinition;
|
||||
import org.activiti.engine.runtime.Execution;
|
||||
import org.activiti.engine.runtime.Job;
|
||||
import org.activiti.engine.runtime.ProcessInstance;
|
||||
import org.activiti.engine.task.Task;
|
||||
import org.alfresco.repo.jscript.ScriptNode;
|
||||
import org.alfresco.repo.workflow.BPMEngineRegistry;
|
||||
import org.alfresco.repo.workflow.WorkflowConstants;
|
||||
import org.alfresco.repo.workflow.WorkflowModel;
|
||||
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowException;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowInstance;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowNode;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowPath;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTask;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTaskDefinition;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTimer;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Spring-configured JUnit 4 test case.
|
||||
* Uses Spring to load up a test context and runs each test case in a transaction which gets rolled back.
|
||||
* Loads up the activiti-context.xml and test-database-context.xml.
|
||||
*
|
||||
* @author Nick Smith
|
||||
* @since 3.4.e
|
||||
*/
|
||||
public class ActivitiWorkflowComponentTest extends AbstractActivitiComponentTest
|
||||
{
|
||||
@Test
|
||||
public void testDeployDefinition() throws Exception
|
||||
{
|
||||
ProcessDefinition defInDB = repo.createProcessDefinitionQuery()
|
||||
.processDefinitionKey(TEST_TASK_KEY)
|
||||
.singleResult();
|
||||
assertNull("The definition is already deployed!", defInDB);
|
||||
|
||||
WorkflowDefinition definition = deployTestTaskDefinition();
|
||||
String localDefId = BPMEngineRegistry.getLocalId(definition.getId());
|
||||
ProcessDefinition processDef = repo.createProcessDefinitionQuery()
|
||||
.processDefinitionId(localDefId)
|
||||
.singleResult();
|
||||
assertNotNull("Process Definition should have been deployed!", processDef);
|
||||
|
||||
ProcessDefinition def2InDB = repo.createProcessDefinitionQuery()
|
||||
.processDefinitionKey(TEST_ADHOC_KEY)
|
||||
.singleResult();
|
||||
assertNull("The definition is already deployed!", def2InDB);
|
||||
|
||||
WorkflowDefinition definition2 = deployTestTaskDefinition();
|
||||
String localDef2Id = BPMEngineRegistry.getLocalId(definition2.getId());
|
||||
ProcessDefinition processDef2 = repo.createProcessDefinitionQuery()
|
||||
.processDefinitionId(localDef2Id)
|
||||
.singleResult();
|
||||
assertNotNull("Process Definition should have been deployed!", processDef2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsDefinitionDeployed() throws Exception
|
||||
{
|
||||
InputStream input = getInputStream(TEST_TASK_DEF);
|
||||
|
||||
boolean result = workflowEngine.isDefinitionDeployed(input, XML);
|
||||
assertFalse("Should return false before process def deployed.", result);
|
||||
|
||||
deployTestTaskDefinition();
|
||||
|
||||
input = getInputStream(TEST_TASK_DEF);
|
||||
result = workflowEngine.isDefinitionDeployed(input, XML);
|
||||
assertTrue("Should return true after process def deployed.", result);
|
||||
|
||||
// Check doesn't find Adhoc definition.
|
||||
input = getInputStream(TEST_ADHOC_DEF);
|
||||
result = workflowEngine.isDefinitionDeployed(input, XML);
|
||||
assertFalse("Should not find Adhoc definition.", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUndeployDefinition() throws Exception
|
||||
{
|
||||
WorkflowDefinition definition = deployTestTaskDefinition();
|
||||
String localId = BPMEngineRegistry.getLocalId(definition.getId());
|
||||
|
||||
long defCount = repo.createProcessDefinitionQuery()
|
||||
.processDefinitionId(localId)
|
||||
.count();
|
||||
assertEquals("The deployed process definition should exist!", 1, defCount);
|
||||
|
||||
workflowEngine.undeployDefinition(definition.getId());
|
||||
|
||||
defCount = repo.createProcessDefinitionQuery()
|
||||
.processDefinitionId(localId)
|
||||
.count();
|
||||
assertEquals("The undeployed process definition should not exist!", 0, defCount);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDefinitionById() throws Exception
|
||||
{
|
||||
WorkflowDefinition definition = deployTestTaskDefinition();
|
||||
WorkflowDefinition result = workflowEngine.getDefinitionById(definition.getId());
|
||||
|
||||
assertNotNull("The workflow definition was not found!", result);
|
||||
|
||||
assertEquals(definition.getId(), result.getId());
|
||||
assertEquals(definition.getDescription(), result.getDescription());
|
||||
assertEquals(definition.getName(), result.getName());
|
||||
assertEquals(definition.getTitle(), result.getTitle());
|
||||
assertEquals(definition.getVersion(), result.getVersion());
|
||||
|
||||
WorkflowTaskDefinition resultStartDef = result.getStartTaskDefinition();
|
||||
assertNotNull("Start task is null!", resultStartDef);
|
||||
|
||||
WorkflowTaskDefinition originalStartDef = definition.getStartTaskDefinition();
|
||||
assertEquals("Start task Id does not match!", originalStartDef.getId(), resultStartDef.getId());
|
||||
|
||||
WorkflowNode resultNode = resultStartDef.getNode();
|
||||
assertNotNull("Start Task Node is null!", resultNode);
|
||||
assertEquals("Start Task Node Name does not match!", originalStartDef.getNode().getName(), resultNode.getName());
|
||||
|
||||
TypeDefinition metaData = resultStartDef.getMetadata();
|
||||
assertNotNull("Start Task Metadata is null!", metaData);
|
||||
assertEquals("Start Task Metadata name does not match!", originalStartDef.getMetadata().getName(), metaData.getName());
|
||||
|
||||
workflowEngine.undeployDefinition(definition.getId());
|
||||
WorkflowDefinition nullResult = workflowEngine.getDefinitionById(definition.getId());
|
||||
assertNull("The workflow definition was found but should be null!", nullResult);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDefinitionByName() throws Exception
|
||||
{
|
||||
WorkflowDefinition definition = deployTestTaskDefinition();
|
||||
WorkflowDefinition result = workflowEngine.getDefinitionByName(definition.getName());
|
||||
|
||||
assertNotNull("The workflow definition was not found!", result);
|
||||
|
||||
assertEquals(definition.getId(), result.getId());
|
||||
assertEquals(definition.getDescription(), result.getDescription());
|
||||
assertEquals(definition.getName(), result.getName());
|
||||
assertEquals(definition.getTitle(), result.getTitle());
|
||||
assertEquals(definition.getVersion(), result.getVersion());
|
||||
|
||||
workflowEngine.undeployDefinition(definition.getId());
|
||||
WorkflowDefinition nullResult = workflowEngine.getDefinitionByName(definition.getName());
|
||||
assertNull("The workflow definition was found but should be null!", nullResult);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDefinitions() throws Exception
|
||||
{
|
||||
List<WorkflowDefinition> startDefs = workflowEngine.getDefinitions();
|
||||
|
||||
WorkflowDefinition defV1 = deployTestTaskDefinition();
|
||||
List<WorkflowDefinition> definitions = workflowEngine.getDefinitions();
|
||||
checkDefinitions(definitions, startDefs, defV1);
|
||||
|
||||
// Deploy version 2 of testTask def.
|
||||
WorkflowDefinition defV2 = deployTestTaskDefinition();
|
||||
// Check new version replaces old version.
|
||||
definitions = workflowEngine.getDefinitions();
|
||||
checkDefinitions(definitions, startDefs, defV2);
|
||||
|
||||
// Deploy new type of definition.
|
||||
WorkflowDefinition adhocDef = deployTestAdhocDefinition();
|
||||
// Check that definitions of a different type are picked up.
|
||||
definitions = workflowEngine.getDefinitions();
|
||||
checkDefinitions(definitions, startDefs, defV2, adhocDef);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGetAllDefinitions() throws Exception
|
||||
{
|
||||
List<WorkflowDefinition> startDefs = workflowEngine.getAllDefinitions();
|
||||
|
||||
WorkflowDefinition defV1 = deployTestTaskDefinition();
|
||||
List<WorkflowDefinition> definitions = workflowEngine.getAllDefinitions();
|
||||
checkDefinitions(definitions, startDefs, defV1);
|
||||
|
||||
// Deploy version 2 of testTask def.
|
||||
WorkflowDefinition defV2 = deployTestTaskDefinition();
|
||||
// Check new version replaces old version.
|
||||
definitions = workflowEngine.getAllDefinitions();
|
||||
checkDefinitions(definitions, startDefs, defV1, defV2);
|
||||
|
||||
// Deploy new type of definition.
|
||||
WorkflowDefinition adhocDef = deployTestAdhocDefinition();
|
||||
// Check that definitions of a different type are picked up.
|
||||
definitions = workflowEngine.getAllDefinitions();
|
||||
checkDefinitions(definitions, startDefs, defV1, defV2, adhocDef);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStartWorkflow() throws Exception
|
||||
{
|
||||
WorkflowDefinition def = deployTestTaskDefinition();
|
||||
|
||||
// Fill a map of default properties to start the workflow with
|
||||
Map<QName, Serializable> properties = new HashMap<QName, Serializable>();
|
||||
Date dueDate = Calendar.getInstance().getTime();
|
||||
properties.put(WorkflowModel.PROP_WORKFLOW_DESCRIPTION, "description123");
|
||||
properties.put(WorkflowModel.PROP_WORKFLOW_DUE_DATE, dueDate);
|
||||
properties.put(WorkflowModel.PROP_WORKFLOW_PRIORITY, 2);
|
||||
// properties.put(WorkflowModel.ASSOC_PACKAGE, null);
|
||||
// properties.put(WorkflowModel.PROP_CONTEXT, null);
|
||||
|
||||
|
||||
// Call the start method
|
||||
WorkflowPath path = workflowEngine.startWorkflow(def.getId(), properties);
|
||||
assertNotNull("The workflow path is null!", path);
|
||||
String executionId = BPMEngineRegistry.getLocalId(path.getId());
|
||||
Execution execution = runtime.createExecutionQuery()
|
||||
.executionId(executionId)
|
||||
.singleResult();
|
||||
assertNotNull("No execution was created int he DB!", execution);
|
||||
|
||||
WorkflowInstance instance = path.getInstance();
|
||||
assertNotNull("The workflow instance is null!",instance);
|
||||
String procInstanceId = BPMEngineRegistry.getLocalId(instance.getId());
|
||||
ProcessInstance procInstance = runtime.createProcessInstanceQuery()
|
||||
.processInstanceId(procInstanceId)
|
||||
.singleResult();
|
||||
assertNotNull("No process instance was created!", procInstance);
|
||||
|
||||
WorkflowNode node = path.getNode();
|
||||
assertNotNull("The workflow node is null!", node);
|
||||
String nodeName = node.getName();
|
||||
|
||||
assertEquals("task", nodeName);
|
||||
|
||||
// Check if company home is added as variable and can be fetched
|
||||
ScriptNode companyHome = (ScriptNode) runtime.getVariable(procInstanceId, "companyhome");
|
||||
assertNotNull(companyHome);
|
||||
assertEquals("companyHome", companyHome.getNodeRef().getStoreRef().getIdentifier());
|
||||
|
||||
// Check if the initiator is added as variable
|
||||
ScriptNode initiator = (ScriptNode) runtime.getVariable(procInstanceId, "initiator");
|
||||
assertNotNull(initiator);
|
||||
assertEquals("admin", initiator.getNodeRef().getStoreRef().getIdentifier());
|
||||
|
||||
// Check if the initiator home is also set as variable
|
||||
ScriptNode initiatorHome = (ScriptNode) runtime.getVariable(procInstanceId, "initiatorhome");
|
||||
assertNotNull(initiatorHome);
|
||||
assertEquals("admin-home", initiatorHome.getNodeRef().getStoreRef().getIdentifier());
|
||||
|
||||
// Check if start-date is set and no end-date is set
|
||||
assertNotNull(path.getInstance().getStartDate());
|
||||
assertNull(path.getInstance().getEndDate());
|
||||
|
||||
// Also check if the task that is created, has all default properties initialised
|
||||
Task task = taskService.createTaskQuery().processInstanceId(procInstanceId).singleResult();
|
||||
assertNotNull("Task should have been created", task);
|
||||
assertEquals("task", task.getTaskDefinitionKey());
|
||||
String defaultSetVariable = (String) taskService.getVariableLocal(task.getId(), "test_myProp");
|
||||
assertEquals("Default value", defaultSetVariable);
|
||||
|
||||
// Also check default value of task description is taken from WF-porps
|
||||
assertEquals("description123", task.getDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSignal() throws Exception
|
||||
{
|
||||
WorkflowDefinition def = deployTestSignallingDefinition();
|
||||
ProcessInstance processInstance = runtime.startProcessInstanceById(BPMEngineRegistry.getLocalId(def.getId()));
|
||||
|
||||
String procId = processInstance.getId();
|
||||
List<String> nodeIds = runtime.getActiveActivityIds(procId);
|
||||
assertEquals(1, nodeIds.size());
|
||||
assertEquals("task1", nodeIds.get(0));
|
||||
|
||||
String pathId = BPMEngineRegistry.createGlobalId(ActivitiConstants.ENGINE_ID, procId);
|
||||
WorkflowPath path = workflowEngine.signal(pathId, null);
|
||||
assertEquals(pathId, path.getId());
|
||||
assertEquals("task2", path.getNode().getName());
|
||||
assertEquals(pathId, path.getInstance().getId());
|
||||
assertTrue(path.isActive());
|
||||
|
||||
nodeIds = runtime.getActiveActivityIds(procId);
|
||||
assertEquals(1, nodeIds.size());
|
||||
assertEquals("task2", nodeIds.get(0));
|
||||
|
||||
// Should end the WorkflowInstance
|
||||
path = workflowEngine.signal(pathId, null);
|
||||
assertEquals(pathId, path.getId());
|
||||
assertNull(path.getNode());
|
||||
assertEquals(pathId, path.getInstance().getId());
|
||||
assertFalse(path.isActive());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCancelWorkflow() throws Exception
|
||||
{
|
||||
WorkflowDefinition def = deployTestAdhocDefinition();
|
||||
|
||||
ProcessInstance processInstance = runtime.startProcessInstanceById(BPMEngineRegistry.getLocalId(def.getId()));
|
||||
|
||||
// Validate if a workflow exists
|
||||
List<WorkflowInstance> instances = workflowEngine.getActiveWorkflows(def.getId());
|
||||
assertNotNull(instances);
|
||||
assertEquals(1, instances.size());
|
||||
assertEquals(processInstance.getId(), BPMEngineRegistry.getLocalId(instances.get(0).getId()));
|
||||
|
||||
// Call cancel method on component
|
||||
WorkflowInstance cancelledWorkflow = workflowEngine.cancelWorkflow(instances.get(0).getId());
|
||||
assertFalse(cancelledWorkflow.isActive());
|
||||
|
||||
instances = workflowEngine.getActiveWorkflows(def.getId());
|
||||
assertNotNull(instances);
|
||||
assertEquals(0, instances.size());
|
||||
|
||||
// Histrotic process instance shouldn't be present
|
||||
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
|
||||
.processInstanceId(processInstance.getProcessInstanceId())
|
||||
.singleResult();
|
||||
|
||||
assertNull(historicProcessInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCancelUnexistingWorkflow() throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
String globalId = workflowEngine.createGlobalId("unexistingWorkflowId");
|
||||
workflowEngine.cancelWorkflow(globalId);
|
||||
fail("Exception expected");
|
||||
}
|
||||
catch(WorkflowException e)
|
||||
{
|
||||
// Inore this
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteWorkflow() throws Exception
|
||||
{
|
||||
WorkflowDefinition def = deployTestAdhocDefinition();
|
||||
|
||||
ProcessInstance processInstance = runtime.startProcessInstanceById(BPMEngineRegistry.getLocalId(def.getId()));
|
||||
|
||||
// Validate if a workflow exists
|
||||
List<WorkflowInstance> instances = workflowEngine.getActiveWorkflows(def.getId());
|
||||
assertNotNull(instances);
|
||||
assertEquals(1, instances.size());
|
||||
assertEquals(processInstance.getId(), BPMEngineRegistry.getLocalId(instances.get(0).getId()));
|
||||
|
||||
// Call delete method on component
|
||||
workflowEngine.deleteWorkflow(instances.get(0).getId());
|
||||
|
||||
instances = workflowEngine.getActiveWorkflows(def.getId());
|
||||
assertNotNull(instances);
|
||||
assertEquals(0, instances.size());
|
||||
|
||||
// Historic process instance shouldn't be present
|
||||
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
|
||||
.processInstanceId(processInstance.getProcessInstanceId())
|
||||
.singleResult();
|
||||
|
||||
assertNull(historicProcessInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteFinishedWorkflow() throws Exception
|
||||
{
|
||||
WorkflowDefinition def = deployTestAdhocDefinition();
|
||||
|
||||
ProcessInstance processInstance = runtime.startProcessInstanceById(BPMEngineRegistry.getLocalId(def.getId()));
|
||||
|
||||
// Validate if a workflow exists
|
||||
List<WorkflowInstance> instances = workflowEngine.getActiveWorkflows(def.getId());
|
||||
assertNotNull(instances);
|
||||
assertEquals(1, instances.size());
|
||||
assertEquals(processInstance.getId(), BPMEngineRegistry.getLocalId(instances.get(0).getId()));
|
||||
|
||||
WorkflowInstance instance = instances.get(0);
|
||||
|
||||
WorkflowTask startTask = workflowEngine.getStartTask(instance.getId());
|
||||
workflowEngine.endTask(startTask.getId(), null);
|
||||
|
||||
WorkflowTask adhocTask = workflowEngine.getTasksForWorkflowPath(instance.getId()).get(0);
|
||||
workflowEngine.endTask(adhocTask.getId(), null);
|
||||
|
||||
// Validate if workflow is ended and has history
|
||||
instances = workflowEngine.getActiveWorkflows(def.getId());
|
||||
assertNotNull(instances);
|
||||
assertEquals(0, instances.size());
|
||||
|
||||
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
|
||||
.processInstanceId(processInstance.getProcessInstanceId())
|
||||
.singleResult();
|
||||
|
||||
assertNotNull(historicProcessInstance);
|
||||
|
||||
|
||||
// Call delete method on component
|
||||
workflowEngine.deleteWorkflow(instance.getId());
|
||||
|
||||
// Historic process instance shouldn't be present anymore
|
||||
historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
|
||||
.processInstanceId(processInstance.getProcessInstanceId())
|
||||
.singleResult();
|
||||
|
||||
assertNull(historicProcessInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteUnexistingWorkflow() throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
String globalId = workflowEngine.createGlobalId("unexistingWorkflowId");
|
||||
workflowEngine.deleteWorkflow(globalId);
|
||||
fail("Exception expected");
|
||||
}
|
||||
catch(WorkflowException e)
|
||||
{
|
||||
// Inore this
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetActiveWorkflows() throws Exception
|
||||
{
|
||||
WorkflowDefinition def = deployTestAdhocDefinition();
|
||||
String activitiProcessDefinitionId = BPMEngineRegistry.getLocalId(def.getId());
|
||||
|
||||
ProcessInstance activeInstance = runtime.startProcessInstanceById(activitiProcessDefinitionId);
|
||||
ProcessInstance completedInstance = runtime.startProcessInstanceById(activitiProcessDefinitionId);
|
||||
ProcessInstance cancelledInstance = runtime.startProcessInstanceById(activitiProcessDefinitionId);
|
||||
ProcessInstance deletedInstance = runtime.startProcessInstanceById(activitiProcessDefinitionId);
|
||||
|
||||
// Complete completedProcessInstance.
|
||||
String completedId = completedInstance.getId();
|
||||
boolean isActive = true;
|
||||
while (isActive)
|
||||
{
|
||||
Execution execution = runtime.createExecutionQuery()
|
||||
.processInstanceId(completedId)
|
||||
.singleResult();
|
||||
runtime.signal(execution.getId());
|
||||
ProcessInstance instance = runtime.createProcessInstanceQuery()
|
||||
.processInstanceId(completedId)
|
||||
.singleResult();
|
||||
isActive = instance != null;
|
||||
}
|
||||
|
||||
// Deleted and canceled instances shouldn't be returned
|
||||
workflowEngine.cancelWorkflow(workflowEngine.createGlobalId(cancelledInstance.getId()));
|
||||
workflowEngine.deleteWorkflow(workflowEngine.createGlobalId(deletedInstance.getId()));
|
||||
|
||||
// Validate if a workflow exists
|
||||
List<WorkflowInstance> instances = workflowEngine.getActiveWorkflows(def.getId());
|
||||
assertNotNull(instances);
|
||||
assertEquals(1, instances.size());
|
||||
String instanceId = instances.get(0).getId();
|
||||
assertEquals(activeInstance.getId(), BPMEngineRegistry.getLocalId(instanceId));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCompletedWorkflows() throws Exception
|
||||
{
|
||||
WorkflowDefinition def = deployTestAdhocDefinition();
|
||||
String activitiProcessDefinitionId = BPMEngineRegistry.getLocalId(def.getId());
|
||||
|
||||
runtime.startProcessInstanceById(activitiProcessDefinitionId);
|
||||
ProcessInstance completedInstance = runtime.startProcessInstanceById(activitiProcessDefinitionId);
|
||||
ProcessInstance cancelledInstance = runtime.startProcessInstanceById(activitiProcessDefinitionId);
|
||||
ProcessInstance deletedInstance = runtime.startProcessInstanceById(activitiProcessDefinitionId);
|
||||
|
||||
// Complete completedProcessInstance.
|
||||
String completedId = completedInstance.getId();
|
||||
boolean isActive = true;
|
||||
while (isActive)
|
||||
{
|
||||
Execution execution = runtime.createExecutionQuery()
|
||||
.processInstanceId(completedId)
|
||||
.singleResult();
|
||||
runtime.signal(execution.getId());
|
||||
ProcessInstance instance = runtime.createProcessInstanceQuery()
|
||||
.processInstanceId(completedId)
|
||||
.singleResult();
|
||||
isActive = instance != null;
|
||||
}
|
||||
|
||||
// Deleted and canceled instances shouldn't be returned
|
||||
workflowEngine.cancelWorkflow(workflowEngine.createGlobalId(cancelledInstance.getId()));
|
||||
workflowEngine.deleteWorkflow(workflowEngine.createGlobalId(deletedInstance.getId()));
|
||||
|
||||
// Validate if a workflow exists
|
||||
List<WorkflowInstance> instances = workflowEngine.getCompletedWorkflows(def.getId());
|
||||
assertNotNull(instances);
|
||||
assertEquals(1, instances.size());
|
||||
String instanceId = instances.get(0).getId();
|
||||
assertEquals(completedId, BPMEngineRegistry.getLocalId(instanceId));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetWorkflows() throws Exception
|
||||
{
|
||||
WorkflowDefinition def = deployTestAdhocDefinition();
|
||||
String activitiProcessDefinitionId = BPMEngineRegistry.getLocalId(def.getId());
|
||||
|
||||
ProcessInstance activeInstance = runtime.startProcessInstanceById(activitiProcessDefinitionId);
|
||||
ProcessInstance completedInstance = runtime.startProcessInstanceById(activitiProcessDefinitionId);
|
||||
ProcessInstance cancelledInstance = runtime.startProcessInstanceById(activitiProcessDefinitionId);
|
||||
ProcessInstance deletedInstance = runtime.startProcessInstanceById(activitiProcessDefinitionId);
|
||||
|
||||
// Complete completedProcessInstance.
|
||||
String completedId = completedInstance.getId();
|
||||
boolean isActive = true;
|
||||
while (isActive)
|
||||
{
|
||||
Execution execution = runtime.createExecutionQuery()
|
||||
.processInstanceId(completedId)
|
||||
.singleResult();
|
||||
runtime.signal(execution.getId());
|
||||
ProcessInstance instance = runtime.createProcessInstanceQuery()
|
||||
.processInstanceId(completedId)
|
||||
.singleResult();
|
||||
isActive = instance != null;
|
||||
}
|
||||
|
||||
// Deleted and canceled instances shouldn't be returned
|
||||
workflowEngine.cancelWorkflow(workflowEngine.createGlobalId(cancelledInstance.getId()));
|
||||
workflowEngine.deleteWorkflow(workflowEngine.createGlobalId(deletedInstance.getId()));
|
||||
|
||||
// Validate if a workflow exists
|
||||
List<WorkflowInstance> instances = workflowEngine.getWorkflows(def.getId());
|
||||
assertNotNull(instances);
|
||||
assertEquals(2, instances.size());
|
||||
String instanceId = instances.get(0).getId();
|
||||
assertEquals(activeInstance.getId(), BPMEngineRegistry.getLocalId(instanceId));
|
||||
instanceId = instances.get(1).getId();
|
||||
assertEquals(completedId, BPMEngineRegistry.getLocalId(instanceId));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetWorkflowById() throws Exception
|
||||
{
|
||||
WorkflowDefinition def = deployTestAdhocDefinition();
|
||||
|
||||
Date startTime = new SimpleDateFormat("dd-MM-yyy hh:mm:ss").parse("01-01-2011 12:11:10");
|
||||
ClockUtil.setCurrentTime(startTime);
|
||||
|
||||
// Add some variables which should be used in the WorkflowInstance
|
||||
Map<String, Object> variables = new HashMap<String, Object>();
|
||||
|
||||
Date dueDate = Calendar.getInstance().getTime();
|
||||
putVariable(variables, WorkflowModel.PROP_WORKFLOW_DUE_DATE, dueDate);
|
||||
putVariable(variables, WorkflowModel.PROP_WORKFLOW_DESCRIPTION, "I'm the description");
|
||||
putVariable(variables, WorkflowModel.PROP_CONTEXT, new ActivitiScriptNode(testWorkflowContext, serviceRegistry));
|
||||
putVariable(variables, WorkflowModel.ASSOC_PACKAGE, new ActivitiScriptNode(testWorkflowPackage, serviceRegistry));
|
||||
putVariable(variables, WorkflowModel.PROP_WORKFLOW_PRIORITY, 3);
|
||||
variables.put(WorkflowConstants.PROP_INITIATOR, new ActivitiScriptNode(adminHomeNode, serviceRegistry));
|
||||
|
||||
ProcessInstance processInstance = runtime.startProcessInstanceById(BPMEngineRegistry.getLocalId(def.getId()), variables);
|
||||
String globalProcessInstanceId = BPMEngineRegistry.createGlobalId(
|
||||
ActivitiConstants.ENGINE_ID, processInstance.getProcessInstanceId());
|
||||
|
||||
WorkflowInstance workflowInstance = workflowEngine.getWorkflowById(globalProcessInstanceId);
|
||||
assertNotNull(workflowInstance);
|
||||
|
||||
assertEquals(globalProcessInstanceId, workflowInstance.getId());
|
||||
assertNull(workflowInstance.getEndDate());
|
||||
assertTrue(workflowInstance.isActive());
|
||||
assertEquals("I'm the description", workflowInstance.getDescription());
|
||||
assertEquals(dueDate, workflowInstance.getDueDate());
|
||||
assertEquals(def.getId(), workflowInstance.getDefinition().getId());
|
||||
|
||||
assertEquals(adminHomeNode, workflowInstance.getInitiator());
|
||||
assertEquals(testWorkflowContext, workflowInstance.getContext());
|
||||
assertEquals(testWorkflowPackage, workflowInstance.getWorkflowPackage());
|
||||
|
||||
assertNotNull(workflowInstance.getPriority());
|
||||
assertEquals(3, workflowInstance.getPriority().intValue());
|
||||
|
||||
assertEquals(startTime, workflowInstance.getStartDate());
|
||||
|
||||
// Reset current time used in activiti
|
||||
ClockUtil.setCurrentTime(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCompletedWorkflowById() throws Exception
|
||||
{
|
||||
WorkflowDefinition def = deployTestAdhocDefinition();
|
||||
|
||||
Date startTime = new SimpleDateFormat("dd-MM-yyy hh:mm:ss").parse("01-01-2011 01:02:03");
|
||||
ClockUtil.setCurrentTime(startTime);
|
||||
|
||||
// Add some variables which should be used in the WorkflowInstance
|
||||
Map<String, Object> variables = new HashMap<String, Object>();
|
||||
|
||||
Date dueDate = Calendar.getInstance().getTime();
|
||||
putVariable(variables, WorkflowModel.PROP_WORKFLOW_DUE_DATE, dueDate);
|
||||
putVariable(variables, WorkflowModel.PROP_WORKFLOW_DESCRIPTION, "I'm the description");
|
||||
putVariable(variables, WorkflowModel.PROP_CONTEXT, new ActivitiScriptNode(testWorkflowContext, serviceRegistry));
|
||||
putVariable(variables, WorkflowModel.ASSOC_PACKAGE, new ActivitiScriptNode(testWorkflowPackage, serviceRegistry));
|
||||
putVariable(variables, WorkflowModel.PROP_WORKFLOW_PRIORITY, 3);
|
||||
variables.put(WorkflowConstants.PROP_INITIATOR, new ActivitiScriptNode(adminHomeNode, serviceRegistry));
|
||||
|
||||
ProcessInstance processInstance = runtime.startProcessInstanceById(BPMEngineRegistry.getLocalId(def.getId()), variables);
|
||||
String globalProcessInstanceId = BPMEngineRegistry.createGlobalId(
|
||||
ActivitiConstants.ENGINE_ID, processInstance.getProcessInstanceId());
|
||||
|
||||
Date endTime = new SimpleDateFormat("dd-MM-yyy hh:mm:ss").parse("01-01-2011 02:03:04");
|
||||
ClockUtil.setCurrentTime(endTime);
|
||||
|
||||
// Finish the task
|
||||
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
|
||||
taskService.complete(task.getId());
|
||||
|
||||
WorkflowInstance workflowInstance = workflowEngine.getWorkflowById(globalProcessInstanceId);
|
||||
assertNotNull(workflowInstance);
|
||||
|
||||
assertEquals(globalProcessInstanceId, workflowInstance.getId());
|
||||
assertEquals(endTime, workflowInstance.getEndDate());
|
||||
assertFalse(workflowInstance.isActive());
|
||||
assertEquals("I'm the description", workflowInstance.getDescription());
|
||||
assertEquals(dueDate, workflowInstance.getDueDate());
|
||||
assertEquals(def.getId(), workflowInstance.getDefinition().getId());
|
||||
|
||||
assertEquals(adminHomeNode, workflowInstance.getInitiator());
|
||||
assertEquals(testWorkflowContext, workflowInstance.getContext());
|
||||
assertEquals(testWorkflowPackage, workflowInstance.getWorkflowPackage());
|
||||
|
||||
assertNotNull(workflowInstance.getPriority());
|
||||
assertEquals(3, workflowInstance.getPriority().intValue());
|
||||
assertEquals(startTime, workflowInstance.getStartDate());
|
||||
|
||||
// Reset current time used in activiti
|
||||
ClockUtil.setCurrentTime(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTimers() throws Exception
|
||||
{
|
||||
WorkflowDefinition def = deployTestJobDefinition();
|
||||
|
||||
ProcessInstance processInstance = runtime.startProcessInstanceById(BPMEngineRegistry.getLocalId(def.getId()));
|
||||
|
||||
// One timer should be active on workflow
|
||||
String workflowInstanceId = BPMEngineRegistry.createGlobalId(ActivitiConstants.ENGINE_ID,
|
||||
processInstance.getProcessInstanceId());
|
||||
|
||||
// Query the timer in activity to have reference
|
||||
Job timerJob = managementService.createJobQuery().timers().processInstanceId(processInstance.getId()).singleResult();
|
||||
String globalJobId = BPMEngineRegistry.createGlobalId(ActivitiConstants.ENGINE_ID, timerJob.getId());
|
||||
|
||||
// Ask workflowEngine for timers
|
||||
List<WorkflowTimer> timers = workflowEngine.getTimers(workflowInstanceId);
|
||||
assertNotNull(timers);
|
||||
assertEquals(1, timers.size());
|
||||
|
||||
WorkflowTimer timer = timers.get(0);
|
||||
assertEquals(globalJobId, timer.getId());
|
||||
assertEquals(timerJob.getDuedate(), timer.getDueDate());
|
||||
|
||||
// Check the path of the timer
|
||||
String expectedTimerPathId = BPMEngineRegistry.createGlobalId(ActivitiConstants.ENGINE_ID, timerJob.getExecutionId());
|
||||
assertNotNull(timer.getPath());
|
||||
assertEquals(expectedTimerPathId, timer.getPath().getId());
|
||||
|
||||
// Check the workflow-instance associated with the path
|
||||
assertEquals(workflowInstanceId, timer.getPath().getInstance().getId());
|
||||
|
||||
// Check the task returned by the timer
|
||||
Task waitingTask = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
|
||||
|
||||
assertNotNull(timer.getTask());
|
||||
assertEquals(BPMEngineRegistry.createGlobalId(ActivitiConstants.ENGINE_ID, waitingTask.getId()), timer.getTask().getId());
|
||||
|
||||
// When task with boundry-timer on it is finished, no timers should be available
|
||||
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
|
||||
taskService.complete(task.getId());
|
||||
|
||||
timers = workflowEngine.getTimers(workflowInstanceId);
|
||||
|
||||
assertNotNull(timers);
|
||||
assertEquals(0, timers.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetWorkflowImage()
|
||||
{
|
||||
WorkflowDefinition definitionWithoutImage = deployTestAdhocDefinition();
|
||||
WorkflowDefinition definitionWithImage = deployTestDiagramDefinition();
|
||||
|
||||
// Start process-instance that shouldn't have an image
|
||||
ProcessInstance processInstance = runtime.startProcessInstanceById(BPMEngineRegistry.getLocalId(definitionWithoutImage.getId()));
|
||||
String worklfowId = BPMEngineRegistry.createGlobalId(ActivitiConstants.ENGINE_ID, processInstance.getId());
|
||||
|
||||
assertFalse(workflowEngine.hasWorkflowImage(worklfowId));
|
||||
assertNull(workflowEngine.getWorkflowImage(worklfowId));
|
||||
|
||||
// Start process-instance that SHOULD have an image
|
||||
ProcessInstance processInstanceWithImage = runtime.startProcessInstanceById(BPMEngineRegistry.getLocalId(definitionWithImage.getId()));
|
||||
String worklfowWithImageId = BPMEngineRegistry.createGlobalId(ActivitiConstants.ENGINE_ID, processInstanceWithImage.getId());
|
||||
|
||||
assertTrue(workflowEngine.hasWorkflowImage(worklfowWithImageId));
|
||||
assertNotNull(workflowEngine.getWorkflowImage(worklfowWithImageId));
|
||||
}
|
||||
|
||||
|
||||
private void putVariable(Map<String, Object> variables, QName varName, Object value)
|
||||
{
|
||||
String variableName = mapQNameToName(varName);
|
||||
variables.put(variableName, value);
|
||||
}
|
||||
|
||||
private void checkDefinitions(List<WorkflowDefinition> actual,List<WorkflowDefinition> startDefs, WorkflowDefinition... expected)
|
||||
{
|
||||
assertEquals("The number of process definitions expected does not match the actual number!", startDefs.size() + expected.length, actual.size());
|
||||
ArrayList<String> ids = new ArrayList<String>(actual.size());
|
||||
for (WorkflowDefinition def : actual)
|
||||
{
|
||||
ids.add(def.getId());
|
||||
}
|
||||
for (WorkflowDefinition exp: expected)
|
||||
{
|
||||
assertTrue("Results did not contain expected definition: "+exp, ids.contains(exp.getId()));
|
||||
}
|
||||
List<String> startIds = new ArrayList<String>(startDefs.size());
|
||||
for (WorkflowDefinition def : startDefs)
|
||||
{
|
||||
startIds.add(def.getId());
|
||||
}
|
||||
for (WorkflowDefinition exp: expected)
|
||||
{
|
||||
assertFalse("Starting Definitions should not contain expected definition: "+exp, startIds.contains(exp.getId()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.workflow.activiti;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||
import org.alfresco.repo.workflow.AbstractWorkflowServiceIntegrationTest;
|
||||
import org.alfresco.repo.workflow.WorkflowModel;
|
||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowPath;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTask;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTaskDefinition;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTaskQuery;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* @author Nick Smith
|
||||
* @since 3.4.e
|
||||
*/
|
||||
public class ActivitiWorkflowServiceIntegrationTest extends AbstractWorkflowServiceIntegrationTest
|
||||
{
|
||||
public void testOutcome() throws Exception
|
||||
{
|
||||
WorkflowDefinition definition = deployDefinition("alfresco/workflow/review.bpmn20.xml");
|
||||
|
||||
personManager.setUser(USER1);
|
||||
|
||||
// Create workflow parameters
|
||||
Map<QName, Serializable> params = new HashMap<QName, Serializable>();
|
||||
Serializable wfPackage = workflowService.createPackage(null);
|
||||
params.put(WorkflowModel.ASSOC_PACKAGE, wfPackage);
|
||||
NodeRef assignee = personManager.get(USER2);
|
||||
params.put(WorkflowModel.ASSOC_ASSIGNEE, assignee); // task instance field
|
||||
|
||||
WorkflowPath path = workflowService.startWorkflow(definition.getId(), params);
|
||||
String instanceId = path.getInstance().getId();
|
||||
|
||||
WorkflowTask startTask = workflowService.getStartTask(instanceId);
|
||||
workflowService.endTask(startTask.getId(), null);
|
||||
|
||||
List<WorkflowPath> paths = workflowService.getWorkflowPaths(instanceId);
|
||||
assertEquals(1, paths.size());
|
||||
path = paths.get(0);
|
||||
|
||||
List<WorkflowTask> tasks = workflowService.getTasksForWorkflowPath(path.getId());
|
||||
assertEquals(1, tasks.size());
|
||||
WorkflowTask reviewTask = tasks.get(0);
|
||||
|
||||
// Set the transition property
|
||||
QName outcomePropName = QName.createQName(NamespaceService.WORKFLOW_MODEL_1_0_URI, "reviewOutcome");
|
||||
Map<QName, Serializable> props = new HashMap<QName, Serializable>();
|
||||
props.put(outcomePropName, "Approve");
|
||||
workflowService.updateTask(reviewTask.getId(), props, null, null);
|
||||
|
||||
// End task and check outcome property
|
||||
WorkflowTask result = workflowService.endTask(reviewTask.getId(), null);
|
||||
Serializable outcome = result.getProperties().get(WorkflowModel.PROP_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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Actually tests if the priority is the default value. This is based on the assumption that custom
|
||||
* tasks are defaulted to a priority of 50 (which is invalid). I'm testing that the code I wrote decides this is an
|
||||
* invalid number and sets it to the default value (2).
|
||||
*/
|
||||
public void testPriorityIsValid()
|
||||
{
|
||||
WorkflowDefinition definition = deployDefinition("activiti/testCustomActiviti.bpmn20.xml");
|
||||
|
||||
personManager.setUser(USER1);
|
||||
|
||||
// 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());
|
||||
for (WorkflowTask workflowTask : tasks)
|
||||
{
|
||||
Map<QName, Serializable> props = workflowTask.getProperties();
|
||||
TypeDefinition typeDefinition = workflowTask.getDefinition().getMetadata();
|
||||
Map<QName, PropertyDefinition> propertyDefs = typeDefinition.getProperties();
|
||||
PropertyDefinition priorDef = propertyDefs.get(WorkflowModel.PROP_PRIORITY);
|
||||
assertEquals(props.get(WorkflowModel.PROP_PRIORITY),Integer.valueOf(priorDef.getDefaultValue()));
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetWorkflowTaskDefinitionsWithMultiInstanceTask()
|
||||
{
|
||||
// Test added to validate fix for ALF-14224
|
||||
WorkflowDefinition definition = deployDefinition(getParallelReviewDefinitionPath());
|
||||
String workflowDefId = definition.getId();
|
||||
List<WorkflowTaskDefinition> taskDefs = workflowService.getTaskDefinitions(workflowDefId);
|
||||
assertEquals(4, taskDefs.size());
|
||||
|
||||
// The first task is the start-task, the second one is a multi-instance UserTask. This should have the right form-key
|
||||
WorkflowTaskDefinition taskDef = taskDefs.get(1);
|
||||
assertEquals("wf:activitiReviewTask", taskDef.getId());
|
||||
}
|
||||
|
||||
public void testAccessStartTaskAsAssigneeFromTaskPartOfProcess()
|
||||
{
|
||||
// Test added to validate fix for CLOUD-1929 - start-task can be accesses by assignee of a task
|
||||
// part of that process
|
||||
WorkflowDefinition definition = deployDefinition(getAdhocDefinitionPath());
|
||||
|
||||
// Start process as USER1
|
||||
personManager.setUser(USER1);
|
||||
|
||||
// Create workflow parameters
|
||||
Map<QName, Serializable> params = new HashMap<QName, Serializable>();
|
||||
Serializable wfPackage = workflowService.createPackage(null);
|
||||
params.put(WorkflowModel.ASSOC_PACKAGE, wfPackage);
|
||||
NodeRef assignee = personManager.get(USER2);
|
||||
params.put(WorkflowModel.ASSOC_ASSIGNEE, assignee); // task instance field
|
||||
|
||||
WorkflowPath path = workflowService.startWorkflow(definition.getId(), params);
|
||||
String instanceId = path.getInstance().getId();
|
||||
|
||||
WorkflowTask startTask = workflowService.getStartTask(instanceId);
|
||||
workflowService.endTask(startTask.getId(), null);
|
||||
|
||||
List<WorkflowTask> tasks = workflowService.getTasksForWorkflowPath(path.getId());
|
||||
assertEquals(1, tasks.size());
|
||||
|
||||
|
||||
// Assign task to user3
|
||||
workflowService.updateTask(tasks.get(0).getId(), Collections.singletonMap(WorkflowModel.ASSOC_ASSIGNEE,
|
||||
(Serializable) personManager.get(USER3)), null, null);
|
||||
|
||||
// Authenticate as user3
|
||||
personManager.setUser(USER3);
|
||||
|
||||
// When fetchin the start-task, no exception should be thrown
|
||||
startTask = workflowService.getStartTask(instanceId);
|
||||
assertNotNull(startTask);
|
||||
startTask = workflowService.getTaskById(startTask.getId());
|
||||
assertNotNull(startTask);
|
||||
|
||||
// Accessing by user4 shouldn't be possible
|
||||
personManager.setUser(USER4);
|
||||
try
|
||||
{
|
||||
workflowService.getStartTask(instanceId);
|
||||
fail("AccessDeniedException expected");
|
||||
}
|
||||
catch(AccessDeniedException expected)
|
||||
{
|
||||
// Expected excaption
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
workflowService.getTaskById(startTask.getId());
|
||||
fail("AccessDeniedException expected");
|
||||
}
|
||||
catch(AccessDeniedException expected)
|
||||
{
|
||||
// Expected exception
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void checkTaskQueryStartTaskCompleted(String workflowInstanceId, WorkflowTask startTask)
|
||||
{
|
||||
// In activiti, start-tasks only show up when the taskId or workflowInstanceId is passed in.
|
||||
List<String> expectedTasks = Arrays.asList(startTask.getId());
|
||||
|
||||
checkProcessIdQuery(workflowInstanceId, expectedTasks, WorkflowTaskState.COMPLETED);
|
||||
checkTaskIdQuery(startTask.getId(), WorkflowTaskState.COMPLETED);
|
||||
|
||||
// Check additional filtering, when workflowInstanceId is passed
|
||||
QName startTaskName = QName.createQName(NamespaceService.WORKFLOW_MODEL_1_0_URI, "submitAdhocTask");
|
||||
checkTaskNameQuery(startTaskName, expectedTasks, WorkflowTaskState.COMPLETED, workflowInstanceId);
|
||||
checkActorIdQuery(USER1, expectedTasks, WorkflowTaskState.COMPLETED, workflowInstanceId);
|
||||
checkIsActiveQuery(expectedTasks, WorkflowTaskState.COMPLETED, workflowInstanceId);
|
||||
checkTaskPropsQuery(expectedTasks, WorkflowTaskState.COMPLETED, workflowInstanceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkTaskQueryTaskCompleted(String workflowInstanceId, WorkflowTask theTask, WorkflowTask startTask)
|
||||
{
|
||||
List<String> withoutStartTask = Arrays.asList(theTask.getId());
|
||||
List<String> bothTasks= Arrays.asList(theTask.getId(), startTask.getId());
|
||||
|
||||
checkProcessIdQuery(workflowInstanceId, bothTasks, WorkflowTaskState.COMPLETED);
|
||||
|
||||
// Adhoc task should only be returned
|
||||
QName taskName = QName.createQName(NamespaceService.WORKFLOW_MODEL_1_0_URI, "adhocTask");
|
||||
checkTaskNameQuery(taskName, withoutStartTask, WorkflowTaskState.COMPLETED, null);
|
||||
|
||||
// Completed adhocTask is assigned to USER2
|
||||
checkActorIdQuery(USER2, withoutStartTask, WorkflowTaskState.COMPLETED, null);
|
||||
|
||||
checkIsActiveQuery(bothTasks, WorkflowTaskState.COMPLETED, workflowInstanceId);
|
||||
|
||||
// Task has custom property set
|
||||
checkTaskPropsQuery(withoutStartTask, WorkflowTaskState.COMPLETED, null);
|
||||
|
||||
// Process properties
|
||||
checkProcessPropsQuery(withoutStartTask, WorkflowTaskState.COMPLETED);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkQueryTasksInactiveWorkflow(String workflowInstanceId)
|
||||
{
|
||||
WorkflowTaskQuery taskQuery = createWorkflowTaskQuery(WorkflowTaskState.COMPLETED);
|
||||
taskQuery.setActive(false);
|
||||
taskQuery.setProcessId(workflowInstanceId);
|
||||
|
||||
List<WorkflowTask> tasks = workflowService.queryTasks(taskQuery);
|
||||
assertNotNull(tasks);
|
||||
|
||||
assertEquals(3, tasks.size());
|
||||
|
||||
taskQuery = createWorkflowTaskQuery(WorkflowTaskState.COMPLETED);
|
||||
taskQuery.setActive(true);
|
||||
taskQuery.setProcessId(workflowInstanceId);
|
||||
checkNoTasksFoundUsingQuery(taskQuery);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getEngine()
|
||||
{
|
||||
return ActivitiConstants.ENGINE_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTestDefinitionPath()
|
||||
{
|
||||
return "activiti/testTransaction.bpmn20.xml";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getAdhocDefinitionPath()
|
||||
{
|
||||
return "alfresco/workflow/adhoc.bpmn20.xml";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getPooledReviewDefinitionPath()
|
||||
{
|
||||
return "alfresco/workflow/review-pooled.bpmn20.xml";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getParallelReviewDefinitionPath()
|
||||
{
|
||||
return "alfresco/workflow/parallel-review.bpmn20.xml";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTestTimerDefinitionPath()
|
||||
{
|
||||
return "activiti/testTimer.bpmn20.xml";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected QName getAdhocProcessName()
|
||||
{
|
||||
return QName.createQName("activitiAdhoc");
|
||||
}
|
||||
}
|
@@ -0,0 +1,331 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.workflow.jbpm;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.jscript.ScriptNode;
|
||||
import org.alfresco.repo.model.Repository;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.scripts.ScriptException;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.model.FileFolderService;
|
||||
import org.alfresco.service.cmr.model.FileInfo;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.cmr.security.PersonService;
|
||||
import org.alfresco.service.cmr.site.SiteService;
|
||||
import org.alfresco.service.cmr.site.SiteVisibility;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.BaseAlfrescoSpringTest;
|
||||
import org.alfresco.util.GUID;
|
||||
import org.alfresco.util.PropertyMap;
|
||||
import org.dom4j.DocumentHelper;
|
||||
import org.dom4j.Element;
|
||||
import org.jbpm.context.exe.ContextInstance;
|
||||
import org.jbpm.graph.exe.ExecutionContext;
|
||||
import org.jbpm.graph.exe.Token;
|
||||
import org.jbpm.taskmgmt.exe.TaskInstance;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
public class AlfrescoJavaScriptIntegrationTest extends BaseAlfrescoSpringTest
|
||||
{
|
||||
private static final QName fooName = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "Foo");
|
||||
private static final QName barName = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "Bar");
|
||||
private static final QName docName = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "Doc");
|
||||
private static final String BASIC_USER = "basic"+GUID.generate();
|
||||
private static String systemUser = AuthenticationUtil.getSystemUserName();
|
||||
|
||||
private ServiceRegistry services;
|
||||
private ExecutionContext context;
|
||||
private HashMap<String, Object> variables;
|
||||
private PersonService personService;
|
||||
private Repository repository;
|
||||
|
||||
/**
|
||||
* Test that JavaScript can still be run even if no Authentication is provided.
|
||||
* This can occur if, e.g. the action is executed as part of an asynchronous task.
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testRunsWithoutAuthentication() throws Exception
|
||||
{
|
||||
NodeRef systemNode = personService.getPerson(systemUser);
|
||||
NodeRef baseUserNode = personService.getPerson(BASIC_USER);
|
||||
TestUserStore userStore = new TestUserStore();
|
||||
variables.put("userStore", userStore);
|
||||
Element script = buildScript("userStore.storeUsers(person)");
|
||||
|
||||
// Check authentication cleared.
|
||||
AuthenticationUtil.clearCurrentSecurityContext();
|
||||
assertNull(AuthenticationUtil.getFullyAuthenticatedUser());
|
||||
assertNull(AuthenticationUtil.getRunAsUser());
|
||||
|
||||
// Check uses system user when no authentication set and no task assignee.
|
||||
AlfrescoJavaScript scriptHandler = new AlfrescoJavaScript();
|
||||
scriptHandler.setScript(script);
|
||||
scriptHandler.execute(context);
|
||||
assertEquals(systemUser, userStore.runAsUser);
|
||||
assertEquals(systemUser, userStore.fullUser);
|
||||
assertEquals(systemNode, userStore.person.getNodeRef());
|
||||
|
||||
// Check authentication is correctly reset.
|
||||
assertNull(AuthenticationUtil.getFullyAuthenticatedUser());
|
||||
assertNull(AuthenticationUtil.getRunAsUser());
|
||||
|
||||
// Check that when a task assignee exists, then he/she is used for authentication.
|
||||
TaskInstance taskInstance = mock(TaskInstance.class);
|
||||
when(taskInstance.getActorId()).thenReturn(BASIC_USER);
|
||||
when(context.getTaskInstance()).thenReturn(taskInstance);
|
||||
scriptHandler = new AlfrescoJavaScript();
|
||||
scriptHandler.setScript(script);
|
||||
scriptHandler.execute(context);
|
||||
assertEquals(BASIC_USER, userStore.runAsUser);
|
||||
assertEquals(BASIC_USER, userStore.fullUser);
|
||||
assertEquals(baseUserNode, userStore.person.getNodeRef());
|
||||
|
||||
// Check authentication is correctly reset.
|
||||
assertNull(AuthenticationUtil.getFullyAuthenticatedUser());
|
||||
assertNull(AuthenticationUtil.getRunAsUser());
|
||||
}
|
||||
|
||||
/**
|
||||
* See Jira issue ALF-657.
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testRunAsAdminMoveContent() throws Exception
|
||||
{
|
||||
NodeRef fooFolder = nodeService.createNode(rootNodeRef,
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
fooName,
|
||||
ContentModel.TYPE_FOLDER).getChildRef();
|
||||
|
||||
NodeRef barFolder = nodeService.createNode(rootNodeRef,
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
barName,
|
||||
ContentModel.TYPE_FOLDER).getChildRef();
|
||||
|
||||
NodeRef doc = nodeService.createNode(fooFolder,
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
docName,
|
||||
ContentModel.TYPE_CONTENT).getChildRef();
|
||||
PermissionService permissions = services.getPermissionService();
|
||||
permissions.setPermission(doc, BASIC_USER, PermissionService.ALL_PERMISSIONS, true);
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(BASIC_USER);
|
||||
|
||||
Element script = buildScript("doc.move(bar)");
|
||||
|
||||
variables.put("doc", new JBPMNode(doc, services));
|
||||
variables.put("bar", new JBPMNode(barFolder, services));
|
||||
assertEquals(fooFolder, nodeService.getPrimaryParent(doc).getParentRef());
|
||||
try
|
||||
{
|
||||
AlfrescoJavaScript scriptHandler = new AlfrescoJavaScript();
|
||||
scriptHandler.setScript(script);
|
||||
scriptHandler.execute(context);
|
||||
fail("The user should not have permission to write to bar!");
|
||||
}
|
||||
catch (ScriptException e)
|
||||
{
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
assertEquals(fooFolder, nodeService.getPrimaryParent(doc).getParentRef());
|
||||
|
||||
AlfrescoJavaScript scriptHandler = new AlfrescoJavaScript();
|
||||
scriptHandler.setScript(script);
|
||||
scriptHandler.setRunas(AuthenticationUtil.getAdminUserName());
|
||||
scriptHandler.execute(context);
|
||||
assertEquals(barFolder, nodeService.getPrimaryParent(doc).getParentRef());
|
||||
}
|
||||
|
||||
/**
|
||||
* See Jira issue ALF-5346.
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testRunAsAdminMoveContentBetweenSites() throws Exception
|
||||
{
|
||||
SiteService siteService = services.getSiteService();
|
||||
FileFolderService fileFolderService = services.getFileFolderService();
|
||||
|
||||
String siteAName = "siteA"+GUID.generate();
|
||||
String siteBName = "siteB"+GUID.generate();
|
||||
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
|
||||
|
||||
siteService.createSite(
|
||||
"testSitePreset", siteAName, "title", "description", SiteVisibility.PRIVATE);
|
||||
|
||||
siteService.createSite(
|
||||
"testSitePreset", siteBName, "title", "description", SiteVisibility.PRIVATE);
|
||||
|
||||
NodeRef docLibA = siteService.createContainer(siteAName, "documentLibrary", ContentModel.TYPE_FOLDER, null);
|
||||
NodeRef docLibB = siteService.createContainer(siteBName, "documentLibrary", ContentModel.TYPE_FOLDER, null);
|
||||
|
||||
FileInfo docInfo = fileFolderService.create(docLibA, "test.txt", ContentModel.TYPE_CONTENT);
|
||||
NodeRef doc = docInfo.getNodeRef();
|
||||
ContentWriter writer = fileFolderService.getWriter(doc);
|
||||
writer.putContent("Just some old content that doesn't mean anything");
|
||||
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(BASIC_USER);
|
||||
|
||||
Element script = buildScript("doc.move(companyhome.childByNamePath(\"Sites/"+ siteBName +"/documentLibrary\"))");
|
||||
|
||||
NodeRef companyHome = repository.getCompanyHome();
|
||||
variables.put("companyhome", new JBPMNode(companyHome, services));
|
||||
variables.put("doc", new JBPMNode(doc, services));
|
||||
assertEquals(docLibA, nodeService.getPrimaryParent(doc).getParentRef());
|
||||
try
|
||||
{
|
||||
AlfrescoJavaScript scriptHandler = new AlfrescoJavaScript();
|
||||
scriptHandler.setScript(script);
|
||||
scriptHandler.execute(context);
|
||||
fail("The user should not have permission to write to Site B!");
|
||||
} catch(ScriptException e)
|
||||
{
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
assertEquals(docLibA, nodeService.getPrimaryParent(doc).getParentRef());
|
||||
|
||||
AlfrescoJavaScript scriptHandler = new AlfrescoJavaScript();
|
||||
scriptHandler.setScript(script);
|
||||
scriptHandler.setRunas(AuthenticationUtil.getAdminUserName());
|
||||
scriptHandler.execute(context);
|
||||
assertEquals(docLibB, nodeService.getPrimaryParent(doc).getParentRef());
|
||||
}
|
||||
|
||||
public void testScopeVariables() throws Exception
|
||||
{
|
||||
String admin = AuthenticationUtil.getAdminUserName();
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(admin);
|
||||
NodeRef person = personService.getPerson(admin);
|
||||
Serializable userHome = nodeService.getProperty(person, ContentModel.PROP_HOMEFOLDER);
|
||||
|
||||
AlfrescoJavaScript scriptHandler = new AlfrescoJavaScript();
|
||||
String key = "result";
|
||||
|
||||
// Check person node set.
|
||||
Element script = buildScript("executionContext.setVariable('" + key + "', person)");
|
||||
scriptHandler.setScript(script);
|
||||
scriptHandler.execute(context);
|
||||
ScriptNode value = (ScriptNode) variables.get(key);
|
||||
assertEquals(person, value.getNodeRef());
|
||||
|
||||
// Check user home set.
|
||||
script = buildScript("executionContext.setVariable('" + key + "', userhome)");
|
||||
scriptHandler.setScript(script);
|
||||
scriptHandler.execute(context);
|
||||
value = (ScriptNode) variables.get(key);
|
||||
assertEquals(userHome, value.getNodeRef());
|
||||
|
||||
// Check company home set.
|
||||
NodeRef companyHome = repository.getCompanyHome();
|
||||
script = buildScript("executionContext.setVariable('" + key + "', companyhome)");
|
||||
scriptHandler.setScript(script);
|
||||
scriptHandler.execute(context);
|
||||
value = (ScriptNode) variables.get(key);
|
||||
assertEquals(companyHome, value.getNodeRef());
|
||||
}
|
||||
|
||||
private Element buildScript(String expression)
|
||||
{
|
||||
Element script = DocumentHelper.createElement("script");
|
||||
script.setText(expression);
|
||||
return script;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
protected void onSetUp() throws Exception
|
||||
{
|
||||
super.onSetUp();
|
||||
|
||||
this.services = (ServiceRegistry) applicationContext.getBean("ServiceRegistry");
|
||||
repository = (Repository) applicationContext.getBean("repositoryHelper");
|
||||
personService = services.getPersonService();
|
||||
createUser(BASIC_USER);
|
||||
|
||||
// Sets up the Execution Context
|
||||
context = mock(ExecutionContext.class);
|
||||
ContextInstance contextInstance = mock(ContextInstance.class);
|
||||
when(context.getContextInstance()).thenReturn(contextInstance);
|
||||
variables = new HashMap<String, Object>();
|
||||
when(contextInstance.getVariables()).thenReturn(variables);
|
||||
when(contextInstance.getVariables( any(Token.class))).thenReturn(variables);
|
||||
when(context.getVariable(anyString())).thenAnswer(new Answer<Object>()
|
||||
{
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable
|
||||
{
|
||||
String key = (String)invocation.getArguments()[0];
|
||||
return variables.get(key);
|
||||
}
|
||||
});
|
||||
doAnswer(new Answer<Void>()
|
||||
{
|
||||
public Void answer(InvocationOnMock invocation) throws Throwable
|
||||
{
|
||||
String key = (String)invocation.getArguments()[0];
|
||||
Object value= invocation.getArguments()[1];
|
||||
variables.put(key, value);
|
||||
return null;
|
||||
}
|
||||
}).when(context).setVariable(anyString(), any());
|
||||
}
|
||||
|
||||
private void createUser(String userName)
|
||||
{
|
||||
if (this.authenticationService.authenticationExists(userName) == false)
|
||||
{
|
||||
this.authenticationService.createAuthentication(userName, "PWD".toCharArray());
|
||||
|
||||
PropertyMap ppOne = new PropertyMap(4);
|
||||
ppOne.put(ContentModel.PROP_USERNAME, userName);
|
||||
ppOne.put(ContentModel.PROP_FIRSTNAME, "firstName");
|
||||
ppOne.put(ContentModel.PROP_LASTNAME, "lastName");
|
||||
ppOne.put(ContentModel.PROP_EMAIL, "email@email.com");
|
||||
ppOne.put(ContentModel.PROP_JOBTITLE, "jobTitle");
|
||||
personService.createPerson(ppOne);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TestUserStore
|
||||
{
|
||||
private String runAsUser;
|
||||
private String fullUser;
|
||||
private ScriptNode person = null;
|
||||
|
||||
public void storeUsers(ScriptNode user)
|
||||
{
|
||||
fullUser = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
runAsUser = AuthenticationUtil.getRunAsUser();
|
||||
this.person = user;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,670 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.workflow.jbpm;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.workflow.BPMEngineRegistry;
|
||||
import org.alfresco.repo.workflow.TaskComponent;
|
||||
import org.alfresco.repo.workflow.WorkflowComponent;
|
||||
import org.alfresco.repo.workflow.WorkflowModel;
|
||||
import org.alfresco.repo.workflow.WorkflowPackageComponent;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.security.PersonService;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowDeployment;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowException;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowInstance;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowPath;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTask;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.BaseAlfrescoSpringTest;
|
||||
import org.alfresco.util.PropertyMap;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.extensions.surf.util.I18NUtil;
|
||||
|
||||
|
||||
/**
|
||||
* JBPM Engine Tests
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class JBPMEngineTest extends BaseAlfrescoSpringTest
|
||||
{
|
||||
private static final String USER1 = "JbpmEngineTestJohn";
|
||||
private static final String USER2 = "JbpmEngineTestJane";
|
||||
private static final String USER3 = "JbpmEngineTestJoe";
|
||||
|
||||
private WorkflowComponent workflowComponent;
|
||||
private TaskComponent taskComponent;
|
||||
private WorkflowPackageComponent packageComponent;
|
||||
private PersonService personService;
|
||||
private WorkflowDefinition testWorkflowDef;
|
||||
private NodeRef person1;
|
||||
private NodeRef person2;
|
||||
private NodeRef person3;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected void onSetUpInTransaction() throws Exception
|
||||
{
|
||||
super.onSetUpInTransaction();
|
||||
|
||||
personService = (PersonService) applicationContext.getBean("PersonService");
|
||||
person1 = createPerson(USER1);
|
||||
person2 = createPerson(USER2);
|
||||
person3 = createPerson(USER3);
|
||||
|
||||
BPMEngineRegistry registry = (BPMEngineRegistry)applicationContext.getBean("bpm_engineRegistry");
|
||||
workflowComponent = registry.getWorkflowComponent(JBPMEngine.ENGINE_ID);
|
||||
taskComponent = registry.getTaskComponent(JBPMEngine.ENGINE_ID);
|
||||
packageComponent = (WorkflowPackageComponent)applicationContext.getBean("workflowPackageImpl");
|
||||
|
||||
// deploy test process messages
|
||||
I18NUtil.registerResourceBundle("jbpmresources/test-messages");
|
||||
|
||||
// deploy test process definition
|
||||
ClassPathResource processDef = new ClassPathResource("jbpmresources/test_processdefinition.xml");
|
||||
assertFalse(workflowComponent.isDefinitionDeployed(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML));
|
||||
WorkflowDeployment deployment = workflowComponent.deployDefinition(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML);
|
||||
testWorkflowDef = deployment.definition;
|
||||
assertNotNull(testWorkflowDef);
|
||||
assertEquals("jbpm$test", testWorkflowDef.name);
|
||||
assertEquals("1", testWorkflowDef.version);
|
||||
assertTrue(workflowComponent.isDefinitionDeployed(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML));
|
||||
|
||||
authenticationComponent.setCurrentUser(AuthenticationUtil.getAdminUserName());
|
||||
}
|
||||
|
||||
public void todoTestGetStartTask() throws Exception
|
||||
{
|
||||
//TODO Implement
|
||||
}
|
||||
|
||||
public void testGetWorkflowDefinitions()
|
||||
{
|
||||
List<WorkflowDefinition> workflowDefs = workflowComponent.getDefinitions();
|
||||
assertNotNull(workflowDefs);
|
||||
assertTrue(workflowDefs.size() > 0);
|
||||
}
|
||||
|
||||
|
||||
public void testDeployWorkflow() throws Exception
|
||||
{
|
||||
ClassPathResource processDef = new ClassPathResource("jbpmresources/test_processdefinition.xml");
|
||||
WorkflowDeployment deployment = workflowComponent.deployDefinition(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML);
|
||||
testWorkflowDef = deployment.getDefinition();
|
||||
assertNotNull(testWorkflowDef);
|
||||
assertEquals("jbpm$test", testWorkflowDef.getName());
|
||||
assertEquals("2", testWorkflowDef.getVersion());
|
||||
}
|
||||
|
||||
|
||||
public void testStartWorkflow()
|
||||
{
|
||||
try
|
||||
{
|
||||
workflowComponent.startWorkflow("norfolknchance", null);
|
||||
fail("Failed to catch invalid definition id");
|
||||
}
|
||||
catch(WorkflowException e)
|
||||
{
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
// TODO: Determine why process definition is loaded, even though it doesn't exist
|
||||
// try
|
||||
// {
|
||||
// workflowComponent.startProcess("1000", null);
|
||||
// fail("Failed to catch workflow definition id that does not exist");
|
||||
// }
|
||||
// catch(WorkflowException e)
|
||||
// {
|
||||
// }
|
||||
|
||||
WorkflowDefinition workflowDef = getTestDefinition();
|
||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.getId(), null);
|
||||
assertNotNull(path);
|
||||
assertTrue(path.getId().endsWith("-@"));
|
||||
assertNotNull(path.getNode());
|
||||
assertNotNull(path.getInstance());
|
||||
assertEquals(workflowDef.getId(), path.getInstance().getDefinition().getId());
|
||||
}
|
||||
|
||||
|
||||
public void testGetWorkflowById()
|
||||
{
|
||||
WorkflowDefinition workflowDef = getTestDefinition();
|
||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.getId(), null);
|
||||
assertNotNull(path);
|
||||
assertTrue(path.getId().endsWith("-@"));
|
||||
assertNotNull(path.getNode());
|
||||
assertNotNull(path.getInstance());
|
||||
assertEquals(workflowDef.getId(), path.getInstance().getDefinition().getId());
|
||||
WorkflowInstance instance = workflowComponent.getWorkflowById(path.getInstance().getId());
|
||||
assertNotNull(instance);
|
||||
assertEquals(path.getInstance().getId(), instance.getId());
|
||||
|
||||
workflowComponent.cancelWorkflow(instance.getId());
|
||||
WorkflowInstance result = workflowComponent.getWorkflowById(instance.getId());
|
||||
assertNull("The workflow isntance should be null!", result);
|
||||
}
|
||||
|
||||
|
||||
public void testStartWorkflowParameters()
|
||||
{
|
||||
WorkflowDefinition workflowDef = getTestDefinition();
|
||||
|
||||
Map<QName, Serializable> params = new HashMap<QName, Serializable>();
|
||||
params.put(WorkflowModel.PROP_TASK_ID, 3); // protected - shouldn't be written
|
||||
params.put(WorkflowModel.PROP_DUE_DATE, new Date()); // task instance field
|
||||
params.put(WorkflowModel.PROP_PRIORITY, 1); // task instance field
|
||||
params.put(WorkflowModel.PROP_PERCENT_COMPLETE, 10); // context variable
|
||||
params.put(QName.createQName("", "Message"), "Hello World"); // context variable outside of task definition
|
||||
params.put(QName.createQName("", "Array"), new String[] { "one", "two" }); // context variable outside of task definition
|
||||
params.put(QName.createQName("", "NodeRef"), new NodeRef("workspace://1/1001")); // context variable outside of task definition
|
||||
params.put(ContentModel.PROP_OWNER, AuthenticationUtil.getAdminUserName()); // task assignment
|
||||
|
||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.getId(), params);
|
||||
assertNotNull(path);
|
||||
assertTrue(path.getId().endsWith("-@"));
|
||||
assertNotNull(path.getNode());
|
||||
assertNotNull(path.getInstance());
|
||||
assertEquals(workflowDef.getId(), path.getInstance().getDefinition().getId());
|
||||
List<WorkflowTask> tasks1 = workflowComponent.getTasksForWorkflowPath(path.getId());
|
||||
assertNotNull(tasks1);
|
||||
assertEquals(1, tasks1.size());
|
||||
|
||||
WorkflowTask task = tasks1.get(0);
|
||||
assertTrue(task.getProperties().containsKey(WorkflowModel.PROP_TASK_ID));
|
||||
assertTrue(task.getProperties().containsKey(WorkflowModel.PROP_DUE_DATE));
|
||||
assertTrue(task.getProperties().containsKey(WorkflowModel.PROP_PRIORITY));
|
||||
assertTrue(task.getProperties().containsKey(WorkflowModel.PROP_PERCENT_COMPLETE));
|
||||
assertTrue(task.getProperties().containsKey(ContentModel.PROP_OWNER));
|
||||
|
||||
NodeRef initiator = path.getInstance().getInitiator();
|
||||
String initiatorUsername = (String)nodeService.getProperty(initiator, ContentModel.PROP_USERNAME);
|
||||
assertEquals(AuthenticationUtil.getAdminUserName(), initiatorUsername);
|
||||
}
|
||||
|
||||
|
||||
public void testUpdateTask()
|
||||
{
|
||||
WorkflowDefinition workflowDef = getTestDefinition();
|
||||
|
||||
Map<QName, Serializable> params = new HashMap<QName, Serializable>();
|
||||
params.put(WorkflowModel.PROP_TASK_ID, 3); // protected - shouldn't be written
|
||||
params.put(WorkflowModel.PROP_DUE_DATE, new Date()); // task instance field
|
||||
params.put(WorkflowModel.PROP_PRIORITY, 1); // task instance field
|
||||
params.put(WorkflowModel.PROP_PERCENT_COMPLETE, 10); // context variable
|
||||
params.put(QName.createQName("", "Message"), "Hello World"); // context variable outside of task definition
|
||||
params.put(QName.createQName("", "Array"), new String[] { "one", "two" }); // context variable outside of task definition
|
||||
params.put(QName.createQName("", "NodeRef"), new NodeRef("workspace://1/1001")); // context variable outside of task definition
|
||||
params.put(ContentModel.PROP_OWNER, AuthenticationUtil.getAdminUserName()); // task assignment
|
||||
|
||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.getId(), params);
|
||||
assertNotNull(path);
|
||||
assertTrue(path.getId().endsWith("-@"));
|
||||
assertNotNull(path.getNode());
|
||||
assertNotNull(path.getInstance());
|
||||
assertEquals(workflowDef.getId(), path.getInstance().getDefinition().getId());
|
||||
List<WorkflowTask> tasks1 = workflowComponent.getTasksForWorkflowPath(path.getId());
|
||||
assertNotNull(tasks1);
|
||||
assertEquals(1, tasks1.size());
|
||||
|
||||
WorkflowTask task = tasks1.get(0);
|
||||
assertTrue(task.getProperties().containsKey(WorkflowModel.PROP_TASK_ID));
|
||||
assertTrue(task.getProperties().containsKey(WorkflowModel.PROP_DUE_DATE));
|
||||
assertTrue(task.getProperties().containsKey(WorkflowModel.PROP_PRIORITY));
|
||||
assertTrue(task.getProperties().containsKey(WorkflowModel.PROP_PERCENT_COMPLETE));
|
||||
assertTrue(task.getProperties().containsKey(ContentModel.PROP_OWNER));
|
||||
|
||||
// update with null parameters
|
||||
try
|
||||
{
|
||||
WorkflowTask taskU1 = taskComponent.updateTask(task.getId(), null, null, null);
|
||||
assertNotNull(taskU1);
|
||||
}
|
||||
catch(Throwable e)
|
||||
{
|
||||
fail("Task update failed with null parameters");
|
||||
}
|
||||
|
||||
// update property value
|
||||
Map<QName, Serializable> updateProperties2 = new HashMap<QName, Serializable>();
|
||||
updateProperties2.put(WorkflowModel.PROP_PERCENT_COMPLETE, 100);
|
||||
WorkflowTask taskU2 = taskComponent.updateTask(task.getId(), updateProperties2, null, null);
|
||||
assertEquals(100, taskU2.getProperties().get(WorkflowModel.PROP_PERCENT_COMPLETE));
|
||||
|
||||
// add to assocation
|
||||
QName assocName = QName.createQName("", "TestAssoc");
|
||||
List<NodeRef> toAdd = new ArrayList<NodeRef>();
|
||||
toAdd.add(new NodeRef("workspace://1/1001"));
|
||||
toAdd.add(new NodeRef("workspace://1/1002"));
|
||||
toAdd.add(new NodeRef("workspace://1/1003"));
|
||||
Map<QName, List<NodeRef>> addAssocs = new HashMap<QName, List<NodeRef>>();
|
||||
addAssocs.put(assocName, toAdd);
|
||||
WorkflowTask taskU3 = taskComponent.updateTask(task.getId(), null, addAssocs, null);
|
||||
assertNotNull(taskU3.getProperties().get(assocName));
|
||||
assertEquals(3, ((List<?>)taskU3.getProperties().get(assocName)).size());
|
||||
|
||||
// add to assocation again
|
||||
List<NodeRef> toAddAgain = new ArrayList<NodeRef>();
|
||||
toAddAgain.add(new NodeRef("workspace://1/1004"));
|
||||
toAddAgain.add(new NodeRef("workspace://1/1005"));
|
||||
Map<QName, List<NodeRef>> addAssocsAgain = new HashMap<QName, List<NodeRef>>();
|
||||
addAssocsAgain.put(assocName, toAddAgain);
|
||||
WorkflowTask taskU4 = taskComponent.updateTask(task.getId(), null, addAssocsAgain, null);
|
||||
assertNotNull(taskU4.getProperties().get(assocName));
|
||||
assertEquals(5, ((List<?>)taskU4.getProperties().get(assocName)).size());
|
||||
|
||||
// remove assocation
|
||||
List<NodeRef> toRemove = new ArrayList<NodeRef>();
|
||||
toRemove.add(new NodeRef("workspace://1/1002"));
|
||||
toRemove.add(new NodeRef("workspace://1/1003"));
|
||||
Map<QName, List<NodeRef>> removeAssocs = new HashMap<QName, List<NodeRef>>();
|
||||
removeAssocs.put(assocName, toRemove);
|
||||
WorkflowTask taskU5 = taskComponent.updateTask(task.getId(), null, null, removeAssocs);
|
||||
assertNotNull(taskU5.getProperties().get(assocName));
|
||||
assertEquals(3, ((List<?>)taskU5.getProperties().get(assocName)).size());
|
||||
}
|
||||
|
||||
|
||||
public void testGetWorkflowInstances()
|
||||
{
|
||||
WorkflowDefinition workflowDef = getTestDefinition();
|
||||
workflowComponent.startWorkflow(workflowDef.getId(), null);
|
||||
workflowComponent.startWorkflow(workflowDef.getId(), null);
|
||||
List<WorkflowInstance> instances = workflowComponent.getActiveWorkflows(workflowDef.getId());
|
||||
assertNotNull(instances);
|
||||
assertEquals(2, instances.size());
|
||||
for (WorkflowInstance instance : instances)
|
||||
{
|
||||
assertEquals(workflowDef.getId(), instance.getDefinition().getId());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void testGetPositions()
|
||||
{
|
||||
WorkflowDefinition workflowDef = getTestDefinition();
|
||||
workflowComponent.startWorkflow(workflowDef.getId(), null);
|
||||
List<WorkflowInstance> instances = workflowComponent.getActiveWorkflows(workflowDef.getId());
|
||||
assertNotNull(instances);
|
||||
assertEquals(1, instances.size());
|
||||
List<WorkflowPath> paths = workflowComponent.getWorkflowPaths(instances.get(0).getId());
|
||||
assertNotNull(paths);
|
||||
assertEquals(1, paths.size());
|
||||
assertEquals(instances.get(0).getId(), paths.get(0).getInstance().getId());
|
||||
assertTrue(paths.get(0).getId().endsWith("-@"));
|
||||
}
|
||||
|
||||
|
||||
public void testCancelWorkflowInstance() throws Exception
|
||||
{
|
||||
WorkflowDefinition workflowDef = getTestDefinition();
|
||||
workflowComponent.startWorkflow(workflowDef.getId(), null);
|
||||
List<WorkflowInstance> instances1 = workflowComponent.getActiveWorkflows(workflowDef.getId());
|
||||
assertNotNull(instances1);
|
||||
assertEquals(1, instances1.size());
|
||||
List<WorkflowTask> tasks = taskComponent.getAssignedTasks(AuthenticationUtil.getAdminUserName(), WorkflowTaskState.IN_PROGRESS, false);
|
||||
assertNotNull(tasks);
|
||||
assertTrue(tasks.size() > 0);
|
||||
WorkflowInstance cancelledInstance = workflowComponent.cancelWorkflow(instances1.get(0).getId());
|
||||
assertNotNull(cancelledInstance);
|
||||
assertFalse(cancelledInstance.isActive());
|
||||
List<WorkflowInstance> instances2 = workflowComponent.getActiveWorkflows(workflowDef.getId());
|
||||
assertNotNull(instances2);
|
||||
assertEquals(0, instances2.size());
|
||||
List<WorkflowTask> tasks1 = taskComponent.getAssignedTasks(AuthenticationUtil.getAdminUserName(), WorkflowTaskState.IN_PROGRESS, false);
|
||||
assertNotNull(tasks1);
|
||||
tasks1 = filterTasksByWorkflowInstance(tasks1, cancelledInstance.getId());
|
||||
assertEquals(0, tasks1.size());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* See Alf-2764 in Jira.
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testCancelForEachFork() throws Exception
|
||||
{
|
||||
// Deploy Parallel Loop Review process definition.
|
||||
ClassPathResource processDef = new ClassPathResource("test/alfresco/parallel_loop_review_processdefinition.xml");
|
||||
WorkflowDeployment deployment = workflowComponent.deployDefinition(processDef.getInputStream(),
|
||||
MimetypeMap.MIMETYPE_XML);
|
||||
WorkflowDefinition parallelDef = deployment.getDefinition();
|
||||
assertNotNull(parallelDef);
|
||||
|
||||
// Set Current User to USER1.
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(USER1);
|
||||
|
||||
// Set up parameters
|
||||
QName approvePercentName = QName.createQName(NamespaceService.WORKFLOW_MODEL_1_0_URI, "requiredApprovePercent");
|
||||
NodeRef pckgNode = packageComponent.createPackage(null);
|
||||
List<NodeRef> assignees = Arrays.asList(person1, person2, person3);
|
||||
Map<QName, Serializable> parameters = new HashMap<QName, Serializable>();
|
||||
parameters.put(WorkflowModel.ASSOC_ASSIGNEES, (Serializable) assignees);
|
||||
parameters.put(WorkflowModel.ASSOC_PACKAGE, pckgNode);
|
||||
parameters.put(approvePercentName, 60f );
|
||||
|
||||
// Start workflow
|
||||
WorkflowPath path = workflowComponent.startWorkflow(parallelDef.getId(), parameters);
|
||||
WorkflowTask startTask = workflowComponent.getTasksForWorkflowPath(path.getId()).get(0);
|
||||
taskComponent.endTask(startTask.getId(), null);
|
||||
checkInstanceExists(path.getInstance().getId(), parallelDef.getId(), true);
|
||||
|
||||
// Set all users to reject document.
|
||||
ParallelReject(USER1);
|
||||
ParallelReject(USER2);
|
||||
ParallelReject(USER3);
|
||||
|
||||
// Send review back round the loop.
|
||||
List<WorkflowTask> tasks = workflowComponent.getTasksForWorkflowPath(path.getId());
|
||||
assertEquals(1, tasks.size());
|
||||
taskComponent.endTask(tasks.get(0).getId(), "again");
|
||||
|
||||
// Try to cancel workflow
|
||||
WorkflowInstance cancelledWf = workflowComponent.cancelWorkflow(path.getInstance().getId());
|
||||
checkInstanceExists(cancelledWf.getId(), parallelDef.getId(), false);
|
||||
}
|
||||
|
||||
private void checkInstanceExists(String instanceId, String defId, boolean expected)
|
||||
{
|
||||
boolean match=false;
|
||||
List<WorkflowInstance> activeWfs = workflowComponent.getActiveWorkflows(defId);
|
||||
for (WorkflowInstance instance : activeWfs)
|
||||
{
|
||||
if(instance.getId().equals(instanceId))
|
||||
{
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertEquals( expected, match);
|
||||
}
|
||||
|
||||
private void ParallelReject(String user)
|
||||
{
|
||||
List<WorkflowTask> tasks = taskComponent.getAssignedTasks(user, WorkflowTaskState.IN_PROGRESS, false);
|
||||
assertEquals(1, tasks.size());
|
||||
WorkflowTask task = tasks.get(0);
|
||||
taskComponent.endTask(task.getId(), "reject");
|
||||
}
|
||||
|
||||
public void testSignal()
|
||||
{
|
||||
Map<QName, Serializable> parameters = new HashMap<QName, Serializable>();
|
||||
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "testNode"), rootNodeRef);
|
||||
WorkflowDefinition workflowDef = getTestDefinition();
|
||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.getId(), parameters);
|
||||
assertNotNull(path);
|
||||
WorkflowPath updatedPath = workflowComponent.signal(path.getId(), path.getNode().getTransitions()[1].getId());
|
||||
assertNotNull(updatedPath);
|
||||
}
|
||||
|
||||
|
||||
public void testGetAssignedTasks()
|
||||
{
|
||||
WorkflowDefinition workflowDef = getTestDefinition();
|
||||
Map<QName, Serializable> parameters = new HashMap<QName, Serializable>();
|
||||
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "reviewer"), AuthenticationUtil.getAdminUserName());
|
||||
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "testNode"), rootNodeRef);
|
||||
parameters.put(QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "package"), packageComponent.createPackage(null));
|
||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.getId(), parameters);
|
||||
assertNotNull(path);
|
||||
List<WorkflowTask> tasks = workflowComponent.getTasksForWorkflowPath(path.getId());
|
||||
assertNotNull(tasks);
|
||||
assertEquals(1, tasks.size());
|
||||
WorkflowTask updatedTask = taskComponent.endTask(tasks.get(0).getId(), path.getNode().getTransitions()[0].getId());
|
||||
assertNotNull(updatedTask);
|
||||
List<WorkflowTask> completedTasks = taskComponent.getAssignedTasks(AuthenticationUtil.getAdminUserName(), WorkflowTaskState.COMPLETED, false);
|
||||
assertNotNull(completedTasks);
|
||||
completedTasks = filterTasksByWorkflowInstance(completedTasks, path.getInstance().getId());
|
||||
assertEquals(1, completedTasks.size());
|
||||
List<WorkflowTask> assignedTasks = taskComponent.getAssignedTasks(AuthenticationUtil.getAdminUserName(), WorkflowTaskState.IN_PROGRESS, false);
|
||||
assertNotNull(assignedTasks);
|
||||
assignedTasks = filterTasksByWorkflowInstance(assignedTasks, path.getInstance().getId());
|
||||
assertEquals(1, assignedTasks.size());
|
||||
assertEquals("review", assignedTasks.get(0).getName());
|
||||
}
|
||||
|
||||
|
||||
public void xtestMultiAssign()
|
||||
{
|
||||
WorkflowDefinition workflowDef = getTestDefinition();
|
||||
List<String> bpm_assignees = new ArrayList<String>();
|
||||
bpm_assignees.add(AuthenticationUtil.getAdminUserName());
|
||||
bpm_assignees.add("bob");
|
||||
bpm_assignees.add("fred");
|
||||
Map<QName, Serializable> parameters = new HashMap<QName, Serializable>();
|
||||
parameters.put(QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "assignees"), (Serializable)bpm_assignees);
|
||||
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "testNode"), rootNodeRef);
|
||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.getId(), parameters);
|
||||
assertNotNull(path);
|
||||
List<WorkflowTask> tasks = workflowComponent.getTasksForWorkflowPath(path.getId());
|
||||
assertNotNull(tasks);
|
||||
assertEquals(1, tasks.size());
|
||||
WorkflowTask updatedTask = taskComponent.endTask(tasks.get(0).getId(), "multi");
|
||||
assertNotNull(updatedTask);
|
||||
}
|
||||
|
||||
|
||||
public void testEndTask()
|
||||
{
|
||||
WorkflowDefinition workflowDef = getTestDefinition();
|
||||
Map<QName, Serializable> parameters = new HashMap<QName, Serializable>();
|
||||
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "reviewer"), AuthenticationUtil.getAdminUserName());
|
||||
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "testNode"), rootNodeRef);
|
||||
parameters.put(QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "package"), packageComponent.createPackage(null));
|
||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.getId(), parameters);
|
||||
assertNotNull(path);
|
||||
List<WorkflowTask> tasks1 = workflowComponent.getTasksForWorkflowPath(path.getId());
|
||||
assertNotNull(tasks1);
|
||||
assertEquals(1, tasks1.size());
|
||||
assertEquals(WorkflowTaskState.IN_PROGRESS, tasks1.get(0).getState());
|
||||
WorkflowTask updatedTask = taskComponent.endTask(tasks1.get(0).getId(), null);
|
||||
assertNotNull(updatedTask);
|
||||
assertEquals(WorkflowTaskState.COMPLETED, updatedTask.getState());
|
||||
List<WorkflowTask> completedTasks = taskComponent.getAssignedTasks(AuthenticationUtil.getAdminUserName(), WorkflowTaskState.COMPLETED, false);
|
||||
assertNotNull(completedTasks);
|
||||
completedTasks = filterTasksByWorkflowInstance(completedTasks, path.getInstance().getId());
|
||||
assertEquals(1, completedTasks.size());
|
||||
assertEquals(WorkflowTaskState.COMPLETED, completedTasks.get(0).getState());
|
||||
}
|
||||
|
||||
|
||||
public void testGetTask()
|
||||
{
|
||||
WorkflowDefinition workflowDef = getTestDefinition();
|
||||
Map<QName, Serializable> parameters = new HashMap<QName, Serializable>();
|
||||
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "reviewer"), AuthenticationUtil.getAdminUserName());
|
||||
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "testNode"), rootNodeRef);
|
||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.getId(), parameters);
|
||||
assertNotNull(path);
|
||||
assertNotNull(path);
|
||||
List<WorkflowTask> tasks1 = workflowComponent.getTasksForWorkflowPath(path.getId());
|
||||
assertNotNull(tasks1);
|
||||
assertEquals(1, tasks1.size());
|
||||
WorkflowTask getTask = taskComponent.getTaskById(tasks1.get(0).getId());
|
||||
assertNotNull(getTask);
|
||||
assertEquals(getTask.getId(), tasks1.get(0).getId());
|
||||
}
|
||||
|
||||
|
||||
public void testNodeRef()
|
||||
{
|
||||
WorkflowDefinition workflowDef = getTestDefinition();
|
||||
Map<QName, Serializable> parameters = new HashMap<QName, Serializable>();
|
||||
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "reviewer"), AuthenticationUtil.getAdminUserName());
|
||||
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "testNode"), rootNodeRef);
|
||||
parameters.put(QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "package"), packageComponent.createPackage(null));
|
||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.getId(), parameters);
|
||||
assertNotNull(path);
|
||||
List<WorkflowTask> tasks1 = workflowComponent.getTasksForWorkflowPath(path.getId());
|
||||
assertNotNull(tasks1);
|
||||
assertEquals(1, tasks1.size());
|
||||
assertEquals(WorkflowTaskState.IN_PROGRESS, tasks1.get(0).getState());
|
||||
WorkflowTask updatedTask = taskComponent.endTask(tasks1.get(0).getId(), null);
|
||||
assertNotNull(updatedTask);
|
||||
}
|
||||
|
||||
|
||||
public void testScript() throws IOException
|
||||
{
|
||||
// deploy test script definition
|
||||
ClassPathResource processDef = new ClassPathResource("jbpmresources/test_script.xml");
|
||||
assertFalse(workflowComponent.isDefinitionDeployed(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML));
|
||||
WorkflowDeployment deployment = workflowComponent.deployDefinition(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML);
|
||||
assertNotNull(deployment);
|
||||
|
||||
WorkflowDefinition workflowDef = deployment.getDefinition();
|
||||
Map<QName, Serializable> parameters = new HashMap<QName, Serializable>();
|
||||
parameters.put(QName.createQName(NamespaceService.DEFAULT_URI, "testNode"), rootNodeRef);
|
||||
parameters.put(QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "package"), packageComponent.createPackage(null));
|
||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.getId(), parameters);
|
||||
assertNotNull(path);
|
||||
List<WorkflowTask> tasks1 = workflowComponent.getTasksForWorkflowPath(path.getId());
|
||||
assertNotNull(tasks1);
|
||||
assertEquals(1, tasks1.size());
|
||||
assertEquals(WorkflowTaskState.IN_PROGRESS, tasks1.get(0).getState());
|
||||
WorkflowTask updatedTask = taskComponent.endTask(tasks1.get(0).getId(), null);
|
||||
assertNotNull(updatedTask);
|
||||
}
|
||||
|
||||
public void testWorkflowDefinitionVisibility()
|
||||
{
|
||||
// retrieve workflow definitions
|
||||
List<WorkflowDefinition> defs = workflowComponent.getDefinitions();
|
||||
List<WorkflowDefinition> allDefs = workflowComponent.getAllDefinitions();
|
||||
|
||||
assertFalse(defs.isEmpty());
|
||||
assertFalse(allDefs.isEmpty());
|
||||
}
|
||||
|
||||
// public void testAssignTaskVariablesWithScript() throws Exception
|
||||
// {
|
||||
// WorkflowDefinition definition = workflowComponent.getDefinitionByName("jbpm$testwf:testTaskVarScriptAssign");
|
||||
// assertNotNull(definition);
|
||||
//
|
||||
// String testwfUrl = "http://www.alfresco.org/model/workflow/test/1.0";
|
||||
// QName simpleTextName = QName.createQName(testwfUrl, "simpleText");
|
||||
// QName listConstrainedName = QName.createQName(testwfUrl, "listConstrainedText");
|
||||
//
|
||||
// String simpleTextValue = "Foo";
|
||||
// String listConstrainedValue = "Second";
|
||||
//
|
||||
//
|
||||
// Map<QName, Serializable> params = new HashMap<QName, Serializable>();
|
||||
// params.put(simpleTextName, simpleTextValue);
|
||||
// params.put(listConstrainedName, listConstrainedValue);
|
||||
// params.put(WorkflowModel.ASSOC_PACKAGE, packageComponent.createPackage(null));
|
||||
//
|
||||
// WorkflowPath path = workflowComponent.startWorkflow(definition.getId(), params);
|
||||
// // End start task.
|
||||
// List<WorkflowTask> tasks = workflowComponent.getTasksForWorkflowPath(path.getId());
|
||||
//
|
||||
// // Get Start Task
|
||||
// assertEquals(1, tasks.size());
|
||||
// WorkflowTask startTask = tasks.get(0);
|
||||
// QName startTaskName = definition.getStartTaskDefinition().getMetadata().getName();
|
||||
// assertEquals("This is not the start task!", startTaskName, startTask.getDefinition().getMetadata().getName());
|
||||
//
|
||||
// taskComponent.endTask(startTask.getId(), null);
|
||||
//
|
||||
// tasks = workflowComponent.getTasksForWorkflowPath(path.getId());
|
||||
//
|
||||
// // Get Task
|
||||
// assertEquals(1, tasks.size());
|
||||
// WorkflowTask task = tasks.get(0);
|
||||
// QName taskName = QName.createQName(testwfUrl, "assignVarTask");
|
||||
// assertEquals("This is not the start task!", taskName, task.getDefinition().getMetadata().getName());
|
||||
//
|
||||
// Map<QName, Serializable> props = task.getProperties();
|
||||
// assertEquals("Simple Text property value doesn't match!", simpleTextValue, props.get(simpleTextName));
|
||||
// assertEquals("List Constrained property value doesn't match!", listConstrainedValue, props.get(listConstrainedName));
|
||||
// }
|
||||
|
||||
/**
|
||||
* Locate the Test Workflow Definition
|
||||
*
|
||||
* @return workflow definition
|
||||
*/
|
||||
private WorkflowDefinition getTestDefinition()
|
||||
{
|
||||
return testWorkflowDef;
|
||||
}
|
||||
|
||||
|
||||
private NodeRef createPerson(String userName)
|
||||
{
|
||||
// if user with given user name doesn't already exist then create user
|
||||
if (this.authenticationService.authenticationExists(userName) == false)
|
||||
{
|
||||
// create user
|
||||
this.authenticationService.createAuthentication(userName, "password".toCharArray());
|
||||
}
|
||||
|
||||
// if person node with given user name doesn't already exist then create
|
||||
// person
|
||||
if (this.personService.personExists(userName) == false)
|
||||
{
|
||||
// create person properties
|
||||
PropertyMap personProps = new PropertyMap();
|
||||
personProps.put(ContentModel.PROP_USERNAME, userName);
|
||||
|
||||
// create person node for user
|
||||
return personService.createPerson(personProps);
|
||||
}
|
||||
return personService.getPerson(userName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter task list by workflow instance
|
||||
*
|
||||
* @param tasks
|
||||
* @param processInstanceId
|
||||
* @return
|
||||
*/
|
||||
private List<WorkflowTask> filterTasksByWorkflowInstance(List<WorkflowTask> tasks, String workflowInstanceId)
|
||||
{
|
||||
List<WorkflowTask> filteredTasks = new ArrayList<WorkflowTask>();
|
||||
for (WorkflowTask task : tasks)
|
||||
{
|
||||
if (task.getPath().getInstance().getId().equals(workflowInstanceId))
|
||||
{
|
||||
filteredTasks.add(task);
|
||||
}
|
||||
}
|
||||
return filteredTasks;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,267 @@
|
||||
package org.alfresco.repo.workflow.jbpm;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.model.Repository;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.repo.workflow.WorkflowModel;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.model.FileFolderService;
|
||||
import org.alfresco.service.cmr.model.FileInfo;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
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.cmr.workflow.WorkflowTaskState;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.BaseSpringTest;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* This test shows a performance benefit from a usage of direct queries
|
||||
* instead of creating required classes like WorkflowTask in a loop with collecting
|
||||
* required properties from different services.
|
||||
*
|
||||
* @author arsenyko
|
||||
*
|
||||
*/
|
||||
public class JBPMJunit4LoadTests extends BaseSpringTest
|
||||
{
|
||||
|
||||
private static String WORKFLOW_NAME = "jbpm$wf:adhoc";
|
||||
private static String WORKFLOW_NODE_NAME = "workflow-test-19243cbb-c58a-485e-bcd9-2e2be030dfb9.txt";
|
||||
private static int WORKFLOW_COUNT = 2000;
|
||||
|
||||
private static List<String> workflowIds = null;
|
||||
private static NodeRef rootNode = null;
|
||||
|
||||
private ServiceRegistry serviceRegistry;
|
||||
private RetryingTransactionHelper retryingTransactionHelper;
|
||||
private static NodeService nodeService;
|
||||
private static WorkflowService workflowService;
|
||||
private FileFolderService fileFolderService;
|
||||
|
||||
private Repository repositoryHelper;
|
||||
|
||||
private JBPMEngine jbpmEngine;
|
||||
|
||||
private NodeRef companyHomeNodeRef;
|
||||
|
||||
public void onSetUp() throws Exception
|
||||
{
|
||||
serviceRegistry = (ServiceRegistry) getApplicationContext().getBean(ServiceRegistry.SERVICE_REGISTRY);
|
||||
repositoryHelper = (Repository) getApplicationContext().getBean("repositoryHelper");
|
||||
jbpmEngine = (JBPMEngine) getApplicationContext().getBean("jbpm_engine");
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
|
||||
|
||||
retryingTransactionHelper = serviceRegistry.getTransactionService().getRetryingTransactionHelper();
|
||||
fileFolderService = serviceRegistry.getFileFolderService();
|
||||
workflowService = serviceRegistry.getWorkflowService();
|
||||
nodeService = serviceRegistry.getNodeService();
|
||||
|
||||
companyHomeNodeRef = repositoryHelper.getCompanyHome();
|
||||
System.out.println(" -------------- ");
|
||||
createWorkflowStuff();
|
||||
}
|
||||
|
||||
public void createWorkflowStuff() throws Exception
|
||||
{
|
||||
System.out.println(" [createWorkflowStuff] Started at " + new Date().toString());
|
||||
|
||||
if (rootNode == null)
|
||||
{
|
||||
workflowIds =new ArrayList<String>();
|
||||
RetryingTransactionCallback<Void> callback = new RetryingTransactionCallback<Void>(){
|
||||
|
||||
@Override
|
||||
public Void execute() throws Throwable
|
||||
{
|
||||
FileInfo rootInfo = fileFolderService.create(companyHomeNodeRef,
|
||||
WORKFLOW_NODE_NAME,
|
||||
ContentModel.TYPE_FOLDER);
|
||||
rootNode = rootInfo.getNodeRef();
|
||||
FileInfo contentInfo = fileFolderService.create(rootNode,
|
||||
WORKFLOW_NODE_NAME,
|
||||
ContentModel.TYPE_CONTENT);
|
||||
NodeRef content = contentInfo.getNodeRef();
|
||||
ContentService contentService = serviceRegistry.getContentService();
|
||||
ContentWriter writer = contentService.getWriter(content, ContentModel.PROP_CONTENT, true);
|
||||
writer.setMimetype("text/plain");
|
||||
writer.setEncoding("UTF-8");
|
||||
writer.putContent("many workflows many workflows many workflows many workflows many workflows many workflows many workflows many workflows");
|
||||
System.out.println(" [createWorkflowStuff] Workflow root node '" + WORKFLOW_NODE_NAME + "' has been created");
|
||||
|
||||
WorkflowDefinition wfDef = jbpmEngine.getDefinitionByName(WORKFLOW_NAME);
|
||||
long startTime = new Date().getTime();
|
||||
for (Integer i = 0; i < WORKFLOW_COUNT; i++)
|
||||
{
|
||||
// We are creating workflows in usual way, but with new persistent objects.
|
||||
// There is a some performance issue with sesssion.flash() in each iteration,
|
||||
// but this was made to avoid a lot of changes in a logic related to org.alfresco.service.cmr.workflow.*
|
||||
// classes.
|
||||
Map<QName, Serializable> properties = prepareWorkflowProperties(rootNode, content, i.toString());
|
||||
WorkflowPath path = workflowService.startWorkflow(wfDef.getId(), properties);
|
||||
workflowIds.add(path.getInstance().getId());
|
||||
// jbpmEngine.startWorkflow_ALF1787(wfDef.id, prepareWorkflowProperties(fileInfo.getNodeRef(), i.toString()));
|
||||
}
|
||||
long endTime = new Date().getTime();
|
||||
System.out.println(" [createWorkflowStuff] Execution time (ms): " + (endTime - startTime));
|
||||
return null;
|
||||
}
|
||||
|
||||
};
|
||||
retryingTransactionHelper.setMaxRetries(1);
|
||||
retryingTransactionHelper.doInTransaction(callback);
|
||||
System.out.println(" [createWorkflowStuff] Finished at " + new Date().toString());
|
||||
}
|
||||
else
|
||||
{
|
||||
System.out.println(" [createWorkflowStuff] Workflow node '" + WORKFLOW_NODE_NAME + "' already exists");
|
||||
}
|
||||
}
|
||||
|
||||
//@Test
|
||||
// public void testQuery1() throws Exception
|
||||
// {
|
||||
// RetryingTransactionCallback<Void> callback = new RetryingTransactionCallback<Void>(){
|
||||
//
|
||||
// @Override
|
||||
// public Void execute() throws Throwable
|
||||
// {
|
||||
// JbpmTemplate jbpmTemplate = (JbpmTemplate) applicationContext.getBean("jbpm_template");
|
||||
// List<Object[]> result = (List<Object[]>) jbpmTemplate.execute(new JbpmCallback()
|
||||
// {
|
||||
// public List<Object[]> doInJbpm(JbpmContext context)
|
||||
// {
|
||||
// Session session = context.getSession();
|
||||
// Query query = session.getNamedQuery("org.alfresco.repo.workflow.findTaskInstancesByActorId");
|
||||
// return query.setString("actorId", "admin").list();
|
||||
// }
|
||||
// });
|
||||
// for(Object[] ti : result)
|
||||
// {
|
||||
// System.out.println(Arrays.toString(ti));
|
||||
// }
|
||||
// System.out.println(result.size());
|
||||
// return null;
|
||||
// }
|
||||
// };
|
||||
// retryingTransactionHelper.setMaxRetries(1);
|
||||
// retryingTransactionHelper.doInTransaction(callback);
|
||||
// }
|
||||
|
||||
@Test
|
||||
public void testGetAssignedTasks_NEW() throws Exception
|
||||
{
|
||||
final int RUN_COUNT = 7;
|
||||
RetryingTransactionCallback<Void> callback = new RetryingTransactionCallback<Void>(){
|
||||
|
||||
@Override
|
||||
public Void execute() throws Throwable
|
||||
{
|
||||
Date beginTime = new Date();
|
||||
System.out.println(" [testGetAssignedTasks_NEW] Started at " + beginTime.toString());
|
||||
List<WorkflowTask> tasks = workflowService.getAssignedTasks("admin", WorkflowTaskState.IN_PROGRESS);
|
||||
Date endTime = new Date();
|
||||
System.out.println(" [testGetAssignedTasks_NEW] Retrieved tasks: " + tasks.size() + " in " + (endTime.getTime() - beginTime.getTime()) + " ms");
|
||||
System.out.println(" [testGetAssignedTasks_NEW] Finished at " + endTime.toString());
|
||||
return null;
|
||||
}
|
||||
};
|
||||
retryingTransactionHelper.setMaxRetries(1);
|
||||
for(int i=0; i<RUN_COUNT; i++)
|
||||
{
|
||||
retryingTransactionHelper.doInTransaction(callback);
|
||||
}
|
||||
}
|
||||
/*
|
||||
@Test
|
||||
public void testGetAssignedTasks_OLD() throws Exception
|
||||
{
|
||||
RetryingTransactionCallback<Void> callback = new RetryingTransactionCallback<Void>(){
|
||||
|
||||
@Override
|
||||
public Void execute() throws Throwable
|
||||
{
|
||||
Date beginTime = new Date();
|
||||
System.out.println(" [testGetAssignedTasks_OLD] Started at " + beginTime.toString());
|
||||
List<WorkflowTask> tasks = jbpmEngine.getAssignedTasks_OLD("admin", WorkflowTaskState.IN_PROGRESS);
|
||||
Date endTime = new Date();
|
||||
System.out.println(" [testGetAssignedTasks_OLD] Retrieved tasks: " + tasks.size() + " in " + (endTime.getTime() - beginTime.getTime()) + " ms");
|
||||
System.out.println(" [testGetAssignedTasks_OLD] Finished at " + new Date().toString());
|
||||
return null;
|
||||
}
|
||||
};
|
||||
retryingTransactionHelper.setMaxRetries(1);
|
||||
retryingTransactionHelper.doInTransaction(callback);
|
||||
}
|
||||
*/
|
||||
|
||||
public void onTearDown() throws Exception
|
||||
{
|
||||
System.out.println(" -------------- ");
|
||||
}
|
||||
|
||||
private Map<QName, Serializable> prepareWorkflowProperties(NodeRef root, NodeRef content, String id)
|
||||
{
|
||||
NodeRef packageRef = makePackage(root, content, id);
|
||||
Map<QName, Serializable> parameters = new HashMap<QName, Serializable>();
|
||||
parameters.put(WorkflowModel.ASSOC_PACKAGE, packageRef);
|
||||
parameters.put(WorkflowModel.ASSOC_ASSIGNEE, "admin");
|
||||
parameters.put(WorkflowModel.PROP_WORKFLOW_DESCRIPTION, "Test workflow '" + id + "'");
|
||||
parameters.put(WorkflowModel.PROP_WORKFLOW_DEFINITION_NAME, "test_workflow_" + id);
|
||||
return parameters;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param root
|
||||
* @param content
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
private NodeRef makePackage(NodeRef root, NodeRef content, String id)
|
||||
{
|
||||
NodeRef container = fileFolderService.create(root, "package"+id, ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
NodeRef packageRef = workflowService.createPackage(container);
|
||||
nodeService.addChild(packageRef, content, ContentModel.ASSOC_CONTAINS,
|
||||
QName.createQName(NamespaceService.DEFAULT_URI, id));
|
||||
return packageRef;
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void cleanup()
|
||||
{
|
||||
// Clean up workflows
|
||||
if(workflowIds !=null)
|
||||
{
|
||||
for (String wfId : workflowIds)
|
||||
{
|
||||
try
|
||||
{
|
||||
workflowService.cancelWorkflow(wfId);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
//NOOP
|
||||
}
|
||||
}
|
||||
}
|
||||
nodeService.deleteNode(rootNode);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.workflow.jbpm;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.service.descriptor.DescriptorService;
|
||||
import org.alfresco.util.BaseSpringTest;
|
||||
import org.jbpm.JbpmContext;
|
||||
import org.jbpm.db.GraphSession;
|
||||
import org.jbpm.graph.def.ProcessDefinition;
|
||||
import org.jbpm.graph.exe.ProcessInstance;
|
||||
import org.jbpm.graph.exe.Token;
|
||||
import org.springmodules.workflow.jbpm31.JbpmCallback;
|
||||
import org.springmodules.workflow.jbpm31.JbpmTemplate;
|
||||
|
||||
|
||||
/**
|
||||
* Test Usage of jBPM within Alfresco Spring Context
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class JBPMSpringTest extends BaseSpringTest
|
||||
{
|
||||
JbpmTemplate jbpmTemplate;
|
||||
DescriptorService descriptorService;
|
||||
|
||||
|
||||
//@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected void onSetUpInTransaction() throws Exception
|
||||
{
|
||||
jbpmTemplate = (JbpmTemplate)applicationContext.getBean("jbpm_template");
|
||||
descriptorService = (DescriptorService)applicationContext.getBean("DescriptorService");
|
||||
}
|
||||
|
||||
public void testHelloWorld()
|
||||
throws Exception
|
||||
{
|
||||
deployProcessDefinition();
|
||||
processInstanceIsCreatedWhenUserSubmitsWebappForm();
|
||||
theProcessInstanceContinuesWhenAnAsyncMessageIsReceived();
|
||||
undeployProcessDefinition();
|
||||
}
|
||||
|
||||
private void deployProcessDefinition()
|
||||
{
|
||||
// This test shows a process definition and one execution
|
||||
// of the process definition. The process definition has
|
||||
// 3 nodes: an unnamed start-state, a state 's' and an
|
||||
// end-state named 'end'.
|
||||
final ProcessDefinition processDefinition = ProcessDefinition.parseXmlString(
|
||||
"<process-definition name='hello world'>" +
|
||||
" <start-state name='start'>" +
|
||||
" <transition to='s' />" +
|
||||
" </start-state>" +
|
||||
" <node name='s'>" +
|
||||
" <action class='org.alfresco.repo.workflow.jbpm.JBPMTestSpringActionHandler' config-type='bean'>" +
|
||||
" <value>a test value</value>" +
|
||||
" </action>" +
|
||||
" <transition to='end' />" +
|
||||
" </node>" +
|
||||
" <end-state name='end' />" +
|
||||
"</process-definition>"
|
||||
);
|
||||
|
||||
|
||||
jbpmTemplate.execute(new JbpmCallback()
|
||||
{
|
||||
public Object doInJbpm(JbpmContext context)
|
||||
{
|
||||
context.deployProcessDefinition(processDefinition);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void undeployProcessDefinition()
|
||||
{
|
||||
jbpmTemplate.execute(new JbpmCallback()
|
||||
{
|
||||
public Object doInJbpm(JbpmContext context)
|
||||
{
|
||||
GraphSession graphSession = context.getGraphSession();
|
||||
ProcessDefinition processDefinition = graphSession.findLatestProcessDefinition("hello world");
|
||||
graphSession.deleteProcessDefinition(processDefinition.getId());
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void processInstanceIsCreatedWhenUserSubmitsWebappForm()
|
||||
{
|
||||
jbpmTemplate.execute(new JbpmCallback()
|
||||
{
|
||||
public Object doInJbpm(JbpmContext context)
|
||||
{
|
||||
GraphSession graphSession = context.getGraphSession();
|
||||
ProcessDefinition processDefinition = graphSession.findLatestProcessDefinition("hello world");
|
||||
|
||||
// With the processDefinition that we retrieved from the database, we
|
||||
// can create an execution of the process definition just like in the
|
||||
// hello world example (which was without persistence).
|
||||
ProcessInstance processInstance = new ProcessInstance(processDefinition);
|
||||
|
||||
Token token = processInstance.getRootToken();
|
||||
assertEquals("start", token.getNode().getName());
|
||||
// Let's start the process execution
|
||||
token.signal();
|
||||
// Now the process is in the state 's'.
|
||||
assertEquals("s", token.getNode().getName());
|
||||
// Spring based action has been called, check the result by looking at the
|
||||
// process variable set by the action
|
||||
String result = "Repo: " + descriptorService.getServerDescriptor().getVersion() + ", Value: a test value, Node: s, Token: /";
|
||||
assertEquals(result, processInstance.getContextInstance().getVariable("jbpm.test.action.result"));
|
||||
|
||||
context.save(processInstance);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void theProcessInstanceContinuesWhenAnAsyncMessageIsReceived()
|
||||
{
|
||||
jbpmTemplate.execute(new JbpmCallback()
|
||||
{
|
||||
public Object doInJbpm(JbpmContext context)
|
||||
{
|
||||
GraphSession graphSession = context.getGraphSession();
|
||||
|
||||
// First, we need to get the process instance back out of the database.
|
||||
// There are several options to know what process instance we are dealing
|
||||
// with here. The easiest in this simple test case is just to look for
|
||||
// the full list of process instances. That should give us only one
|
||||
// result. So let's look up the process definition.
|
||||
ProcessDefinition processDefinition = graphSession.findLatestProcessDefinition("hello world");
|
||||
|
||||
// Now, we search for all process instances of this process definition.
|
||||
List<?> processInstances = graphSession.findProcessInstances(processDefinition.getId());
|
||||
|
||||
// Because we know that in the context of this unit test, there is
|
||||
// only one execution. In real life, the processInstanceId can be
|
||||
// extracted from the content of the message that arrived or from
|
||||
// the user making a choice.
|
||||
ProcessInstance processInstance = (ProcessInstance) processInstances.get(0);
|
||||
|
||||
// Now we can continue the execution. Note that the processInstance
|
||||
// delegates signals to the main path of execution (=the root token).
|
||||
processInstance.signal();
|
||||
|
||||
// After this signal, we know the process execution should have
|
||||
// arrived in the end-state.
|
||||
assertTrue(processInstance.hasEnded());
|
||||
|
||||
// Now we can update the state of the execution in the database
|
||||
context.save(processInstance);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.workflow.jbpm;
|
||||
|
||||
import org.alfresco.repo.workflow.AbstractMultitenantWorkflowTest;
|
||||
|
||||
/**
|
||||
* @author Nick Smith
|
||||
* @since 4.0
|
||||
*
|
||||
*/
|
||||
public class JbpmMultitenantWorkflowTest extends AbstractMultitenantWorkflowTest
|
||||
{
|
||||
@Override
|
||||
protected String getEngine()
|
||||
{
|
||||
return JBPMEngine.ENGINE_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTestDefinitionPath()
|
||||
{
|
||||
return "jbpmresources/test_simple_processdefinition.xml";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTestDefinitionKey()
|
||||
{
|
||||
return "jbpm$test";
|
||||
}
|
||||
|
||||
protected String getAdhocDefinitionPath()
|
||||
{
|
||||
return "alfresco/workflow/adhoc_processdefinition.xml";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getAdhocDefinitionKey()
|
||||
{
|
||||
return "jbpm$wf:adhoc";
|
||||
}
|
||||
|
||||
public void testSetup() throws Exception
|
||||
{
|
||||
// dummy test
|
||||
}
|
||||
}
|
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.workflow.jbpm;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.workflow.WorkflowAdminServiceImpl;
|
||||
import org.alfresco.repo.workflow.WorkflowModel;
|
||||
import org.alfresco.repo.workflow.WorkflowTestHelper;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowDeployment;
|
||||
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.QName;
|
||||
import org.alfresco.util.ApplicationContextHelper;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* @author Nick Smith
|
||||
* @since 4.0
|
||||
*
|
||||
*/
|
||||
public class JbpmTimerTest extends TestCase
|
||||
{
|
||||
private static final String simpleDefLocation = "jbpmresources/test_simpleTimer.xml";
|
||||
private static final String exceptionDefLocation = "jbpmresources/test_timerException.xml";
|
||||
|
||||
private WorkflowService workflowService;
|
||||
private WorkflowTestHelper testHelper;
|
||||
private String defId;
|
||||
|
||||
public void testTimerException() throws Exception
|
||||
{
|
||||
defId = deployDefinition(exceptionDefLocation);
|
||||
|
||||
NodeRef pckg = workflowService.createPackage(null);
|
||||
Map<QName, Serializable> params = new HashMap<QName, Serializable>();
|
||||
params.put(WorkflowModel.ASSOC_PACKAGE, pckg);
|
||||
params.put(WorkflowModel.ASSOC_ASSIGNEE, AuthenticationUtil.getAdminUserName());
|
||||
|
||||
WorkflowPath path = workflowService.startWorkflow(defId, params);
|
||||
String instanceId = path.getInstance().getId();
|
||||
WorkflowTask start = workflowService.getStartTask(instanceId);
|
||||
workflowService.endTask(start.getId(), null);
|
||||
Thread.sleep(30000);
|
||||
System.out.println("Done!");
|
||||
}
|
||||
|
||||
public void testTimerIsReassignable() throws Exception
|
||||
{
|
||||
defId = deployDefinition(simpleDefLocation);
|
||||
|
||||
NodeRef pckg = workflowService.createPackage(null);
|
||||
Map<QName, Serializable> params = new HashMap<QName, Serializable>();
|
||||
params.put(WorkflowModel.ASSOC_PACKAGE, pckg);
|
||||
params.put(WorkflowModel.ASSOC_ASSIGNEE, AuthenticationUtil.getAdminUserName());
|
||||
|
||||
WorkflowPath path = workflowService.startWorkflow(defId, params);
|
||||
String instanceId = path.getInstance().getId();
|
||||
WorkflowTask start = workflowService.getStartTask(instanceId);
|
||||
workflowService.endTask(start.getId(), null);
|
||||
|
||||
List<WorkflowTask> tasks = workflowService.getTasksForWorkflowPath(path.getId());
|
||||
WorkflowTask task = tasks.get(0);
|
||||
assertTrue(workflowService.isTaskReassignable(task, AuthenticationUtil.getAdminUserName()));
|
||||
|
||||
// Wait for timer to end task
|
||||
Thread.sleep(30000);
|
||||
assertFalse(workflowService.isTaskReassignable(task, AuthenticationUtil.getAdminUserName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception
|
||||
{
|
||||
ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
|
||||
ServiceRegistry services = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
|
||||
workflowService = services.getWorkflowService();
|
||||
WorkflowAdminServiceImpl adminService = (WorkflowAdminServiceImpl) ctx.getBean(WorkflowAdminServiceImpl.NAME);
|
||||
|
||||
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
|
||||
testHelper = new WorkflowTestHelper(adminService, JBPMEngine.ENGINE_ID, false);
|
||||
testHelper.setVisible(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
private String deployDefinition(String location)
|
||||
{
|
||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||
InputStream input = classLoader.getResourceAsStream(exceptionDefLocation);
|
||||
input = classLoader.getResourceAsStream(location);
|
||||
WorkflowDeployment deployment
|
||||
= workflowService.deployDefinition(JBPMEngine.ENGINE_ID, input, MimetypeMap.MIMETYPE_XML);
|
||||
return deployment.getDefinition().getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception
|
||||
{
|
||||
workflowService.undeployDefinition(defId);
|
||||
testHelper.tearDown();
|
||||
AuthenticationUtil.clearCurrentSecurityContext();
|
||||
}
|
||||
|
||||
public static void throwException() throws HibernateException
|
||||
{
|
||||
throw new HibernateException("My Timer Exception");
|
||||
}
|
||||
}
|
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.workflow.jbpm;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.repo.workflow.AbstractWorkflowServiceIntegrationTest;
|
||||
import org.alfresco.repo.workflow.WorkflowModel;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowPath;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTask;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* JBPM Workflow Service Implementation Tests
|
||||
*
|
||||
* @author Nick Smith
|
||||
* @since 3.4.e
|
||||
*/
|
||||
public class JbpmWorkflowServiceIntegrationTest extends AbstractWorkflowServiceIntegrationTest
|
||||
{
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public void disabledTestAsynchronousTaskExecutes() throws Exception
|
||||
{
|
||||
setComplete();
|
||||
endTransaction();
|
||||
|
||||
String defId = null;
|
||||
String instanceId = null;
|
||||
try
|
||||
{
|
||||
WorkflowDefinition def = deployDefinition(getAsyncAdhocPath());
|
||||
defId = def.getId();
|
||||
|
||||
// Create workflow parameters
|
||||
Map<QName, Serializable> params = new HashMap<QName, Serializable>();
|
||||
Serializable wfPackage = workflowService.createPackage(null);
|
||||
params.put(WorkflowModel.ASSOC_PACKAGE, wfPackage);
|
||||
Date dueDate = new Date();
|
||||
params.put(WorkflowModel.PROP_WORKFLOW_DUE_DATE, dueDate);
|
||||
params.put(WorkflowModel.PROP_WORKFLOW_PRIORITY, 1);
|
||||
NodeRef assignee = personManager.get(USER2);
|
||||
params.put(WorkflowModel.ASSOC_ASSIGNEE, assignee);
|
||||
|
||||
WorkflowPath path = workflowService.startWorkflow(defId, params);
|
||||
instanceId = path.getInstance().getId();
|
||||
|
||||
// End the Start Task.
|
||||
List<WorkflowTask> tasks = workflowService.getTasksForWorkflowPath(path.getId());
|
||||
assertEquals(1, tasks.size());
|
||||
WorkflowTask startTask = tasks.get(0);
|
||||
workflowService.endTask(startTask.getId(), null);
|
||||
|
||||
// Wait for async execution to occur.
|
||||
Thread.sleep(1000);
|
||||
|
||||
// Should move past the asynchronous adhoc task.
|
||||
tasks = workflowService.getTasksForWorkflowPath(path.getId());
|
||||
assertEquals(1, tasks.size());
|
||||
WorkflowTask endTask = tasks.get(0);
|
||||
assertEquals("wf:completedAdhocTask", endTask.getName());
|
||||
|
||||
// Check async task assigned to USER2
|
||||
tasks = workflowService.getAssignedTasks(USER2, WorkflowTaskState.IN_PROGRESS);
|
||||
assertEquals(1, tasks.size());
|
||||
WorkflowTask adhocTask = tasks.get(0);
|
||||
assertEquals("wf:adhocTask", adhocTask.getName());
|
||||
}
|
||||
finally
|
||||
{
|
||||
if(instanceId != null)
|
||||
{
|
||||
workflowService.cancelWorkflow(instanceId);
|
||||
}
|
||||
if(defId != null)
|
||||
{
|
||||
workflowService.undeployDefinition(defId);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private String getAsyncAdhocPath()
|
||||
{
|
||||
return "jbpmresources/async_adhoc_processdefinition.xml";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getEngine()
|
||||
{
|
||||
return JBPMEngine.ENGINE_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTestDefinitionPath()
|
||||
{
|
||||
return "jbpmresources/test_simple_processdefinition.xml";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getAdhocDefinitionPath()
|
||||
{
|
||||
return "alfresco/workflow/adhoc_processdefinition.xml";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getPooledReviewDefinitionPath()
|
||||
{
|
||||
return "alfresco/workflow/review_pooled_processdefinition.xml";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getParallelReviewDefinitionPath()
|
||||
{
|
||||
return "alfresco/workflow/parallelreview_processdefinition.xml";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTestTimerDefinitionPath()
|
||||
{
|
||||
return "jbpmresources/test_timer.xml";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected QName getAdhocProcessName()
|
||||
{
|
||||
return QName.createQName(NamespaceService.WORKFLOW_MODEL_1_0_URI, "adhoc");
|
||||
}
|
||||
}
|
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.workflow.jbpm;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.workflow.BPMEngineRegistry;
|
||||
import org.alfresco.repo.workflow.TaskComponent;
|
||||
import org.alfresco.repo.workflow.WorkflowComponent;
|
||||
import org.alfresco.repo.workflow.WorkflowModel;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
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.security.PersonService;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowDeployment;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowPath;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTask;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.BaseSpringTest;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
|
||||
/**
|
||||
* Review and Approve workflow specific Tests
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class ReviewAndApproveTest extends BaseSpringTest
|
||||
{
|
||||
AuthenticationComponent authenticationComponent;
|
||||
PersonService personService;
|
||||
WorkflowComponent workflowComponent;
|
||||
TaskComponent taskComponent;
|
||||
WorkflowDefinition testWorkflowDef;
|
||||
NodeRef testNodeRef;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected void onSetUpInTransaction() throws Exception
|
||||
{
|
||||
personService = (PersonService)applicationContext.getBean("personService");
|
||||
BPMEngineRegistry registry = (BPMEngineRegistry)applicationContext.getBean("bpm_engineRegistry");
|
||||
workflowComponent = registry.getWorkflowComponent(JBPMEngine.ENGINE_ID);
|
||||
taskComponent = registry.getTaskComponent(JBPMEngine.ENGINE_ID);
|
||||
|
||||
// deploy latest review and approve process definition
|
||||
ClassPathResource processDef = new ClassPathResource("alfresco/workflow/review_processdefinition.xml");
|
||||
WorkflowDeployment deployment = workflowComponent.deployDefinition(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML);
|
||||
testWorkflowDef = deployment.getDefinition();
|
||||
assertNotNull(testWorkflowDef);
|
||||
|
||||
// run as system
|
||||
authenticationComponent = (AuthenticationComponent)applicationContext.getBean("authenticationComponent");
|
||||
authenticationComponent.setSystemUserAsCurrentUser();
|
||||
|
||||
// get valid node ref
|
||||
NodeService nodeService = (NodeService)applicationContext.getBean(ServiceRegistry.NODE_SERVICE.getLocalName());
|
||||
testNodeRef = nodeService.getRootNode(new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "SpacesStore"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTearDownInTransaction()
|
||||
{
|
||||
authenticationComponent.clearCurrentSecurityContext();
|
||||
}
|
||||
|
||||
|
||||
public void testSubmitForReview()
|
||||
{
|
||||
WorkflowDefinition workflowDef = testWorkflowDef;
|
||||
|
||||
Map<QName, Serializable> params = new HashMap<QName, Serializable>();
|
||||
params.put(WorkflowModel.ASSOC_PACKAGE, testNodeRef);
|
||||
Date reviewDueDate = new Date();
|
||||
params.put(WorkflowModel.PROP_WORKFLOW_DUE_DATE, reviewDueDate);
|
||||
NodeRef reviewer = personService.getPerson(AuthenticationUtil.getAdminUserName());
|
||||
params.put(WorkflowModel.ASSOC_ASSIGNEE, reviewer);
|
||||
params.put(WorkflowModel.PROP_WORKFLOW_DESCRIPTION, "Test review");
|
||||
|
||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.getId(), params);
|
||||
assertNotNull(path);
|
||||
List<WorkflowTask> tasks1 = workflowComponent.getTasksForWorkflowPath(path.getId());
|
||||
assertNotNull(tasks1);
|
||||
assertEquals(1, tasks1.size());
|
||||
|
||||
WorkflowTask task = tasks1.get(0);
|
||||
assertTrue(task.getProperties().containsKey(WorkflowModel.ASSOC_PACKAGE));
|
||||
WorkflowTask endedTask = taskComponent.endTask(task.getId(), null);
|
||||
assertNotNull(endedTask);
|
||||
assertTrue(endedTask.getProperties().containsKey(WorkflowModel.PROP_OUTCOME));
|
||||
assertEquals("", endedTask.getProperties().get(WorkflowModel.PROP_OUTCOME));
|
||||
assertEquals("Test review", endedTask.getProperties().get(WorkflowModel.PROP_DESCRIPTION));
|
||||
assertEquals("Test review", endedTask.getPath().getInstance().getDescription());
|
||||
|
||||
List<WorkflowTask> assignedTasks = taskComponent.getAssignedTasks(AuthenticationUtil.getAdminUserName(), WorkflowTaskState.IN_PROGRESS, false);
|
||||
assertNotNull(assignedTasks);
|
||||
assignedTasks = filterTasksByWorkflowInstance(assignedTasks, path.getInstance().getId());
|
||||
|
||||
assertEquals(testNodeRef, assignedTasks.get(0).getProperties().get(WorkflowModel.ASSOC_PACKAGE));
|
||||
assertEquals(reviewDueDate, assignedTasks.get(0).getProperties().get(WorkflowModel.PROP_DUE_DATE));
|
||||
}
|
||||
|
||||
public void testCompletedItems()
|
||||
{
|
||||
WorkflowDefinition workflowDef = testWorkflowDef;
|
||||
|
||||
List<NodeRef> nodeRefs = new ArrayList<NodeRef>();
|
||||
nodeRefs.add(testNodeRef);
|
||||
nodeRefs.add(testNodeRef);
|
||||
|
||||
Map<QName, Serializable> params = new HashMap<QName, Serializable>();
|
||||
params.put(WorkflowModel.ASSOC_PACKAGE, testNodeRef);
|
||||
params.put(WorkflowModel.PROP_COMPLETED_ITEMS, (Serializable)nodeRefs);
|
||||
Date reviewDueDate = new Date();
|
||||
params.put(WorkflowModel.PROP_WORKFLOW_DUE_DATE, reviewDueDate);
|
||||
NodeRef reviewer = personService.getPerson(AuthenticationUtil.getAdminUserName());
|
||||
params.put(WorkflowModel.ASSOC_ASSIGNEE, reviewer);
|
||||
|
||||
WorkflowPath path = workflowComponent.startWorkflow(workflowDef.getId(), params);
|
||||
assertNotNull(path);
|
||||
List<WorkflowTask> tasks1 = workflowComponent.getTasksForWorkflowPath(path.getId());
|
||||
assertNotNull(tasks1);
|
||||
assertEquals(1, tasks1.size());
|
||||
|
||||
WorkflowTask task = tasks1.get(0);
|
||||
assertTrue(task.getProperties().containsKey(WorkflowModel.PROP_COMPLETED_ITEMS));
|
||||
assertEquals(2, ((List<?>)task.getProperties().get(WorkflowModel.PROP_COMPLETED_ITEMS)).size());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Filter task list by workflow instance
|
||||
*
|
||||
* @param tasks
|
||||
* @param processInstanceId
|
||||
* @return
|
||||
*/
|
||||
private List<WorkflowTask> filterTasksByWorkflowInstance(List<WorkflowTask> tasks, String workflowInstanceId)
|
||||
{
|
||||
List<WorkflowTask> filteredTasks = new ArrayList<WorkflowTask>();
|
||||
for (WorkflowTask task : tasks)
|
||||
{
|
||||
if (task.getPath().getInstance().getId().equals(workflowInstanceId))
|
||||
{
|
||||
filteredTasks.add(task);
|
||||
}
|
||||
}
|
||||
return filteredTasks;
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user