package org.jbpm.jbpm983; import org.jbpm.db.AbstractDbTestCase; import org.jbpm.graph.def.ActionHandler; import org.jbpm.graph.def.ProcessDefinition; import org.jbpm.graph.exe.ExecutionContext; import org.jbpm.graph.exe.ProcessInstance; /** * Concurrent process execution fails. * * @see <a href="https://jira.jboss.org/jira/browse/JBPM-983">JBPM-983</a> * @author Tom Baeyens */ public class JBPM983Test extends AbstractDbTestCase { protected void setUp() throws Exception { super.setUp(); ProcessDefinition subProcessDefinition = ProcessDefinition.parseXmlString(SUBPROCESS_XML); deployProcessDefinition(subProcessDefinition); ProcessDefinition processDefinition = ProcessDefinition.parseXmlString(PROCESS_XML); deployProcessDefinition(processDefinition); // [JBPM-2115] multiple threads not supported on DB2 < 9.7 // multiple threads not supported on HSQL String dialect = getHibernateDialect(); if (dialect.indexOf("DB2") == -1 && dialect.indexOf("HSQL") == -1) { jbpmConfiguration.getJobExecutor().setNbrOfThreads(4); } } protected void tearDown() throws Exception { jbpmConfiguration.getJobExecutor().setNbrOfThreads(1); super.tearDown(); } static final String SUBPROCESS_XML = "<?xml version='1.0'?>" + "<process-definition xmlns='urn:jbpm.org:jpdl-3.2' name='subprocess'>" + "<start-state name='start-state1'>" + " <description>start of the process</description>" + " <transition name='start-to-check' to='fileCheck'/>" + "</start-state>" + "<node name='fileCheck' async='true'>" + " <action name='action_filecheck' class='" + TestAction.class.getName() + "'>" + " </action>" + " <transition name='check-to-do' to='doWhatever'/>" + "</node>" + "<node name='doWhatever' async='true'>" + " <action name='action_do' class='" + TestAction.class.getName() + "'/>" + " <transition name='check-to-end' to='end-state-success'/>" + "</node>" + "<end-state name='end-state-success'>" + " <description>process finished normally</description>" + "</end-state>" + "</process-definition>"; static final String PROCESS_XML = "<?xml version='1.0'?>" + "<process-definition xmlns='urn:jbpm.org:jpdl-3.2' name='superprocess'>" + "<start-state name='start-state1'>" + " <description>start of the process</description>" + " <transition name='start-to-check' to='fileCheck'/>" + "</start-state>" + "" + "<node name='fileCheck' async='true'>" + " <action name='action_check' class='" + TestAction.class.getName() + "'/>" + " <transition name='check-to-fork' to='fork1'/>" + "</node>" + "<fork name='fork1'>" + " <transition name='toNode1' to='node1'/>" + " <transition name='toNode2' to='node2'/>" + "</fork>" + "<process-state name='node1' async='true'>" + " <sub-process name='subprocess'/>" + " <transition name='node1toJoin1' to='join1'/>" + "</process-state>" + "<process-state name='node2' async='true'>" + " <sub-process name='subprocess'/>" + " <transition name='node2toJoin1' to='join1'/>" + "</process-state>" + "<join name='join1'>" + " <transition name='joinToEnd' to='end-state-success'/>" + "</join>" + "<end-state name='end-state-success'>" + " <description>process finished normally</description>" + "</end-state>" + "</process-definition>"; static final int INSTANCE_COUNT = 10; public void testConcurrentJobs() throws Exception { long[] processInstanceIds = new long[INSTANCE_COUNT]; for (int i = 0; i < INSTANCE_COUNT; i++) { ProcessInstance processInstance = jbpmContext.newProcessInstanceForUpdate("superprocess"); processInstance.getContextInstance().setVariable("test", "true"); processInstance.signal(); processInstanceIds[i] = processInstance.getId(); } processJobs(); for (int i = 0; i < INSTANCE_COUNT; i++) { long piId = processInstanceIds[i]; ProcessInstance pi = jbpmContext.loadProcessInstance(piId); assertEquals("end-state-success", pi.getRootToken().getNode().getName()); } } public static class TestAction implements ActionHandler { private static final long serialVersionUID = 1L; public void execute(ExecutionContext executionContext) throws Exception { Thread.sleep(200); executionContext.leaveNode(); } } }