You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by xu...@apache.org on 2011/05/11 16:43:01 UTC

svn commit: r1101900 - in /openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/timer: EjbTimerServiceImpl.java TimerData.java TimerImpl.java

Author: xuhaihong
Date: Wed May 11 14:43:01 2011
New Revision: 1101900

URL: http://svn.apache.org/viewvc?rev=1101900&view=rev
Log:
OPENEJB-1544 Correct current timer exception logic to confirm EJB31 spec: 18.4.3 Timer Expiration and Timeout Callback Method and 18.4.4 Timer Cancellation (Patch from Shawn Jiang)

Modified:
    openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/timer/EjbTimerServiceImpl.java
    openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/timer/TimerData.java
    openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/timer/TimerImpl.java

Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/timer/EjbTimerServiceImpl.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/timer/EjbTimerServiceImpl.java?rev=1101900&r1=1101899&r2=1101900&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/timer/EjbTimerServiceImpl.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/timer/EjbTimerServiceImpl.java Wed May 11 14:43:01 2011
@@ -28,6 +28,7 @@ import javax.ejb.ScheduleExpression;
 import javax.ejb.Timer;
 import javax.ejb.TimerConfig;
 import javax.transaction.Status;
+import javax.transaction.SystemException;
 import javax.transaction.TransactionManager;
 
 import org.apache.openejb.BeanContext;
@@ -313,8 +314,8 @@ public class EjbTimerServiceImpl impleme
             if (timer == null) {
                 return;
             }
-
             for (int tries = 0; tries < (1 + retryAttempts); tries++) {
+                boolean retry = false;
                 // if transacted, begin the transaction
                 if (transacted) {
                     try {
@@ -324,41 +325,45 @@ public class EjbTimerServiceImpl impleme
                         return;
                     }
                 }
-
                 // call the timeout method
                 try {
                     RpcContainer container = (RpcContainer) deployment.getContainer();
                     Method ejbTimeout = timerData.getTimeoutMethod();
                     container.invoke(deployment.getDeploymentID(), InterfaceType.TIMEOUT, ejbTimeout.getDeclaringClass(), ejbTimeout, new Object[] { timer }, timerData.getPrimaryKey());
                 } catch (RuntimeException e) {
+                    retry = true;
                     // exception from a timer does not necessairly mean failure
                     log.warning("RuntimeException from ejbTimeout on " + deployment.getDeploymentID(), e);
+                    try {
+                        transactionManager.setRollbackOnly();
+                    } catch (SystemException e1) {
+                        log.warning("Exception occured while setting RollbackOnly for container transaction", e1);
+                    }
                 } catch (OpenEJBException e) {
+                    retry = true;
                     log.warning("Exception from ejbTimeout on " + deployment.getDeploymentID(), e);
+                    if (transacted) {
+                        try {
+                            transactionManager.setRollbackOnly();
+                        } catch (SystemException e1) {
+                            log.warning("Exception occured while setting RollbackOnly for container transaction", e1);
+                        }
+                    }
                 } finally {
                     try {
-                        if (!transacted || transactionManager.getStatus() == Status.STATUS_ACTIVE) {
-                            // clean up the timer store
-                            //TODO shall we do all this via Quartz listener ???
-                            if (timerData.getType() == TimerType.SingleAction) {
-                                timerStore.removeTimer(timerData.getId());
+                        if (!transacted) {
+                            if (retry) {
+                                continue;
                             } else {
-                                timerStore.updateIntervalTimer(timerData);
-                            }
-
-                            // commit the tx
-                            if (transacted) {
-                                transactionManager.commit();
+                                return;
                             }
-
-                            // all is cool
-                            //noinspection ReturnInsideFinallyBlock
+                        } else if (transactionManager.getStatus() == Status.STATUS_ACTIVE) {
+                            transactionManager.commit();
                             return;
                         } else {
-                            // tx was marked rollback, so roll it back
-                            if (transacted) {
-                                transactionManager.rollback();
-                            }
+                            // tx was marked rollback, so roll it back and retry.
+                            transactionManager.rollback();
+                            continue;
                         }
                     } catch (Exception e) {
                         log.warning("Exception occured while completing container transaction", e);
@@ -373,9 +378,16 @@ public class EjbTimerServiceImpl impleme
             log.warning("Error occured while calling ejbTimeout", e);
             throw e;
         } finally {
-            // if this is a single action timer, mark it as cancelled
+            // clean up the timer store
+            //TODO shall we do all this via Quartz listener ???
             if (timerData.getType() == TimerType.SingleAction) {
-                cancelled(timerData);
+                timerStore.removeTimer(timerData.getId());
+                timerData.setExpired(true);
+            } else if (timerData.getType() == TimerType.Calendar && timerData.getNextTimeout() == null) {
+                timerStore.removeTimer(timerData.getId());
+                timerData.setExpired(true);
+            } else {
+                timerStore.updateIntervalTimer(timerData);
             }
         }
     }
@@ -400,4 +412,4 @@ public class EjbTimerServiceImpl impleme
             });
         }
     }*/
