[jbpm-commits] JBoss JBPM SVN: r3535 - in jbpm3/trunk/modules/core/src: main/java/org/jbpm/persistence and 6 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Tue Dec 23 08:31:21 EST 2008


Author: alex.guizar at jboss.com
Date: 2008-12-23 08:31:21 -0500 (Tue, 23 Dec 2008)
New Revision: 3535

Added:
   jbpm3/trunk/modules/core/src/test/java/org/jbpm/jbpm1775/
   jbpm3/trunk/modules/core/src/test/java/org/jbpm/jbpm1775/JBPM1775Test.java
Modified:
   jbpm3/trunk/modules/core/src/main/java/org/jbpm/graph/def/GraphElement.java
   jbpm3/trunk/modules/core/src/main/java/org/jbpm/persistence/PersistenceService.java
   jbpm3/trunk/modules/core/src/main/java/org/jbpm/persistence/db/DbPersistenceService.java
   jbpm3/trunk/modules/core/src/main/java/org/jbpm/persistence/jta/JtaDbPersistenceService.java
   jbpm3/trunk/modules/core/src/main/resources/org/jbpm/graph/def/ProcessDefinition.hbm.xml
   jbpm3/trunk/modules/core/src/main/resources/org/jbpm/graph/def/Transition.hbm.xml
   jbpm3/trunk/modules/core/src/main/resources/org/jbpm/taskmgmt/def/Task.hbm.xml
Log:
[JBPM-1775] check whether the transaction is still active before scanning the exception handlers, so that exception handlers can be loaded lazily.

Modified: jbpm3/trunk/modules/core/src/main/java/org/jbpm/graph/def/GraphElement.java
===================================================================
--- jbpm3/trunk/modules/core/src/main/java/org/jbpm/graph/def/GraphElement.java	2008-12-23 12:43:49 UTC (rev 3534)
+++ jbpm3/trunk/modules/core/src/main/java/org/jbpm/graph/def/GraphElement.java	2008-12-23 13:31:21 UTC (rev 3535)
@@ -40,13 +40,14 @@
 import org.jbpm.instantiation.UserCodeInterceptorConfig;
 import org.jbpm.job.ExecuteActionJob;
 import org.jbpm.msg.MessageService;
+import org.jbpm.persistence.db.DbPersistenceService;
 import org.jbpm.signal.EventService;
 import org.jbpm.svc.Service;
 import org.jbpm.svc.Services;
 import org.jbpm.util.EqualsUtil;
 
