6 Replies Latest reply on Apr 30, 2010 6:20 PM by andy.miller

    Possible Bug with EJB 3 Timers

    andy.miller

      I have recently added an EJB 3 Timer to my application, and in testing it out, the timer never expired, and called the method in the stateless session bean that has the @Timeout annotation.

       

      Here is the code:

       

      package services.ejb;

       

      import java.math.BigDecimal;
      import java.util.Calendar;
      import java.util.Date;
      import java.util.List;

       

      import javax.annotation.Resource;
      import javax.ejb.Stateless;
      import javax.ejb.Timeout;
      import javax.ejb.Timer;
      import javax.ejb.TimerService;
      import javax.persistence.EntityManager;
      import javax.persistence.PersistenceContext;
      import javax.persistence.Query;

       

      import services.ejb.OrderManager;
      import services.entities.Address;
      import services.entities.Customer;
      import services.entities.Order;
      import services.entities.OrderLine;
      import services.exceptions.CreateDataException;

       

      @Stateless
      public class OrderManagerBean implements OrderManager {

       

          @Resource
          TimerService timerService;
         
          @PersistenceContext (unitName="services")
          protected EntityManager entityManager;

       

      ...

      public void createOrderPurgeTimer(boolean runWithTimer) throws CreateDataException {
             
              for (Object object : timerService.getTimers()) {
                  Timer timer = (Timer) object;
                  timer.cancel();
              }
             
              if (runWithTimer) {
                  long twentyFourHours = 1000 * 60 * 60 * 24;
                  timerService.createTimer(twentyFourHours, twentyFourHours, null);
              }
             
              return;
             
          }
         
          @Timeout
          public void purgeOldOrders(Timer timer) {
             
              // Delete the previous days worth of orders
             
              Query query = entityManager.createNativeQuery("delete from Order where orderDate < :date");
             
              Calendar now = Calendar.getInstance();
             
              // Back up to the top of the hour, so we only delete orders from the previous period'
             
              now.set(Calendar.MINUTE, 0);
              now.set(Calendar.SECOND, 0);
             
              query.setParameter("date", new Date(now.getTimeInMillis()));
              query.executeUpdate();
             
              return;
             
          }

       

      }

       

      In the above stateless session bean, I have a method to create the timer, and the one that is the callback when the timer should expire.  It creates a single timer that should expire every twenty four hours, so the initial expiration, and the interval are both set to 24 hours.  I have a servlet that calls the method to create the timer, along with other reference data needed for the application, and I can see the timer has been persisted in the database, and here is what it looks like:

       

      TIMERID = 1272464496401, TARGETID = [target=jboss.j2ee:ear=OrderManagerApp.ear,jar=OrderManagerEJB.jar,name=OrderManagerBean,service=EJB3], INITIALDATE=2010-04-29 08:26:29, TIMERINTERVAL=86400000, INSTANCEPK=NULL, INFO=NULL

       

      So, I created the timer through the createOrderPurgeTimer method on the OrderManagerBean, and everything looks correct.  The INITIALDATE is 24 hours after I created it, and the TIMERINTERVAL is 24 hours in milliseconds, as I would expect.

       

      So, I was expecting, after allowing the application to run all day and night, that at 8:26:49 this morning (the INITIALDATE) the timer would expire, and call the purgeOldOrders method on the OrderManagerBean.

       

      I know this didn't happen, because there is no error created from the method (maybe it failed), and because in looking at the invocation statistics from the JMX Console I see the following:

       

      InvocationStatistics concurrentCalls='0'
      method name='createOrderPurgeTimer' count='1' minTime='78' maxTime='78' totalTime='78'
      method name='createOrder' count='15' minTime='0' maxTime='4' totalTime='18'

       

      As you can see, the only two methods called on the bean are the createOrderPurgeTimer, and the createOrder (I didn't include that method in the above code snippet).  No call to the purgeOldOrders method at all, and its more than 2 hours after the INITIALDATE that is in the TIMER table.

       

      I don't believe I have done anything wrong in the code.

        • 1. Re: Possible Bug with EJB 3 Timers
          jaikiran

          Is this JBoss AS 5.1.0 with the latest EJB3 plugin http://www.jboss.org/ejb3/ejb3plugin.html? The reason I ask is because, there were some fixes around InvocationStatistics after AS 5.1.0 (if I remember right). I'll give this a try with a simple application and see if there's any issue around it.

          • 2. Re: Possible Bug with EJB 3 Timers
            andy.miller

            It's actually on EAP 5.0.0, and I was going to try EAP 5.0.1.  I would assume the fixes for this problem made it into EAP 5.0.0?

            • 3. Re: Possible Bug with EJB 3 Timers
              jaikiran

              If it's EAP-5.0.0, then it should already have the fixes that I was talking about. Let me see why you are running into this issue.

               

              By the way, if you have the application at hand, can you just give it a try by changing the interval to maybe 5 minutes and see if it works? Just as a quick test.

              • 4. Re: Possible Bug with EJB 3 Timers
                andy.miller

                jaikiran pai wrote:

                 

                If it's EAP-5.0.0, then it should already have the fixes that I was talking about. Let me see why you are running into this issue.

                 

                By the way, if you have the application at hand, can you just give it a try by changing the interval to maybe 5 minutes and see if it works? Just as a quick test.

                I will definitely modify the application for a shorter duration, like 5 minutes and give it another try.  I'll let you know when I have that done.  I am going through e-mail right now, and once I'm done with that, I'll shift my attention to another test.

                • 5. Re: Possible Bug with EJB 3 Timers
                  andy.miller

                  jaikiran pai wrote:

                   

                  If it's EAP-5.0.0, then it should already have the fixes that I was talking about. Let me see why you are running into this issue.

                   

                  By the way, if you have the application at hand, can you just give it a try by changing the interval to maybe 5 minutes and see if it works? Just as a quick test.

                  So, I got around to do a quicker test.  I changed the code to have the timer expire in five minutes, and I got the same results.  The timer just does not expire.  What's funny, is when I started up, the old timer that was still in the table, did expire.

                   

                  So, as a simply test, after the new 5 minute timer didn't expire, I decided to shut down the server and restart it, and see if it expired on startup like the old timer, but it didn't.

                   

                  I'm not sure what's going on, but this definitely doesn't work.

                  • 6. Re: Possible Bug with EJB 3 Timers
                    andy.miller

                    Andrig Miller wrote:

                     

                    jaikiran pai wrote:

                     

                    If it's EAP-5.0.0, then it should already have the fixes that I was talking about. Let me see why you are running into this issue.

                     

                    By the way, if you have the application at hand, can you just give it a try by changing the interval to maybe 5 minutes and see if it works? Just as a quick test.

                    So, I got around to do a quicker test.  I changed the code to have the timer expire in five minutes, and I got the same results.  The timer just does not expire.  What's funny, is when I started up, the old timer that was still in the table, did expire.

                     

                    So, as a simply test, after the new 5 minute timer didn't expire, I decided to shut down the server and restart it, and see if it expired on startup like the old timer, but it didn't.

                     

                    I'm not sure what's going on, but this definitely doesn't work.

                    Well, more weirdness.  I all seems to be working just fine now.  I'm going to try to set it back to 24 hours, and see what happens.  I put a log statement in the method annotated with the @Timeout, and restarted everything, including recreating the timer through the application, and its working as excepted.  ?????