0 Replies Latest reply on Feb 19, 2008 5:14 PM by pathourigan

    Scalabilty of event-driven state transition signalling

    pathourigan

      Hi Folks,

      We have an application based on the JBPM framework that acts as an orchestration engine for one of our clients. Currently we are investigating an issue whereby the round trip time for a request is scaling in a linear fashion. Effectively for 1 thread we receive a round trip time of N secs, for 2 threads its approx 2N secs, 3 threads is 3N secs, etc. as you could imagine this is not ideal ;)

      In order to determine the problem we went back to first principles and derived a threaded test case using junit to simulate our issue that operates free of any app server container.

      One of the aread that we focused in on is the token#signal method, specifically when it has an event to process behind that signal. We also focussed in on the JBPMContext#close method.

      Firstly I have a mini project that shows poor performance of an event-driven state signal when run in a multi-threaded test. I based the unit test on the test cases written in chapter 3, http://docs.jboss.com/jbpm/v3/userguide/tutorial.html#helloworldexample and http://docs.jboss.com/jbpm/v3/userguide/tutorial.html#databaseexample.


      Attached at the bottom of the post is the code and configuration files necessary to run the tests. If you require me to zip the eclispe project workspace and send to you please just ask.

      Effectively the results show that when the test is run for the persistent, state signal, event driven test, we seem to get results that show the same type of problem we are experiencing in our orchestration application.

      We see the signal method sometimes take an extended period of time. I realise the signal method is a blocking method but should it happen to this extent?



      Code-------



      /*
       * Created on 15-Feb-08
       */
      import com.clarkware.junitperf.*;
      import junit.framework.Test;
      
      /**
       * @author patrick.hourigan
       */
      public class ConcurrentTestRunner {
      
       private static String testCaseType;
       private static String testSuiteType;
       private static int maxUsers;
      
       public static Test suite() {
      
       int test = 1;
       if (testSuiteType.equalsIgnoreCase("y")
       && testCaseType.equalsIgnoreCase("y")) {
       test = 4;
       }
      
       if (testSuiteType.equalsIgnoreCase("y")
       && testCaseType.equalsIgnoreCase("n")) {
       test = 3;
       }
      
       if (testSuiteType.equalsIgnoreCase("n")
       && testCaseType.equalsIgnoreCase("y")) {
       test = 2;
      
       }
      
       Test testCase = null;
       Test loadTest = null;
      
       switch (test) {
      
       case (1) :
       /** Test for non persistent, simple state signalling */
       testCase = new TestSimpleStateTransition("testSimpleState");
       loadTest = new LoadTest(testCase, maxUsers);
       break;
       case (2) :
       /** Test for non persistent, event driven state signalling */
       testCase = new TestSimpleStateTransition("testEventDrivenState");
       loadTest = new LoadTest(testCase, maxUsers);
       break;
       case (3) :
       /** Test for persistent, simple state signalling */
       testCase =
       new TestDbPersistentStateTransition("testSimpleState");
       loadTest = new LoadTest(testCase, maxUsers);
       break;
       case (4) :
       /** Test for persistent event driven state signalling */
       testCase =
       new TestDbPersistentStateTransition("testEventDrivenState");
       loadTest = new LoadTest(testCase, maxUsers);
       break;
       }
      
       return loadTest;
       }
      
       public static void main(String[] args) {
       // This is the thread counter. Change to set to the concurrency count of a test.
       maxUsers = Integer.valueOf(args[0]).intValue();
      
       testSuiteType = args[1];
       testCaseType = args[2];
      
       junit.textui.TestRunner.run(suite());
       }
      }
      


      /*
       * Created on 15-Feb-08
       */
      
      import java.util.List;
      
      import junit.framework.TestCase;
      
      import org.jbpm.JbpmConfiguration;
      import org.jbpm.JbpmContext;
      import org.jbpm.db.GraphSession;
      import org.jbpm.graph.def.ProcessDefinition;
      import org.jbpm.graph.exe.ProcessInstance;
      import org.jbpm.graph.exe.Token;
      
      /**
       * @author patrick.hourigan
       */
      public class TestDbPersistentStateTransition extends TestCase {
      
       static JbpmConfiguration jbpmConfiguration = null;
      
       static {
       jbpmConfiguration = getJBPMConfiguration();
      
       // Stupid way of quickly assesing when to not
       // recreate the schema a break the journal on db400.
       // If running on db400 manually run the RunOnceTestFixture class
       // and journal the tables
       String reCreate = System.getProperty("recreateDb");
       boolean runningOnDB400 = (reCreate == null) ? false : true;
      
       if (!runningOnDB400) {
       System.out.println("About to re-create the database");
       RunOnceTestFixture.setUpDB();
       }
      
       deployProcessDefinitions();
       }
      
       public TestDbPersistentStateTransition() {
       super();
       }
      
       public static JbpmConfiguration getJBPMConfiguration() {
       // First we create a JbpmConfiguration statically. One JbpmConfiguration
       // can be used for all threads in the system, that is why we can safely
       // make it static.
      
       // A jbpm-context mechanism separates the jbpm core
       // engine from the services that jbpm uses from
       // the environment.
      
       JbpmConfiguration config =
       JbpmConfiguration
       .parseXmlString(
       "<jbpm-configuration>"
       + " <jbpm-context>"
       + " <service name=\"persistence\" factory=\"org.jbpm.persistence.db.DbPersistenceServiceFactory\" />"
       + " <service name=\"message\" factory=\"org.jbpm.msg.db.DbMessageServiceFactory\" />"
       + " <service name=\"scheduler\" factory=\"org.jbpm.scheduler.db.DbSchedulerServiceFactory\" />"
       + " <service name=\"logging\" factory=\"org.jbpm.logging.db.DbLoggingServiceFactory\" />"
       + " <service name=\"authentication\" factory=\"org.jbpm.security.authentication.DefaultAuthenticationServiceFactory\" />"
       + " </jbpm-context>"
       +
      
       // Also all the resource files that are used by jbpm are
       // referenced from the jbpm.cfg.xml
      
       " <string name='resource.hibernate.cfg.xml' "
       + " value='hibernate.cfg.xml' />"
       + " <string name='resource.business.calendar' "
       + " value='org/jbpm/calendar/jbpm.business.calendar.properties' />"
       + " <string name='resource.default.modules' "
       + " value='org/jbpm/graph/def/jbpm.default.modules.properties' />"
       + " <string name='resource.converter' "
       + " value='org/jbpm/db/hibernate/jbpm.converter.properties' />"
       + " <string name='resource.action.types' "
       + " value='org/jbpm/graph/action/action.types.xml' />"
       + " <string name='resource.node.types' "
       + " value='org/jbpm/graph/node/node.types.xml' />"
       + " <string name='resource.varmapping' "
       + " value='org/jbpm/context/exe/jbpm.varmapping.xml' />"
       + "</jbpm-configuration>");
      
       return config;
      
       }
      
       public TestDbPersistentStateTransition(String arg0) {
       super(arg0);
       }
      
       public static void deployProcessDefinitions() {
       // This test shows a process definition and one execution
       // of the process definition. The process definition has
       // 3 nodes: an unnamed start-state, a state 's' and an
       // end-state named 'end'.
       ProcessDefinition simpleProcDefn =
       ProcessDefinition.parseXmlString(
       "<process-definition name='hello world'>"
       + " <start-state name='start'>"
       + " <transition to='s' />"
       + " </start-state>"
       + " <state name='s'>"
       + " <transition to='end' />"
       + " </state>"
       + " <end-state name='end' />"
       + "</process-definition>");
      
       // This test shows aprocess definition with a and one execution
       // of the process definition. The process definition has
       // 3 nodes: an unnamed start-state, a state 's' and an
       // end-state named 'end'.
       ProcessDefinition eventDrivenProcDefn =
       ProcessDefinition.parseXmlString(
       "<process-definition name='hello world with events'>"
       + " <start-state name='start'>"
       + " <transition to='s' />"
       + " </start-state>"
       + " <state name='s'>"
       + " <event type=\"node-enter\">"
       + " <action class=\"SimpleEventDrivenActionHandler\" config-type=\"bean\" />"
       + " </event>"
       + " <transition to='end' />"
       + " </state>"
       + " <end-state name='end' />"
       + "</process-definition>");
      
       // Lookup the pojo persistence context-builder that is configured above
       JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
       try {
       // Deploy the process definition in the database
       jbpmContext.deployProcessDefinition(simpleProcDefn);
       jbpmContext.deployProcessDefinition(eventDrivenProcDefn);
      
       } finally {
       // Tear down the pojo persistence context.
       // This includes flush the SQL for inserting the process definition
       // to the database.
       jbpmContext.close();
       }
       }
      
       public void testSimpleState() {
       long rtt = System.currentTimeMillis();
      
       // Lookup the pojo persistence context-builder that is configured above
       JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
       try {
      
       GraphSession graphSession = jbpmContext.getGraphSession();
      
       ProcessDefinition processDefinition =
       graphSession.findLatestProcessDefinition(
       "hello world");
      
       ProcessInstance processInstance =
       new ProcessInstance(processDefinition);
      
       Token token = processInstance.getRootToken();
       assertEquals("start", token.getNode().getName());
      
       // Let's start the process execution
       long st = System.currentTimeMillis();
       token.signal();
       long runTime = System.currentTimeMillis() - st;
       System.out.println(
       Thread.currentThread().getName()
       + ": Signal A : RunTime "
       + (runTime)
       + " ms");
      
       assertEquals("s", token.getNode().getName());
      
       jbpmContext.save(processInstance);
      
       } finally {
       long st = System.currentTimeMillis();
       jbpmContext.close();
       long runTime = System.currentTimeMillis() - st;
       System.out.println(
       Thread.currentThread().getName()
       + ": jBPM Context Close : RunTime "
       + (runTime)
       + " ms");
      
       }
      
       System.out.println(
       Thread.currentThread().getName()
       + this.getName()
       + ": Round Trip Time "
       + (System.currentTimeMillis() - rtt)
       + " ms");
       }
      
       public void testEventDrivenState() {
       long rtt = System.currentTimeMillis();
      
       // Lookup the pojo persistence context-builder that is configured above
       JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
       try {
      
       GraphSession graphSession = jbpmContext.getGraphSession();
      
       ProcessDefinition processDefinition =
       graphSession.findLatestProcessDefinition("hello world with events");
      
       ProcessInstance processInstance =
       new ProcessInstance(processDefinition);
      
       Token token = processInstance.getRootToken();
       assertEquals("start", token.getNode().getName());
      
       // Let's start the process execution
       long st = System.currentTimeMillis();
       token.signal();
       long runTime = System.currentTimeMillis() - st;
       System.out.println(
       Thread.currentThread().getName()
       + ": Signal A : RunTime "
       + (runTime)
       + " ms");
      
       assertEquals("s", token.getNode().getName());
      
       jbpmContext.save(processInstance);
      
       } finally {
       long st = System.currentTimeMillis();
       jbpmContext.close();
       long runTime = System.currentTimeMillis() - st;
       System.out.println(
       Thread.currentThread().getName()
       + ": jBPM Context Close : RunTime "
       + (runTime)
       + " ms");
      
       }
      
       System.out.println(
       Thread.currentThread().getName()
       + this.getName()
       + ": Round Trip Time "
       + (System.currentTimeMillis() - rtt)
       + " ms");
       }
      }
      


      
      /*
       * Created on 15-Feb-08
       */
      import junit.framework.TestCase;
      
      import org.jbpm.graph.def.ProcessDefinition;
      import org.jbpm.graph.exe.ProcessInstance;
      import org.jbpm.graph.exe.Token;
      
      /**
       * A Simple test to show how state transistions in jBPM operate.
       *
       * @author patrick.hourigan
       */
      public class TestSimpleStateTransition extends TestCase {
      
       public TestSimpleStateTransition() {
       super();
       }
      
       public TestSimpleStateTransition(String arg0) {
       super(arg0);
       }
      
       public void testSimpleState() {
       long rtt = System.currentTimeMillis();
      
       ProcessDefinition processDefinition =
       ProcessDefinition.parseXmlString(
       "<process-definition>"
       + " <start-state>"
       + " <transition to='s' />"
       + " </start-state>"
       + " <state name='s'>"
       + " <transition to='end' />"
       + " </state>"
       + " <end-state name='end' />"
       + "</process-definition>");
      
       ProcessInstance processInstance =
       new ProcessInstance(processDefinition);
      
       Token token = processInstance.getRootToken();
      
       assertSame(processDefinition.getStartState(), token.getNode());
      
       // Let's start the process execution, leaving the start-state
       // over its default transition.
       long st = System.currentTimeMillis();
       token.signal();
       long runTime = System.currentTimeMillis() - st;
       System.out.println(
       Thread.currentThread().getName()
       + ": Signal A : RunTime "
       + (runTime)
       + " ms");
      
       // The signal method will block until the process execution
       // enters a wait state.
      
       // The process execution will have entered the first wait state
       // in state 's'. So the main path of execution is now
       // positioned in state 's'
       assertSame(processDefinition.getNode("s"), token.getNode());
      
       // Let's send another signal. This will resume execution by
       // leaving the state 's' over its default transition.
       st = System.currentTimeMillis();
       token.signal();
       runTime = System.currentTimeMillis() - st;
       System.out.println(
       Thread.currentThread().getName()
       + ": Signal B : RunTime "
       + (runTime)
       + " ms");
      
       // Now the signal method returned because the process instance
       // has arrived in the end-state.
       assertSame(processDefinition.getNode("end"), token.getNode());
      
       System.out.println(
       Thread.currentThread().getName()
       + this.getName()
       + ": Round Trip Time "
       + (System.currentTimeMillis() - rtt)
       + " ms");
       }
      
       public void testEventDrivenState() {
       long rtt = System.currentTimeMillis();
      
       ProcessDefinition processDefinition =
       ProcessDefinition.parseXmlString(
       "<process-definition name='hello world with events'>"
       + " <start-state name='start'>"
       + " <transition to='s' />"
       + " </start-state>"
       + " <state name='s'>"
       + " <event type=\"node-enter\">"
       + " <action class=\"SimpleEventDrivenActionHandler\" config-type=\"bean\" />"
       + " </event>"
       + " <transition to='end' />"
       + " </state>"
       + " <end-state name='end' />"
       + "</process-definition>");
      
       ProcessInstance processInstance =
       new ProcessInstance(processDefinition);
      
       Token token = processInstance.getRootToken();
      
       assertSame(processDefinition.getStartState(), token.getNode());
      
       // Let's start the process execution, leaving the start-state
       // over its default transition.
       long st = System.currentTimeMillis();
       token.signal();
       long runTime = System.currentTimeMillis() - st;
       System.out.println(
       Thread.currentThread().getName()
       + ": Signal A : RunTime "
       + (runTime)
       + " ms");
      
       // The signal method will block until the process execution
       // enters a wait state.
      
       // The process execution will have entered the first wait state
       // in state 's'. So the main path of execution is now
       // positioned in state 's'
       assertSame(processDefinition.getNode("s"), token.getNode());
      
       // Let's send another signal. This will resume execution by
       // leaving the state 's' over its default transition.
       st = System.currentTimeMillis();
       token.signal();
       runTime = System.currentTimeMillis() - st;
       System.out.println(
       Thread.currentThread().getName()
       + ": Signal B : RunTime "
       + (runTime)
       + " ms");
      
       // Now the signal method returned because the process instance
       // has arrived in the end-state.
       assertSame(processDefinition.getNode("end"), token.getNode());
      
       System.out.println(
       Thread.currentThread().getName()
       + this.getName()
       + ": Round Trip Time "
       + (System.currentTimeMillis() - rtt)
       + " ms");
       }
      
      }
      


      import org.jbpm.graph.def.ActionHandler;
      import org.jbpm.graph.exe.ExecutionContext;
      
      /**
       * @author patrick.hourigan
       */
      public class SimpleEventDrivenActionHandler implements ActionHandler {
      
       /* (non-Javadoc)
       * @see org.jbpm.graph.def.ActionHandler#execute(org.jbpm.graph.exe.ExecutionContext)
       */
       public void execute(ExecutionContext arg0) throws Exception {
       long st = System.currentTimeMillis();
      
       //System.out.println("Entering " + this.getClass().getName());
      
       long runTime = System.currentTimeMillis() - st;
       System.out.println(
       Thread.currentThread().getName()
       + ": event action execute: RunTime "
       + (runTime)
       + " ms");
      
       }
      
      }
      


      /*
       * Created on 15-Feb-08
       */
      import org.jbpm.JbpmConfiguration;
      
      /**
       * Simple Test Fixture that should be run once to install the process definitions
       * into the db and to re-create the DataBase on the iSeries.
       *
       * @author patrick.hourigan
       */
      public class RunOnceTestFixture {
      
       public static void main(String[] args) {
       setUpDB();
       }
      
       public static void setUpDB() {
       JbpmConfiguration jbpmConfiguration =
       TestDbPersistentStateTransition.getJBPMConfiguration();
       try {
       jbpmConfiguration.dropSchema();
       } finally {
       jbpmConfiguration.createSchema();
       }
       }
      }
      


      Hibernate Configs if needed

      # C3P0
      hibernate.c3p0.min_size=5
      hibernate.c3p0.max_size=30
      hibernate.c3p0.timeout=300
      hibernate.c3p0.max_statements=0
      hibernate.c3p0.idle_test_period=600
      hibernate.c3p0.acquire_increment=2
      
      hibernate.dialect=org.hibernate.dialect.MySQLDialect
      hibernate.connection.driver_class=com.mysql.jdbc.Driver
      hibernate.connection.url=jdbc:mysql://localhost/babybpm
      hibernate.connection.username=babybpm
      hibernate.connection.password=password
      hibernate.connection.isolation=2
      hibernate.show_sql=false
      


      <?xml version='1.0' encoding='utf-8'?>
      
      <!DOCTYPE hibernate-configuration PUBLIC
       "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
       "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
      
      <hibernate-configuration>
       <session-factory>
      
       <!-- ############################################ -->
       <!-- # mapping files with external dependencies # -->
       <!-- ############################################ -->
      
       <!-- following mapping file has a dependendy on -->
       <!-- 'bsh-{version}.jar'. -->
       <!-- uncomment this if you don't have bsh on your -->
       <!-- classpath. you won't be able to use the -->
       <!-- script element in process definition files -->
       <mapping resource="org/jbpm/graph/action/Script.hbm.xml" />
      
       <!-- following mapping files have a dependendy on -->
       <!-- 'jbpm-identity-{version}.jar', mapping files -->
       <!-- of the pluggable jbpm identity component. -->
       <!-- comment out the following 3 lines if you don't-->
       <!-- want to use the default jBPM identity mgmgt -->
       <!-- component -->
       <mapping resource="org/jbpm/identity/User.hbm.xml" />
       <mapping resource="org/jbpm/identity/Group.hbm.xml" />
       <mapping resource="org/jbpm/identity/Membership.hbm.xml" />
      
       <!-- ###################### -->
       <!-- # jbpm mapping files # -->
       <!-- ###################### -->
      
       <!-- hql queries and type defs -->
       <mapping resource="org/jbpm/db/hibernate.queries.hbm.xml" />
      
       <!-- graph.def mapping files -->
       <mapping resource="org/jbpm/graph/def/ProcessDefinition.hbm.xml" />
       <mapping resource="org/jbpm/graph/def/Node.hbm.xml" />
       <mapping resource="org/jbpm/graph/def/Transition.hbm.xml" />
       <mapping resource="org/jbpm/graph/def/Event.hbm.xml" />
       <mapping resource="org/jbpm/graph/def/Action.hbm.xml" />
       <mapping resource="org/jbpm/graph/def/SuperState.hbm.xml" />
       <mapping resource="org/jbpm/graph/def/ExceptionHandler.hbm.xml" />
       <mapping resource="org/jbpm/instantiation/Delegation.hbm.xml" />
      
       <!-- graph.node mapping files -->
       <mapping resource="org/jbpm/graph/node/StartState.hbm.xml" />
       <mapping resource="org/jbpm/graph/node/EndState.hbm.xml" />
       <mapping resource="org/jbpm/graph/node/ProcessState.hbm.xml" />
       <mapping resource="org/jbpm/graph/node/Decision.hbm.xml" />
       <mapping resource="org/jbpm/graph/node/Fork.hbm.xml" />
       <mapping resource="org/jbpm/graph/node/Join.hbm.xml" />
       <mapping resource="org/jbpm/graph/node/State.hbm.xml" />
       <mapping resource="org/jbpm/graph/node/TaskNode.hbm.xml" />
      
       <!-- context.def mapping files -->
       <mapping resource="org/jbpm/context/def/ContextDefinition.hbm.xml" />
       <mapping resource="org/jbpm/context/def/VariableAccess.hbm.xml" />
      
       <!-- taskmgmt.def mapping files -->
       <mapping resource="org/jbpm/taskmgmt/def/TaskMgmtDefinition.hbm.xml" />
       <mapping resource="org/jbpm/taskmgmt/def/Swimlane.hbm.xml" />
       <mapping resource="org/jbpm/taskmgmt/def/Task.hbm.xml" />
       <mapping resource="org/jbpm/taskmgmt/def/TaskController.hbm.xml" />
      
       <!-- module.def mapping files -->
       <mapping resource="org/jbpm/module/def/ModuleDefinition.hbm.xml" />
      
       <!-- bytes mapping files -->
       <mapping resource="org/jbpm/bytes/ByteArray.hbm.xml" />
      
       <!-- file.def mapping files -->
       <mapping resource="org/jbpm/file/def/FileDefinition.hbm.xml" />
      
       <!-- scheduler.def mapping files -->
       <mapping resource="org/jbpm/scheduler/def/CreateTimerAction.hbm.xml" />
       <mapping resource="org/jbpm/scheduler/def/CancelTimerAction.hbm.xml" />
      
       <!-- graph.exe mapping files -->
       <mapping resource="org/jbpm/graph/exe/Comment.hbm.xml" />
       <mapping resource="org/jbpm/graph/exe/ProcessInstance.hbm.xml" />
       <mapping resource="org/jbpm/graph/exe/Token.hbm.xml" />
       <mapping resource="org/jbpm/graph/exe/RuntimeAction.hbm.xml" />
      
       <!-- module.exe mapping files -->
       <mapping resource="org/jbpm/module/exe/ModuleInstance.hbm.xml" />
      
       <!-- context.exe mapping files -->
       <mapping resource="org/jbpm/context/exe/ContextInstance.hbm.xml" />
       <mapping resource="org/jbpm/context/exe/TokenVariableMap.hbm.xml" />
       <mapping resource="org/jbpm/context/exe/VariableInstance.hbm.xml" />
       <mapping resource="org/jbpm/context/exe/variableinstance/ByteArrayInstance.hbm.xml" />
       <mapping resource="org/jbpm/context/exe/variableinstance/DateInstance.hbm.xml" />
       <mapping resource="org/jbpm/context/exe/variableinstance/DoubleInstance.hbm.xml" />
       <mapping resource="org/jbpm/context/exe/variableinstance/HibernateLongInstance.hbm.xml" />
       <mapping resource="org/jbpm/context/exe/variableinstance/HibernateStringInstance.hbm.xml" />
       <mapping resource="org/jbpm/context/exe/variableinstance/LongInstance.hbm.xml" />
       <mapping resource="org/jbpm/context/exe/variableinstance/NullInstance.hbm.xml" />
       <mapping resource="org/jbpm/context/exe/variableinstance/StringInstance.hbm.xml" />
      
       <!-- msg.db mapping files -->
       <mapping resource="org/jbpm/msg/Message.hbm.xml" />
       <mapping resource="org/jbpm/msg/db/TextMessage.hbm.xml" />
       <mapping resource="org/jbpm/command/ExecuteActionCommand.hbm.xml" />
       <mapping resource="org/jbpm/command/ExecuteNodeCommand.hbm.xml" />
       <mapping resource="org/jbpm/command/SignalCommand.hbm.xml" />
       <mapping resource="org/jbpm/command/TaskInstanceEndCommand.hbm.xml" />
      
       <!-- taskmgmt.exe mapping files -->
       <mapping resource="org/jbpm/taskmgmt/exe/TaskMgmtInstance.hbm.xml" />
       <mapping resource="org/jbpm/taskmgmt/exe/TaskInstance.hbm.xml" />
       <mapping resource="org/jbpm/taskmgmt/exe/PooledActor.hbm.xml" />
       <mapping resource="org/jbpm/taskmgmt/exe/SwimlaneInstance.hbm.xml" />
      
       <!-- scheduler.exe mapping files -->
       <mapping resource="org/jbpm/scheduler/exe/Timer.hbm.xml" />
      
       <!-- logging mapping files -->
       <mapping resource="org/jbpm/logging/log/ProcessLog.hbm.xml" />
       <mapping resource="org/jbpm/logging/log/MessageLog.hbm.xml" />
       <mapping resource="org/jbpm/logging/log/CompositeLog.hbm.xml" />
       <mapping resource="org/jbpm/graph/log/ActionLog.hbm.xml" />
       <mapping resource="org/jbpm/graph/log/NodeLog.hbm.xml" />
       <mapping resource="org/jbpm/graph/log/ProcessInstanceCreateLog.hbm.xml" />
       <mapping resource="org/jbpm/graph/log/ProcessInstanceEndLog.hbm.xml" />
       <mapping resource="org/jbpm/graph/log/SignalLog.hbm.xml" />
       <mapping resource="org/jbpm/graph/log/TokenCreateLog.hbm.xml" />
       <mapping resource="org/jbpm/graph/log/TokenEndLog.hbm.xml" />
       <mapping resource="org/jbpm/graph/log/TransitionLog.hbm.xml" />
       <mapping resource="org/jbpm/context/log/VariableLog.hbm.xml" />
       <mapping resource="org/jbpm/context/log/VariableCreateLog.hbm.xml" />
       <mapping resource="org/jbpm/context/log/VariableDeleteLog.hbm.xml" />
       <mapping resource="org/jbpm/context/log/VariableUpdateLog.hbm.xml" />
       <mapping resource="org/jbpm/context/log/variableinstance/ByteArrayUpdateLog.hbm.xml" />
       <mapping resource="org/jbpm/context/log/variableinstance/DateUpdateLog.hbm.xml" />
       <mapping resource="org/jbpm/context/log/variableinstance/DoubleUpdateLog.hbm.xml" />
       <mapping resource="org/jbpm/context/log/variableinstance/HibernateLongUpdateLog.hbm.xml" />
       <mapping resource="org/jbpm/context/log/variableinstance/HibernateStringUpdateLog.hbm.xml" />
       <mapping resource="org/jbpm/context/log/variableinstance/LongUpdateLog.hbm.xml" />
       <mapping resource="org/jbpm/context/log/variableinstance/StringUpdateLog.hbm.xml" />
       <mapping resource="org/jbpm/taskmgmt/log/TaskLog.hbm.xml" />
       <mapping resource="org/jbpm/taskmgmt/log/TaskCreateLog.hbm.xml" />
       <mapping resource="org/jbpm/taskmgmt/log/TaskAssignLog.hbm.xml" />
       <mapping resource="org/jbpm/taskmgmt/log/TaskEndLog.hbm.xml" />
       <mapping resource="org/jbpm/taskmgmt/log/SwimlaneLog.hbm.xml" />
       <mapping resource="org/jbpm/taskmgmt/log/SwimlaneCreateLog.hbm.xml" />
       <mapping resource="org/jbpm/taskmgmt/log/SwimlaneAssignLog.hbm.xml" />
      
       <!--
       <mapping resource="com/mdsuk/bpm/engine/queue/impl/AwaitingProviderFlagResetter.xml" />
      
       <mapping resource="com/mdsuk/bpm/engine/process/management/server/pmDaoMappings.xml" />
       <mapping resource="com/mdsuk/bpm/engine/process/management/server/GroupFinder.xml" />
      
       <mapping resource="com/mdsuk/bpm/engine/process/management/processaction/ProcessAction.hbm.xml" />
      
       <mapping resource="com/mdsuk/bpm/engine/process/management/processaction/processAction-query.xml" />
      
       <mapping resource="com/mdsuk/bpm/engine/process/definition/util/ProcessDefinitonFiles.hbm.xml" />
      
       <mapping resource="com/mdsuk/bpm/engine/queue/DBQueueItem.hbm.xml" />
      
       <mapping resource="com/mdsuk/bpm/engine/administration/Archiver.xml" />
       -->
       </session-factory>
      </hibernate-configuration>