/*
* Copyright 2013 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.
* 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.jbpm.executor.ejb.impl.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;
import javax.ejb.EJB;
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.executor.impl.jpa.ExecutorJPAAuditService;
import org.jbpm.services.ejb.api.ExecutorServiceEJB;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.kie.api.executor.CommandContext;
import org.kie.api.executor.ErrorInfo;
import org.kie.api.executor.ExecutionResults;
import org.kie.api.executor.RequestInfo;
import org.kie.api.executor.STATUS;
import org.kie.api.runtime.query.QueryContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@RunWith(Arquillian.class)
public class BasicExecutorIntegrationTest {
private static final Logger logger = LoggerFactory.getLogger(BasicExecutorIntegrationTest.class);
public static final Map<String, Object> cachedEntities = new HashMap<String, Object>();
@Deployment
public static WebArchive createDeployment() {
File archive = new File("target/executor-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.executor.ejb.impl.test"); // test cases
return war;
}
@EJB
protected ExecutorServiceEJB executorService;
@PersistenceUnit(unitName="org.jbpm.domain")
protected EntityManagerFactory emf = null;
@Before
public void setUp() {
}
@After
public void tearDown() {
executorService.clearAllRequests();
executorService.clearAllErrors();
System.clearProperty("org.kie.executor.msg.length");
System.clearProperty("org.kie.executor.stacktrace.length");
}
@Test
public void simpleExcecutionTest() throws InterruptedException {
CommandContext ctxCMD = new CommandContext();
ctxCMD.setData("businessKey", UUID.randomUUID().toString());
executorService.scheduleRequest("org.jbpm.executor.commands.PrintOutCommand", ctxCMD);
Thread.sleep(10000);
List<RequestInfo> inErrorRequests = executorService.getInErrorRequests(new QueryContext());
assertEquals(0, inErrorRequests.size());
List<RequestInfo> queuedRequests = executorService.getQueuedRequests(new QueryContext());
assertEquals(0, queuedRequests.size());
List<RequestInfo> executedRequests = executorService.getCompletedRequests(new QueryContext());
assertEquals(1, executedRequests.size());
}
@Test
public void callbackTest() throws InterruptedException {
CommandContext commandContext = new CommandContext();
commandContext.setData("businessKey", UUID.randomUUID().toString());
cachedEntities.put((String) commandContext.getData("businessKey"), new AtomicLong(1));
commandContext.setData("callbacks", "org.jbpm.executor.ejb.impl.test.SimpleIncrementCallback");
executorService.scheduleRequest("org.jbpm.executor.commands.PrintOutCommand", commandContext);
Thread.sleep(10000);
List<RequestInfo> inErrorRequests = executorService.getInErrorRequests(new QueryContext());
assertEquals(0, inErrorRequests.size());
List<RequestInfo> queuedRequests = executorService.getQueuedRequests(new QueryContext());
assertEquals(0, queuedRequests.size());
List<RequestInfo> executedRequests = executorService.getCompletedRequests(new QueryContext());
assertEquals(1, executedRequests.size());
assertEquals(2, ((AtomicLong) cachedEntities.get((String) commandContext.getData("businessKey"))).longValue());
}
@Test
public void addAnotherCallbackTest() throws InterruptedException {
CommandContext commandContext = new CommandContext();
commandContext.setData("businessKey", UUID.randomUUID().toString());
cachedEntities.put((String) commandContext.getData("businessKey"), new AtomicLong(1));
commandContext.setData("callbacks", "org.jbpm.executor.ejb.impl.test.SimpleIncrementCallback");
executorService.scheduleRequest("org.jbpm.executor.ejb.impl.test.AddAnotherCallbackCommand", commandContext);
Thread.sleep(10000);
List<RequestInfo> inErrorRequests = executorService.getInErrorRequests(new QueryContext());
assertEquals(0, inErrorRequests.size());
List<RequestInfo> queuedRequests = executorService.getQueuedRequests(new QueryContext());
assertEquals(0, queuedRequests.size());
List<RequestInfo> executedRequests = executorService.getCompletedRequests(new QueryContext());
assertEquals(1, executedRequests.size());
assertEquals(2, ((AtomicLong) cachedEntities.get((String) commandContext.getData("businessKey"))).longValue());
ExecutionResults results = null;
byte[] responseData = executedRequests.get(0).getResponseData();
ObjectInputStream in = null;
try {
in = new ObjectInputStream(new ByteArrayInputStream(responseData));
results = (ExecutionResults) in.readObject();
} catch (Exception e) {
logger.warn("Exception while serializing context data", e);
return;
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
String result = (String)results.getData("custom");
assertNotNull(result);
assertEquals("custom callback invoked", result);
}
@Test
public void multipleCallbackTest() throws InterruptedException {
CommandContext commandContext = new CommandContext();
commandContext.setData("businessKey", UUID.randomUUID().toString());
cachedEntities.put((String) commandContext.getData("businessKey"), new AtomicLong(1));
commandContext.setData("callbacks", "org.jbpm.executor.ejb.impl.test.SimpleIncrementCallback, org.jbpm.executor.ejb.impl.test.CustomCallback");
executorService.scheduleRequest("org.jbpm.executor.commands.PrintOutCommand", commandContext);
Thread.sleep(10000);
List<RequestInfo> inErrorRequests = executorService.getInErrorRequests(new QueryContext());
assertEquals(0, inErrorRequests.size());
List<RequestInfo> queuedRequests = executorService.getQueuedRequests(new QueryContext());
assertEquals(0, queuedRequests.size());
List<RequestInfo> executedRequests = executorService.getCompletedRequests(new QueryContext());
assertEquals(1, executedRequests.size());
assertEquals(2, ((AtomicLong) cachedEntities.get((String) commandContext.getData("businessKey"))).longValue());
ExecutionResults results = null;
byte[] responseData = executedRequests.get(0).getResponseData();
ObjectInputStream in = null;
try {
in = new ObjectInputStream(new ByteArrayInputStream(responseData));
results = (ExecutionResults) in.readObject();
} catch (Exception e) {
logger.warn("Exception while serializing context data", e);
return;
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
String result = (String)results.getData("custom");
assertNotNull(result);
assertEquals("custom callback invoked", result);
}
@Test
public void executorExceptionTest() throws InterruptedException {
CommandContext commandContext = new CommandContext();
commandContext.setData("businessKey", UUID.randomUUID().toString());
cachedEntities.put((String) commandContext.getData("businessKey"), new AtomicLong(1));
commandContext.setData("callbacks", "org.jbpm.executor.ejb.impl.test.SimpleIncrementCallback");
commandContext.setData("retries", 0);
executorService.scheduleRequest("org.jbpm.executor.ejb.impl.test.ThrowExceptionCommand", commandContext);
logger.info("{} Sleeping for 10 secs", System.currentTimeMillis());
Thread.sleep(10000);
List<RequestInfo> inErrorRequests = executorService.getInErrorRequests(new QueryContext());
assertEquals(1, inErrorRequests.size());
logger.info("Error: {}", inErrorRequests.get(0));
List<ErrorInfo> errors = executorService.getAllErrors(new QueryContext());
logger.info("Errors: {}", errors);
assertEquals(1, errors.size());
}
@Test
public void defaultRequestRetryTest() throws InterruptedException {
CommandContext ctxCMD = new CommandContext();
ctxCMD.setData("businessKey", UUID.randomUUID().toString());
executorService.scheduleRequest("org.jbpm.executor.ejb.impl.test.ThrowExceptionCommand", ctxCMD);
Thread.sleep(12000);
List<RequestInfo> inErrorRequests = executorService.getInErrorRequests(new QueryContext());
assertEquals(1, inErrorRequests.size());
List<ErrorInfo> errors = executorService.getAllErrors(new QueryContext());
logger.info("Errors: {}", errors);
// Three retries means 4 executions in total 1(regular) + 3(retries)
assertEquals(4, errors.size());
}
@Test
public void cancelRequestTest() throws InterruptedException {
// The executor is on purpose not started to not fight against race condition
// with the request cancelations.
CommandContext ctxCMD = new CommandContext();
String businessKey = UUID.randomUUID().toString();
ctxCMD.setData("businessKey", businessKey);
Long requestId = executorService.scheduleRequest("org.jbpm.executor.commands.PrintOutCommand", ctxCMD);
List<RequestInfo> requests = executorService.getRequestsByBusinessKey(businessKey, new QueryContext());
assertNotNull(requests);
assertEquals(1, requests.size());
assertEquals(requestId, requests.get(0).getId());
// cancel the task immediately
executorService.cancelRequest(requestId);
List<RequestInfo> cancelledRequests = executorService.getCancelledRequests(new QueryContext());
assertEquals(1, cancelledRequests.size());
}
@Test
public void executorExceptionTrimmingTest() throws InterruptedException {
System.setProperty("org.kie.executor.msg.length", "10");
System.setProperty("org.kie.executor.stacktrace.length", "20");
CommandContext commandContext = new CommandContext();
commandContext.setData("businessKey", UUID.randomUUID().toString());
cachedEntities.put((String) commandContext.getData("businessKey"), new AtomicLong(1));
commandContext.setData("callbacks", "org.jbpm.executor.ejb.impl.test.SimpleIncrementCallback");
commandContext.setData("retries", 0);
executorService.scheduleRequest("org.jbpm.executor.ejb.impl.test.ThrowExceptionCommand", commandContext);
logger.info("{} Sleeping for 10 secs", System.currentTimeMillis());
Thread.sleep(10000);
List<RequestInfo> inErrorRequests = executorService.getInErrorRequests(new QueryContext());
assertEquals(1, inErrorRequests.size());
logger.info("Error: {}", inErrorRequests.get(0));
List<ErrorInfo> errors = executorService.getAllErrors(new QueryContext());
logger.info("Errors: {}", errors);
assertEquals(1, errors.size());
ErrorInfo error = errors.get(0);
assertEquals(10, error.getMessage().length());
assertEquals(20, error.getStacktrace().length());
}
@Test
public void reoccurringExcecutionTest() throws InterruptedException {
CommandContext ctxCMD = new CommandContext();
ctxCMD.setData("businessKey", UUID.randomUUID().toString());
executorService.scheduleRequest("org.jbpm.executor.commands.ReoccurringPrintOutCommand", ctxCMD);
Thread.sleep(10000);
List<RequestInfo> inErrorRequests = executorService.getInErrorRequests(new QueryContext());
assertEquals(0, inErrorRequests.size());
List<RequestInfo> queuedRequests = executorService.getQueuedRequests(new QueryContext());
assertEquals(1, queuedRequests.size());
List<RequestInfo> executedRequests = executorService.getCompletedRequests(new QueryContext());
assertEquals(4, executedRequests.size());
}
@Test
public void cleanupLogExcecutionTest() throws InterruptedException {
CommandContext ctxCMD = new CommandContext();
ctxCMD.setData("businessKey", UUID.randomUUID().toString());
Long requestId = executorService.scheduleRequest("org.jbpm.executor.commands.ReoccurringPrintOutCommand", ctxCMD);
Thread.sleep(9000);
List<RequestInfo> inErrorRequests = executorService.getInErrorRequests(new QueryContext());
assertEquals(0, inErrorRequests.size());
List<RequestInfo> queuedRequests = executorService.getQueuedRequests(new QueryContext());
assertEquals(1, queuedRequests.size());
List<RequestInfo> executedRequests = executorService.getCompletedRequests(new QueryContext());
assertEquals(3, executedRequests.size());
executorService.cancelRequest(requestId+3);
List<RequestInfo> canceled = executorService.getCancelledRequests(new QueryContext());
ExecutorJPAAuditService auditService = new ExecutorJPAAuditService(emf);
int resultCount = auditService.requestInfoLogDeleteBuilder()
.date(canceled.get(0).getTime())
.status(STATUS.ERROR)
.build()
.execute();
assertEquals(0, resultCount);
resultCount = auditService.errorInfoLogDeleteBuilder()
.date(canceled.get(0).getTime())
.build()
.execute();
assertEquals(0, resultCount);
ctxCMD = new CommandContext();
ctxCMD.setData("businessKey", UUID.randomUUID().toString());
ctxCMD.setData("SingleRun", "true");
ctxCMD.setData("EmfName", "org.jbpm.domain");
ctxCMD.setData("SkipProcessLog", "true");
ctxCMD.setData("SkipTaskLog", "true");
executorService.scheduleRequest("org.jbpm.executor.commands.LogCleanupCommand", ctxCMD);
Thread.sleep(5000);
inErrorRequests = executorService.getInErrorRequests(new QueryContext());
assertEquals(0, inErrorRequests.size());
queuedRequests = executorService.getQueuedRequests(new QueryContext());
assertEquals(0, queuedRequests.size());
executedRequests = executorService.getCompletedRequests(new QueryContext());
assertEquals(1, executedRequests.size());
}
@Test
public void cancelRequestWithSearchByCommandTest() throws InterruptedException {
CommandContext ctxCMD = new CommandContext();
String businessKey = UUID.randomUUID().toString();
ctxCMD.setData("businessKey", businessKey);
Long requestId = executorService.scheduleRequest("org.jbpm.executor.test.CustomCommand", ctxCMD);
List<RequestInfo> requests = executorService.getRequestsByCommand("org.jbpm.executor.test.CustomCommand", new QueryContext());
assertNotNull(requests);
assertEquals(1, requests.size());
assertEquals(requestId, requests.get(0).getId());
// cancel the task immediately
executorService.cancelRequest(requestId);
List<RequestInfo> cancelledRequests = executorService.getCancelledRequests(new QueryContext());
assertEquals(1, cancelledRequests.size());
}
}