[jbpm-commits] JBoss JBPM SVN: r4762 - in jbpm3/branches/jbpm-3.2.5.SP/modules: core/src/main/java/org/jbpm/job/executor and 18 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Thu May 7 14:52:11 EDT 2009


Author: alex.guizar at jboss.com
Date: 2009-05-07 14:52:11 -0400 (Thu, 07 May 2009)
New Revision: 4762

Added:
   jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/AbstractEnterpriseTestCase.java
   jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/console/
   jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/console/ConsoleAvailabilityTest.java
   jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/jbpm1952/
   jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/jbpm1952/JBPM1952Test.java
Removed:
   jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/main/java/org/jbpm/ejb/impl/ExecuteJobsCommand.java
   jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/jbpm1952/JBPM1952Test.java
Modified:
   jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/db/ContextSession.java
   jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/job/executor/JobExecutorThread.java
   jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/job/executor/LockMonitorThread.java
   jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/persistence/db/DbPersistenceService.java
   jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/persistence/jta/JtaDbPersistenceService.java
   jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/svc/Services.java
   jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/util/ClassLoaderUtil.java
   jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/resources/org/jbpm/default.jbpm.cfg.xml
   jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/jpdl/par/ProcessClassLoaderTest.java
   jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/optimisticlocking/LockingTest.java
   jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/persistence/db/PersistenceServiceDbTest.java
   jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/main/etc/jbpm.cfg.xml
   jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/main/java/org/jbpm/ejb/impl/ExecuteJobCommand.java
   jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/config/AppServerConfigurationsTest.java
   jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/ejbtimer/EjbSchedulerTest.java
   jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/jbpm1903/JBPM1903Test.java
   jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/jms/JmsMessageTest.java
   jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/jta/JtaDbPersistenceTest.java
Log:
[JBPM-1952] merge r4073 from trunk

