/* * JBoss, Home of Professional Open Source * Copyright 2005, JBoss Inc., and individual contributors as indicated * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jbpm.jbpm1072; import org.jbpm.db.AbstractDbTestCase; import org.jbpm.graph.def.ActionHandler; import org.jbpm.graph.def.Event; import org.jbpm.graph.def.EventCallback; import org.jbpm.graph.def.ProcessDefinition; import org.jbpm.graph.exe.ExecutionContext; import org.jbpm.graph.exe.ProcessInstance; import org.jbpm.job.executor.JobExecutor; /** * Concurrent job executors can process the same job in parallel. The test * simulates multiple nodes in the network processing a common job set. The key * setting is to give each job executor a different name; normally, a job * executor is named after the node's inet address * * @see <a href="https://jira.jboss.org/jira/browse/JBPM-1072">JBPM-1072</a> * @author Jiri Pechanec * @author Alejandro Guizar */ public class JBPM1072Test extends AbstractDbTestCase { private static final int JOB_EXECUTOR_COUNT = 4; private JobExecutor[] jobExecutors = new JobExecutor[JOB_EXECUTOR_COUNT]; private static final String PROCESS_DEFINITION = "<process-definition name='jbpm1072'>" + " <event type='process-end'>" + " <action expression='#{eventCallback.processEnd}' />" + " </event>" + " <start-state name='start-state1'>" + " <transition to='Service 1'></transition>" + " </start-state>" + " <node name='Service 1' async='true'>" + " <action class='" + Counter.class.getName() + "' />" + " <transition to='Service 2' />" + " </node>" + " <node name='Service 2' async='true'>" + " <action class='" + Counter.class.getName() + "' />" + " <transition to='end-state1' />" + " </node>" + " <end-state name='end-state1' />" + "</process-definition>"; protected void setUp() throws Exception { super.setUp(); ProcessDefinition processDefinition = ProcessDefinition.parseXmlString(PROCESS_DEFINITION); deployProcessDefinition(processDefinition); startJobExecutors(); } protected void tearDown() throws Exception { stopJobExecutors(); EventCallback.clear(); super.tearDown(); } public void testMultipleJobExecutors() { // multiple job executors not supported on hsql if (getHibernateDialect().indexOf("HSQL") != -1) return; // kick off process instance ProcessInstance processInstance = jbpmContext.newProcessInstanceForUpdate("jbpm1072"); processInstance.getContextInstance().setVariable("eventCallback", new EventCallback()); processInstance.signal(); closeJbpmContext(); try { EventCallback.waitForEvent(Event.EVENTTYPE_PROCESS_END); } finally { createJbpmContext(); } processInstance = jbpmContext.loadProcessInstance(processInstance.getId()); Integer count = (Integer) processInstance.getContextInstance().getVariable("count"); assertEquals(2, count.intValue()); } private void startJobExecutors() { for (int i = 0; i < jobExecutors.length; i++) { JobExecutor jobExecutor = (JobExecutor) jbpmContext.getObjectFactory().createObject("jbpm.job.executor"); if (i > 0) assert jobExecutor != jobExecutors[i - 1] : "expected " + jobExecutor + " to be unique"; jobExecutor.setName(jobExecutor.getName() + '/' + i); jobExecutor.start(); jobExecutors[i] = jobExecutor; } } private void stopJobExecutors() { for (int i = jobExecutors.length - 1; i >= 0; i--) { try { jobExecutors[i].stopAndJoin(); } catch (InterruptedException e) { // continue to next executor } } } public static class Counter implements ActionHandler { private static final long serialVersionUID = 1L; public void execute(ExecutionContext exeContext) throws Exception { Integer count = (Integer) exeContext.getVariable("count"); exeContext.setVariable("count", new Integer(count != null ? count.intValue() + 1 : 1)); exeContext.leaveNode(); } } }