/*
* 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.kie.server.integrationtests.jbpm;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.kie.api.KieServices;
import org.kie.internal.executor.api.STATUS;
import org.kie.server.api.model.ReleaseId;
import org.kie.server.api.model.instance.JobRequestInstance;
import org.kie.server.api.model.instance.RequestInfoInstance;
import org.kie.server.api.exception.KieServicesException;
import org.kie.server.integrationtests.category.Smoke;
import static org.junit.Assert.*;
import static org.hamcrest.core.AnyOf.*;
import static org.hamcrest.core.IsEqual.*;
import org.kie.server.integrationtests.shared.KieServerDeployer;
import org.kie.server.integrationtests.shared.KieServerSynchronization;
public class JobServiceIntegrationTest extends JbpmKieServerBaseIntegrationTest {
private static ReleaseId releaseId = new ReleaseId("org.kie.server.testing", "definition-project",
"1.0.0.Final");
protected static final String BUSINESS_KEY = "test key";
protected static final String PRINT_OUT_COMMAND = "org.jbpm.executor.commands.PrintOutCommand";
protected static final String LOG_CLEANUP_COMMAND = "org.jbpm.executor.commands.LogCleanupCommand";
@BeforeClass
public static void buildAndDeployArtifacts() {
KieServerDeployer.buildAndDeployCommonMavenParent();
KieServerDeployer.buildAndDeployMavenProject(ClassLoader.class.getResource("/kjars-sources/definition-project").getFile());
kieContainer = KieServices.Factory.get().newKieContainer(releaseId);
createContainer(CONTAINER_ID, releaseId);
}
@Before
public void finishAllJobs() throws Exception {
List<String> status = new ArrayList<String>();
status.add(STATUS.QUEUED.toString());
status.add(STATUS.RUNNING.toString());
status.add(STATUS.RETRYING.toString());
List<RequestInfoInstance> requests = jobServicesClient.getRequestsByStatus(status, 0, 100);
for (RequestInfoInstance instance : requests) {
jobServicesClient.cancelRequest(instance.getId());
KieServerSynchronization.waitForJobToFinish(jobServicesClient, instance.getId());
}
}
@Override
protected void addExtraCustomClasses(Map<String, Class<?>> extraClasses) throws Exception {
extraClasses.put(PERSON_CLASS_NAME, Class.forName(PERSON_CLASS_NAME, true, kieContainer.getClassLoader()));
}
@Test
public void testScheduleViewAndCancelJob() {
Calendar tomorrow = Calendar.getInstance();
tomorrow.add(Calendar.DATE, 1);
JobRequestInstance jobRequestInstance = createJobRequestInstance();
jobRequestInstance.setScheduledDate(tomorrow.getTime());
Long jobId = jobServicesClient.scheduleRequest(jobRequestInstance);
assertNotNull(jobId);
assertTrue( jobId.longValue() > 0);
RequestInfoInstance jobRequest = jobServicesClient.getRequestById(jobId, false, false);
RequestInfoInstance expected = createExpectedRequestInfoInstance(jobId, STATUS.QUEUED);
assertRequestInfoInstance(expected, jobRequest);
assertNotNull(jobRequest.getScheduledDate());
jobServicesClient.cancelRequest(jobId);
jobRequest = jobServicesClient.getRequestById(jobId, false, false);
expected.setStatus(STATUS.CANCELLED.toString());
assertRequestInfoInstance(expected, jobRequest);
}
@Test
@Category(Smoke.class)
public void testScheduleAndRunJob() throws Exception {
JobRequestInstance jobRequestInstance = createJobRequestInstance();
Long jobId = jobServicesClient.scheduleRequest(jobRequestInstance);
assertNotNull(jobId);
assertTrue( jobId.longValue() > 0);
RequestInfoInstance jobRequest = jobServicesClient.getRequestById(jobId, false, false);
assertNotNull(jobRequest);
assertEquals(jobId, jobRequest.getId());
assertEquals(BUSINESS_KEY, jobRequest.getBusinessKey());
assertThat(jobRequest.getStatus(),anyOf(
equalTo(STATUS.QUEUED.toString()),
equalTo(STATUS.RUNNING.toString()),
equalTo(STATUS.DONE.toString())));
assertEquals(PRINT_OUT_COMMAND, jobRequest.getCommandName());
KieServerSynchronization.waitForJobToFinish(jobServicesClient, jobId);
jobRequest = jobServicesClient.getRequestById(jobId, false, false);
assertNotNull(jobRequest);
assertEquals(jobId, jobRequest.getId());
assertEquals(BUSINESS_KEY, jobRequest.getBusinessKey());
assertEquals(STATUS.DONE.toString(), jobRequest.getStatus());
assertEquals(PRINT_OUT_COMMAND, jobRequest.getCommandName());
}
@Test
public void testScheduleAndRunJobWithCustomTypeFromContainer() throws Exception {
int currentNumberOfDone = jobServicesClient.getRequestsByContainer(CONTAINER_ID, Collections.singletonList(STATUS.DONE.toString()), 0, 100).size();
Class<?> personClass = Class.forName(PERSON_CLASS_NAME, true, kieContainer.getClassLoader());
Map<String, Object> data = new HashMap<String, Object>();
data.put("businessKey", BUSINESS_KEY);
data.put("person", createPersonInstance(USER_JOHN));
JobRequestInstance jobRequestInstance = new JobRequestInstance();
jobRequestInstance.setCommand(PRINT_OUT_COMMAND);
jobRequestInstance.setData(data);
Long jobId = jobServicesClient.scheduleRequest(CONTAINER_ID, jobRequestInstance);
assertNotNull(jobId);
assertTrue( jobId.longValue() > 0);
RequestInfoInstance jobRequest = jobServicesClient.getRequestById(jobId, false, false);
assertNotNull(jobRequest);
assertEquals(jobId, jobRequest.getId());
assertEquals(BUSINESS_KEY, jobRequest.getBusinessKey());
assertThat(jobRequest.getStatus(),anyOf(
equalTo(STATUS.QUEUED.toString()),
equalTo(STATUS.RUNNING.toString()),
equalTo(STATUS.DONE.toString())));
assertEquals(PRINT_OUT_COMMAND, jobRequest.getCommandName());
KieServerSynchronization.waitForJobToFinish(jobServicesClient, jobId);
jobRequest = jobServicesClient.getRequestById(jobId, false, true);
assertNotNull(jobRequest);
assertEquals(jobId, jobRequest.getId());
assertEquals(BUSINESS_KEY, jobRequest.getBusinessKey());
assertEquals(STATUS.DONE.toString(), jobRequest.getStatus());
assertEquals(PRINT_OUT_COMMAND, jobRequest.getCommandName());
Map<String, Object> requestData = jobRequest.getData();
assertNotNull(requestData);
assertEquals(3, requestData.size());
assertTrue(requestData.containsKey("person"));
assertTrue(requestData.containsKey("businessKey"));
assertTrue(requestData.containsKey("deploymentId"));
assertTrue(personClass.isAssignableFrom(requestData.get("person").getClass()));
assertTrue(String.class.isAssignableFrom(requestData.get("businessKey").getClass()));
assertTrue(String.class.isAssignableFrom(requestData.get("deploymentId").getClass()));
assertEquals(USER_JOHN, valueOf(requestData.get("person"), "name"));
assertEquals(CONTAINER_ID, requestData.get("deploymentId"));
assertEquals(BUSINESS_KEY, requestData.get("businessKey"));
Map<String, Object> responseData = jobRequest.getResponseData();
assertNotNull(responseData);
assertEquals(0, responseData.size());
List<RequestInfoInstance> result = jobServicesClient.getRequestsByContainer(CONTAINER_ID, Arrays.asList(STATUS.QUEUED.name()), 0, 100);
assertNotNull(result);
assertEquals(0, result.size());
result = jobServicesClient.getRequestsByContainer(CONTAINER_ID, Arrays.asList(STATUS.DONE.name()), 0, 100);
assertNotNull(result);
assertEquals(1 + currentNumberOfDone, result.size());
}
@Test
public void testScheduleSearchByStatusAndCancelJob() {
int currentNumberOfCancelled = jobServicesClient.getRequestsByStatus(Collections.singletonList(STATUS.CANCELLED.toString()), 0, 100).size();
Calendar tomorrow = Calendar.getInstance();
tomorrow.add(Calendar.DATE, 1);
JobRequestInstance jobRequestInstance = createJobRequestInstance();
jobRequestInstance.setScheduledDate(tomorrow.getTime());
Long jobId = jobServicesClient.scheduleRequest(jobRequestInstance);
assertNotNull(jobId);
assertTrue( jobId.longValue() > 0);
List<String> status = new ArrayList<String>();
status.add(STATUS.QUEUED.toString());
List<RequestInfoInstance> result = jobServicesClient.getRequestsByStatus(status, 0, 100);
assertNotNull(result);
assertEquals(1, result.size());
RequestInfoInstance jobRequest = result.get(0);
RequestInfoInstance expected = createExpectedRequestInfoInstance(jobId, STATUS.QUEUED);
assertRequestInfoInstance(expected, jobRequest);
assertNotNull(jobRequest.getScheduledDate());
jobServicesClient.cancelRequest(jobId);
result = jobServicesClient.getRequestsByStatus(status, 0, 100);
assertNotNull(result);
assertEquals(0, result.size());
// clear status to search only for canceled
status.clear();
status.add(STATUS.CANCELLED.toString());
result = jobServicesClient.getRequestsByStatus(status, 0, 100);
assertNotNull(result);
assertEquals(1 + currentNumberOfCancelled, result.size());
}
@Test
public void testScheduleAndRequeueJob() throws Exception {
String command = "org.jbpm.executor.commands.DelayedPrintOutCommand";
Map<String, Object> data = new HashMap<String, Object>();
data.put("businessKey", BUSINESS_KEY);
data.put("delay", "wrong-value");
data.put("retries", 0);
JobRequestInstance jobRequestInstance = new JobRequestInstance();
jobRequestInstance.setCommand(command);
jobRequestInstance.setData(data);
Long jobId = jobServicesClient.scheduleRequest(jobRequestInstance);
assertNotNull(jobId);
assertTrue( jobId.longValue() > 0);
RequestInfoInstance jobRequest = jobServicesClient.getRequestById(jobId, false, false);
assertNotNull(jobRequest);
assertEquals(jobId, jobRequest.getId());
assertEquals(BUSINESS_KEY, jobRequest.getBusinessKey());
assertThat(jobRequest.getStatus(),anyOf(
equalTo(STATUS.QUEUED.toString()),
equalTo(STATUS.RUNNING.toString()),
equalTo(STATUS.ERROR.toString())));
assertEquals(command, jobRequest.getCommandName());
KieServerSynchronization.waitForJobToFinish(jobServicesClient, jobId);
RequestInfoInstance expected = createExpectedRequestInfoInstance(jobId, STATUS.ERROR);
expected.setCommandName(command);
jobRequest = jobServicesClient.getRequestById(jobId, false, false);
assertRequestInfoInstance(expected, jobRequest);
jobServicesClient.requeueRequest(jobId);
jobRequest = jobServicesClient.getRequestById(jobId, false, false);
expected.setStatus(STATUS.QUEUED.toString());
assertRequestInfoInstance(expected, jobRequest);
}
@Test
public void testScheduleSearchByKeyJob() throws Exception {
int currentNumberOfRequests = jobServicesClient.getRequestsByBusinessKey(BUSINESS_KEY, 0, 100).size();
Calendar tomorrow = Calendar.getInstance();
tomorrow.add(Calendar.DATE, 1);
JobRequestInstance jobRequestInstance = createJobRequestInstance();
jobRequestInstance.setScheduledDate(tomorrow.getTime());
Long jobId = jobServicesClient.scheduleRequest(jobRequestInstance);
assertNotNull(jobId);
assertTrue(jobId.longValue() > 0);
List<RequestInfoInstance> result = jobServicesClient.getRequestsByBusinessKey(BUSINESS_KEY, 0, 100);
assertNotNull(result);
assertEquals(1 + currentNumberOfRequests, result.size());
List<RequestInfoInstance> queuedJobs = result.stream().
filter(n -> n.getStatus().equals(STATUS.QUEUED.name())).collect(Collectors.toList());
assertNotNull(queuedJobs);
assertEquals(1, queuedJobs.size());
RequestInfoInstance expected = createExpectedRequestInfoInstance(jobId, STATUS.QUEUED);
RequestInfoInstance queuedJob = queuedJobs.get(0);
assertRequestInfoInstance(expected, queuedJob);
result = jobServicesClient.getRequestsByBusinessKey(BUSINESS_KEY, Arrays.asList(STATUS.QUEUED.name()), 0, 100);
assertNotNull(result);
assertEquals(1, result.size());
assertRequestInfoInstance(expected, result.get(0));
jobServicesClient.cancelRequest(jobId);
}
@Test
public void testScheduleSearchByCommandCancelJob() throws Exception {
String firstCommand = PRINT_OUT_COMMAND;
String secondCommand = LOG_CLEANUP_COMMAND;
int originalNumberOfSecondCommands = jobServicesClient.getRequestsByCommand(secondCommand, 0, 100).size();
Map<String, Object> data = new HashMap<String, Object>();
data.put("businessKey", BUSINESS_KEY);
Calendar tomorrow = Calendar.getInstance();
tomorrow.add(Calendar.DATE, 1);
JobRequestInstance jobRequestInstance = new JobRequestInstance();
jobRequestInstance.setCommand(firstCommand);
jobRequestInstance.setData(data);
jobRequestInstance.setScheduledDate(tomorrow.getTime());
// Executing fist command.
Long jobId = jobServicesClient.scheduleRequest(jobRequestInstance);
assertNotNull(jobId);
assertTrue( jobId.longValue() > 0);
// Number of commands should be same as we are checking second command.
int numberOfSecondCommands = jobServicesClient.getRequestsByCommand(secondCommand, 0, 100).size();
assertEquals(originalNumberOfSecondCommands, numberOfSecondCommands);
jobServicesClient.cancelRequest(jobId);
jobRequestInstance = new JobRequestInstance();
jobRequestInstance.setCommand(secondCommand);
jobRequestInstance.setData(data);
jobRequestInstance.setScheduledDate(tomorrow.getTime());
// Executing second command.
jobId = jobServicesClient.scheduleRequest(jobRequestInstance);
assertNotNull(jobId);
assertTrue( jobId.longValue() > 0);
// Number of commands should raise.
numberOfSecondCommands = jobServicesClient.getRequestsByCommand(secondCommand, 0, 100).size();
assertEquals(1 + originalNumberOfSecondCommands, numberOfSecondCommands);
numberOfSecondCommands = jobServicesClient.getRequestsByCommand(secondCommand, Arrays.asList(STATUS.QUEUED.name()), 0, 100).size();
assertEquals(1, numberOfSecondCommands);
jobServicesClient.cancelRequest(jobId);
}
@Test
public void testScheduleViewUpdateDataAndCancelJob() {
Calendar tomorrow = Calendar.getInstance();
tomorrow.add(Calendar.DATE, 1);
Map<String, Object> data = new HashMap<String, Object>();
data.put("businessKey", BUSINESS_KEY);
data.put("customValue", "just a simple value");
data.put("processInstanceId", 1234);
JobRequestInstance jobRequestInstance = createJobRequestInstance();
jobRequestInstance.setScheduledDate(tomorrow.getTime());
jobRequestInstance.setData(data);
Long jobId = jobServicesClient.scheduleRequest(jobRequestInstance);
assertNotNull(jobId);
assertTrue( jobId.longValue() > 0);
RequestInfoInstance jobRequest = jobServicesClient.getRequestById(jobId, false, true);
RequestInfoInstance expected = createExpectedRequestInfoInstance(jobId, STATUS.QUEUED);
assertRequestInfoInstance(expected, jobRequest);
assertNotNull(jobRequest.getScheduledDate());
Map<String, Object> jobsData = jobRequest.getData();
assertNotNull(jobsData);
assertEquals("just a simple value", jobsData.get("customValue"));
assertEquals(1234, jobsData.get("processInstanceId"));
Map<String, Object> updates = new HashMap<>();
updates.put("customValue", "updated string");
jobServicesClient.updateRequestData(jobId, null, updates);
jobRequest = jobServicesClient.getRequestById(jobId, false, true);
jobsData = jobRequest.getData();
assertNotNull(jobsData);
assertEquals("updated string", jobsData.get("customValue"));
assertEquals(1234, jobsData.get("processInstanceId"));
List<RequestInfoInstance> processRequests = jobServicesClient.getRequestsByProcessInstance(1234L, Arrays.asList(STATUS.QUEUED.name()), 0, 100);
assertNotNull(processRequests);
assertEquals(1, processRequests.size());
jobServicesClient.cancelRequest(jobId);
jobRequest = jobServicesClient.getRequestById(jobId, false, false);
expected.setStatus(STATUS.CANCELLED.toString());
assertRequestInfoInstance(expected, jobRequest);
}
private void assertRequestInfoInstance(RequestInfoInstance expected, RequestInfoInstance actual) {
assertNotNull(actual);
assertEquals(expected.getId(), actual.getId());
assertEquals(expected.getBusinessKey(), actual.getBusinessKey());
assertEquals(expected.getStatus(), actual.getStatus());
assertEquals(expected.getCommandName(), actual.getCommandName());
}
private RequestInfoInstance createExpectedRequestInfoInstance(Long jobId, STATUS expected) {
return RequestInfoInstance.builder()
.id(jobId)
.businessKey(BUSINESS_KEY)
.status(expected.toString())
.command(PRINT_OUT_COMMAND)
.build();
}
private JobRequestInstance createJobRequestInstance() {
Map<String, Object> data = new HashMap<>();
data.put("businessKey", BUSINESS_KEY);
JobRequestInstance jobRequestInstance = new JobRequestInstance();
jobRequestInstance.setCommand(PRINT_OUT_COMMAND);
jobRequestInstance.setData(data);
return jobRequestInstance;
}
@Test
public void testExecutorServiceDisabling() throws Exception {
String command = "invalidCommand";
Map<String, Object> data = new HashMap<String, Object>();
data.put("businessKey", BUSINESS_KEY);
Calendar tomorrow = Calendar.getInstance();
tomorrow.add(Calendar.DATE, 1);
JobRequestInstance jobRequestInstance = new JobRequestInstance();
jobRequestInstance.setCommand(command);
jobRequestInstance.setData(data);
jobRequestInstance.setScheduledDate(tomorrow.getTime());
// Executing fist command.
try {
jobServicesClient.scheduleRequest(jobRequestInstance);
} catch (Exception e){
assertTrue(e instanceof KieServicesException);
assertTrue(e.getMessage().contains("Invalid command type"));
}
}
@Test
public void testScheduleAndRunJobWithoutData() throws Exception {
JobRequestInstance jobRequestInstance = new JobRequestInstance();
jobRequestInstance.setCommand(PRINT_OUT_COMMAND);
Long jobId = jobServicesClient.scheduleRequest(jobRequestInstance);
assertNotNull(jobId);
assertTrue( jobId.longValue() > 0);
RequestInfoInstance jobRequest = jobServicesClient.getRequestById(jobId, false, false);
assertNotNull(jobRequest);
assertEquals(jobId, jobRequest.getId());
assertThat(jobRequest.getStatus(),anyOf(
equalTo(STATUS.QUEUED.toString()),
equalTo(STATUS.RUNNING.toString()),
equalTo(STATUS.DONE.toString())));
assertEquals(PRINT_OUT_COMMAND, jobRequest.getCommandName());
KieServerSynchronization.waitForJobToFinish(jobServicesClient, jobId);
jobRequest = jobServicesClient.getRequestById(jobId, false, false);
assertNotNull(jobRequest);
assertEquals(jobId, jobRequest.getId());
assertEquals(STATUS.DONE.toString(), jobRequest.getStatus());
assertEquals(PRINT_OUT_COMMAND, jobRequest.getCommandName());
}
}