Modified: jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/db/ContextSession.java
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/db/ContextSession.java	2009-05-07 16:08:10 UTC (rev 4761)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/db/ContextSession.java	2009-05-07 18:52:11 UTC (rev 4762)
@@ -30,10 +30,12 @@
  */
 public class ContextSession {
 
-  JbpmSession jbpmSession = null;
-  Session session = null;
-  
-  
+  final JbpmSession jbpmSession;
+  final Session session;
+
+  /**
+   * @deprecated use {@link #ContextSession(Session)} instead
+   */
   public ContextSession(JbpmSession jbpmSession) {
     this.jbpmSession = jbpmSession;
     this.session = jbpmSession.getSession();
@@ -41,10 +43,10 @@
 
   public ContextSession(Session session) {
     this.session = session;
-    this.jbpmSession = new JbpmSession(session);
+    this.jbpmSession = null;
   }
 
-  /**
+  /*
    * converts all newly created variable values that are inside the 
    * variableUpdates into {@link VariableInstance}s
    * as a preparation for storage in the database.

Modified: jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/job/executor/JobExecutorThread.java
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/job/executor/JobExecutorThread.java	2009-05-07 16:08:10 UTC (rev 4761)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/job/executor/JobExecutorThread.java	2009-05-07 18:52:11 UTC (rev 4762)
@@ -10,7 +10,6 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.hibernate.HibernateException;
 
 import org.jbpm.JbpmConfiguration;
 import org.jbpm.JbpmContext;
@@ -18,8 +17,8 @@
 import org.jbpm.graph.exe.ProcessInstance;
 import org.jbpm.job.Job;
 import org.jbpm.persistence.JbpmPersistenceException;
+import org.jbpm.persistence.db.DbPersistenceService;
 import org.jbpm.persistence.db.StaleObjectLogConfigurer;
-import org.jbpm.svc.Services;
 
 public class JobExecutorThread extends Thread {
 
@@ -140,8 +139,8 @@
           log.debug("acquired lock on jobs: " + acquiredJobs);
         }
         catch (JbpmPersistenceException e) {
-          // if this is a stale object exception, keep it quiet
-          if (Services.isCausedByStaleState(e)) {
+          // if this is a stale state exception, keep it quiet
+          if (DbPersistenceService.isStaleStateException(e)) {
             StaleObjectLogConfigurer.getStaleObjectExceptionsLog().error(
                 "failed to acquire lock on jobs " + jobsToLock);
             acquiredJobs = Collections.EMPTY_LIST;
@@ -173,7 +172,7 @@
       }
       catch (Exception e) {
         log.debug("exception while executing " + job, e);
-        if (!isPersistenceException(e)) {
+        if (!DbPersistenceService.isPersistenceException(e)) {
           StringWriter memoryWriter = new StringWriter();
           e.printStackTrace(new PrintWriter(memoryWriter));
           job.setException(memoryWriter.toString());
@@ -197,7 +196,7 @@
       }
       catch (JbpmPersistenceException e) {
         // if this is a stale state exception, keep it quiet
-        if (Services.isCausedByStaleState(e)) {
+        if (DbPersistenceService.isStaleStateException(e)) {
           StaleObjectLogConfigurer.getStaleObjectExceptionsLog().error(
               "failed to complete job " + job);
         }
@@ -208,14 +207,6 @@
     }
   }
 
-  private static boolean isPersistenceException(Throwable throwable) {
-    do {
-      if (throwable instanceof HibernateException) return true;
-      throwable = throwable.getCause();
-    } while (throwable != null);
-    return false;
-  }
-
   protected Date getNextDueDate() {
     Date nextDueDate = null;
     String threadName = getName();
@@ -238,8 +229,8 @@
         jbpmContext.close();
       }
       catch (JbpmPersistenceException e) {
-        // if this is a stale object exception, keep it quiet
-        if (Services.isCausedByStaleState(e)) {
+        // if this is a stale state exception, keep it quiet
+        if (DbPersistenceService.isStaleStateException(e)) {
           StaleObjectLogConfigurer.getStaleObjectExceptionsLog().error(
               "failed to determine next due date for job executor thread " + threadName);
           nextDueDate = null;

Modified: jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/job/executor/LockMonitorThread.java
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/job/executor/LockMonitorThread.java	2009-05-07 16:08:10 UTC (rev 4761)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/job/executor/LockMonitorThread.java	2009-05-07 18:52:11 UTC (rev 4762)
@@ -12,8 +12,8 @@
 import org.jbpm.db.JobSession;
 import org.jbpm.job.Job;
 import org.jbpm.persistence.JbpmPersistenceException;
+import org.jbpm.persistence.db.DbPersistenceService;
 import org.jbpm.persistence.db.StaleObjectLogConfigurer;
-import org.jbpm.svc.Services;
 
 public class LockMonitorThread extends Thread {
 
@@ -93,8 +93,8 @@
         jbpmContext.close();
       }
       catch (JbpmPersistenceException e) {
-        // if this is a stale object exception, keep it quiet
-        if (Services.isCausedByStaleState(e)) {
+        // if this is a stale state exception, keep it quiet
+        if (DbPersistenceService.isStaleStateException(e)) {
           StaleObjectLogConfigurer.getStaleObjectExceptionsLog().error(
               "optimistic locking failed, could not unlock overdue jobs: " + overdueJobs);
         }

Modified: jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/persistence/db/DbPersistenceService.java
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/persistence/db/DbPersistenceService.java	2009-05-07 16:08:10 UTC (rev 4761)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/persistence/db/DbPersistenceService.java	2009-05-07 18:52:11 UTC (rev 4762)
@@ -27,6 +27,7 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.hibernate.HibernateException;
 import org.hibernate.Session;
 import org.hibernate.SessionFactory;
 import org.hibernate.StaleStateException;
@@ -45,60 +46,44 @@
 import org.jbpm.tx.TxService;
 
 public class DbPersistenceService implements Service, PersistenceService {
-  
+
   private static final long serialVersionUID = 1L;
 
-  protected DbPersistenceServiceFactory persistenceServiceFactory = null;
+  protected final DbPersistenceServiceFactory persistenceServiceFactory;
 
-  protected Connection connection = null;
-  protected boolean mustConnectionBeClosed = false;
+  protected Connection connection;
+  protected boolean mustConnectionBeClosed;
 
-  protected Transaction transaction = null;
+  protected Transaction transaction;
   protected boolean isTransactionEnabled = true;
-  protected boolean isCurrentSessionEnabled = false;
+  protected boolean isCurrentSessionEnabled;
 
-  // boolean isRollbackOnly = false;
-
   protected Session session;
-  protected boolean mustSessionBeFlushed = false;
-  protected boolean mustSessionBeClosed = false;
+  protected boolean mustSessionBeFlushed;
+  protected boolean mustSessionBeClosed;
 
-  protected Services services = null;
+  protected GraphSession graphSession;
+  protected TaskMgmtSession taskMgmtSession;
+  protected JobSession jobSession;
+  protected ContextSession contextSession;
+  protected LoggingSession loggingSession;
 
-  protected GraphSession graphSession = null;
-  protected TaskMgmtSession taskMgmtSession = null;
-  protected JobSession jobSession = null;
-  protected ContextSession contextSession = null;
-  protected LoggingSession loggingSession = null;
+  /** @deprecated for access to other services, invoke {@link JbpmContext#getServices()} */
+  protected Services services;
 
   public DbPersistenceService(DbPersistenceServiceFactory persistenceServiceFactory) {
-    this(persistenceServiceFactory, getCurrentServices());
-  }
-
-  static Services getCurrentServices() {
-    Services services = null;
-    JbpmContext currentJbpmContext = JbpmContext.getCurrentJbpmContext();
-    if (currentJbpmContext!=null) {
-      services = currentJbpmContext.getServices();
-    }
-    return services;
-  }
-
-  DbPersistenceService(DbPersistenceServiceFactory persistenceServiceFactory, Services services) {
     this.persistenceServiceFactory = persistenceServiceFactory;
     this.isTransactionEnabled = persistenceServiceFactory.isTransactionEnabled();
     this.isCurrentSessionEnabled = persistenceServiceFactory.isCurrentSessionEnabled();
-    this.services = services;
   }
 
   public SessionFactory getSessionFactory() {
-    return session != null ? session.getSessionFactory() : persistenceServiceFactory.getSessionFactory();
+    return session != null ? session.getSessionFactory() : persistenceServiceFactory
+        .getSessionFactory();
   }
 
   public Session getSession() {
-    if ( (session==null)
-         && (getSessionFactory()!=null) 
-       ) {
+    if (session == null && getSessionFactory() != null) {
       Connection connection = getConnection(false);
       if (isCurrentSessionEnabled) {
         log.debug("using current hibernate session");
@@ -106,20 +91,22 @@
         mustSessionBeClosed = false;
         mustSessionBeFlushed = false;
         mustConnectionBeClosed = false;
-      } else if (connection!=null) {
-        log.debug("creating hibernate session with connection "+connection);
+      }
+      else if (connection != null) {
+        log.debug("creating hibernate session on " + connection);
         session = getSessionFactory().openSession(connection);
         mustSessionBeClosed = true;
         mustSessionBeFlushed = true;
         mustConnectionBeClosed = false;
-      } else {
+      }
+      else {
         log.debug("creating hibernate session");
         session = getSessionFactory().openSession();
         mustSessionBeClosed = true;
         mustSessionBeFlushed = true;
         mustConnectionBeClosed = false;
       }
-      
+
       if (isTransactionEnabled) {
         beginTransaction();
       }
@@ -130,41 +117,34 @@
   public void beginTransaction() {
     log.debug("beginning hibernate transaction");
     transaction = session.beginTransaction();
-    log.debug("begun hibernate transaction " + transaction.toString());
+    log.debug("begun " + transaction);
   }
 
   public void endTransaction() {
-    if ( (isTransactionEnabled)
-         && (transaction!=null) 
-       ) {
-      if (isRollbackOnly()) {
-        try {
-          log.debug("rolling back hibernate transaction " + transaction.toString());
-          mustSessionBeFlushed = false; // flushing updates that will be rolled back is not very clever :-) 
-          transaction.rollback();
-        } catch (Exception e) {
-          // NOTE that Error's are not caught because that might halt the JVM and mask the original Error.
-          throw new JbpmPersistenceException("couldn't rollback hibernate session", e);
-        }
-      } else {
-        try {
-          log.debug("committing hibernate transaction " + transaction.toString());
-          mustSessionBeFlushed = false; // commit does a flush anyway 
-          transaction.commit();
-        } catch (Exception e) {
-          // NOTE that Error's are not caught because that might halt the JVM and mask the original Error.
-          try {
-            // if the commit fails, we must do a rollback
-            transaction.rollback();
-          } catch (Exception e2) {
-            // if the rollback fails, we did what we could and you're in 
-            // deep shit :-(
-            log.error("problem rolling back after failed commit", e2);
-          }
-          throw new JbpmPersistenceException("couldn't commit hibernate session", e);
-        }
+    if (isTransactionManagedExternally()) {
+      if (session != null && getTxService().isRollbackOnly()) {
+        throw new JbpmException("cannot mark externally managed transaction for rollback");
       }
+      return;
     }
+
+    if (!isTransactionRollbackOnly()) {
+      Exception commitException = commit();
+      if (commitException != null) {
+        rollback();
+        closeSession();
+        closeConnection();
+        throw new JbpmPersistenceException("transaction commit failed", commitException);
+      }
+    }
+    else { // isRollbackOnly==true
+      Exception rollbackException = rollback();
+      if (rollbackException != null) {
+        closeSession();
+        closeConnection();
+        throw new JbpmPersistenceException("transaction rollback failed", rollbackException);
+      }
+    }
   }
 
   public Connection getConnection() {
@@ -172,167 +152,160 @@
   }
 
   public Connection getConnection(boolean resolveSession) {
-    if (connection==null) {
-      if (persistenceServiceFactory.getDataSource()!=null) { 
+    if (connection == null) {
+      if (persistenceServiceFactory.getDataSource() != null) {
         try {
           log.debug("fetching jdbc connection from datasource");
           connection = persistenceServiceFactory.getDataSource().getConnection();
           mustConnectionBeClosed = true;
-        } catch (Exception e) {
-          // NOTE that Error's are not caught because that might halt the JVM and mask the original Error.
-          throw new JbpmException("couldn't obtain connection from datasource", e);
         }
-      } else {
+        catch (Exception e) {
+          // NOTE that Errors are not caught because that might halt the JVM
+          // and mask the original Error.
+          throw new JbpmException("could not obtain connection from datasource", e);
+        }
+      }
+      else {
         if (resolveSession) {
           // initializes the session member
           getSession();
         }
-        if (session!=null) {
+        if (session != null) {
           connection = session.connection();
-          log.debug("fetching connection from hibernate session. this transfers responsibility for closing the jdbc connection to the user! "+connection);
+          log.debug("fetched "
+              + connection
+              + " from hibernate session, client is responsible for closing it!");
           mustConnectionBeClosed = false;
         }
       }
     }
     return connection;
   }
-  
+
   public boolean isTransactionActive() {
     return transaction != null && transaction.isActive();
   }
 
-  protected boolean isTransactionExternallyManaged() {
-    return !(isTransactionEnabled && transaction != null);
+  protected boolean isTransactionManagedExternally() {
+    return !isTransactionEnabled || transaction == null;
   }
 
+  protected boolean isTransactionRollbackOnly() {
+    return getTxService().isRollbackOnly();
+  }
+
   public void close() {
+    endTransaction();
 
-    if ( (session!=null)
-         && isTransactionExternallyManaged()
-         && (isRollbackOnly())
-       ) {
-      throw new JbpmException("setRollbackOnly was invoked while transaction is being managed externally");
-    }
-    
-    if ( (isTransactionEnabled)
-         && (transaction!=null) 
-       ) {
-
-      if (! isRollbackOnly()) {
-        Exception commitException = commit();
-        if (commitException!=null) {
-          rollback();
-          closeSession();
-          closeConnection();
-          throw new JbpmPersistenceException("hibernate commit failed", commitException);
-        }
-
-      } else { // isRollbackOnly==true
-        Exception rollbackException = rollback();
-        if (rollbackException!=null) {
-          closeSession();
-          closeConnection();
-          throw new JbpmPersistenceException("hibernate rollback failed", rollbackException);
-        }
-      }
-    }
-    
     Exception flushException = flushSession();
-    if (flushException!=null) {
-      // JBPM-1465: transaction is either committed or rolled back at this point;
-      // it is also possible that the transaction was initiated externally
+    if (flushException != null) {
+      // JBPM-1465: at this point, the transaction is already committed or rolled back
+      // alternatively, the transaction is being managed externally
       // hence rolling back here is redundant and possibly dangerous
       closeSession();
       closeConnection();
-      throw new JbpmPersistenceException("hibernate flush failed", flushException);
+      throw new JbpmPersistenceException("hibernate flush session failed", flushException);
     }
 
     Exception closeSessionException = closeSession();
-    if (closeSessionException!=null) {
+    if (closeSessionException != null) {
       closeConnection();
       throw new JbpmPersistenceException("hibernate close session failed", closeSessionException);
     }
 
     Exception closeConnectionException = closeConnection();
-    if (closeConnectionException!=null) {
-      throw new JbpmPersistenceException("hibernate close connection failed", closeConnectionException);
+    if (closeConnectionException != null) {
+      throw new JbpmPersistenceException("hibernate close connection failed",
+          closeConnectionException);
     }
   }
 
-  Exception commit() {
+  protected Exception commit() {
     try {
       log.debug("committing " + transaction);
-      mustSessionBeFlushed = false; // commit does a flush anyway 
+      mustSessionBeFlushed = false; // commit does a flush anyway
       transaction.commit();
-    } catch (StaleStateException e) {
-      log.info("problem committing transaction: optimistic locking failed");
-      StaleObjectLogConfigurer.getStaleObjectExceptionsLog().error("optimistic locking failed while committing " + transaction, e);
+    }
+    catch (Exception e) {
+      if (isStaleStateException(e)) {
+        log.info("problem committing transaction: optimistic locking failed");
+        StaleObjectLogConfigurer.getStaleObjectExceptionsLog().error(
+            "optimistic locking failed while committing " + transaction, e);
+      }
+      else {
+        log.error("transaction commit failed", e);
+      }
       return e;
-    } catch (Exception e) {
-      log.error("hibernate commit failed", e);
+    }
+    return null;
+  }
+
+  protected Exception rollback() {
+    try {
+      log.debug("rolling back " + transaction);
+      // flushing updates that will be rolled back is not very clever :-)
+      mustSessionBeFlushed = false;
+      transaction.rollback();
+    }
+    catch (Exception e) {
+      log.error("transaction rollback failed", e);
       return e;
     }
     return null;
   }
 
-  Exception flushSession() {
+  private Exception flushSession() {
     if (mustSessionBeFlushed) {
       try {
         log.debug("flushing " + session);
         session.flush();
-      } catch (StaleStateException e) {
-        log.info("problem flushing session: optimistic locking failed");
-        StaleObjectLogConfigurer.getStaleObjectExceptionsLog().error("optimistic locking failed while flushing " + session, e);
+      }
+      catch (Exception e) {
+        if (isStaleStateException(e)) {
+          log.info("problem flushing session: optimistic locking failed");
+          StaleObjectLogConfigurer.getStaleObjectExceptionsLog().error(
+              "optimistic locking failed while flushing " + session, e);
+        }
+        else {
+          log.error("hibernate flush failed", e);
+        }
         return e;
-      } catch (Exception e) {
-        log.error("hibernate flush failed", e);
-        return e;
       }
     }
     return null;
   }
 
-  Exception closeConnection() {
-    if (mustConnectionBeClosed) {
+  private Exception closeSession() {
+    if (mustSessionBeClosed) {
       try {
-        if ( (connection!=null)
-            && (! connection.isClosed())
-           ) {
-          log.debug("closing jdbc connection");
-          connection.close();
-        } else {
-          log.warn("jdbc connection was already closed");
+        if (session.isOpen()) {
+          log.debug("closing hibernate session");
+          session.close();
         }
-      } catch (Exception e) {
-        log.error("hibernate session close failed", e);
+        else {
+          log.warn("hibernate session was already closed");
+        }
+      }
+      catch (Exception e) {
         return e;
       }
     }
     return null;
   }
 
-  Exception rollback() {
-    try {
-      log.debug("rolling back hibernate transaction");
-      mustSessionBeFlushed = false; // flushing updates that will be rolled back is not very clever :-) 
-      transaction.rollback();
-    } catch (Exception e) {
-      log.error("hibernate rollback failed", e);
-      return e;
-    }
-    return null;
-  }
-
-  Exception closeSession() {
-    if (mustSessionBeClosed) {
+  private Exception closeConnection() {
+    if (mustConnectionBeClosed) {
       try {
-        if(session.isOpen()) {
-          log.debug("closing hibernate session");
-          session.close();
-        } else {
-          log.warn("hibernate session was already closed");
+        if (connection != null) {
+          log.debug("closing jdbc connection");
+          connection.close();
         }
-      } catch (Exception e) {
+        else {
+          log.warn("jdbc connection was already closed");
+        }
+      }
+      catch (Exception e) {
+        log.error("hibernate session close failed", e);
         return e;
       }
     }
@@ -342,54 +315,60 @@
   public void assignId(Object object) {
     try {
       getSession().save(object);
-    } catch (Exception e) {
-      // NOTE that Error's are not caught because that might halt the JVM and mask the original Error.
-      throw new JbpmPersistenceException("couldn't assign id to "+object, e);
     }
+    catch (Exception e) {
+      // NOTE that Errors are not caught because that might halt the JVM
+      // and mask the original Error.
+      throw new JbpmPersistenceException("couldn't assign id to " + object, e);
+    }
   }
 
   // getters and setters //////////////////////////////////////////////////////
 
   public GraphSession getGraphSession() {
-    if (graphSession==null) {
+    if (graphSession == null) {
       Session session = getSession();
-      if (session!=null) {
+      if (session != null) {
         graphSession = new GraphSession(session);
       }
     }
     return graphSession;
   }
+
   public LoggingSession getLoggingSession() {
-    if (loggingSession==null) {
+    if (loggingSession == null) {
       Session session = getSession();
-      if (session!=null) {
+      if (session != null) {
         loggingSession = new LoggingSession(session);
       }
     }
     return loggingSession;
   }
+
   public JobSession getJobSession() {
-    if (jobSession==null) {
+    if (jobSession == null) {
       Session session = getSession();
-      if (session!=null) {
+      if (session != null) {
         jobSession = new JobSession(session);
       }
     }
     return jobSession;
   }
+
   public ContextSession getContextSession() {
-    if (contextSession==null) {
+    if (contextSession == null) {
       Session session = getSession();
-      if (session!=null) {
+      if (session != null) {
         contextSession = new ContextSession(session);
       }
     }
     return contextSession;
   }
+
   public TaskMgmtSession getTaskMgmtSession() {
-    if (taskMgmtSession==null) {
+    if (taskMgmtSession == null) {
       Session session = getSession();
-      if (session!=null) {
+      if (session != null) {
         taskMgmtSession = new TaskMgmtSession(session);
       }
     }
@@ -401,77 +380,146 @@
   }
 
   /**
-   * @deprecated use {@link org.jbpm.tx.TxService} instead.
+   * @deprecated use {@link TxService#isRollbackOnly()} instead
    */
   public boolean isRollbackOnly() {
-    TxService txService = (services!=null ? services.getTxService() : null);
-    if (txService==null) {
-      throw new JbpmException("no jbpm tx service configured");
-    }
-    return txService.isRollbackOnly();
+    return getTxService().isRollbackOnly();
   }
+
   /**
-   * @deprecated use {@link org.jbpm.tx.TxService} instead.
+   * @deprecated use {@link TxService#setRollbackOnly()} instead
    */
-  public void setRollbackOnly(boolean isRollbackOnly) {
-    throw new UnsupportedOperationException("method setRollbackOnly has been removed.  Use TxService instead.");
+  public void setRollbackOnly() {
+    getTxService().setRollbackOnly();
   }
+
   /**
-   * @deprecated use {@link org.jbpm.tx.TxService} instead.
+   * @throws UnsupportedOperationException if <code>rollbackOnly</code> is <code>false</code>
+   * @deprecated use {@link TxService#setRollbackOnly()} instead
    */
-  public void setRollbackOnly() {
-    TxService txService = (services!=null ? services.getTxService() : null);
-    if (txService==null) {
-      throw new JbpmException("no jbpm tx service configured");
+  public void setRollbackOnly(boolean rollbackOnly) {
+    if (!rollbackOnly) {
+      throw new UnsupportedOperationException();
     }
-    txService.setRollbackOnly();
+    setRollbackOnly();
   }
 
+  private TxService getTxService() {
+    return (TxService) Services.getCurrentService(Services.SERVICENAME_TX);
+  }
+
+  /**
+   * Injects an external Hibernate session, disabling transaction management.
+   */
   public void setSession(Session session) {
-    this.session = session;
-    log.debug("injecting a session disables transaction");
-    isTransactionEnabled = false;
+    setSession(session, false);
   }
 
+  /**
+   * Injects an external Hibernate session without affecting transaction management.
+   * 
+   * @deprecated use {@link #setSession(Session, boolean) setSession(session, true)} instead
+   */
   public void setSessionWithoutDisablingTx(Session session) {
+    setSession(session, true);
+  }
+
+  /**
+   * Injects an external Hibernate session. Injecting a session would normally disable transaction
+   * management. The <code>keepTransactionEnabled</code> parameter can be used to prevent
+   * transaction management from being disabled, according to the following table.
+   * <table border="1">
+   * <tr>
+   * <th>is currently enabled?</th>
+   * <th>keep enabled?</th>
+   * <th>enabled onward</th>
+   * </tr>
+   * <tr>
+   * <td>true</td>
+   * <td>true</td>
+   * <td>true (no change)</td>
+   * </tr>
+   * <tr>
+   * <td>true</td>
+   * <td>false</td>
+   * <td>false</td>
+   * </tr>
+   * <tr>
+   * <td>false</td>
+   * <td>n/a</td>
+   * <td>false (no change)</td>
+   * </tr>
+   * </table>
+   */
+  public void setSession(Session session, boolean keepTransactionEnabled) {
     this.session = session;
+    if (isTransactionEnabled && !keepTransactionEnabled) {
+      log.debug("disabling transaction due to session injection");
+      isTransactionEnabled = false;
+    }
   }
 
   public void setConnection(Connection connection) {
     this.connection = connection;
   }
+
   public void setContextSession(ContextSession contextSession) {
     this.contextSession = contextSession;
   }
+
   public void setDataSource(DataSource dataSource) {
     this.persistenceServiceFactory.dataSource = dataSource;
   }
+
   public void setGraphSession(GraphSession graphSession) {
     this.graphSession = graphSession;
   }
+
   public void setLoggingSession(LoggingSession loggingSession) {
     this.loggingSession = loggingSession;
   }
+
   public void setJobSession(JobSession jobSession) {
     this.jobSession = jobSession;
   }
+
   public void setTaskMgmtSession(TaskMgmtSession taskMgmtSession) {
     this.taskMgmtSession = taskMgmtSession;
   }
+
   public void setSessionFactory(SessionFactory sessionFactory) {
     this.persistenceServiceFactory.sessionFactory = sessionFactory;
   }
+
   public Transaction getTransaction() {
     return transaction;
   }
+
   public void setTransaction(Transaction transaction) {
     this.transaction = transaction;
   }
+
   public boolean isTransactionEnabled() {
     return isTransactionEnabled;
   }
+
   public void setTransactionEnabled(boolean isTransactionEnabled) {
     this.isTransactionEnabled = isTransactionEnabled;
   }
+
+  public static boolean isPersistenceException(Exception exception) {
+    for (Throwable t = exception; t != null; t = t.getCause()) {
+      if (t instanceof HibernateException) return true;
+    }
+    return false;
+  }
+
+  public static boolean isStaleStateException(Exception exception) {
+    for (Throwable t = exception; t != null; t = t.getCause()) {
+      if (t instanceof StaleStateException) return true;
+    }
+    return false;
+  }
+
   private static Log log = LogFactory.getLog(DbPersistenceService.class);
 }

Modified: jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/persistence/jta/JtaDbPersistenceService.java
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/persistence/jta/JtaDbPersistenceService.java	2009-05-07 16:08:10 UTC (rev 4761)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/persistence/jta/JtaDbPersistenceService.java	2009-05-07 18:52:11 UTC (rev 4762)
@@ -21,6 +21,7 @@
  */
 package org.jbpm.persistence.jta;
 
+import javax.transaction.Status;
 import javax.transaction.SystemException;
 import javax.transaction.UserTransaction;
 
@@ -29,84 +30,101 @@
 import org.hibernate.engine.SessionFactoryImplementor;
 import org.hibernate.util.JTAHelper;
 import org.jbpm.JbpmException;
-import org.jbpm.persistence.JbpmPersistenceException;
 import org.jbpm.persistence.db.DbPersistenceService;
+import org.jbpm.persistence.db.StaleObjectLogConfigurer;
 
 public class JtaDbPersistenceService extends DbPersistenceService {
 
+  private UserTransaction transaction;
+
   private static final long serialVersionUID = 1L;
 
   private static Log log = LogFactory.getLog(JtaDbPersistenceService.class);
 
-  private UserTransaction userTransaction;
-
   public JtaDbPersistenceService(JtaDbPersistenceServiceFactory persistenceServiceFactory) {
     super(persistenceServiceFactory);
 
-    if (!isJtaTransactionInProgress()) {
-      beginUserTransaction();
+    if (!isTransactionActive()) {
+      beginTransaction();
     }
   }
 
   public boolean isTransactionActive() {
-    return isJtaTransactionInProgress();
+    SessionFactoryImplementor sessionFactory = (SessionFactoryImplementor) getSessionFactory();
+    return JTAHelper.isTransactionInProgress(sessionFactory);
   }
 
-  protected boolean isTransactionExternallyManaged() {
-    return !isJtaTxCreated();
+  protected boolean isTransactionManagedExternally() {
+    return transaction == null;
   }
 
-  public void close() {
-    super.close();
+  protected boolean isTransactionRollbackOnly() {
+    return super.isTransactionRollbackOnly()
+        || JTAHelper.isMarkedForRollback(getTransactionStatus());
+  }
 
-    if (userTransaction != null) {
-      endUserTransaction();
+  public void beginTransaction() {
+    try {
+      log.debug("beginning " + transaction);
+      JtaDbPersistenceServiceFactory jtaFactory = (JtaDbPersistenceServiceFactory) persistenceServiceFactory;
+      transaction = jtaFactory.getUserTransaction();
+      transaction.begin();
     }
+    catch (Exception e) {
+      throw new JbpmException("transaction begin failed", e);
+    }
   }
 
-  boolean isJtaTransactionInProgress() {
-    SessionFactoryImplementor sessionFactory = (SessionFactoryImplementor) getSessionFactory();
-    return JTAHelper.isTransactionInProgress(sessionFactory);
+  private int getTransactionStatus() {
+    try {
+      return transaction.getStatus();
+    }
+    catch (SystemException e) {
+      log.error("could not get transaction status", e);
+      return Status.STATUS_UNKNOWN;
+    }
   }
 
-  void beginUserTransaction() {
+  protected Exception commit() {
+    log.debug("committing " + transaction);
     try {
-      log.debug("begin user transaction");
-      userTransaction = ((JtaDbPersistenceServiceFactory) persistenceServiceFactory)
-          .getUserTransaction();
-      userTransaction.begin();
-    } catch (Exception e) {
-      throw new JbpmException("couldn't begin user transaction", e);
+      transaction.commit();
+      return null;
     }
-  }
-
-  void endUserTransaction() {
-    if (isRollbackOnly() || JTAHelper.isRollback(getUserTransactionStatus())) {
-      log.debug("rolling back user transaction");
-      try {
-        userTransaction.rollback();
-      } catch (Exception e) {
-        throw new JbpmPersistenceException("couldn't rollback user transaction", e);
+    catch (Exception e) {
+      if (isStaleStateException(e)) {
+        log.debug("optimistic locking failed, could not commit " + transaction);
+        StaleObjectLogConfigurer.getStaleObjectExceptionsLog().error(
+            "optimistic locking failed, could not commit " + transaction, e);
       }
-    } else {
-      log.debug("committing user transaction");
-      try {
-        userTransaction.commit();
-      } catch (Exception e) {
-        throw new JbpmPersistenceException("couldn't commit user transaction", e);
+      else {
+        // Switched to debug because either handle OR log 
+        // an exception is best practice, not both!
+        // Example: Clustered JobExecutor may have
+        // Exceptions which should be kept quiet
+        log.debug("transaction commit failed", e);
       }
+      return e;
     }
   }
 
-  int getUserTransactionStatus() {
+  protected Exception rollback() {
+    log.debug("rolling back " + transaction);
     try {
-      return userTransaction.getStatus();
-    } catch (SystemException e) {
-      throw new JbpmPersistenceException("couldn't get status for user transaction", e); 
+      transaction.rollback();
+      return null;
     }
+    catch (Exception e) {
+      // Switched to debug because either handle OR log 
+      // an exception is best practice, not both!
+      // Example: Clustered JobExecutor may have
+      // Exceptions which should be kept quiet
+      log.debug("transaction rollback failed", e);
+      return e;
+    }
   }
 
   public boolean isJtaTxCreated() {
-    return userTransaction != null;
+    return !isTransactionManagedExternally();
   }
 }

Modified: jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/svc/Services.java
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/svc/Services.java	2009-05-07 16:08:10 UTC (rev 4761)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/svc/Services.java	2009-05-07 18:52:11 UTC (rev 4762)
@@ -31,8 +31,6 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.hibernate.StaleStateException;
-import org.hibernate.exception.LockAcquisitionException;
 
 import org.jbpm.JbpmContext;
 import org.jbpm.JbpmException;
@@ -41,6 +39,7 @@
 import org.jbpm.msg.MessageService;
 import org.jbpm.persistence.JbpmPersistenceException;
 import org.jbpm.persistence.PersistenceService;
+import org.jbpm.persistence.db.DbPersistenceService;
 import org.jbpm.persistence.db.StaleObjectLogConfigurer;
 import org.jbpm.scheduler.SchedulerService;
 import org.jbpm.security.AuthenticationService;
@@ -71,19 +70,19 @@
   private static List createDefaultSaveOperations() {
     SaveOperation[] operations = new SaveOperation[4];
     operations[0] = new CheckUnpersistableVariablesOperation();
-    // first we save the runtime data (process instance)
+    // first, save the execution data (process instance)
     operations[1] = new HibernateSaveOperation();
-    // then we insert the logs cause the logs can have references
-    // to the runtime data
+    // then, insert the logs, which may have references to the execution data
     operations[2] = new SaveLogsOperation();
+    // last, save subprocess instances in cascade
     operations[3] = new CascadeSaveOperation();
     return Arrays.asList(operations);
   }
 
   Map serviceFactories;
   Map services;
-  List serviceNames = null;
-  List saveOperations = null;
+  List serviceNames;
+  List saveOperations;
 
   public static Service getCurrentService(String name) {
     return getCurrentService(name, true);
@@ -163,8 +162,6 @@
   }
 
   public void save(ProcessInstance processInstance, JbpmContext jbpmContext) {
-    Iterator iter = saveOperations.iterator();
-
     if (log.isDebugEnabled()) {
       if (saveOperations == defaultSaveOperations) {
         log.debug("executing default save operations");
@@ -174,7 +171,7 @@
       }
     }
 
-    while (iter.hasNext()) {
+    for (Iterator iter = saveOperations.iterator(); iter.hasNext();) {
       SaveOperation saveOperation = (SaveOperation) iter.next();
       saveOperation.save(processInstance, jbpmContext);
     }
@@ -241,8 +238,7 @@
   public void close() {
     if (services != null) {
       Exception firstException = null;
-      Iterator iter = serviceNames.iterator();
-      while (iter.hasNext()) {
+      for (Iterator iter = serviceNames.iterator(); iter.hasNext();) {
         String serviceName = (String) iter.next();
         Service service = (Service) services.get(serviceName);
         if (service != null) {
@@ -251,10 +247,11 @@
             service.close();
           }
           catch (JbpmPersistenceException e) {
-            // if this is a stale state exception, the jbpm configuration has control over the logging
-            if (isCausedByStaleState(e)) {
+            // if this is a stale state exception, keep it quiet
+            if (DbPersistenceService.isStaleStateException(e)) {
+              log.info("optimistic locking failed, could not close service: " + serviceName);
               StaleObjectLogConfigurer.getStaleObjectExceptionsLog().error(
-                  "problem closing service '" + serviceName + "': optimistic locking failed", e);
+                  "optimistic locking failed, could not close service: " + serviceName, e);
             }
             else {
               log.error("problem closing service '" + serviceName + "'", e);
@@ -264,7 +261,8 @@
             }
           }
           catch (Exception e) {
-            // NOTE that Error's are not caught because that might halt the JVM and mask the original Error.
+            // NOTE that Error's are not caught because that might halt the JVM
+            // and mask the original Error.
             log.error("problem closing service '" + serviceName + "'", e);
             if (firstException == null) {
               firstException = e;
@@ -273,26 +271,16 @@
         }
       }
       if (firstException != null) {
-        if (firstException instanceof JbpmException) {
-          throw (JbpmException) firstException;
-        }
-        throw new JbpmException("problem closing services", firstException);
+        throw firstException instanceof JbpmException ? (JbpmException) firstException
+            : new JbpmException("problem closing services", firstException);
       }
     }
   }
 
-  public static boolean isCausedByStaleState(JbpmPersistenceException persistenceException) {
-    for (Throwable cause = persistenceException.getCause(); cause != null; cause = cause.getCause()) {
-      if (cause instanceof StaleStateException || cause instanceof LockAcquisitionException)
-        return true;
-    }
-    return false;
-  }
-
   public static void assignId(Object object) {
     JbpmContext jbpmContext = JbpmContext.getCurrentJbpmContext();
     if (jbpmContext != null) {
-      // give this process instance an id
+      // assign id to the given object
       Services services = jbpmContext.getServices();
       if (services.hasService(Services.SERVICENAME_PERSISTENCE)) {
         PersistenceService persistenceService = services.getPersistenceService();

Modified: jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/util/ClassLoaderUtil.java
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/util/ClassLoaderUtil.java	2009-05-07 16:08:10 UTC (rev 4761)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/java/org/jbpm/util/ClassLoaderUtil.java	2009-05-07 18:52:11 UTC (rev 4762)
@@ -25,6 +25,9 @@
 import java.io.InputStream;
 import java.util.Properties;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
 import org.jbpm.JbpmConfiguration;
 import org.jbpm.JbpmException;
 
@@ -40,7 +43,7 @@
   /**
    * Bad usage of ClassLoader.loadClass() under JDK 6.
    * 
-   * @deprecated Use {@linkplain #classForName(String) classForName()} instead
+   * @deprecated Use {@linkplain #classForName(String)} instead
    * @see <a href="https://jira.jboss.org/jira/browse/JBPM-1976">JBPM-1976</a>
    */
   public static Class loadClass(String className) {
@@ -48,7 +51,7 @@
       return getClassLoader().loadClass(className);
     }
     catch (ClassNotFoundException e) {
-      throw new JbpmException("class not found '" + className + "'", e);
+      throw new JbpmException("class not found: " + className, e);
     }
   }
 
@@ -57,7 +60,7 @@
       return Class.forName(className, true, getClassLoader());
     }
     catch (ClassNotFoundException e) {
-      throw new JbpmException("class not found '" + className + "'", e);
+      throw new JbpmException("class not found: " + className, e);
     }
   }
 
@@ -75,7 +78,7 @@
       }
       catch (ClassNotFoundException e2) {
         // give up
-        throw new JbpmException("class not found '" + className + "'", e);
+        throw new JbpmException("class not found: " + className, e2);
       }
     }
   }
@@ -148,15 +151,24 @@
   }
 
   public static Properties getProperties(String resource) {
-    Properties properties = new Properties();
+    InputStream inStream = getStream(resource);
+    if (inStream == null) throw new JbpmException("resource not found: " + resource);
     try {
-      InputStream inStream = getStream(resource);
+      Properties properties = new Properties();
       properties.load(inStream);
-      inStream.close();
+      return properties;
     }
     catch (IOException e) {
-      throw new JbpmException("couldn't load properties file '" + resource + "'", e);
+      throw new JbpmException("could not load properties from resource: " + resource, e);
     }
-    return properties;
+    finally {
+      try {
+        inStream.close();
+      }
+      catch (IOException e) {
+        Log log = LogFactory.getLog(ClassLoaderUtil.class);
+        log.warn("failed to close stream from resource: " + resource, e);
+      }
+    }
   }
 }

Modified: jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/resources/org/jbpm/default.jbpm.cfg.xml
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/resources/org/jbpm/default.jbpm.cfg.xml	2009-05-07 16:08:10 UTC (rev 4761)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/main/resources/org/jbpm/default.jbpm.cfg.xml	2009-05-07 18:52:11 UTC (rev 4762)
@@ -32,8 +32,9 @@
   <string name="resource.varmapping" value="org/jbpm/context/exe/jbpm.varmapping.xml" />
   <string name="resource.mail.templates" value="jbpm.mail.templates.xml" />
 
-  <!-- class loading -->
+  <!-- class loading
   <string name="jbpm.class.loader" value="context" />
+  -->
   <bean name="process.class.loader.factory" class="org.jbpm.instantiation.SharedProcessClassLoaderFactory" singleton="true" />
 
   <!-- make sure the block size matches the length in ByteArray.hbm.xml -->

Modified: jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/jpdl/par/ProcessClassLoaderTest.java
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/jpdl/par/ProcessClassLoaderTest.java	2009-05-07 16:08:10 UTC (rev 4761)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/jpdl/par/ProcessClassLoaderTest.java	2009-05-07 18:52:11 UTC (rev 4762)
@@ -114,7 +114,7 @@
   public void testContextClassLoader() {
 
     JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString("<jbpm-configuration>"
-        + "  <string name='jbpm.classLoader' value='context' />"
+        + "  <string name='jbpm.class.loader' value='context' />"
         + "</jbpm-configuration>");
 
     JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
@@ -176,7 +176,7 @@
 
   public void testContextClassLoaderException() {
     JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseXmlString("<jbpm-configuration>"
-        + "  <string name='jbpm.classLoader' value='context' />"
+        + "  <string name='jbpm.class.loader' value='context' />"
         + "</jbpm-configuration>");
 
     JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();

Modified: jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/optimisticlocking/LockingTest.java
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/optimisticlocking/LockingTest.java	2009-05-07 16:08:10 UTC (rev 4761)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/optimisticlocking/LockingTest.java	2009-05-07 18:52:11 UTC (rev 4762)
@@ -10,8 +10,8 @@
 import org.jbpm.graph.exe.Comment;
 import org.jbpm.graph.exe.ProcessInstance;
 import org.jbpm.persistence.JbpmPersistenceException;
+import org.jbpm.persistence.db.DbPersistenceService;
 import org.jbpm.persistence.db.StaleObjectLogConfigurer;
-import org.jbpm.svc.Services;
 import org.jbpm.util.Semaphore;
 
 /**
@@ -147,7 +147,7 @@
         }
         catch (JbpmPersistenceException e) {
           // if this is a stale object exception, keep it quiet
-          if (Services.isCausedByStaleState(e)) {
+          if (DbPersistenceService.isStaleStateException(e)) {
             StaleObjectLogConfigurer.getStaleObjectExceptionsLog()
                 .error(getName() + " rolled back");
           }

Modified: jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/persistence/db/PersistenceServiceDbTest.java
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/persistence/db/PersistenceServiceDbTest.java	2009-05-07 16:08:10 UTC (rev 4761)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/core/src/test/java/org/jbpm/persistence/db/PersistenceServiceDbTest.java	2009-05-07 18:52:11 UTC (rev 4762)
@@ -230,7 +230,6 @@
       jbpmContext.close();
     }
 
-    persistenceService.close();
     assertNull(persistenceService.transaction);
     assertNotNull(persistenceService.session);
     assertTrue(persistenceService.session.isOpen());
@@ -266,7 +265,7 @@
     JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
     
     DbPersistenceService dbPersistenceService = null; 
-    Connection connection = null;
+    Connection connection;
     try {
       dbPersistenceService = (DbPersistenceService) jbpmContext.getServices().getPersistenceService();
       connection = jbpmContext.getConnection();
@@ -276,7 +275,7 @@
 
     assertFalse(dbPersistenceService.session.isOpen());
     assertFalse(dbPersistenceService.session.isConnected());
-    // Since 3.2.1, hibernate hides direct access to the connecion after session has closed.  Bummer...
-    // assertFalse(connection.isClosed());
+
+    connection.close();
   }
 }

Modified: jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/main/etc/jbpm.cfg.xml
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/main/etc/jbpm.cfg.xml	2009-05-07 16:08:10 UTC (rev 4761)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/main/etc/jbpm.cfg.xml	2009-05-07 18:52:11 UTC (rev 4762)
@@ -10,12 +10,12 @@
   </jbpm-context>
 
   <!-- use the context class loader -->
-  <string name="jbpm.classLoader" value="context" />
+  <string name="jbpm.class.loader" value="context" />
 
   <!-- 
-    Note, that the default job executor needs to be overwritten with a null value. 
-    In the enterprise configuration there should be no job executor. 
-    Async messaging is there bound to jms and scheduling to ejb timers.  
+    The default job executor needs to be overwritten with a null value. 
+    There should be no job executor in the enterprise configuration. 
+    Async messaging is bound to JMS and scheduling, to EJB timers.  
   -->  
   <null name="jbpm.job.executor" />
 

Modified: jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/main/java/org/jbpm/ejb/impl/ExecuteJobCommand.java
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/main/java/org/jbpm/ejb/impl/ExecuteJobCommand.java	2009-05-07 16:08:10 UTC (rev 4761)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/main/java/org/jbpm/ejb/impl/ExecuteJobCommand.java	2009-05-07 18:52:11 UTC (rev 4762)
@@ -23,26 +23,15 @@
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
-import java.util.List;
 
-import javax.jms.Destination;
-import javax.jms.JMSException;
-import javax.jms.Message;
-import javax.jms.MessageProducer;
-import javax.jms.Session;
-import javax.naming.NamingException;
-
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-
 import org.jbpm.JbpmContext;
+import org.jbpm.JbpmException;
 import org.jbpm.command.Command;
-import org.jbpm.db.JobSession;
+import org.jbpm.graph.exe.ProcessInstance;
 import org.jbpm.job.Job;
-import org.jbpm.msg.jms.JmsMessageService;
-import org.jbpm.msg.jms.JmsMessageServiceFactory;
-import org.jbpm.svc.Services;
-import org.jbpm.util.ArrayUtil;
+import org.jbpm.persistence.db.DbPersistenceService;
 
 /**
  * Individual job processing command.
@@ -60,84 +49,50 @@
   }
 
   public Object execute(JbpmContext jbpmContext) throws Exception {
-    JobSession jobSession = jbpmContext.getJobSession();
-    Job job = jobSession.getJob(jobId);
-    if (job == null) {
-      log.debug("job " + jobId + " was deleted");
-      return null;
-    }
-    String lockOwner = job.getLockOwner();
-    if (lockOwner != null) {
-      log.debug(job + " is locked by " + lockOwner);
-      return null;
-    }
-    lockOwner = Long.toString(jobId);
+    Job job = acquireJob(jbpmContext);
+    executeJob(job, jbpmContext);
+    return job;
+  }
+
+  private Job acquireJob(JbpmContext jbpmContext) {
+    Job job = jbpmContext.getJobSession().loadJob(jobId);
+
+    // register process instance for automatic save
+    // see https://jira.jboss.org/jira/browse/JBPM-1015
+    ProcessInstance processInstance = job.getProcessInstance();
+    jbpmContext.addAutoSaveProcessInstance(processInstance);
+
+    // if job is exclusive, lock process instance
     if (job.isExclusive()) {
-      List exclusiveJobs = jobSession.findExclusiveJobs(lockOwner, job.getProcessInstance());
-      // lock exclusive jobs
-      int jobCount = exclusiveJobs.size();
-      if (jobCount == 0) {
-        // may happen if isolation level is below repeatable read
-        log.debug(job + " was locked during attempt to lock other jobs");
-        return null;
-      }
-      long[] exclusiveJobIds = new long[jobCount];
-      for (int i = 0; i < jobCount; i++) {
-        Job exclusiveJob = (Job) exclusiveJobs.get(i);
-        exclusiveJob.setLockOwner(lockOwner);
-        exclusiveJobIds[i] = exclusiveJob.getId();
-      }
-      log.debug("locking jobs " + ArrayUtil.toString(exclusiveJobIds));
-      // execute exclusive jobs in separate transaction
-      postJobsExecution(jbpmContext, exclusiveJobIds);
+      jbpmContext.getGraphSession().lockProcessInstance(processInstance);
     }
-    else {
-      // lock job to prevent others from deleting it
-      job.setLockOwner(lockOwner);
-      log.debug("executing " + job);
-      executeJob(job, jbpmContext);
-    }
-    return null;
+
+    // mark job as locked to prevent other parts of the engine from deleting it
+    job.setLockOwner(toString());
+    return job;
   }
 
   static void executeJob(Job job, JbpmContext jbpmContext) {
+    log.debug("executing " + job);
     try {
       if (job.execute(jbpmContext)) {
         jbpmContext.getJobSession().deleteJob(job);
       }
     }
-    catch (RuntimeException e) {
-      // nothing to do but clean up and exit
-      throw e;
-    }
     catch (Exception e) {
-      // save data about recoverable error condition
-      log.error("exception while executing " + job, e);
-      StringWriter memoryWriter = new StringWriter();
-      e.printStackTrace(new PrintWriter(memoryWriter));
-      job.setException(memoryWriter.toString());
-      job.setRetries(job.getRetries() - 1);
+      log.debug("exception while executing " + job, e);
+      if (!DbPersistenceService.isPersistenceException(e)) {
+        StringWriter memoryWriter = new StringWriter();
+        e.printStackTrace(new PrintWriter(memoryWriter));
+        job.setException(memoryWriter.toString());
+      }
+      else {
+        // allowing a transaction to proceed after a persistence exception is unsafe
+        throw e instanceof RuntimeException ? (RuntimeException) e :
+        	new JbpmException("failed to execute " + job, e);
+      }
     }
   }
 
-  private static void postJobsExecution(JbpmContext jbpmContext, long[] exclusiveJobIds)
-      throws NamingException, JMSException {
-    Services services = jbpmContext.getServices();
-    JmsMessageServiceFactory messageServiceFactory = (JmsMessageServiceFactory) services.getServiceFactory(Services.SERVICENAME_MESSAGE);
-    Destination destination = messageServiceFactory.getCommandDestination();
-
-    JmsMessageService messageService = (JmsMessageService) services.getMessageService();
-    Session session = messageService.getSession();
-    MessageProducer producer = session.createProducer(destination);
-    try {
-      Command command = new ExecuteJobsCommand(exclusiveJobIds);
-      Message message = session.createObjectMessage(command);
-      producer.send(message);
-    }
-    finally {
-      producer.close();
-    }
-  }
-
   private static Log log = LogFactory.getLog(ExecuteJobCommand.class);
 }

Deleted: jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/main/java/org/jbpm/ejb/impl/ExecuteJobsCommand.java
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/main/java/org/jbpm/ejb/impl/ExecuteJobsCommand.java	2009-05-07 16:08:10 UTC (rev 4761)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/main/java/org/jbpm/ejb/impl/ExecuteJobsCommand.java	2009-05-07 18:52:11 UTC (rev 4762)
@@ -1,61 +0,0 @@
-/*
- * 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.ejb.impl;
-
-import java.util.Iterator;
-import java.util.List;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.jbpm.JbpmContext;
-import org.jbpm.command.Command;
-import org.jbpm.job.Job;
-import org.jbpm.util.ArrayUtil;
-
-/**
- * Batch job processing command.
- * 
- * @author Alejandro Guizar
- */
-public class ExecuteJobsCommand implements Command {
-
-  private long[] jobIds;
-
-  private static final long serialVersionUID = 1L;
-  private static Log log = LogFactory.getLog(ExecuteJobsCommand.class);
-
-  public ExecuteJobsCommand(long[] jobIds) {
-    this.jobIds = jobIds;
-  }
-
-  public Object execute(JbpmContext jbpmContext) throws Exception {
-    log.debug("executing jobs " + ArrayUtil.toString(jobIds));
-    List jobs = jbpmContext.getJobSession().loadJobs(jobIds);
-    for (Iterator i = jobs.iterator(); i.hasNext();) {
-      Job job = (Job) i.next();
-      job.execute(jbpmContext);
-    }
-    return null;
-  }
-
-}

Added: jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/AbstractEnterpriseTestCase.java
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/AbstractEnterpriseTestCase.java	                        (rev 0)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/AbstractEnterpriseTestCase.java	2009-05-07 18:52:11 UTC (rev 4762)
@@ -0,0 +1,200 @@
+/*
+ * 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.enterprise;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.Destination;
+import javax.jms.Session;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+
+import org.apache.cactus.ServletTestCase;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.cfg.Environment;
+import org.jbpm.JbpmContext;
+import org.jbpm.command.Command;
+import org.jbpm.command.CommandService;
+import org.jbpm.command.DeleteProcessDefinitionCommand;
+import org.jbpm.command.DeployProcessCommand;
+import org.jbpm.command.GetProcessInstanceCommand;
+import org.jbpm.command.SignalCommand;
+import org.jbpm.command.StartProcessInstanceCommand;
+import org.jbpm.ejb.LocalCommandServiceHome;
+import org.jbpm.graph.def.EventCallback;
+import org.jbpm.graph.def.ProcessDefinition;
+import org.jbpm.graph.exe.ProcessInstance;
+import org.jbpm.persistence.db.DbPersistenceServiceFactory;
+import org.jbpm.svc.Services;
+
+public abstract class AbstractEnterpriseTestCase extends ServletTestCase {
+
+  protected CommandService commandService;
+
+  private List processDefinitions = new ArrayList();
+
+  private static Context environment;
+  private static LocalCommandServiceHome commandServiceHome;
+  private static Destination commandQueue;
+  private static ConnectionFactory jmsConnectionFactory;
+
+  private static final Log log = LogFactory.getLog(AbstractEnterpriseTestCase.class);
+
+  protected AbstractEnterpriseTestCase() {
+  }
+
+  protected void setUp() throws Exception {
+    commandService = createCommandService();
+    log.info("### " + getName() + " started ###");
+  }
+
+  protected void tearDown() throws Exception {
+    log.info("### " + getName() + " done ###");
+    for (Iterator i = processDefinitions.iterator(); i.hasNext();) {
+      ProcessDefinition processDefinition = (ProcessDefinition) i.next();
+      deleteProcessDefinition(processDefinition.getId());
+    }
+    commandService = null;
+    EventCallback.clear();
+  }
+
+  protected CommandService createCommandService() throws Exception {
+    if (commandServiceHome == null) {
+      commandServiceHome = (LocalCommandServiceHome) getEnvironment()
+          .lookup("ejb/CommandServiceBean");
+    }
+    return commandServiceHome.create();
+  }
+
+  protected ProcessDefinition deployProcessDefinition(String xml) {
+    ProcessDefinition processDefinition = (ProcessDefinition) commandService.execute(
+        new DeployProcessCommand(xml));
+    processDefinitions.add(processDefinition);
+    return processDefinition;
+  }
+
+  protected ProcessDefinition deployProcessDefinition(byte[] processArchive) {
+    ProcessDefinition processDefinition = (ProcessDefinition) commandService.execute(
+        new DeployProcessCommand(processArchive));
+    processDefinitions.add(processDefinition);
+    return processDefinition;
+  }
+
+  protected ProcessInstance startProcessInstance(String processName) {
+    StartProcessInstanceCommand command = new StartProcessInstanceCommand();
+    command.setProcessDefinitionName(processName);
+    command.setVariables(Collections.singletonMap("eventCallback", new EventCallback()));
+    return (ProcessInstance) commandService.execute(command);
+  }
+
+  protected void signalToken(long tokenId) {
+    commandService.execute(new SignalCommand(tokenId, null));
+  }
+
+  protected boolean hasProcessInstanceEnded(final long processInstanceId) {
+    ProcessInstance processInstance = (ProcessInstance) commandService.execute(
+        new GetProcessInstanceCommand(processInstanceId));
+    return processInstance.hasEnded();
+  }
+
+  protected Object getVariable(final long processInstanceId, final String variableName) {
+    return commandService.execute(new Command() {
+      private static final long serialVersionUID = 1L;
+
+      public Object execute(JbpmContext jbpmContext) throws Exception {
+        ProcessInstance processInstance = jbpmContext.loadProcessInstance(processInstanceId);
+        return processInstance.getContextInstance().getVariable(variableName);
+      }
+    });
+  }
+
+  protected String getHibernateDialect() {
+    return (String) commandService.execute(new Command() {
+      private static final long serialVersionUID = 1L;
+
+      public Object execute(JbpmContext jbpmContext) throws Exception {
+        DbPersistenceServiceFactory factory = (DbPersistenceServiceFactory) jbpmContext
+            .getServiceFactory(Services.SERVICENAME_PERSISTENCE);
+        return factory.getConfiguration().getProperty(Environment.DIALECT);
+      }
+    });
+  }
+
+  private void deleteProcessDefinition(long processDefinitionId) throws Exception {
+    if (true) {
+      // [JBPM-1812] Fix tests that don't cleanup the database
+      // deleting process definition makes subsequent tests unstable
+      return;
+    }
+
+    Connection jmsConnection = getConnectionFactory().createConnection();
+    try {
+      Session jmsSession = jmsConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+      try {
+        Command command = new DeleteProcessDefinitionCommand(processDefinitionId);
+        jmsSession.createProducer(getCommandQueue()).send(jmsSession.createObjectMessage(command));
+      }
+      finally {
+        jmsSession.close();
+      }
+    }
+    finally {
+      jmsConnection.close();
+    }
+  }
+
+  private Destination getCommandQueue() throws NamingException {
+    if (commandQueue == null) {
+      commandQueue = (Destination) getEnvironment().lookup("jms/CommandQueue");
+    }
+    return commandQueue;
+  }
+
+  private ConnectionFactory getConnectionFactory() throws NamingException {
+    if (jmsConnectionFactory == null) {
+      jmsConnectionFactory = (ConnectionFactory) getEnvironment()
+          .lookup("jms/JbpmConnectionFactory");
+    }
+    return jmsConnectionFactory;
+  }
+
+  private static Context getEnvironment() throws NamingException {
+    if (environment == null) {
+      Context initial = new InitialContext();
+      try {
+        environment = (Context) initial.lookup("java:comp/env");
+      }
+      finally {
+        initial.close();
+      }
+    }
+    return environment;
+  }
+
+}
\ No newline at end of file

Modified: jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/config/AppServerConfigurationsTest.java
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/config/AppServerConfigurationsTest.java	2009-05-07 16:08:10 UTC (rev 4761)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/config/AppServerConfigurationsTest.java	2009-05-07 18:52:11 UTC (rev 4762)
@@ -24,7 +24,6 @@
 import junit.framework.Test;
 
 import org.apache.cactus.ServletTestCase;
-
 import org.jbpm.JbpmConfiguration;
 import org.jbpm.enterprise.IntegrationTestSetup;
 import org.jbpm.msg.jms.JmsMessageServiceFactory;

Added: jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/console/ConsoleAvailabilityTest.java
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/console/ConsoleAvailabilityTest.java	                        (rev 0)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/console/ConsoleAvailabilityTest.java	2009-05-07 18:52:11 UTC (rev 4762)
@@ -0,0 +1,105 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2006, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file 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.enterprise.console;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Heiko.Braun <heiko.braun at jboss.com>
+ */
+public class ConsoleAvailabilityTest extends TestCase
+{
+  /**
+   * Verify if the console has been deployed successfully
+   */
+  public void testConsoleDeployment() throws IOException
+  {
+    String host = "localhost";
+    int port = 8080;
+
+    String bindAddress = System.getProperty("jboss.bind.address");
+    if (bindAddress != null)
+    {
+      int colonIndex = bindAddress.lastIndexOf(':');
+      if (colonIndex != -1)
+      {
+        host = bindAddress.substring(0, colonIndex);
+        port = Integer.parseInt(bindAddress.substring(colonIndex + 1));
+      }
+      else
+        host = bindAddress;
+    }
+
+    URL url = new URL("http", host, port, "/jbpm-console");
+    System.out.println("Console URL: " + url);
+
+    List response = doGet(url);
+    String status = (String) response.get(0);
+    assertEquals(HttpURLConnection.HTTP_OK, Integer.parseInt(status));
+  }
+
+  /**
+   * Gets the resource pointed by the given URL.
+   * @param url a pointer to a resource
+   * @return response data in the following order:
+   * <
+   * <li>Code</li>
+   * <li>Message</li>
+   * <li>Body</li>
+   * @throws IOException
+   */
+  static List doGet(URL url) throws IOException
+  {
+    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+    try 
+    {
+      List response = new ArrayList();
+      response.add(Integer.toString(connection.getResponseCode()));
+      response.add(connection.getResponseMessage());
+
+      BufferedReader connReader = new BufferedReader(new InputStreamReader(connection
+          .getInputStream()));
+      try
+      {
+        for (String line; (line = connReader.readLine()) != null;)
+          response.add(line);
+      }
+      finally
+      {
+        connReader.close();
+      }
+      return response;
+    }
+    finally 
+    {
+      connection.disconnect();
+    }
+  }
+}

Modified: jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/ejbtimer/EjbSchedulerTest.java
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/ejbtimer/EjbSchedulerTest.java	2009-05-07 16:08:10 UTC (rev 4761)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/ejbtimer/EjbSchedulerTest.java	2009-05-07 18:52:11 UTC (rev 4762)
@@ -22,29 +22,16 @@
 package org.jbpm.enterprise.ejbtimer;
 
 import java.rmi.RemoteException;
-import java.util.Collections;
 
-import javax.naming.Context;
-import javax.naming.InitialContext;
-
 import junit.framework.Test;
 
-import org.apache.cactus.ServletTestCase;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
 import org.jbpm.JbpmContext;
 import org.jbpm.command.Command;
-import org.jbpm.command.DeployProcessCommand;
-import org.jbpm.command.StartProcessInstanceCommand;
-import org.jbpm.ejb.LocalCommandService;
-import org.jbpm.ejb.LocalCommandServiceHome;
+import org.jbpm.enterprise.AbstractEnterpriseTestCase;
 import org.jbpm.enterprise.IntegrationTestSetup;
 import org.jbpm.graph.def.Event;
 import org.jbpm.graph.def.EventCallback;
-import org.jbpm.graph.def.ProcessDefinition;
 import org.jbpm.graph.exe.ProcessInstance;
-import org.jbpm.graph.exe.Token;
 import org.jbpm.scheduler.ejbtimer.EntitySchedulerService;
 
 /**
@@ -52,39 +39,14 @@
  * 
  * @author Alejandro Guizar
  */
-public class EjbSchedulerTest extends ServletTestCase {
+public class EjbSchedulerTest extends AbstractEnterpriseTestCase {
 
-  private LocalCommandService commandService;
-
-  private static LocalCommandServiceHome commandServiceHome;
-
-  private static final Log log = LogFactory.getLog(EjbSchedulerTest.class);
-
   public static Test suite() throws Exception {
     return new IntegrationTestSetup(EjbSchedulerTest.class, "enterprise-test.war");
   }
 
-  protected void setUp() throws Exception {
-    if (commandServiceHome == null) {
-      Context initialContext = new InitialContext();
-      try {
-        commandServiceHome = (LocalCommandServiceHome) initialContext.lookup("java:comp/env/ejb/CommandServiceBean");
-      }
-      finally {
-        initialContext.close();
-      }
-    }
-    commandService = commandServiceHome.create();
-    log.info("### " + getName() + " started ###");
-  }
-
-  protected void tearDown() throws Exception {
-    log.info("### " + getName() + " done ###");
-    commandService = null;
-  }
-
   public void testScheduleFuture() throws Exception {
-    deployProcess("<process-definition name='future'>"
+    deployProcessDefinition("<process-definition name='future'>"
         + "  <event type='process-end'>"
         + "    <action expression='#{eventCallback.processEnd}'/>"
         + "  </event>"
@@ -97,13 +59,13 @@
         + "  </state>"
         + "  <end-state name='end' />"
         + "</process-definition>");
-    long processId = launchProcess("future").getId();
+    long processInstanceId = startProcessInstance("future").getId();
     EventCallback.waitForEvent(Event.EVENTTYPE_PROCESS_END);
-    assertTrue(isProcessFinished(processId));
+    assertTrue("expected process instance " + processInstanceId + " to have ended", hasProcessInstanceEnded(processInstanceId));
   }
 
   public void testSchedulePast() throws Exception {
-    deployProcess("<process-definition name='past'>"
+    deployProcessDefinition("<process-definition name='past'>"
         + "  <event type='process-end'>"
         + "    <action expression='#{eventCallback.processEnd}'/>"
         + "  </event>"
@@ -116,13 +78,13 @@
         + "  </state>"
         + "  <end-state name='end' />"
         + "</process-definition>");
-    long processId = launchProcess("past").getId();
+    long processInstanceId = startProcessInstance("past").getId();
     EventCallback.waitForEvent(Event.EVENTTYPE_PROCESS_END);
-    assertTrue(isProcessFinished(processId));
+    assertTrue("expected process instance " + processInstanceId + " to have ended", hasProcessInstanceEnded(processInstanceId));
   }
 
   public void testScheduleRepeat() throws Exception {
-    deployProcess("<process-definition name='repeat'>"
+    deployProcessDefinition("<process-definition name='repeat'>"
         + "  <event type='timer'>"
         + "    <action expression='#{eventCallback.timer}'/>"
         + "  </event>"
@@ -135,17 +97,18 @@
         + "  </state>"
         + "  <end-state name='end' />"
         + "</process-definition>");
-    long processId = launchProcess("repeat").getId();
+    ProcessInstance processInstance = startProcessInstance("repeat");
+    long processInstanceId = processInstance.getId();
     for (int i = 0; i < 3; i++) {
       EventCallback.waitForEvent(Event.EVENTTYPE_TIMER);
-      assertEquals("a", getProcessState(processId));
+      assertEquals("a", getProcessInstanceState(processInstanceId));
     }
-    signalProcess(processId);
-    assertTrue(isProcessFinished(processId));
+    signalToken(processInstance.getRootToken().getId());
+    assertTrue("expected process instance " + processInstanceId + " to have ended", hasProcessInstanceEnded(processInstanceId));
   }
 
   public void testCancel() throws Exception {
-    deployProcess("<process-definition name='cancel'>"
+    deployProcessDefinition("<process-definition name='cancel'>"
         + "  <event type='timer'>"
         + "    <action expression='#{eventCallback.timer}'/>"
         + "  </event>"
@@ -154,33 +117,41 @@
         + "  </start-state>"
         + "  <state name='a'>"
         + "    <timer duedate='1 second' repeat='1 second' />"
+        + "    <transition to='b' />"
+        + "  </state>"
+        + "  <state name='b'>"
         + "    <transition to='end' />"
         + "  </state>"
         + "  <end-state name='end' />"
         + "</process-definition>");
-    ProcessInstance process = launchProcess("cancel");
-    long processId = process.getId();
+    ProcessInstance processInstance = startProcessInstance("cancel");
+    long processInstanceId = processInstance.getId();
     // first expiration
     EventCallback.waitForEvent(Event.EVENTTYPE_TIMER);
-    assertEquals("a", getProcessState(processId));
+    assertEquals("a", getProcessInstanceState(processInstanceId));
     // repeated expiration
     EventCallback.waitForEvent(Event.EVENTTYPE_TIMER);
-    assertEquals("a", getProcessState(processId));
+    assertEquals("a", getProcessInstanceState(processInstanceId));
+    // cancel timer
+    long rootTokenId = processInstance.getRootToken().getId();
+    signalToken(rootTokenId);
     // no more expirations
-    cancelTimer("a", process.getRootToken().getId());
     try {
-      EventCallback.waitForEvent(Event.EVENTTYPE_TIMER, 2000);
+      EventCallback.waitForEvent(Event.EVENTTYPE_TIMER, 1000);
+      System.out.println("canceled timer fired again, probably due to race condition");
+      EventCallback.waitForEvent(Event.EVENTTYPE_TIMER, 1000);
       fail("expected timeout exception");
     }
     catch (org.jbpm.JbpmException e) {
       // timeout exception was expected
     }
-    signalProcess(processId);
-    assertTrue(isProcessFinished(processId));
+    // proceed to end state
+    signalToken(rootTokenId);
+    assertTrue("expected process instance " + processInstanceId + " to have ended", hasProcessInstanceEnded(processInstanceId));
   }
 
   public void testScheduleSequence() throws Exception {
-    deployProcess("<process-definition name='sequence'>"
+    deployProcessDefinition("<process-definition name='sequence'>"
         + "  <event type='process-end'>"
         + "    <action expression='#{eventCallback.processEnd}'/>"
         + "  </event>"
@@ -191,39 +162,38 @@
         + "    <transition to='a' />"
         + "  </start-state>"
         + "  <state name='a'>"
-        + "    <timer duedate='500 milliseconds' transition='timeout' />"
+        + "    <timer duedate='1 second' transition='timeout' />"
         + "    <transition name='timeout' to='b' />"
         + "  </state>"
         + "  <state name='b'>"
-        + "    <timer duedate='500 milliseconds' transition='timeout' />"
+        + "    <timer duedate='1 second' transition='timeout' />"
         + "    <transition name='timeout' to='c' />"
         + "  </state>"
         + "  <state name='c'>"
-        + "    <timer duedate='500 milliseconds' transition='timeout' />"
+        + "    <timer duedate='1 second' transition='timeout' />"
         + "    <transition name='timeout' to='d' />"
         + "  </state>"
         + "  <state name='d'>"
-        + "    <timer duedate='500 milliseconds' transition='timeout' />"
+        + "    <timer duedate='1 second' transition='timeout' />"
         + "    <transition name='timeout' to='e' />"
         + "  </state>"
         + "  <state name='e'>"
-        + "    <timer duedate='500 milliseconds' transition='timeout' />"
+        + "    <timer duedate='1 second' transition='timeout' />"
         + "    <transition name='timeout' to='end' />"
         + "  </state>"
         + "  <end-state name='end' />"
         + "</process-definition>");
-    long processId = launchProcess("sequence").getId();
-    char state = 'b';
-    for (int i = 0; i < 4; i++) {
+    long processInstanceId = startProcessInstance("sequence").getId();
+    for (char state = 'b'; state <= 'e'; state++) {
       EventCallback.waitForEvent(Event.EVENTTYPE_TIMER);
-      assertEquals(Character.toString(state++), getProcessState(processId));
+      assertEquals(Character.toString(state), getProcessInstanceState(processInstanceId));
     }
     EventCallback.waitForEvent(Event.EVENTTYPE_PROCESS_END);
-    assertTrue(isProcessFinished(processId));
+    assertTrue("expected process instance " + processInstanceId + " to have ended", hasProcessInstanceEnded(processInstanceId));
   }
 
   public void testScheduleFork() throws Exception {
-    deployProcess("<process-definition name='fork'>"
+    deployProcessDefinition("<process-definition name='fork'>"
         + "  <event type='process-end'>"
         + "    <action expression='#{eventCallback.processEnd}'/>"
         + "  </event>"
@@ -238,91 +208,46 @@
         + "    <transition name='e' to='e' />"
         + "  </fork>"
         + "  <state name='a'>"
-        + "    <timer duedate='0.25 seconds' transition='timeout' />"
+        + "    <timer duedate='0 seconds' transition='timeout' />"
         + "    <transition name='timeout' to='j' />"
         + "  </state>"
         + "  <state name='b'>"
-        + "    <timer duedate='0.5 seconds' transition='timeout' />"
+        + "    <timer duedate='1 second' transition='timeout' />"
         + "    <transition name='timeout' to='j' />"
         + "  </state>"
         + "  <state name='c'>"
-        + "    <timer duedate='0.75 seconds' transition='timeout' />"
+        + "    <timer duedate='2 seconds' transition='timeout' />"
         + "    <transition name='timeout' to='j' />"
         + "  </state>"
         + "  <state name='d'>"
-        + "    <timer duedate='1 second' transition='timeout' />"
+        + "    <timer duedate='3 seconds' transition='timeout' />"
         + "    <transition name='timeout' to='j' />"
         + "  </state>"
         + "  <state name='e'>"
-        + "    <timer duedate='1.25 second' transition='timeout' />"
+        + "    <timer duedate='4 seconds' transition='timeout' />"
         + "    <transition name='timeout' to='j' />"
         + "  </state>"
-        + "  <join name='j' async='exclusive'>"
+        + "  <join name='j' async='exclusive' lock='UPGRADE'>"
         + "    <transition to='end' />"
         + "  </join>"
         + "  <end-state name='end' />"
         + "</process-definition>");
-    long processId = launchProcess("fork").getId();
+    long processInstanceId = startProcessInstance("fork").getId();
     EventCallback.waitForEvent(Event.EVENTTYPE_PROCESS_END);
-    assertTrue(isProcessFinished(processId));
+    assertTrue("expected process instance " + processInstanceId + " to have ended", hasProcessInstanceEnded(processInstanceId));
   }
 
-  private ProcessDefinition deployProcess(String xml) throws RemoteException {
-    return (ProcessDefinition) commandService.execute(new DeployProcessCommand(xml));
-  }
-
-  private ProcessInstance launchProcess(String processName) throws RemoteException {
-    StartProcessInstanceCommand command = new StartProcessInstanceCommand();
-    command.setProcessDefinitionName(processName);
-    command.setVariables(Collections.singletonMap("eventCallback", new EventCallback()));
-    return (ProcessInstance) commandService.execute(command);
-  }
-
-  private void signalProcess(final long processId) throws RemoteException {
-    commandService.execute(new Command() {
-
-      private static final long serialVersionUID = 1L;
-
-      public Object execute(JbpmContext jbpmContext) throws Exception {
-        jbpmContext.loadProcessInstanceForUpdate(processId).signal();
-        return null;
-      }
-    });
-  }
-
-  private String getProcessState(final long processId) throws RemoteException {
+  private String getProcessInstanceState(final long processInstanceId) throws RemoteException {
     return (String) commandService.execute(new Command() {
 
       private static final long serialVersionUID = 1L;
 
       public Object execute(JbpmContext jbpmContext) throws Exception {
-        return jbpmContext.loadProcessInstance(processId).getRootToken().getNode().getName();
+        return jbpmContext.loadProcessInstance(processInstanceId)
+            .getRootToken()
+            .getNode()
+            .getName();
       }
     });
   }
-
-  private boolean isProcessFinished(final long processId) throws RemoteException {
-    Boolean isFinished = (Boolean) commandService.execute(new Command() {
-
-      private static final long serialVersionUID = 1L;
-
-      public Object execute(JbpmContext jbpmContext) throws Exception {
-        return Boolean.valueOf(jbpmContext.loadProcessInstance(processId).hasEnded());
-      }
-    });
-    return isFinished.booleanValue();
-  }
-
-  private void cancelTimer(final String timerName, final long tokenId) throws RemoteException {
-    commandService.execute(new Command() {
-
-      private static final long serialVersionUID = 1L;
-
-      public Object execute(JbpmContext jbpmContext) throws Exception {
-        Token token = jbpmContext.loadToken(tokenId);
-        jbpmContext.getServices().getSchedulerService().deleteTimersByName(timerName, token);
-        return null;
-      }
-    });
-  }
 }

Modified: jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/jbpm1903/JBPM1903Test.java
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/jbpm1903/JBPM1903Test.java	2009-05-07 16:08:10 UTC (rev 4761)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/jbpm1903/JBPM1903Test.java	2009-05-07 18:52:11 UTC (rev 4762)
@@ -29,58 +29,25 @@
 
 import javax.jms.JMSException;
 import javax.jms.Queue;
-import javax.naming.Context;
-import javax.naming.InitialContext;
 
 import junit.framework.Test;
 
-import org.apache.cactus.ServletTestCase;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.jbpm.JbpmContext;
-import org.jbpm.command.Command;
-import org.jbpm.command.DeployProcessCommand;
-import org.jbpm.command.StartProcessInstanceCommand;
-import org.jbpm.ejb.LocalCommandService;
-import org.jbpm.ejb.LocalCommandServiceHome;
+import org.jbpm.enterprise.AbstractEnterpriseTestCase;
 import org.jbpm.enterprise.IntegrationTestSetup;
-import org.jbpm.graph.exe.ProcessInstance;
 import org.jbpm.util.IoUtil;
 
 /**
+ * ENC is not reachable from within action handlers.
+ * 
+ * @see <a href="https://jira.jboss.org/jira/browse/JBPM-1903">JBPM-1903</a>
  * @author Alejandro Guizar
  */
-public class JBPM1903Test extends ServletTestCase {
+public class JBPM1903Test extends AbstractEnterpriseTestCase {
 
-  private LocalCommandService commandService;
-  private static LocalCommandServiceHome commandServiceHome;
-
-  private static final Log log = LogFactory.getLog(JBPM1903Test.class);
-
   public static Test suite() throws Exception {
     return new IntegrationTestSetup(JBPM1903Test.class, "enterprise-test.war");
   }
 
-  protected void setUp() throws Exception {
-    if (commandServiceHome == null) {
-      Context initialContext = new InitialContext();
-      try {
-        commandServiceHome = (LocalCommandServiceHome) initialContext.lookup("java:comp/env/ejb/CommandServiceBean");
-      }
-      finally {
-        initialContext.close();
-      }
-    }
-    commandService = commandServiceHome.create();
-    log.info("### " + getName() + " started ###");
-  }
-
-  protected void tearDown() throws Exception {
-    log.info("### " + getName() + " done ###");
-    commandService = null;
-  }
-
   public void testENCInActionHandler() throws IOException, JMSException {
     byte[] processArchive = createProcessArchive();
     deployProcessDefinition(processArchive);
@@ -106,24 +73,4 @@
     zipOut.close();
     return memoryOut.toByteArray();
   }
-
-  private void deployProcessDefinition(byte[] processArchive) {
-    commandService.execute(new DeployProcessCommand(processArchive));
-  }
-
-  private ProcessInstance startProcessInstance(String processName) {
-    return (ProcessInstance) commandService.execute(new StartProcessInstanceCommand().processDefinitionName(processName));
-  }
-
-  private Object getVariable(final long processInstanceId, final String variableName) {
-    return commandService.execute(new Command() {
-
-      private static final long serialVersionUID = 1L;
-
-      public Object execute(JbpmContext jbpmContext) throws Exception {
-        ProcessInstance processInstance = jbpmContext.loadProcessInstance(processInstanceId);
-        return processInstance.getContextInstance().getVariable(variableName);
-      }
-    });
-  }
 }

Copied: jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/jbpm1952 (from rev 4073, jbpm3/trunk/modules/enterprise/src/test/java/org/jbpm/enterprise/jbpm1952)

Deleted: jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/jbpm1952/JBPM1952Test.java
===================================================================
--- jbpm3/trunk/modules/enterprise/src/test/java/org/jbpm/enterprise/jbpm1952/JBPM1952Test.java	2009-02-28 01:05:43 UTC (rev 4073)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/jbpm1952/JBPM1952Test.java	2009-05-07 18:52:11 UTC (rev 4762)
@@ -1,72 +0,0 @@
-package org.jbpm.enterprise.jbpm1952;
-
-import junit.framework.Test;
-
-import org.jboss.bpm.api.test.IntegrationTestSetup;
-import org.jbpm.enterprise.AbstractEnterpriseTestCase;
-
-/**
- * Use JMS instead of DBMS for storing jobs, so that each job is not taken by multiple job executor
- * threads.
- * 
- * @see <a href="https://jira.jboss.org/jira/browse/JBPM-1952">JBPM-1952</a>
- * @author Alejandro Guizar
- */
-public class JBPM1952Test extends AbstractEnterpriseTestCase {
-
-  private static final int PROCESS_EXECUTION_COUNT = 20;
-
-  public static Test suite() {
-    return new IntegrationTestSetup(JBPM1952Test.class, "enterprise-test.war");
-  }
-
-  public void testStaleStateInAsyncFork() {
-    deployProcessDefinition("<process-definition name='jbpm1952'>"
-        + "  <event type='process-end'>"
-        + "    <action expression='#{eventCallback.processEnd}' />"
-        + "  </event>"
-        + "  <start-state>"
-        + "    <transition to='a' />"
-        + "  </start-state>"
-        + "  <node name='a' async='true'>"
-        + "    <transition to='b' />"
-        + "  </node>"
-        + "  <node name='b' async='true'>"
-        + "    <transition to='fork' />"
-        + "  </node>"
-        + "  <fork name='fork'>"
-        + "    <transition to='c1' name='to_c1'/>"
-        + "    <transition to='c2' name='to_c2'/>"
-        + "    <transition to='c3' name='to_c3'/>"
-        + "  </fork>"
-        + "  <node name='c1' async='true'>"
-        + "    <transition to='join' />"
-        + "  </node>"
-        + "  <node name='c2' async='true'>"
-        + "    <transition to='join' />"
-        + "  </node>"
-        + "  <node name='c3' async='true'>"
-        + "    <transition to='join' />"
-        + "  </node>"
-        + "  <join name='join' async='exclusive'>"
-        + "    <transition to='d' />"
-        + "  </join>"
-        + "  <node name='d' async='true'>"
-        + "    <transition to='end' />"
-        + "  </node>"
-        + "  <end-state name='end'/>"
-        + "</process-definition>");
-
-    long[] processInstanceIds = new long[PROCESS_EXECUTION_COUNT];
-    for (int i = 0; i < PROCESS_EXECUTION_COUNT; i++) {
-      processInstanceIds[i] = startProcessInstance("jbpm1952").getId();
-    }
-
-    for (int i = 0; i < PROCESS_EXECUTION_COUNT; i++) {
-      long processInstanceId = processInstanceIds[i];
-      assertTrue("expected process instance " + processInstanceId + " to have ended",
-          waitForProcessInstanceEnd(processInstanceId));
-    }
-  }
-
-}

Copied: jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/jbpm1952/JBPM1952Test.java (from rev 4073, jbpm3/trunk/modules/enterprise/src/test/java/org/jbpm/enterprise/jbpm1952/JBPM1952Test.java)
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/jbpm1952/JBPM1952Test.java	                        (rev 0)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/jbpm1952/JBPM1952Test.java	2009-05-07 18:52:11 UTC (rev 4762)
@@ -0,0 +1,75 @@
+package org.jbpm.enterprise.jbpm1952;
+
+import junit.framework.Test;
+
+import org.jbpm.enterprise.AbstractEnterpriseTestCase;
+import org.jbpm.enterprise.IntegrationTestSetup;
+import org.jbpm.graph.def.Event;
+import org.jbpm.graph.def.EventCallback;
+
+/**
+ * Use JMS instead of DBMS for storing jobs, so that each job is not taken by multiple job executor
+ * threads.
+ * 
+ * @see <a href="https://jira.jboss.org/jira/browse/JBPM-1952">JBPM-1952</a>
+ * @author Alejandro Guizar
+ */
+public class JBPM1952Test extends AbstractEnterpriseTestCase {
+
+  private static final int PROCESS_EXECUTION_COUNT = 20;
+
+  public static Test suite() {
+    return new IntegrationTestSetup(JBPM1952Test.class, "enterprise-test.war");
+  }
+
+  public void testStaleStateInAsyncFork() {
+    deployProcessDefinition("<process-definition name='jbpm1952'>"
+        + "  <event type='process-end'>"
+        + "    <action expression='#{eventCallback.processEnd}' />"
+        + "  </event>"
+        + "  <start-state>"
+        + "    <transition to='a' />"
+        + "  </start-state>"
+        + "  <node name='a' async='true'>"
+        + "    <transition to='b' />"
+        + "  </node>"
+        + "  <node name='b' async='true'>"
+        + "    <transition to='fork' />"
+        + "  </node>"
+        + "  <fork name='fork'>"
+        + "    <transition to='c1' name='to_c1'/>"
+        + "    <transition to='c2' name='to_c2'/>"
+        + "    <transition to='c3' name='to_c3'/>"
+        + "  </fork>"
+        + "  <node name='c1' async='true'>"
+        + "    <transition to='join' />"
+        + "  </node>"
+        + "  <node name='c2' async='true'>"
+        + "    <transition to='join' />"
+        + "  </node>"
+        + "  <node name='c3' async='true'>"
+        + "    <transition to='join' />"
+        + "  </node>"
+        + "  <join name='join' async='exclusive'>"
+        + "    <transition to='d' />"
+        + "  </join>"
+        + "  <node name='d' async='true'>"
+        + "    <transition to='end' />"
+        + "  </node>"
+        + "  <end-state name='end'/>"
+        + "</process-definition>");
+
+    long[] processInstanceIds = new long[PROCESS_EXECUTION_COUNT];
+    for (int i = 0; i < PROCESS_EXECUTION_COUNT; i++) {
+      processInstanceIds[i] = startProcessInstance("jbpm1952").getId();
+    }
+
+    EventCallback.waitForEvent(PROCESS_EXECUTION_COUNT, Event.EVENTTYPE_PROCESS_END);
+
+    for (int i = 0; i < PROCESS_EXECUTION_COUNT; i++) {
+      long processInstanceId = processInstanceIds[i];
+      assertTrue("expected process instance " + processInstanceId + " to have ended", hasProcessInstanceEnded(processInstanceId));
+    }
+  }
+
+}

Modified: jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/jms/JmsMessageTest.java
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/jms/JmsMessageTest.java	2009-05-07 16:08:10 UTC (rev 4761)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/jms/JmsMessageTest.java	2009-05-07 18:52:11 UTC (rev 4762)
@@ -21,75 +21,29 @@
  */
 package org.jbpm.enterprise.jms;
 
-import java.util.Collections;
-
-import javax.naming.Context;
-import javax.naming.InitialContext;
-
 import junit.framework.Test;
 
-import org.apache.cactus.ServletTestCase;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.hibernate.cfg.Environment;
-
-import org.jbpm.JbpmContext;
-import org.jbpm.command.Command;
-import org.jbpm.command.DeployProcessCommand;
-import org.jbpm.command.StartProcessInstanceCommand;
-import org.jbpm.ejb.LocalCommandService;
-import org.jbpm.ejb.LocalCommandServiceHome;
+import org.jbpm.enterprise.AbstractEnterpriseTestCase;
 import org.jbpm.enterprise.IntegrationTestSetup;
 import org.jbpm.graph.def.Event;
 import org.jbpm.graph.def.EventCallback;
-import org.jbpm.graph.def.ProcessDefinition;
-import org.jbpm.graph.exe.ProcessInstance;
 import org.jbpm.msg.jms.JmsMessageService;
-import org.jbpm.persistence.db.DbPersistenceServiceFactory;
-import org.jbpm.svc.Services;
 
 /**
  * Exercises for the {@linkplain JmsMessageService JMS message service}.
  * 
  * @author Alejandro Guizar
  */
-public class JmsMessageTest extends ServletTestCase {
+public class JmsMessageTest extends AbstractEnterpriseTestCase {
 
-  private LocalCommandService commandService;
+  private static final int PROCESS_INSTANCE_COUNT = 5;
 
-  private static LocalCommandServiceHome commandServiceHome;
-
-  static final int processExecutionCount = 5;
-  static final int maxWaitTime = 10 * 1000;
-
-  private static final Log log = LogFactory.getLog(JmsMessageTest.class);
-
   public static Test suite() throws Exception {
     return new IntegrationTestSetup(JmsMessageTest.class, "enterprise-test.war");
   }
 
-  protected void setUp() throws Exception {
-    if (commandServiceHome == null) {
-      Context initialContext = new InitialContext();
-      try {
-        commandServiceHome = (LocalCommandServiceHome) initialContext.lookup("java:comp/env/ejb/CommandServiceBean");
-      }
-      finally {
-        initialContext.close();
-      }
-    }
-    commandService = commandServiceHome.create();
-    log.info("### " + getName() + " started ###");
-  }
-
-  protected void tearDown() throws Exception {
-    log.info("### " + getName() + " done ###");
-    commandService = null;
-    EventCallback.clear();
-  }
-
   public void testAsyncNode() {
-    deployProcess("<process-definition name='node'>"
+    deployProcessDefinition("<process-definition name='node'>"
         + "  <event type='process-end'>"
         + "    <action expression='#{eventCallback.processEnd}'/>"
         + "  </event>"
@@ -102,13 +56,13 @@
         + "  <end-state name='end' />"
         + "</process-definition>");
 
-    long processId = launchProcess("node").getId();
+    long processInstanceId = startProcessInstance("node").getId();
     EventCallback.waitForEvent(Event.EVENTTYPE_PROCESS_END);
-    assertTrue("Process has ended", hasProcessEnded(processId));
+    assertTrue("expected process instance " + processInstanceId + " to have ended", hasProcessInstanceEnded(processInstanceId));
   }
 
   public void testAsyncAction() {
-    deployProcess("<process-definition name='action'>"
+    deployProcessDefinition("<process-definition name='action'>"
         + "  <start-state name='start'>"
         + "    <transition to='a' />"
         + "  </start-state>"
@@ -126,15 +80,15 @@
         + "  <end-state name='end' />"
         + "</process-definition>");
 
-    long processId = launchProcess("action").getId();
+    long processInstanceId = startProcessInstance("action").getId();
     EventCallback.waitForEvent(Event.EVENTTYPE_NODE_ENTER);
     EventCallback.waitForEvent(Event.EVENTTYPE_NODE_LEAVE);
     EventCallback.waitForEvent(Event.EVENTTYPE_TRANSITION);
-    assertTrue("Process has ended", hasProcessEnded(processId));
+    assertTrue("expected process instance " + processInstanceId + " to have ended", hasProcessInstanceEnded(processInstanceId));
   }
 
   public void testAsyncSequence() {
-    deployProcess("<process-definition name='sequence'>"
+    deployProcessDefinition("<process-definition name='sequence'>"
         + "  <event type='process-end'>"
         + "    <action expression='#{eventCallback.processEnd}'/>"
         + "  </event>"
@@ -159,9 +113,9 @@
         + "  <end-state name='end' />"
         + "</process-definition>");
 
-    long processId = launchProcess("sequence").getId();
+    long processInstanceId = startProcessInstance("sequence").getId();
     EventCallback.waitForEvent(Event.EVENTTYPE_PROCESS_END);
-    assertTrue("Process has ended", hasProcessEnded(processId));
+    assertTrue("expected process instance " + processInstanceId + " to have ended", hasProcessInstanceEnded(processInstanceId));
   }
 
   public void testAsyncFork() throws Exception {
@@ -170,7 +124,7 @@
       return;
     }
 
-    deployProcess("<process-definition name='fork'>"
+    deployProcessDefinition("<process-definition name='fork'>"
         + "  <event type='process-end'>"
         + "    <action expression='#{eventCallback.processEnd}'/>"
         + "  </event>"
@@ -205,25 +159,18 @@
         + "  <end-state name='end' />"
         + "</process-definition>");
 
-    long processId = launchProcess("fork").getId();
+    long processInstanceId = startProcessInstance("fork").getId();
     EventCallback.waitForEvent(Event.EVENTTYPE_PROCESS_END);
-    assertTrue("Process has ended", hasProcessEnded(processId));
+    assertTrue("expected process instance " + processInstanceId + " to have ended", hasProcessInstanceEnded(processInstanceId));
   }
 
-  private String getHibernateDialect() {
-    return (String) commandService.execute(new Command() {
-
-      private static final long serialVersionUID = 1L;
-
-      public Object execute(JbpmContext jbpmContext) throws Exception {
-        DbPersistenceServiceFactory factory = (DbPersistenceServiceFactory) jbpmContext.getServiceFactory(Services.SERVICENAME_PERSISTENCE);
-        return factory.getConfiguration().getProperty(Environment.DIALECT);
-      }
-    });
-  }
-
   public void testAsyncExecutions() {
-    deployProcess("<process-definition name='execution'>"
+    // [JBPM-1811] JmsMessageTest fails intermittently on HSQLDB
+    if (getHibernateDialect().indexOf("HSQL") != -1) {
+      return;
+    }
+
+    deployProcessDefinition("<process-definition name='execution'>"
         + "  <event type='process-end'>"
         + "    <action expression='#{eventCallback.processEnd}' />"
         + "  </event>"
@@ -254,41 +201,18 @@
         + "  <end-state name='end' />"
         + "</process-definition>");
 
-    long[] processIds = new long[processExecutionCount];
-    for (int i = 0; i < processExecutionCount; i++) {
-      processIds[i] = launchProcess("execution").getId();
+    long[] processInstanceIds = new long[PROCESS_INSTANCE_COUNT];
+    for (int i = 0; i < PROCESS_INSTANCE_COUNT; i++) {
+      processInstanceIds[i] = startProcessInstance("execution").getId();
       EventCallback.waitForEvent(Event.EVENTTYPE_NODE_ENTER);
     }
 
-    EventCallback.waitForEvent(processExecutionCount, Event.EVENTTYPE_NODE_LEAVE);
-    EventCallback.waitForEvent(processExecutionCount, Event.EVENTTYPE_PROCESS_END);
+    EventCallback.waitForEvent(PROCESS_INSTANCE_COUNT, Event.EVENTTYPE_NODE_LEAVE);
+    EventCallback.waitForEvent(PROCESS_INSTANCE_COUNT, Event.EVENTTYPE_PROCESS_END);
 
-    for (int i = 0; i < processExecutionCount; i++) {
-      long processId = processIds[i];
-      assertTrue("expected process " + processId + " to have ended", hasProcessEnded(processId));
+    for (int i = 0; i < PROCESS_INSTANCE_COUNT; i++) {
+      long processInstanceId = processInstanceIds[i];
+      assertTrue("expected process instance " + processInstanceId + " to have ended", hasProcessInstanceEnded(processInstanceId));
     }
   }
-
-  private ProcessDefinition deployProcess(String xml) {
-    return (ProcessDefinition) commandService.execute(new DeployProcessCommand(xml));
-  }
-
-  private ProcessInstance launchProcess(String processName) {
-    StartProcessInstanceCommand command = new StartProcessInstanceCommand();
-    command.setProcessDefinitionName(processName);
-    command.setVariables(Collections.singletonMap("eventCallback", new EventCallback()));
-    return (ProcessInstance) commandService.execute(command);
-  }
-
-  private boolean hasProcessEnded(final long processId) {
-    Boolean isFinished = (Boolean) commandService.execute(new Command() {
-
-      private static final long serialVersionUID = 1L;
-
-      public Object execute(JbpmContext jbpmContext) throws Exception {
-        return Boolean.valueOf(jbpmContext.loadProcessInstance(processId).hasEnded());
-      }
-    });
-    return isFinished.booleanValue();
-  }
 }

Modified: jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/jta/JtaDbPersistenceTest.java
===================================================================
--- jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/jta/JtaDbPersistenceTest.java	2009-05-07 16:08:10 UTC (rev 4761)
+++ jbpm3/branches/jbpm-3.2.5.SP/modules/enterprise/src/test/java/org/jbpm/enterprise/jta/JtaDbPersistenceTest.java	2009-05-07 18:52:11 UTC (rev 4762)
@@ -21,191 +21,80 @@
  */
 package org.jbpm.enterprise.jta;
 
-import javax.naming.Context;
-import javax.naming.InitialContext;
-import javax.naming.NamingException;
-import javax.transaction.UserTransaction;
-
 import junit.framework.Test;
 
-import org.apache.cactus.ServletTestCase;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.HibernateException;
 
 import org.jbpm.JbpmConfiguration;
 import org.jbpm.JbpmContext;
+import org.jbpm.command.Command;
+import org.jbpm.command.CommandService;
+import org.jbpm.command.impl.CommandServiceImpl;
+import org.jbpm.enterprise.AbstractEnterpriseTestCase;
 import org.jbpm.enterprise.IntegrationTestSetup;
-import org.jbpm.graph.def.ProcessDefinition;
-import org.jbpm.graph.exe.ProcessInstance;
-import org.jbpm.persistence.jta.JtaDbPersistenceService;
 
-public class JtaDbPersistenceTest extends ServletTestCase {
+public class JtaDbPersistenceTest extends AbstractEnterpriseTestCase {
 
-  private JbpmConfiguration jbpmConfiguration;
-  private UserTransaction tx;
-  private boolean rollback;
+  private static final Log log = LogFactory.getLog(JtaDbPersistenceTest.class);
 
-  private static long definitionId;
-
   public static Test suite() throws Exception {
     return new IntegrationTestSetup(JtaDbPersistenceTest.class, "enterprise-test.war");
   }
 
-  protected void setUp() throws Exception {
-    jbpmConfiguration = JbpmConfiguration.getInstance();
+  protected CommandService createCommandService() throws Exception {
+    return getName().indexOf("CMT") != -1 ? super.createCommandService() : new CommandServiceImpl(
+        JbpmConfiguration.getInstance());
   }
 
-  public void testUserTx() throws Exception {
-    tx = getUserTransaction();
-    testServiceTx();
+  public void testCMTSuccess() throws Exception {
+    playTransaction(false);
   }
 
-  public void testUserTxRollback() throws Exception {
-    tx = getUserTransaction();
-    testServiceTxRollback();
+  public void testCMTFailure() throws Exception {
+    playTransaction(true);
   }
 
-  public void testServiceTx() throws Exception {
-    long definitionId = deployProcess();
-    long instanceId = launchProcess(definitionId);
-    signal(instanceId);
-    assertTrue(hasEnded(instanceId));
+  public void testBMTSuccess() throws Exception {
+    playTransaction(false);
   }
 
-  public void testServiceTxRollback() throws Exception {
-    rollback = true;
-    long definitionId = deployProcess();
-    long instanceId = launchProcess(definitionId);
-    signal(instanceId);
-    assertFalse(hasEnded(instanceId));
+  public void testBMTFailure() throws Exception {
+    playTransaction(true);
   }
 
-  private long deployProcess() throws Exception {
-    if (definitionId == 0) {
-      try {
-        if (tx != null) tx.begin();
-        JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
-        try {
-          assertEquals(tx == null, isTxCreatedByService(jbpmContext));
-          ProcessDefinition definition = ProcessDefinition.parseXmlString("<process-definition name='tx'>"
-              + "  <start-state name='start'>"
-              + "    <transition to='midway' />"
-              + "  </start-state>"
-              + "  <state name='midway'>"
-              + "    <transition to='end' />"
-              + "  </state>"
-              + "  <end-state name='end' />"
-              + "</process-definition>");
-          jbpmContext.deployProcessDefinition(definition);
-          definitionId = definition.getId();
-        }
-        catch (RuntimeException e) {
-          if (tx == null) jbpmContext.setRollbackOnly();
-          throw e;
-        }
-        finally {
-          jbpmContext.close();
-        }
-        if (tx != null) tx.commit();
-      }
-      catch (Exception e) {
-        if (tx != null) tx.rollback();
-        throw e;
-      }
-    }
-    return definitionId;
-  }
-
-  private long launchProcess(long definitionId) throws Exception {
+  private void playTransaction(boolean fail) throws Exception {
+    deployProcessDefinition("<process-definition name='jta'>"
+        + "  <start-state name='start'>"
+        + "    <transition to='midway' />"
+        + "  </start-state>"
+        + "  <state name='midway'>"
+        + "    <transition to='end' />"
+        + "  </state>"
+        + "  <end-state name='end' />"
+        + "</process-definition>");
+    long processInstanceId = startProcessInstance("jta").getId();
     try {
-      if (tx != null) tx.begin();
-      JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
-      ProcessInstance instance;
-      try {
-        assertEquals(tx == null, isTxCreatedByService(jbpmContext));
-        ProcessDefinition definition = jbpmContext.getGraphSession().loadProcessDefinition(
-            definitionId);
-        instance = new ProcessInstance(definition);
-        instance.signal();
-        jbpmContext.save(instance);
-      }
-      catch (RuntimeException e) {
-        if (tx == null) jbpmContext.setRollbackOnly();
-        throw e;
-      }
-      finally {
-        jbpmContext.close();
-      }
-      if (tx != null) tx.commit();
-      return instance.getId();
+      signal(processInstanceId, fail);
     }
-    catch (Exception e) {
-      if (tx != null) tx.rollback();
-      throw e;
+    catch (RuntimeException e) {
+      log.debug("signal failed on process instance #" + processInstanceId, e);
     }
+    assertEquals(!fail, hasProcessInstanceEnded(processInstanceId));
   }
 
-  private void signal(long instanceId) throws Exception {
-    try {
-      if (tx != null) tx.begin();
-      JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
-      try {
-        assertEquals(tx == null, isTxCreatedByService(jbpmContext));
-        ProcessInstance instance = jbpmContext.loadProcessInstanceForUpdate(instanceId);
-        instance.signal();
-        if (rollback && tx == null) jbpmContext.setRollbackOnly();
-      }
-      catch (RuntimeException e) {
-        if (tx == null) jbpmContext.setRollbackOnly();
-        throw e;
-      }
-      finally {
-        jbpmContext.close();
-      }
-      if (tx != null) {
-        if (rollback)
-          tx.rollback();
-        else
-          tx.commit();
-      }
-    }
-    catch (Exception e) {
-      if (tx != null) tx.rollback();
-      throw e;
-    }
-  }
+  private void signal(final long processInstanceId, final boolean fail) throws Exception {
+    commandService.execute(new Command() {
 
-  private boolean hasEnded(long instanceId) throws Exception {
-    try {
-      if (tx != null) tx.begin();
-      JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
-      ProcessInstance instance;
-      try {
-        assertEquals(tx == null, isTxCreatedByService(jbpmContext));
-        instance = jbpmContext.loadProcessInstanceForUpdate(instanceId);
+      private static final long serialVersionUID = 1L;
+
+      public Object execute(JbpmContext jbpmContext) throws Exception {
+        jbpmContext.loadProcessInstance(processInstanceId).signal();
+        if (fail) throw new HibernateException("simulated failure");
+        return null;
       }
-      catch (RuntimeException e) {
-        if (tx == null) jbpmContext.setRollbackOnly();
-        throw e;
-      }
-      finally {
-        jbpmContext.close();
-      }
-      if (tx != null) tx.commit();
-      return instance.hasEnded();
-    }
-    catch (Exception e) {
-      if (tx != null) tx.rollback();
-      throw e;
-    }
+    });
   }
 
-  private boolean isTxCreatedByService(JbpmContext jbpmContext) {
-    JtaDbPersistenceService persistenceService = (JtaDbPersistenceService) jbpmContext.getServices()
-        .getPersistenceService();
-    return persistenceService.isJtaTxCreated();
-  }
-
-  private static UserTransaction getUserTransaction() throws NamingException {
-    Context initial = new InitialContext();
-    return (UserTransaction) initial.lookup("java:comp/UserTransaction");
-  }
 }




More information about the jbpm-commits mailing list