/* * Copyright 2015 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * * 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.jbpm.services.ejb.timer.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.io.File; import java.io.FilenameFilter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import javax.persistence.EntityManagerFactory; import javax.persistence.PersistenceUnit; import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.arquillian.junit.Arquillian; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.spec.WebArchive; import org.jbpm.runtime.manager.impl.DefaultRegisterableItemsFactory; import org.jbpm.services.ejb.timer.EjbSchedulerService; import org.jbpm.services.task.identity.JBossUserGroupCallbackImpl; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.kie.api.event.process.DefaultProcessEventListener; import org.kie.api.event.process.ProcessEventListener; import org.kie.api.event.process.ProcessNodeTriggeredEvent; import org.kie.api.io.ResourceType; import org.kie.api.runtime.KieSession; import org.kie.api.runtime.manager.RuntimeEngine; import org.kie.api.runtime.manager.RuntimeEnvironment; import org.kie.api.runtime.manager.RuntimeEnvironmentBuilder; import org.kie.api.runtime.manager.RuntimeManager; import org.kie.api.runtime.manager.RuntimeManagerFactory; import org.kie.api.runtime.process.ProcessInstance; import org.kie.api.task.model.TaskSummary; import org.kie.internal.io.ResourceFactory; import org.kie.internal.runtime.manager.context.EmptyContext; import org.kie.internal.task.api.UserGroupCallback; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @RunWith(Arquillian.class) public class EjbTimerServiceIntegrationTest { private static final Logger logger = LoggerFactory.getLogger(EjbTimerServiceIntegrationTest.class); private UserGroupCallback userGroupCallback; private RuntimeManager manager; @Deployment public static WebArchive createDeployment() { File archive = new File("target/timer-war-ejb-app.war"); if (!archive.exists()) { throw new IllegalStateException("There is no archive yet generated, run maven build or mvn assembly:assembly"); } WebArchive war = ShrinkWrap.createFromZipFile(WebArchive.class, archive); war.addPackage("org.jbpm.services.ejb.timer.test"); // test cases war.addAsResource("BPMN2-TimerTask.bpmn2"); war.addAsResource("HumanTaskWithDeadlines.bpmn"); return war; } @Before public void setup() { Properties properties= new Properties(); properties.setProperty("mary", "HR"); properties.setProperty("john", "HR"); properties.setProperty("krisv", "HR"); userGroupCallback = new JBossUserGroupCallbackImpl(properties); } @After public void cleanup() { cleanupSingletonSessionId(); } @PersistenceUnit(unitName="org.jbpm.domain") private EntityManagerFactory emf; @Test public void testProcessWithTimerOverEJBTimerService2SecDelay() throws InterruptedException { testProcessWithTimerOverEJBTimerService("2s"); } @Test public void testProcessWithTimerOverEJBTimerService0SecDelay() throws InterruptedException { testProcessWithTimerOverEJBTimerService("0s"); } public void testProcessWithTimerOverEJBTimerService(String delay) throws InterruptedException { cleanupSingletonSessionId(); final List<String> timerExecution = new ArrayList<String>(); RuntimeEnvironment environment = RuntimeEnvironmentBuilder.Factory.get() .newDefaultBuilder() .entityManagerFactory(emf) .userGroupCallback(userGroupCallback) .addAsset(ResourceFactory.newClassPathResource("BPMN2-TimerTask.bpmn2"), ResourceType.BPMN2) .schedulerService(new EjbSchedulerService()) .registerableItemsFactory(new DefaultRegisterableItemsFactory(){ @Override public List<ProcessEventListener> getProcessEventListeners( RuntimeEngine runtime) { List<ProcessEventListener> listeners = super.getProcessEventListeners(runtime); listeners.add(new DefaultProcessEventListener(){ @Override public void afterNodeTriggered(ProcessNodeTriggeredEvent event) { if (event.getNodeInstance().getNodeName().equals("Event")) { timerExecution.add(event.getNodeInstance().getNodeName()); } } }); return listeners; } }) .get(); manager = RuntimeManagerFactory.Factory.get().newSingletonRuntimeManager(environment); assertNotNull(manager); RuntimeEngine runtime = manager.getRuntimeEngine(EmptyContext.get()); KieSession ksession = runtime.getKieSession(); assertNotNull(ksession); Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("x", delay); ProcessInstance instance = ksession.startProcess("IntermediateCatchEvent", parameters); assertNotNull(instance); Thread.sleep(3000); instance = ksession.getProcessInstance(instance.getId()); assertNull(instance); assertEquals(1, timerExecution.size()); manager.disposeRuntimeEngine(runtime); // close manager which will close session maintained by the manager manager.close(); } @Test public void testProcessWithTimerOverEJBTimerServiceCancelTimer() throws InterruptedException { cleanupSingletonSessionId(); final List<String> timerExecution = new ArrayList<String>(); RuntimeEnvironment environment = RuntimeEnvironmentBuilder.Factory.get() .newDefaultBuilder() .entityManagerFactory(emf) .userGroupCallback(userGroupCallback) .addAsset(ResourceFactory.newClassPathResource("BPMN2-TimerTask.bpmn2"), ResourceType.BPMN2) .schedulerService(new EjbSchedulerService()) .registerableItemsFactory(new DefaultRegisterableItemsFactory(){ @Override public List<ProcessEventListener> getProcessEventListeners( RuntimeEngine runtime) { List<ProcessEventListener> listeners = super.getProcessEventListeners(runtime); listeners.add(new DefaultProcessEventListener(){ @Override public void afterNodeTriggered(ProcessNodeTriggeredEvent event) { if (event.getNodeInstance().getNodeName().equals("Event")) { timerExecution.add(event.getNodeInstance().getNodeName()); } } }); return listeners; } }) .get(); manager = RuntimeManagerFactory.Factory.get().newSingletonRuntimeManager(environment); assertNotNull(manager); RuntimeEngine runtime = manager.getRuntimeEngine(EmptyContext.get()); KieSession ksession = runtime.getKieSession(); assertNotNull(ksession); ProcessInstance instance = ksession.startProcess("IntermediateCatchEvent"); assertNotNull(instance); ksession.abortProcessInstance(instance.getId()); instance = ksession.getProcessInstance(instance.getId()); assertNull(instance); Thread.sleep(3000); assertEquals(0, timerExecution.size()); manager.disposeRuntimeEngine(runtime); // close manager which will close session maintained by the manager manager.close(); } @Test public void testProcessWithHTDeadlineTimerOverEJBTimerService() throws InterruptedException { cleanupSingletonSessionId(); RuntimeEnvironment environment = RuntimeEnvironmentBuilder.Factory.get() .newDefaultBuilder() .entityManagerFactory(emf) .userGroupCallback(userGroupCallback) .addAsset(ResourceFactory.newClassPathResource("HumanTaskWithDeadlines.bpmn"), ResourceType.BPMN2) .schedulerService(new EjbSchedulerService()) .get(); manager = RuntimeManagerFactory.Factory.get().newSingletonRuntimeManager(environment); assertNotNull(manager); RuntimeEngine runtime = manager.getRuntimeEngine(EmptyContext.get()); KieSession ksession = runtime.getKieSession(); assertNotNull(ksession); ProcessInstance processInstance = ksession.startProcess("htdeadlinetest"); assertTrue(processInstance.getState() == ProcessInstance.STATE_ACTIVE); List<TaskSummary> krisTasks = runtime.getTaskService().getTasksAssignedAsPotentialOwner("krisv", "en-UK"); assertEquals(1, krisTasks.size()); List<TaskSummary> johnTasks = runtime.getTaskService().getTasksAssignedAsPotentialOwner("john", "en-UK"); assertEquals(0, johnTasks.size()); List<TaskSummary> maryTasks = runtime.getTaskService().getTasksAssignedAsPotentialOwner("mary", "en-UK"); assertEquals(0, maryTasks.size()); // now wait for 2 seconds for first reassignment Thread.sleep(3000); krisTasks = runtime.getTaskService().getTasksAssignedAsPotentialOwner("krisv", "en-UK"); assertEquals(0, krisTasks.size()); johnTasks = runtime.getTaskService().getTasksAssignedAsPotentialOwner("john", "en-UK"); assertEquals(1, johnTasks.size()); maryTasks = runtime.getTaskService().getTasksAssignedAsPotentialOwner("mary", "en-UK"); assertEquals(0, maryTasks.size()); runtime.getTaskService().start(johnTasks.get(0).getId(), "john"); // now wait for 2 more seconds for second reassignment Thread.sleep(2000); krisTasks = runtime.getTaskService().getTasksAssignedAsPotentialOwner("krisv", "en-UK"); assertEquals(0, krisTasks.size()); johnTasks = runtime.getTaskService().getTasksAssignedAsPotentialOwner("john", "en-UK"); assertEquals(1, johnTasks.size()); maryTasks = runtime.getTaskService().getTasksAssignedAsPotentialOwner("mary", "en-UK"); assertEquals(0, maryTasks.size()); // now wait for 1 seconds to make sure that reassignment did not happen any more since task was already started Thread.sleep(3000); krisTasks = runtime.getTaskService().getTasksAssignedAsPotentialOwner("krisv", "en-UK"); assertEquals(0, krisTasks.size()); johnTasks = runtime.getTaskService().getTasksAssignedAsPotentialOwner("john", "en-UK"); assertEquals(0, johnTasks.size()); maryTasks = runtime.getTaskService().getTasksAssignedAsPotentialOwner("mary", "en-UK"); assertEquals(1, maryTasks.size()); runtime.getTaskService().start(maryTasks.get(0).getId(), "mary"); runtime.getTaskService().complete(maryTasks.get(0).getId(), "mary", null); // now wait for 2 seconds to make sure that reassignment did not happen any more since task was completed Thread.sleep(2000); processInstance = ksession.getProcessInstance(processInstance.getId()); assertNull(processInstance); // close manager which will close session maintained by the manager manager.close(); } protected void cleanupSingletonSessionId() { File tempDir = new File(getLocation()); if (tempDir.exists()) { String[] jbpmSerFiles = tempDir.list(new FilenameFilter() { @Override public boolean accept(File dir, String name) { return name.endsWith("-jbpmSessionId.ser"); } }); for (String file : jbpmSerFiles) { logger.debug("Temp dir to be removed {} file {}",tempDir, file); new File(tempDir, file).delete(); } } } protected String getLocation() { String location = System.getProperty("jbpm.data.dir", System.getProperty("jboss.server.data.dir")); if (location == null) { location = System.getProperty("java.io.tmpdir"); } return location; } }