/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti.engine.test.bpmn.async;
import java.util.Date;
import java.util.List;
import org.activiti.engine.history.HistoricVariableInstance;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.history.HistoryLevel;
import org.activiti.engine.impl.persistence.entity.MessageEntity;
import org.activiti.engine.impl.test.PluggableActivitiTestCase;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.Job;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.test.Deployment;
import org.junit.Assert;
/**
*
* @author Daniel Meyer
*/
public class AsyncTaskTest extends PluggableActivitiTestCase {
public static boolean INVOCATION;
@Deployment
public void testAsyncServiceNoListeners() {
INVOCATION = false;
// start process
runtimeService.startProcessInstanceByKey("asyncService");
// now there should be one job in the database:
assertEquals(1, managementService.createJobQuery().count());
// the service was not invoked:
assertFalse(INVOCATION);
waitForJobExecutorToProcessAllJobs(10000L, 100L);
// the service was invoked
assertTrue(INVOCATION);
// and the job is done
assertEquals(0, managementService.createJobQuery().count());
}
@Deployment
public void testAsyncServiceListeners() {
String pid = runtimeService.startProcessInstanceByKey("asyncService").getProcessInstanceId();
assertEquals(1, managementService.createJobQuery().count());
// the listener was not yet invoked:
assertNull(runtimeService.getVariable(pid, "listener"));
waitForJobExecutorToProcessAllJobs(10000L, 100L);
assertEquals(0, managementService.createJobQuery().count());
}
@Deployment
public void testAsyncServiceConcurrent() {
INVOCATION = false;
// start process
runtimeService.startProcessInstanceByKey("asyncService");
// now there should be one job in the database:
assertEquals(1, managementService.createJobQuery().count());
// the service was not invoked:
assertFalse(INVOCATION);
waitForJobExecutorToProcessAllJobs(10000L, 100L);
// the service was invoked
assertTrue(INVOCATION);
// and the job is done
assertEquals(0, managementService.createJobQuery().count());
}
@Deployment
public void testAsyncServiceMultiInstance() {
INVOCATION = false;
// start process
runtimeService.startProcessInstanceByKey("asyncService");
// now there should be one job in the database:
assertEquals(1, managementService.createJobQuery().count());
// the service was not invoked:
assertFalse(INVOCATION);
waitForJobExecutorToProcessAllJobs(10000L, 100L);
// the service was invoked
assertTrue(INVOCATION);
// and the job is done
assertEquals(0, managementService.createJobQuery().count());
}
@Deployment
public void testFailingAsyncServiceTimer() {
// start process
runtimeService.startProcessInstanceByKey("asyncService");
// now there should be one job in the database, and it is a message
assertEquals(1, managementService.createJobQuery().count());
Job job = managementService.createJobQuery().singleResult();
if (!(job instanceof MessageEntity)) {
fail("the job must be a message");
}
try {
managementService.executeJob(job.getId());
fail();
} catch (Exception e) {
// exception expected
}
// the service failed: the execution is still sitting in the service task:
Execution execution = runtimeService.createExecutionQuery().singleResult();
assertNotNull(execution);
assertEquals("service", runtimeService.getActiveActivityIds(execution.getId()).get(0));
// there is still a single job because the timer was created in the same transaction as the
// service was executed (which rolled back)
assertEquals(1, managementService.createJobQuery().count());
runtimeService.deleteProcessInstance(execution.getId(), "dead");
}
// TODO: Think about this:
@Deployment
public void FAILING_testFailingAsycServiceTimer() {
// start process
runtimeService.startProcessInstanceByKey("asyncService");
// now there are two jobs the message and a timer:
assertEquals(2, managementService.createJobQuery().count());
// let 'max-retires' on the message be reached
waitForJobExecutorToProcessAllJobs(10000L, 100L);
// the service failed: the execution is still sitting in the service task:
Execution execution = runtimeService.createExecutionQuery().singleResult();
assertNotNull(execution);
assertEquals("service", runtimeService.getActiveActivityIds(execution.getId()).get(0));
// there are tow jobs, the message and the timer (the message will not be retried anymore, max retires is reached.)
assertEquals(2, managementService.createJobQuery().count());
// now the timer triggers:
Context.getProcessEngineConfiguration().getClock().setCurrentTime(new Date(System.currentTimeMillis() + 10000));
waitForJobExecutorToProcessAllJobs(10000L, 100L);
// and we are done:
assertNull(runtimeService.createExecutionQuery().singleResult());
// and there are no more jobs left:
assertEquals(0, managementService.createJobQuery().count());
}
@Deployment
public void testAsyncServiceSubProcessTimer() {
INVOCATION = false;
// start process
runtimeService.startProcessInstanceByKey("asyncService");
// now there should be two jobs in the database:
assertEquals(2, managementService.createJobQuery().count());
// the service was not invoked:
assertFalse(INVOCATION);
waitForJobExecutorToProcessAllJobs(10000L, 100L);
// the service was invoked
assertTrue(INVOCATION);
// both the timer and the message are cancelled
assertEquals(0, managementService.createJobQuery().count());
}
@Deployment
public void testAsyncServiceSubProcess() {
// start process
runtimeService.startProcessInstanceByKey("asyncService");
assertEquals(1, managementService.createJobQuery().count());
waitForJobExecutorToProcessAllJobs(10000L, 100L);
// both the timer and the message are cancelled
assertEquals(0, managementService.createJobQuery().count());
}
@Deployment
public void testAsyncTask() {
// start process
runtimeService.startProcessInstanceByKey("asyncTask");
// now there should be one job in the database:
assertEquals(1, managementService.createJobQuery().count());
waitForJobExecutorToProcessAllJobs(10000L, 100L);
// the job is done
assertEquals(0, managementService.createJobQuery().count());
}
@Deployment
public void testAsyncEndEvent() {
// start process
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("asyncEndEvent");
// now there should be one job in the database:
assertEquals(1, managementService.createJobQuery().count());
Object value = runtimeService.getVariable(processInstance.getId(), "variableSetInExecutionListener");
assertNull(value);
waitForJobExecutorToProcessAllJobs(2000L, 200L);
// the job is done
assertEquals(0, managementService.createJobQuery().count());
assertProcessEnded(processInstance.getId());
if (processEngineConfiguration.getHistoryLevel().isAtLeast(HistoryLevel.AUDIT)) {
List<HistoricVariableInstance> variables = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstance.getId()).list();
assertEquals(3, variables.size());
Object historyValue = null;
for (HistoricVariableInstance variable : variables) {
if ("variableSetInExecutionListener".equals(variable.getVariableName())) {
historyValue = variable.getValue();
}
}
assertEquals("firstValue", historyValue);
}
}
@Deployment
public void testAsyncScript() {
// start process
runtimeService.startProcessInstanceByKey("asyncScript").getProcessInstanceId();
// now there should be one job in the database:
assertEquals(1, managementService.createJobQuery().count());
// the script was not invoked:
String eid = runtimeService.createExecutionQuery().singleResult().getId();
assertNull(runtimeService.getVariable(eid, "invoked"));
waitForJobExecutorToProcessAllJobs(10000L, 100L);
// and the job is done
assertEquals(0, managementService.createJobQuery().count());
// the script was invoked
assertEquals("true", runtimeService.getVariable(eid, "invoked"));
runtimeService.signal(eid);
}
@Deployment(resources={"org/activiti/engine/test/bpmn/async/AsyncTaskTest.testAsyncCallActivity.bpmn20.xml",
"org/activiti/engine/test/bpmn/async/AsyncTaskTest.testAsyncServiceNoListeners.bpmn20.xml"})
public void testAsyncCallActivity() throws Exception {
// start process
runtimeService.startProcessInstanceByKey("asyncCallactivity");
// now there should be one job in the database:
assertEquals(1, managementService.createJobQuery().count());
waitForJobExecutorToProcessAllJobs(10000L, 250L);
assertEquals(0, managementService.createJobQuery().count());
assertEquals(0, runtimeService.createProcessInstanceQuery().count());
}
@Deployment(resources = {"org/activiti/engine/test/bpmn/async/AsyncTaskTest.testBasicAsyncCallActivity.bpmn20.xml",
"org/activiti/engine/test/bpmn/StartToEndTest.testStartToEnd.bpmn20.xml"})
public void testBasicAsyncCallActivity() {
runtimeService.startProcessInstanceByKey("myProcess");
Assert.assertEquals("There should be one job available.", 1, managementService.createJobQuery().count());
waitForJobExecutorToProcessAllJobs(10000L, 500L);
assertEquals(0, managementService.createJobQuery().count());
}
@Deployment
public void testAsyncUserTask() {
// start process
String pid = runtimeService.startProcessInstanceByKey("asyncUserTask").getProcessInstanceId();
// now there should be one job in the database:
assertEquals(1, managementService.createJobQuery().count());
// the listener was not yet invoked:
assertNull(runtimeService.getVariable(pid, "listener"));
// the task listener was not yet invoked:
assertNull(runtimeService.getVariable(pid, "taskListener"));
// there is no usertask
assertNull(taskService.createTaskQuery().singleResult());
waitForJobExecutorToProcessAllJobs(10000L, 500L);
// the listener was now invoked:
assertNotNull(runtimeService.getVariable(pid, "listener"));
// the task listener was now invoked:
assertNotNull(runtimeService.getVariable(pid, "taskListener"));
// there is a usertask
assertNotNull(taskService.createTaskQuery().singleResult());
// and no more job
assertEquals(0, managementService.createJobQuery().count());
String taskId = taskService.createTaskQuery().singleResult().getId();
taskService.complete(taskId);
}
@Deployment
public void testMultiInstanceAsyncTask() {
// start process
runtimeService.startProcessInstanceByKey("asyncTask");
// now there should be one job in the database:
assertEquals(1, managementService.createJobQuery().count());
waitForJobExecutorToProcessAllJobs(5000L, 500L);
// the job is done
assertEquals(0, managementService.createJobQuery().count());
}
}