/*
* 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.integrationtests;
import static org.junit.Assert.*;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import org.drools.compiler.compiler.DroolsError;
import org.jbpm.test.util.AbstractBaseTest;
import org.junit.Test;
import org.kie.api.runtime.process.ProcessInstance;
import org.kie.internal.runtime.StatefulKnowledgeSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ProcessMultiThreadTest extends AbstractBaseTest {
private static final Logger logger = LoggerFactory.getLogger(ProcessMultiThreadTest.class);
@Test
public void testMultiThreadProcessInstanceSignalling() {
final int THREAD_COUNT = 2;
try {
boolean success = true;
final Thread[] t = new Thread[THREAD_COUNT];
builder.addProcessFromXml(new InputStreamReader( getClass().getResourceAsStream( "test_ProcessMultithreadEvent.rf" ) ) );
if (builder.getErrors().getErrors().length > 0) {
for (DroolsError error: builder.getErrors().getErrors()) {
logger.error(error.toString());
}
fail("Could not parse process");
}
StatefulKnowledgeSession session = createKieSession(true, builder.getPackage());
session = JbpmSerializationHelper.getSerialisedStatefulKnowledgeSession(session);
List<String> list = new ArrayList<String>();
session.setGlobal("list", list);
ProcessInstance processInstance = session.startProcess("org.drools.integrationtests.multithread");
final ProcessInstanceSignalRunner[] r = new ProcessInstanceSignalRunner[THREAD_COUNT];
for ( int i = 0; i < t.length; i++ ) {
r[i] = new ProcessInstanceSignalRunner(i, processInstance, "event" + (i+1));
t[i] = new Thread( r[i], "thread-" + i );
t[i].start();
}
for ( int i = 0; i < t.length; i++ ) {
t[i].join();
if ( r[i].getStatus() == ProcessInstanceSignalRunner.Status.FAIL ) {
success = false;
}
}
if ( !success ) {
fail( "Multithread test failed. Look at the stack traces for details. " );
}
assertEquals(2, list.size());
assertFalse(list.get(0).equals(list.get(1)));
assertEquals(ProcessInstance.STATE_COMPLETED, processInstance.getState());
} catch ( Exception e ) {
e.printStackTrace();
fail( "Should not raise any exception: " + e.getMessage() );
}
}
public static class ProcessInstanceSignalRunner implements Runnable {
private ProcessInstance processInstance;
private String type;
private Status status;
private int id;
public ProcessInstanceSignalRunner(int id, ProcessInstance processInstance, String type) {
this.id = id;
this.processInstance = processInstance;
this.type = type;
this.status = Status.SUCCESS;
}
public void run() {
try {
processInstance.signalEvent(type, null);
} catch ( Exception e ) {
this.status = Status.FAIL;
logger.warn("{} failed: {}",Thread.currentThread().getName(), e.getMessage());
}
}
public static enum Status {
SUCCESS, FAIL
}
public int getId() {
return id;
}
public Status getStatus() {
return status;
}
}
}