4 Replies Latest reply on Apr 7, 2005 2:43 PM by mka

    EJB TimerService in a clustered environment

    kraftek

      There is a problem with timer ID generation (class org.jboss.ejb.txtimer.BigIntegerTimerIdGenerator) in a clustered environment. Everything is fine as long as I use for persistence purposes a database per server in cluster. But if I use a shared database for the whole cluster (which I find more likely to happen in a production environment), I will have duplicate IDs generated by this class (and hence will get SQLExceptions when trying to create a timer).

      Hence, I have created a class that produces a "unique" ID for any server in the cluster and now everything is as it should be.
      It may not be the best idea of implementation, but is a fast and simple solution that produces the expected behaviour.

      Therefore I propose the following replacement for org.jboss.ejb.txtimer.BigIntegerTimerIdGenerator class:

      package org.jboss.ejb.txtimer;
      
      import java.math.BigInteger;
      import java.net.InetAddress;
      
      public class BigIntegerTimerIdGenerator implements TimerIdGenerator {
      
       private static BigInteger nextTimerId = BigInteger.valueOf(0);
       private static String offset = "";
       static {
       try {
       offset = InetAddress.getLocalHost().getHostAddress().replaceAll("\\.", "");
       } catch (Exception ignored) {}
       }
      
       public synchronized String nextTimerId() {
       nextTimerId = nextTimerId.add(BigInteger.valueOf(1));
       return offset + nextTimerId.toString();
       }
      }



        • 1. Re: EJB TimerService in a clustered environment
          kraftek

          The previous code may result in generating duplicate IDs. Here is the corrected code:

          package org.jboss.ejb.txtimer;
          
          import java.math.BigInteger;
          import java.net.InetAddress;
          
          public class BigIntegerClusteredTimerIdGenerator implements TimerIdGenerator {
           private static BigInteger nextTimerId = BigInteger.valueOf(0);
           private static String offset = "";
          
           static {
           try {
           byte[] ob = InetAddress.getLocalHost().getAddress();
           for (int i=0; i<ob.length; i++) {
           if (ob[ i ] < 10) {
           offset += "0";
           }
           offset += String.valueOf(ob[ i ]);
           }
           } catch (Exception e) {
           }
           }
          
           public synchronized String nextTimerId() {
           nextTimerId = nextTimerId.add(BigInteger.valueOf(1));
           return offset + nextTimerId.toString();
           }
          }
          


          • 2. Re: EJB TimerService in a clustered environment
            mka

            Hi Cosmin,
            I was wondering how you even get JBOSS to persist the timer events to a database. My problem is I want to ensure my timer events are valid, and continue to work after the server is restarted. Is this possible?

            Thanks.

            • 3. Re: EJB TimerService in a clustered environment
              kraftek

              Hi Marcus.

              They say that JBoss persists the timers to a database so that, if the server crashes, they will be restored at the next startup. This is true only if the server crashes, but not for a normal shutdown.
              My feeling is that they delete all timers that are not related to entity beans (ie. the field InstancePK in TIMERS table is NULL). In my case, I'm using only stateless session beans, so...

              Two possible workarounds for persisting your timers in the case of a normal shutdown would be:

              1. To modify yourself the JBoss'es source code, but you have to be careful not to break something in it.

              2. To create a table (besides TIMERS) that will keep the necessary information to re-create the timers each time the server starts. For example, you can keep there the start date, interval, next run date, and at the startup (or at least when you'd want to create the timers) you can re-compute the next run and create a new timer.
              I have opted for the second one and it works fine for me.
              By the way, I'm using JBoss 4.0.1sp1 (JBoss 4.0.2RC1 presents the same situation).

              • 4. Re: EJB TimerService in a clustered environment
                mka

                Yes the second one sounds like the best way, and had started to work in that direction. But tell me, how do you get the startup notification from JBOSS? This is the part I'm totally lost.

                And thanks for the response by the way.