-public abstract class GraphElement implements Identifiable, Serializable
-{
+public abstract class GraphElement implements Identifiable, Serializable {
+
   private static final long serialVersionUID = 1L;
 
   long id = 0;
@@ -56,12 +57,10 @@
   protected Map events = null;
   protected List exceptionHandlers = null;
 
-  public GraphElement()
-  {
+  public GraphElement() {
   }
 
-  public GraphElement(String name)
-  {
+  public GraphElement(String name) {
     setName(name);
   }
 
@@ -77,61 +76,56 @@
   /**
    * gets the events, keyd by eventType (java.lang.String).
    */
-  public Map getEvents()
-  {
+  public Map getEvents() {
     return events;
   }
 
-  public boolean hasEvents()
-  {
+  public boolean hasEvents() {
     return ((events != null) && (events.size() > 0));
   }
 
-  public Event getEvent(String eventType)
-  {
+  public Event getEvent(String eventType) {
     Event event = null;
-    if (events != null)
-    {
-      event = (Event)events.get(eventType);
+    if (events != null) {
+      event = (Event) events.get(eventType);
     }
     return event;
   }
 
-  public boolean hasEvent(String eventType)
-  {
+  public boolean hasEvent(String eventType) {
     boolean hasEvent = false;
-    if (events != null)
-    {
+    if (events != null) {
       hasEvent = events.containsKey(eventType);
     }
     return hasEvent;
   }
 
-  public Event addEvent(Event event)
-  {
-    if (event == null)
-      throw new IllegalArgumentException("can't add a null event to a graph element");
-    if (event.getEventType() == null)
-      throw new IllegalArgumentException("can't add an event without an eventType to a graph element");
-    if (events == null)
+  public Event addEvent(Event event) {
+    if (event == null) {
+      throw new IllegalArgumentException("can't add null event to graph element");
+    }
+    if (event.getEventType() == null) {
+      throw new IllegalArgumentException("can't add an event without type to graph element");
+    }
+    if (events == null) {
       events = new HashMap();
+    }
     events.put(event.getEventType(), event);
     event.graphElement = this;
     return event;
   }
 
-  public Event removeEvent(Event event)
-  {
+  public Event removeEvent(Event event) {
     Event removedEvent = null;
-    if (event == null)
-      throw new IllegalArgumentException("can't remove a null event from a graph element");
-    if (event.getEventType() == null)
-      throw new IllegalArgumentException("can't remove an event without an eventType from a graph element");
-    if (events != null)
-    {
-      removedEvent = (Event)events.remove(event.getEventType());
-      if (removedEvent != null)
-      {
+    if (event == null) {
+      throw new IllegalArgumentException("can't remove null event from graph element");
+    }
+    if (event.getEventType() == null) {
+      throw new IllegalArgumentException("can't remove an event without type from graph element");
+    }
+    if (events != null) {
+      removedEvent = (Event) events.remove(event.getEventType());
+      if (removedEvent != null) {
         event.graphElement = null;
       }
     }
@@ -143,90 +137,76 @@
   /**
    * is the list of exception handlers associated to this graph element.
    */
-  public List getExceptionHandlers()
-  {
+  public List getExceptionHandlers() {
     return exceptionHandlers;
   }
 
-  public ExceptionHandler addExceptionHandler(ExceptionHandler exceptionHandler)
-  {
-    if (exceptionHandler == null)
-      throw new IllegalArgumentException("can't add a null exceptionHandler to a graph element");
-    if (exceptionHandlers == null)
+  public ExceptionHandler addExceptionHandler(ExceptionHandler exceptionHandler) {
+    if (exceptionHandler == null) {
+      throw new IllegalArgumentException("can't add null exceptionHandler to graph element");
+    }
+    if (exceptionHandlers == null) {
       exceptionHandlers = new ArrayList();
+    }
     exceptionHandlers.add(exceptionHandler);
     exceptionHandler.graphElement = this;
     return exceptionHandler;
   }
 
-  public void removeExceptionHandler(ExceptionHandler exceptionHandler)
-  {
-    if (exceptionHandler == null)
-      throw new IllegalArgumentException("can't remove a null exceptionHandler from an graph element");
-    if (exceptionHandlers != null)
-    {
-      if (exceptionHandlers.remove(exceptionHandler))
-      {
-        exceptionHandler.graphElement = null;
-      }
+  public void removeExceptionHandler(ExceptionHandler exceptionHandler) {
+    if (exceptionHandler == null) {
+      throw new IllegalArgumentException("can't remove null exceptionHandler from graph element");
     }
+    if (exceptionHandlers != null && exceptionHandlers.remove(exceptionHandler)) {
+      exceptionHandler.graphElement = null;
+    }
   }
 
-  public void reorderExceptionHandler(int oldIndex, int newIndex)
-  {
-    if ((exceptionHandlers != null) && (Math.min(oldIndex, newIndex) >= 0) && (Math.max(oldIndex, newIndex) < exceptionHandlers.size()))
-    {
+  public void reorderExceptionHandler(int oldIndex, int newIndex) {
+    if ((exceptionHandlers != null)
+        && (Math.min(oldIndex, newIndex) >= 0)
+        && (Math.max(oldIndex, newIndex) < exceptionHandlers.size())) {
       Object o = exceptionHandlers.remove(oldIndex);
       exceptionHandlers.add(newIndex, o);
+    } else {
+      throw new IndexOutOfBoundsException("couldn't reorder element from index '" + oldIndex
+          + "' to index '" + newIndex + "' in " + exceptionHandlers);
     }
-    else
-    {
-      throw new IndexOutOfBoundsException("couldn't reorder element from index '" + oldIndex + "' to index '" + newIndex + "' in exceptionHandler-list '"
-          + exceptionHandlers + "'");
-    }
   }
 
   // event handling ///////////////////////////////////////////////////////////
 
-  public void fireEvent(String eventType, ExecutionContext executionContext)
-  {
+  public void fireEvent(String eventType, ExecutionContext executionContext) {
     log.debug("event '" + eventType + "' on '" + this + "' for '" + executionContext.getToken() + "'");
-    try
-    {
+    try {
       executionContext.setEventSource(this);
-      
-      // TODO: Is is a valid condition that the jbpmContext is not there?
+
+      // TODO: Is it a valid condition that the jbpmContext is not there?
       JbpmContext jbpmContext = executionContext.getJbpmContext();
-      if (jbpmContext != null)
-      {
+      if (jbpmContext != null) {
         Services services = jbpmContext.getServices();
-        if (services != null)
-        {
-          EventService evService = (EventService)services.getService(EventService.SERVICE_NAME);
-          if (evService != null)
-          {
+        if (services != null) {
+          EventService evService = (EventService) services.getService(EventService.SERVICE_NAME);
+          if (evService != null) {
             evService.fireEvent(eventType, this, executionContext);
           }
         }
       }
-      
+
       fireAndPropagateEvent(eventType, executionContext);
-    }
-    finally
-    {
+    } finally {
       executionContext.setEventSource(null);
     }
   }
 
-  public void fireAndPropagateEvent(String eventType, ExecutionContext executionContext)
-  {
-    // calculate if the event was fired on this element or if it was a propagated event
+  public void fireAndPropagateEvent(String eventType, ExecutionContext executionContext) {
+    // calculate if the event was fired on this element or if it was a
+    // propagated event
     boolean isPropagated = !(this.equals(executionContext.getEventSource()));
 
     // execute static actions
     Event event = getEvent(eventType);
-    if (event != null)
-    {
+    if (event != null) {
       // update the context
       executionContext.setEvent(event);
       // execute the static actions specified in the process definition
@@ -242,30 +222,22 @@
 
     // propagate the event to the parent element
     GraphElement parent = getParent();
-    if (parent != null)
-    {
+    if (parent != null) {
       parent.fireAndPropagateEvent(eventType, executionContext);
     }
   }
 
-  void executeActions(List actions, ExecutionContext executionContext, boolean isPropagated)
-  {
-    if (actions != null)
-    {
+  void executeActions(List actions, ExecutionContext executionContext, boolean isPropagated) {
+    if (actions != null) {
       Iterator iter = actions.iterator();
-      while (iter.hasNext())
-      {
-        Action action = (Action)iter.next();
-        if (action.acceptsPropagatedEvents() || (!isPropagated))
-        {
-          if (action.isAsync())
-          {
+      while (iter.hasNext()) {
+        Action action = (Action) iter.next();
+        if (action.acceptsPropagatedEvents() || (!isPropagated)) {
+          if (action.isAsync()) {
             ExecuteActionJob job = createAsyncActionExecutionJob(executionContext.getToken(), action);
-            MessageService messageService = (MessageService)Services.getCurrentService(Services.SERVICENAME_MESSAGE);
+            MessageService messageService = (MessageService) Services.getCurrentService(Services.SERVICENAME_MESSAGE);
             messageService.send(job);
-          }
-          else
-          {
+          } else {
             executeAction(action, executionContext);
           }
         }
@@ -273,8 +245,7 @@
     }
   }
 
-  protected ExecuteActionJob createAsyncActionExecutionJob(Token token, Action action)
-  {
+  protected ExecuteActionJob createAsyncActionExecutionJob(Token token, Action action) {
     ExecuteActionJob job = new ExecuteActionJob(token);
     job.setAction(action);
     job.setDueDate(new Date());
@@ -282,8 +253,7 @@
     return job;
   }
 
-  public void executeAction(Action action, ExecutionContext executionContext)
-  {
+  public void executeAction(Action action, ExecutionContext executionContext) {
     Token token = executionContext.getToken();
 
     // create action log
@@ -296,89 +266,55 @@
     // is already locked, the token doesn't need to be locked.
     boolean actionMustBeLocked = (executionContext.getEvent() != null) && (!token.isLocked());
 
-    try
-    {
+    try {
       // update the execution context
       executionContext.setAction(action);
 
       // execute the action
       log.debug("executing action '" + action + "'");
       String lockOwnerId = "token[" + token.getId() + "]";
-      try
-      {
-        if (actionMustBeLocked)
-        {
+      try {
+        if (actionMustBeLocked) {
           token.lock(lockOwnerId);
         }
 
-        if (UserCodeInterceptorConfig.userCodeInterceptor != null)
-        {
+        if (UserCodeInterceptorConfig.userCodeInterceptor != null) {
           UserCodeInterceptorConfig.userCodeInterceptor.executeAction(action, executionContext);
-        }
-        else
-        {
+        } else {
           action.execute(executionContext);
         }
 
-      }
-      finally
-      {
-        if (actionMustBeLocked)
-        {
+      } finally {
+        if (actionMustBeLocked) {
           token.unlock(lockOwnerId);
         }
       }
 
-    }
-    catch (Exception exception)
-    {
-      // NOTE that Error's are not caught because that might halt the JVM and mask the original Error.
+    } catch (Exception exception) {
+      // NOTE that Errors are not caught because that might halt the JVM and mask the original Error
       log.error("action threw exception: " + exception.getMessage(), exception);
 
       // log the action exception
       actionLog.setException(exception);
 
-      // If an exception is already set we are in an action of an exception handler
-      // in this case don't give the exception to the handlers but throw it to the client
-      // see https://jira.jboss.org/jira/browse/JBPM-1887
-      if (executionContext.getException() == null)
-      {
-        // if an exception handler is available
-        raiseException(exception, executionContext);
-      }
-      else
-      {
-        // if there is no parent we need to throw an action exception to the client
-        if (exception instanceof JbpmException)
-        {
-          throw (JbpmException)exception;
-        }
-        else
-        {
-          throw new DelegationException(exception, executionContext);
-        }
-      }
-    }
-    finally
-    {
+      // if an exception handler is available
+      raiseException(exception, executionContext);
+    } finally {
       executionContext.setAction(null);
       token.endCompositeLog();
     }
   }
 
-  List getRuntimeActionsForEvent(ExecutionContext executionContext, String eventType)
-  {
+  List getRuntimeActionsForEvent(ExecutionContext executionContext, String eventType) {
     List runtimeActionsForEvent = null;
     List runtimeActions = executionContext.getProcessInstance().getRuntimeActions();
-    if (runtimeActions != null)
-    {
+    if (runtimeActions != null) {
       Iterator iter = runtimeActions.iterator();
-      while (iter.hasNext())
-      {
-        RuntimeAction runtimeAction = (RuntimeAction)iter.next();
+      while (iter.hasNext()) {
+        RuntimeAction runtimeAction = (RuntimeAction) iter.next();
         // if the runtime-action action is registered on this element and this eventType
-        if ((this.equals(runtimeAction.getGraphElement())) && (eventType.equals(runtimeAction.getEventType())))
-        {
+        if ((this.equals(runtimeAction.getGraphElement()))
+            && (eventType.equals(runtimeAction.getEventType()))) {
           // ... add its action to the list of runtime actions
           if (runtimeActionsForEvent == null)
             runtimeActionsForEvent = new ArrayList();
@@ -418,67 +354,82 @@
    * exception handler does not throw an exception, the exception is considered handled. Otherwise the search for an
    * applicable exception handler continues where it left of with the newly thrown exception.
    */
-  public void raiseException(Throwable exception, ExecutionContext executionContext) throws DelegationException
-  {
-    boolean isHandled = false;
-    if (exceptionHandlers != null)
-    {
-      try
-      {
-        ExceptionHandler exceptionHandler = findExceptionHandler(exception);
-        if (exceptionHandler != null)
-        {
-          executionContext.setException(exception);
-          exceptionHandler.handleException(this, executionContext);
-          isHandled = true;
+  public void raiseException(Throwable exception, ExecutionContext executionContext)
+      throws DelegationException {
+    if (isAbleToHandleExceptions(executionContext)) {
+      if (exceptionHandlers != null) {
+        try {
+          ExceptionHandler exceptionHandler = findExceptionHandler(exception);
+          if (exceptionHandler != null) {
+            executionContext.setException(exception);
+            exceptionHandler.handleException(this, executionContext);
+            return;
+          }
+        } catch (Exception e) {
+          // NOTE that Error's are not caught because that might halt the JVM
+          // and mask the original Error.
+          exception = e;
         }
       }
-      catch (Exception e)
-      {
-        // NOTE that Error's are not caught because that might halt the JVM and mask the original Error.
-        exception = e;
-      }
-    }
 
-    if (!isHandled)
-    {
       GraphElement parent = getParent();
       // if this graph element has a parent
-      if ((parent != null) && (parent != this))
-      {
-        // action to the parent
+      if ((parent != null) && (!equals(parent))) {
+        // raise to the parent
         parent.raiseException(exception, executionContext);
+        return;
       }
-      else
-      {
-        // rollback the actions
-        // rollbackActions(executionContext);
+    }
 
-        // if there is no parent we need to throw an action exception to the client
-        if (exception instanceof JbpmException)
-        {
-          throw (JbpmException)exception;
+    // rollback the actions
+    // rollbackActions(executionContext);
+
+    // if there is no parent we need to throw a delegation exception to the client
+    throw exception instanceof JbpmException ? (JbpmException) exception : new DelegationException(
+        exception, executionContext);
+  }
+
+  /**
+   * Tells whether the given context is valid for exception handling by checking for:
+   * <ul>
+   * <li>the absence of a previous exception</li>
+   * <li>an active transaction, or no transaction at all</li>
+   * </ul>
+   */
+  private static boolean isAbleToHandleExceptions(ExecutionContext executionContext) {
+    /* if an exception is already set, we are already handling an exception;
+     * in this case don't give the exception to the handlers but throw it to the client
+     * see https://jira.jboss.org/jira/browse/JBPM-1887 */
+    if (executionContext.getException() != null)
+      return false;
+
+    /* check whether the transaction is still active before scanning the exception handlers.
+     * that way we can load the exception handlers lazily
+     * see https://jira.jboss.org/jira/browse/JBPM-1775 */
+    JbpmContext jbpmContext = executionContext.getJbpmContext();
+    if (jbpmContext != null) {
+      Services services = jbpmContext.getServices();
+      if (services != null) {
+        Service service = services.getPersistenceService();
+        if (service instanceof DbPersistenceService) {
+          DbPersistenceService persistenceService = (DbPersistenceService) service;
+          return persistenceService.isTransactionActive() || persistenceService.getTransaction() == null;
         }
-        else
-        {
-          throw new DelegationException(exception, executionContext);
-        }
       }
     }
+
+    // no transaction detected, probably running in memory only
+    return true;
   }
 
-  protected ExceptionHandler findExceptionHandler(Throwable exception)
-  {
+  protected ExceptionHandler findExceptionHandler(Throwable exception) {
     ExceptionHandler exceptionHandler = null;
 
-    if (exceptionHandlers != null)
-    {
+    if (exceptionHandlers != null) {
       Iterator iter = exceptionHandlers.iterator();
-      while (iter.hasNext() && (exceptionHandler == null))
-      {
-        ExceptionHandler candidate = (ExceptionHandler)iter.next();
-        if (candidate.matches(exception))
-        {
+      while (iter.hasNext() && (exceptionHandler == null)) {
+        ExceptionHandler candidate = (ExceptionHandler) iter.next();
+        if (candidate.matches(exception)) {
           exceptionHandler = candidate;
         }
       }
@@ -487,20 +438,17 @@
     return exceptionHandler;
   }
 
-  public GraphElement getParent()
-  {
+  public GraphElement getParent() {
     return processDefinition;
   }
 
   /**
    * @return all the parents of this graph element ordered by age.
    */
-  public List getParents()
-  {
+  public List getParents() {
     List parents = new ArrayList();
     GraphElement parent = getParent();
-    if (parent != null)
-    {
+    if (parent != null) {
       parent.addParentChain(parents);
     }
     return parents;
@@ -509,33 +457,26 @@
   /**
    * @return this graph element plus all the parents ordered by age.
    */
-  public List getParentChain()
-  {
+  public List getParentChain() {
     List parents = new ArrayList();
     this.addParentChain(parents);
     return parents;
   }
 
-  void addParentChain(List parentChain)
-  {
+  void addParentChain(List parentChain) {
     parentChain.add(this);
     GraphElement parent = getParent();
-    if (parent != null)
-    {
+    if (parent != null) {
       parent.addParentChain(parentChain);
     }
   }
 
-  public String toString()
-  {
+  public String toString() {
     String className = getClass().getName();
     className = className.substring(className.lastIndexOf('.') + 1);
-    if (name != null)
-    {
+    if (name != null) {
       className = className + "(" + name + ")";
-    }
-    else
-    {
+    } else {
       className = className + "(" + Integer.toHexString(System.identityHashCode(this)) + ")";
     }
     return className;
@@ -544,45 +485,37 @@
   // equals ///////////////////////////////////////////////////////////////////
   // hack to support comparing hibernate proxies against the real objects
   // since this always falls back to ==, we don't need to overwrite the hashcode
-  public boolean equals(Object o)
-  {
+  public boolean equals(Object o) {
     return EqualsUtil.equals(this, o);
   }
 
   // getters and setters //////////////////////////////////////////////////////
 
-  public long getId()
-  {
+  public long getId() {
     return id;
   }
 
-  public String getName()
-  {
+  public String getName() {
     return name;
   }
 
-  public void setName(String name)
-  {
+  public void setName(String name) {
     this.name = name;
   }
 
-  public String getDescription()
-  {
+  public String getDescription() {
     return description;
   }
 
-  public void setDescription(String description)
-  {
+  public void setDescription(String description) {
     this.description = description;
   }
 
-  public ProcessDefinition getProcessDefinition()
-  {
+  public ProcessDefinition getProcessDefinition() {
     return processDefinition;
   }
 
-  public void setProcessDefinition(ProcessDefinition processDefinition)
-  {
+  public void setProcessDefinition(ProcessDefinition processDefinition) {
     this.processDefinition = processDefinition;
   }
 

Modified: jbpm3/trunk/modules/core/src/main/java/org/jbpm/persistence/PersistenceService.java
===================================================================
--- jbpm3/trunk/modules/core/src/main/java/org/jbpm/persistence/PersistenceService.java	2008-12-23 12:43:49 UTC (rev 3534)
+++ jbpm3/trunk/modules/core/src/main/java/org/jbpm/persistence/PersistenceService.java	2008-12-23 13:31:21 UTC (rev 3535)
@@ -38,8 +38,17 @@
   ContextSession getContextSession();
   TaskMgmtSession getTaskMgmtSession();
 
+  /**
+   * @deprecated use {@link org.jbpm.tx.TxService} instead.
+   */
   boolean isRollbackOnly();
+  /**
+   * @deprecated use {@link org.jbpm.tx.TxService} instead.
+   */
   void setRollbackOnly(boolean isRollbackOnly);
+  /**
+   * @deprecated use {@link org.jbpm.tx.TxService} instead.
+   */
   void setRollbackOnly();
 
   void setGraphSession(GraphSession graphSession);

Modified: jbpm3/trunk/modules/core/src/main/java/org/jbpm/persistence/db/DbPersistenceService.java
===================================================================
--- jbpm3/trunk/modules/core/src/main/java/org/jbpm/persistence/db/DbPersistenceService.java	2008-12-23 12:43:49 UTC (rev 3534)
+++ jbpm3/trunk/modules/core/src/main/java/org/jbpm/persistence/db/DbPersistenceService.java	2008-12-23 13:31:21 UTC (rev 3535)
@@ -197,17 +197,21 @@
     return connection;
   }
   
-  protected boolean isTransactionActive() {
-      return (isTransactionEnabled && (transaction != null)) ; 
+  public boolean isTransactionActive() {
+    return transaction != null && transaction.isActive();
   }
-  
+
+  protected boolean isTransactionExternallyManaged() {
+    return !(isTransactionEnabled && transaction != null);
+  }
+
   public void close() {
 
     if ( (session!=null)
-         && !isTransactionActive()
+         && isTransactionExternallyManaged()
          && (isRollbackOnly())
        ) {
-      throw new JbpmException("setRollbackOnly was invoked while configuration specifies user managed transactions");
+      throw new JbpmException("setRollbackOnly was invoked while transaction is being managed externally");
     }
     
     if ( (isTransactionEnabled)
@@ -235,8 +239,8 @@
     
     Exception flushException = flushSession();
     if (flushException!=null) {
-      // JBPM-1465 transaction has been either committed or rolled back at this point
-      // on the other hand, it is possible that no transaction is underway
+      // JBPM-1465: transaction is either committed or rolled back at this point;
+      // it is also possible that the transaction was initiated externally
       // hence rolling back here is redundant and possibly dangerous
       closeSession();
       closeConnection();

Modified: jbpm3/trunk/modules/core/src/main/java/org/jbpm/persistence/jta/JtaDbPersistenceService.java
===================================================================
--- jbpm3/trunk/modules/core/src/main/java/org/jbpm/persistence/jta/JtaDbPersistenceService.java	2008-12-23 12:43:49 UTC (rev 3534)
+++ jbpm3/trunk/modules/core/src/main/java/org/jbpm/persistence/jta/JtaDbPersistenceService.java	2008-12-23 13:31:21 UTC (rev 3535)
@@ -30,33 +30,36 @@
 import org.hibernate.util.JTAHelper;
 import org.jbpm.JbpmException;
 import org.jbpm.persistence.db.DbPersistenceService;
-import org.jbpm.persistence.db.DbPersistenceServiceFactory;
 
 public class JtaDbPersistenceService extends DbPersistenceService {
 
   private static final long serialVersionUID = 1L;
-  
-  private static Log log = LogFactory.getLog(JtaDbPersistenceService.class);  
-  
+
+  private static Log log = LogFactory.getLog(JtaDbPersistenceService.class);
+
   private UserTransaction userTransaction;
 
-  public JtaDbPersistenceService(DbPersistenceServiceFactory persistenceServiceFactory) {
+  public JtaDbPersistenceService(JtaDbPersistenceServiceFactory persistenceServiceFactory) {
     super(persistenceServiceFactory);
-    
+
     if (!isJtaTransactionInProgress()) {
-      beginJtaTransaction();
+      beginUserTransaction();
     }
   }
 
-  protected boolean isTransactionActive() {
+  public boolean isTransactionActive() {
     return isJtaTransactionInProgress();
   }
-  
+
+  protected boolean isTransactionExternallyManaged() {
+    return !isJtaTxCreated();
+  }
+
   public void close() {
     super.close();
 
     if (userTransaction != null) {
-      endJtaTransaction();
+      endUserTransaction();
     }
   }
 
@@ -65,18 +68,19 @@
     return JTAHelper.isTransactionInProgress(sessionFactory);
   }
 
-  void beginJtaTransaction() {
+  void beginUserTransaction() {
     try {
       log.debug("begin user transaction");
-      userTransaction = ((JtaDbPersistenceServiceFactory) persistenceServiceFactory).getUserTransaction();
+      userTransaction = ((JtaDbPersistenceServiceFactory) persistenceServiceFactory)
+          .getUserTransaction();
       userTransaction.begin();
     } catch (Exception e) {
       throw new JbpmException("couldn't begin user transaction", e);
     }
   }
 
-  void endJtaTransaction() {
-    if (isRollbackOnly() || JTAHelper.isRollback(getJtaTransactionStatus())) {
+  void endUserTransaction() {
+    if (isRollbackOnly() || JTAHelper.isRollback(getUserTransactionStatus())) {
       log.debug("rolling back user transaction");
       try {
         userTransaction.rollback();
@@ -93,11 +97,11 @@
     }
   }
 
-  int getJtaTransactionStatus() {
+  int getUserTransactionStatus() {
     try {
       return userTransaction.getStatus();
     } catch (SystemException e) {
-      throw new JbpmException("couldn't get status for user transaction", e); 
+      throw new JbpmException("couldn't get status for user transaction", e);
     }
   }
 

Modified: jbpm3/trunk/modules/core/src/main/resources/org/jbpm/graph/def/ProcessDefinition.hbm.xml
===================================================================
--- jbpm3/trunk/modules/core/src/main/resources/org/jbpm/graph/def/ProcessDefinition.hbm.xml	2008-12-23 12:43:49 UTC (rev 3534)
+++ jbpm3/trunk/modules/core/src/main/resources/org/jbpm/graph/def/ProcessDefinition.hbm.xml	2008-12-23 13:31:21 UTC (rev 3535)
@@ -19,7 +19,7 @@
       <index column="EVENTTYPE_" type="string"/>
       <one-to-many class="org.jbpm.graph.def.Event" />
     </map>
-    <list name="exceptionHandlers" cascade="all" lazy="false">
+    <list name="exceptionHandlers" cascade="all">
       <key column="PROCESSDEFINITION_" foreign-key="none" />
       <list-index column="GRAPHELEMENTINDEX_" />
       <one-to-many class="org.jbpm.graph.def.ExceptionHandler" />

Modified: jbpm3/trunk/modules/core/src/main/resources/org/jbpm/graph/def/Transition.hbm.xml
===================================================================
--- jbpm3/trunk/modules/core/src/main/resources/org/jbpm/graph/def/Transition.hbm.xml	2008-12-23 12:43:49 UTC (rev 3534)
+++ jbpm3/trunk/modules/core/src/main/resources/org/jbpm/graph/def/Transition.hbm.xml	2008-12-23 13:31:21 UTC (rev 3535)
@@ -20,7 +20,7 @@
       <index column="EVENTTYPE_" type="string" />
       <one-to-many class="org.jbpm.graph.def.Event" />
     </map>
-    <list name="exceptionHandlers" cascade="all" lazy="false">
+    <list name="exceptionHandlers" cascade="all">
       <key column="TRANSITION_" foreign-key="none" />
       <list-index column="GRAPHELEMENTINDEX_" />
       <one-to-many class="org.jbpm.graph.def.ExceptionHandler" />

Modified: jbpm3/trunk/modules/core/src/main/resources/org/jbpm/taskmgmt/def/Task.hbm.xml
===================================================================
--- jbpm3/trunk/modules/core/src/main/resources/org/jbpm/taskmgmt/def/Task.hbm.xml	2008-12-23 12:43:49 UTC (rev 3534)
+++ jbpm3/trunk/modules/core/src/main/resources/org/jbpm/taskmgmt/def/Task.hbm.xml	2008-12-23 13:31:21 UTC (rev 3535)
@@ -22,7 +22,7 @@
       <index column="EVENTTYPE_" type="string"/>
       <one-to-many class="org.jbpm.graph.def.Event" />
     </map>
-    <list name="exceptionHandlers" cascade="all" lazy="false">
+    <list name="exceptionHandlers" cascade="all">
       <key column="TASK_" foreign-key="none" />
       <list-index column="GRAPHELEMENTINDEX_" />
       <one-to-many class="org.jbpm.graph.def.ExceptionHandler" />

Added: jbpm3/trunk/modules/core/src/test/java/org/jbpm/jbpm1775/JBPM1775Test.java
===================================================================
--- jbpm3/trunk/modules/core/src/test/java/org/jbpm/jbpm1775/JBPM1775Test.java	                        (rev 0)
+++ jbpm3/trunk/modules/core/src/test/java/org/jbpm/jbpm1775/JBPM1775Test.java	2008-12-23 13:31:21 UTC (rev 3535)
@@ -0,0 +1,87 @@
+/*
+ * 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.jbpm1775;
+
+import org.jbpm.JbpmException;
+import org.jbpm.db.AbstractDbTestCase;
+import org.jbpm.graph.def.ActionHandler;
+import org.jbpm.graph.def.DelegationException;
+import org.jbpm.graph.def.ProcessDefinition;
+import org.jbpm.graph.exe.ExecutionContext;
+import org.jbpm.graph.exe.ProcessInstance;
+import org.jbpm.persistence.db.DbPersistenceService;
+
+/**
+ * Verify if exception handlers collection can be loaded lazily.
+ * 
+ * @see <a href="https://jira.jboss.org/jira/browse/JBPM-1775">JBPM-1775</a>
+ * @author Alejandro Guizar
+ */
+public class JBPM1775Test extends AbstractDbTestCase {
+
+  public void testExceptionInAction() {
+    ProcessDefinition processDefinition = ProcessDefinition.parseXmlString("<?xml version='1.0'?>"
+        + "<process-definition name='"
+        + getName()
+        + "'>"
+        + "  <exception-handler exception-class='java.lang.IllegalStateException'>"
+        + "    <action class='org.example.NoSuchAction' />"
+        + "  </exception-handler>"
+        + "  <start-state name='start'>"
+        + "    <transition to='end'>"
+        + "      <action class='"
+        + ExceptionAction.class.getName()
+        + "' />"
+        + "    </transition>"
+        + "  </start-state>"
+        + "  <end-state name='end' />"
+        + "</process-definition>");
+    jbpmContext.deployProcessDefinition(processDefinition);
+    try {
+      ProcessInstance processInstance = jbpmContext.newProcessInstance(processDefinition.getName());
+      processInstance.signal();
+      fail("expected delegation exception");
+    } catch (DelegationException e) {
+      assertSame(IllegalStateException.class, e.getCause().getClass());
+      try {
+        closeJbpmContext();
+      } catch (JbpmException je) {
+        // discard failure to close normally
+      }
+      beginSessionTransaction();
+    }
+  }
+
+  public static class ExceptionAction implements ActionHandler {
+    private static final long serialVersionUID = 1L;
+
+    public void execute(ExecutionContext executionContext) throws Exception {
+      // NOTE that manipulating the hibernate transaction directly is bad practice
+      // use JbpmContext or TxService instead!
+      DbPersistenceService persistenceService = (DbPersistenceService) executionContext
+          .getJbpmContext().getServices().getPersistenceService();
+      persistenceService.getTransaction().rollback();
+      // throw exception
+      throw new IllegalStateException("transaction was forcefully rolled back");
+    }
+  }
+}




More information about the jbpm-commits mailing list