/*
* Copyright 2016 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.test.container.test.ejbservices.ejbcompl;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.assertj.core.api.Assertions;
import org.jbpm.test.container.AbstractRuntimeEJBServicesTest;
import org.jbpm.test.container.groups.EAP;
import org.jbpm.test.container.mock.RestService;
import org.jbpm.services.api.model.VariableDesc;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runners.MethodSorters;
import org.kie.api.event.process.DefaultProcessEventListener;
import org.kie.api.event.process.ProcessCompletedEvent;
import org.kie.api.event.process.ProcessNodeTriggeredEvent;
import org.kie.api.runtime.manager.RuntimeEngine;
import org.kie.api.runtime.manager.RuntimeManager;
import org.kie.api.task.model.TaskSummary;
import org.kie.internal.query.QueryContext;
import org.kie.internal.query.QueryFilter;
import org.kie.internal.runtime.manager.context.ProcessInstanceIdContext;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@Category({EAP.class})
public class EThreadInfoTest extends AbstractRuntimeEJBServicesTest {
private static final Object LOCK = new Object();
public static final int TIMEOUT = 4000;
@BeforeClass
public static void startRestService() {
RestService.start();
}
@Before
@Override
public void deployKieJar() {
if (kieJar == null) {
kieJar = archive.deployEJBComplianceKieJar().getIdentifier();
}
RuntimeManager manager = deploymentService.getRuntimeManager(kieJar);
RuntimeEngine engine = manager.getRuntimeEngine(ProcessInstanceIdContext.get());
engine.getKieSession().addEventListener(new DefaultProcessEventListener() {
@Override
public void afterProcessCompleted(ProcessCompletedEvent event) {
if (event.getProcessInstance().getProcessId().equals("org.jboss.qa.bpms.ThreadInfo")) {
synchronized (LOCK) {
LOCK.notifyAll();
}
}
}
@Override
public void afterNodeTriggered(ProcessNodeTriggeredEvent event) {
if (event.getNodeInstance().getNodeName().equals("User Task")) {
synchronized (LOCK) {
LOCK.notifyAll();
}
}
}
});
}
@AfterClass
public static void stopRestService() {
RestService.stop();
}
@Test
public void testTimerThreadInfo() throws Exception {
Long pid = startProcessInstance(THREAD_INFO_PROCESS_ID);
processService.signalProcessInstance(pid, "start", "timer");
waitTillPrepared(); //to make sure the timer is completed
Thread.sleep(TIMEOUT);
System.out.println("After LOCK");
Assertions.assertThat(hasNodeLeft(pid, "timer")).isTrue();
Assertions.assertThat(hasNodeLeft(pid, "Timer")).isTrue();
Collection<VariableDesc> stackTraceHistory = getStackTrace(pid);
Collection<VariableDesc> threadNameHistory = getThreadName(pid);
System.out.println("====stackTraceHistory====");
System.out.println(stackTraceHistory);
System.out.println("====stackTraceHistoryLast====");
System.out.println(stackTraceHistory.iterator().next().getNewValue());
System.out.println("====stackTraceHistorySize====");
System.out.println(stackTraceHistory.size());
System.out.println("====threadNameHistory====");
System.out.println(threadNameHistory);
System.out.println("====threadNameHistoryLast====");
System.out.println(threadNameHistory.iterator().next().getNewValue());
Assertions.assertThat(threadNameHistory.iterator().next().getNewValue()).startsWith("EJB");
}
@Test
public void testLogThreadInfo() throws Exception {
Long pid = startProcessInstance(THREAD_INFO_PROCESS_ID);
processService.signalProcessInstance(pid, "start", "log");
waitTillPrepared(); //to make sure the async task is completed
Thread.sleep(TIMEOUT);
Assertions.assertThat(hasNodeLeft(pid, "log")).isTrue();
Assertions.assertThat(hasNodeLeft(pid, "Log")).isTrue();
Collection<VariableDesc> stackTraceHistory = getStackTrace(pid);
Collection<VariableDesc> threadNameHistory = getThreadName(pid);
System.out.println("====stackTraceHistory====");
System.out.println(stackTraceHistory);
System.out.println("====stackTraceHistoryLast====");
System.out.println(stackTraceHistory.iterator().next().getNewValue());
System.out.println("====stackTraceHistorySize====");
System.out.println(stackTraceHistory.size());
System.out.println("====threadNameHistory====");
System.out.println(threadNameHistory);
System.out.println("====threadNameHistoryLast====");
System.out.println(threadNameHistory.iterator().next().getNewValue());
Assertions.assertThat(threadNameHistory.iterator().next().getNewValue()).startsWith("EJB");
}
@Test
public void testRESTThreadInfo() throws Exception {
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("url", RestService.PING_URL);
parameters.put("method", "GET");
Long pid = startProcessInstance(THREAD_INFO_PROCESS_ID, parameters);
processService.signalProcessInstance(pid, "start", "rest");
waitTillPrepared(); //to make sure the rest request is completed
Thread.sleep(TIMEOUT);
Assertions.assertThat(hasNodeLeft(pid, "rest")).isTrue();
Assertions.assertThat(hasNodeLeft(pid, "REST")).isTrue();
Collection<VariableDesc> result = runtimeDataService.getVariableHistory(pid, "result", new QueryContext());
Assertions.assertThat(result).hasSize(1);
Assertions.assertThat(result.iterator().next().getNewValue()).isEqualTo("pong");
Collection<VariableDesc> status = runtimeDataService.getVariableHistory(pid, "status", new QueryContext());
Assertions.assertThat(status).hasSize(1);
Assertions.assertThat(status.iterator().next().getNewValue()).isEqualTo("200");
Collection<VariableDesc> statusMsg = runtimeDataService.getVariableHistory(pid, "statusMsg", new QueryContext());
Assertions.assertThat(statusMsg).hasSize(1);
Assertions.assertThat(statusMsg.iterator().next().getNewValue()).contains("successfully completed Ok");
Collection<VariableDesc> stackTraceHistory = getStackTrace(pid);
Collection<VariableDesc> threadNameHistory = getThreadName(pid);
System.out.println("====stackTraceHistory====");
System.out.println(stackTraceHistory);
System.out.println("====stackTraceHistoryLast====");
System.out.println(stackTraceHistory.iterator().next().getNewValue());
System.out.println("====stackTraceHistorySize====");
System.out.println(stackTraceHistory.size());
System.out.println("====threadNameHistory====");
System.out.println(threadNameHistory);
System.out.println("====threadNameHistoryLast====");
System.out.println(threadNameHistory.iterator().next().getNewValue());
Assertions.assertThat(threadNameHistory.iterator().next().getNewValue()).startsWith("EJB");
}
@Test
public void testScriptThreadInfo() throws Exception {
Long pid = startProcessInstance(THREAD_INFO_PROCESS_ID);
processService.signalProcessInstance(pid, "start", "script");
waitTillPrepared(); //to make sure the script task is completed
Thread.sleep(TIMEOUT);
Assertions.assertThat(hasNodeLeft(pid, "script")).isTrue();
Assertions.assertThat(hasNodeLeft(pid, "Script")).isTrue();
Collection<VariableDesc> stackTraceHistory = getStackTrace(pid);
Collection<VariableDesc> threadNameHistory = getThreadName(pid);
System.out.println("====stackTraceHistory====");
System.out.println(stackTraceHistory);
System.out.println("====stackTraceHistoryLast====");
System.out.println(stackTraceHistory.iterator().next().getNewValue());
System.out.println("====stackTraceHistorySize====");
System.out.println(stackTraceHistory.size());
System.out.println("====threadNameHistory====");
System.out.println(threadNameHistory);
System.out.println("====threadNameHistoryLast====");
System.out.println(threadNameHistory.iterator().next().getNewValue());
Assertions.assertThat(threadNameHistory.iterator().next().getNewValue()).startsWith("EJB");
}
@Test
public void testHumanTaskThreadInfo() throws Exception {
Long pid = startProcessInstance(THREAD_INFO_PROCESS_ID);
processService.signalProcessInstance(pid, "start", "usertask");
waitTillPrepared(); //to make sure the task is created and available to start
Thread.sleep(TIMEOUT);
List<TaskSummary> taskSummaries = runtimeDataService.getTasksAssignedAsPotentialOwner("john", new QueryFilter());
Assertions.assertThat(taskSummaries).isNotNull().hasSize(1);
userTaskService.start(taskSummaries.get(0).getId(), "john");
userTaskService.complete(taskSummaries.get(0).getId(), "john", new HashMap<String, Object>());
Assertions.assertThat(hasNodeLeft(pid, "usertask")).isTrue();
Assertions.assertThat(hasNodeLeft(pid, "User Task")).isTrue();
Collection<VariableDesc> stackTraceHistory = getStackTrace(pid);
Collection<VariableDesc> threadNameHistory = getThreadName(pid);
System.out.println("====stackTraceHistory====");
System.out.println(stackTraceHistory);
System.out.println("====stackTraceHistoryLast====");
System.out.println(stackTraceHistory.iterator().next().getNewValue());
System.out.println("====stackTraceHistorySize====");
System.out.println(stackTraceHistory.size());
System.out.println("====threadNameHistory====");
System.out.println(threadNameHistory);
System.out.println("====threadNameHistoryLast====");
System.out.println(threadNameHistory.iterator().next().getNewValue());
//in this scenario we have to check the middle value, so it is the old one in the last history entry
Assertions.assertThat(threadNameHistory.iterator().next().getOldValue()).startsWith("EJB");
}
@Test
public void testRuleThreadInfo() throws Exception {
Long pid = startProcessInstance(THREAD_INFO_PROCESS_ID);
processService.signalProcessInstance(pid, "start", "rule");
waitTillPrepared(); //to make sure the rule is fired
Thread.sleep(TIMEOUT);
System.out.println("After LOCK");
Assertions.assertThat(hasNodeLeft(pid, "rule")).isTrue();
Assertions.assertThat(hasNodeLeft(pid, "Rule")).isTrue();
Collection<VariableDesc> stackTraceHistory = getStackTrace(pid);
Collection<VariableDesc> threadNameHistory = getThreadName(pid);
System.out.println("====stackTraceHistory====");
System.out.println(stackTraceHistory);
System.out.println("====stackTraceHistoryLast====");
System.out.println(stackTraceHistory.iterator().next().getNewValue());
System.out.println("====stackTraceHistorySize====");
System.out.println(stackTraceHistory.size());
System.out.println("====threadNameHistory====");
System.out.println(threadNameHistory);
System.out.println("====threadNameHistoryLast====");
System.out.println(threadNameHistory.iterator().next().getNewValue());
Assertions.assertThat(threadNameHistory.iterator().next().getNewValue()).startsWith("EJB");
}
@Test
public void testEmbeddedThreadInfo() throws Exception {
Long pid = startProcessInstance(THREAD_INFO_PROCESS_ID);
processService.signalProcessInstance(pid, "start", "embedded");
waitTillPrepared(); //to make sure the embedded process is completed
Thread.sleep(TIMEOUT);
System.out.println("After LOCK");
Assertions.assertThat(hasNodeLeft(pid, "embedded")).isTrue();
Assertions.assertThat(hasNodeLeft(pid, "Embedded")).isTrue();
Collection<VariableDesc> stackTraceHistory = getStackTrace(pid);
Collection<VariableDesc> threadNameHistory = getThreadName(pid);
System.out.println("====stackTraceHistory====");
System.out.println(stackTraceHistory);
System.out.println("====stackTraceHistoryLast====");
System.out.println(stackTraceHistory.iterator().next().getNewValue());
System.out.println("====stackTraceHistorySize====");
System.out.println(stackTraceHistory.size());
System.out.println("====threadNameHistory====");
System.out.println(threadNameHistory);
System.out.println("====threadNameHistoryLast====");
System.out.println(threadNameHistory.iterator().next().getNewValue());
Assertions.assertThat(threadNameHistory.iterator().next().getNewValue()).startsWith("EJB");
}
@Test
public void testSubProcessThreadInfo() throws Exception {
Long pid = startProcessInstance(THREAD_INFO_PROCESS_ID);
processService.signalProcessInstance(pid, "start", "subprocess");
waitTillPrepared(); //to make sure the subprocess is completed
Thread.sleep(TIMEOUT);
System.out.println("After LOCK");
Assertions.assertThat(hasNodeLeft(pid, "subprocess")).isTrue();
Assertions.assertThat(hasNodeLeft(pid, "HelloWorld_1.0")).isTrue();
Collection<VariableDesc> stackTraceHistory = getStackTrace(pid);
Collection<VariableDesc> threadNameHistory = getThreadName(pid);
System.out.println("====stackTraceHistory====");
System.out.println(stackTraceHistory);
System.out.println("====stackTraceHistoryLast====");
System.out.println(stackTraceHistory.iterator().next().getNewValue());
System.out.println("====stackTraceHistorySize====");
System.out.println(stackTraceHistory.size());
System.out.println("====threadNameHistory====");
System.out.println(threadNameHistory);
System.out.println("====threadNameHistoryLast====");
System.out.println(threadNameHistory.iterator().next().getNewValue());
Assertions.assertThat(threadNameHistory.iterator().next().getNewValue()).startsWith("EJB");
}
//========== PRIVATE METHODS ==========
private Collection<VariableDesc> getStackTrace(Long pid) {
QueryContext query = new QueryContext();
query.setOrderBy("id");
query.setAscending(false);
return runtimeDataService.getVariableHistory(pid, "stackTrace", query);
}
private Collection<VariableDesc> getThreadName(Long pid) {
QueryContext query = new QueryContext();
query.setOrderBy("id");
query.setAscending(false);
return runtimeDataService.getVariableHistory(pid, "threadName", query);
}
private void waitTillPrepared() throws InterruptedException {
synchronized (LOCK) {
LOCK.wait();
}
}
}