-}
+}
\ No newline at end of file

Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/timer/TimerData.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/timer/TimerData.java?rev=1101900&r1=1101899&r2=1101900&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/timer/TimerData.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/timer/TimerData.java Wed May 11 14:43:01 2011
@@ -21,8 +21,6 @@ import java.lang.reflect.Method;
 import java.util.Date;
 
 import javax.ejb.EJBException;
-import javax.ejb.NoMoreTimeoutsException;
-import javax.ejb.NoSuchObjectLocalException;
 import javax.ejb.Timer;
 import javax.ejb.TimerConfig;
 import javax.transaction.Status;
@@ -79,6 +77,14 @@ public abstract class TimerData {
      * when we are registered to avoid multiple registrations.
      */
     private boolean synchronizationRegistered = false;
+    
+    /**
+     *  Used to set timer to expired state after the timeout callback method has been successfully invoked.
+     *  only apply to 
+     *  1, Single action timer
+     *  2, Calendar timer there are no future timeout.
+     */
+    private boolean expired;    
 
     public TimerData(long id, EjbTimerServiceImpl timerService, String deploymentId, Object primaryKey, Method timeoutMethod, TimerConfig timerConfig) {
         this.id = id;
@@ -227,11 +233,7 @@ public abstract class TimerData {
         return trigger;
     }
 
-    public Date getNextTimeout() throws NoSuchObjectLocalException, NoMoreTimeoutsException {
-        if (cancelled) {
-            throw new NoSuchObjectLocalException("The timer has been cancelled");
-        }
-        
+    public Date getNextTimeout() {       
         
         Date nextTimeout = null;
         
@@ -240,19 +242,21 @@ public abstract class TimerData {
             nextTimeout = getTrigger().getNextFireTime();
         }
         
-        
-
-        if (nextTimeout == null) {
-            throw new NoMoreTimeoutsException("The timer has no future timeouts");
-        } 
-        
         return nextTimeout;
     }
 
-    public long getTimeRemaining() throws NoSuchObjectLocalException, NoMoreTimeoutsException {
+    public long getTimeRemaining() {
         Date nextTimeout = getNextTimeout();
         return nextTimeout.getTime() - System.currentTimeMillis();
     }
+    
+    public boolean isExpired() {
+        return expired;
+    }
+
+    public void setExpired(boolean expired){
+        this.expired = expired;
+    }
 
     public abstract TimerType getType();
 

Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/timer/TimerImpl.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/timer/TimerImpl.java?rev=1101900&r1=1101899&r2=1101900&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/timer/TimerImpl.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/timer/TimerImpl.java Wed May 11 14:43:01 2011
@@ -21,6 +21,7 @@ import java.util.Date;
 
 import javax.ejb.EJBContext;
 import javax.ejb.EJBException;
+import javax.ejb.NoMoreTimeoutsException;
 import javax.ejb.NoSuchObjectLocalException;
 import javax.ejb.ScheduleExpression;
 import javax.ejb.Timer;
@@ -44,13 +45,16 @@ public class TimerImpl implements Timer 
 
     public long getTimeRemaining() throws IllegalStateException, NoSuchObjectLocalException {
         checkState();
-        /*long now = System.currentTimeMillis();
-        long then = timerData.getExpiration().getTime();*/
+        Date nextTimeout = timerData.getNextTimeout();
+        if (nextTimeout == null) throw new NoMoreTimeoutsException("The timer has no future timeouts");
         return timerData.getTimeRemaining();
     }
 
     public Date getNextTimeout() throws IllegalStateException, NoSuchObjectLocalException {
         checkState();
+        
+        Date nextTimeout = timerData.getNextTimeout();
+        if (nextTimeout == null) throw new NoMoreTimeoutsException("The timer has no future timeouts");
         return timerData.getNextTimeout();
     }
 
@@ -61,6 +65,9 @@ public class TimerImpl implements Timer 
 
     public TimerHandle getHandle() throws IllegalStateException, NoSuchObjectLocalException {
         checkState();
+        if(!timerData.isPersistent()){
+           throw new IllegalStateException("can't getHandle for a non-persistent timer");
+        }
         return new TimerHandleImpl(timerData.getId(), timerData.getDeploymentId());
     }
 
@@ -93,6 +100,10 @@ public class TimerImpl implements Timer 
         if (timerData.isCancelled()) {
             throw new NoSuchObjectLocalException("Timer has been cancelled");
         }
+        
+        if (timerData.isExpired()){
+            throw new NoSuchObjectLocalException("The timer has expired");
+        }
     }
 
 }