0 Replies Latest reply on Jun 8, 2015 10:23 AM by tanooki

    How to set an EJB timerService bean for JavaEE wabapp in an JBOSS cluster environment to be initialized only once and run on any node (just one)

    tanooki

      I have a JavaEE web module. This module, in startup, have to initialize an ejb timer for doing some work according to a scheduling configuration.

       

      This module is packaging in a WAR. And this WAR is included in a EAR with other arctifacts.The EAR is deploying in a JBOSS EAP 6.2 server clusterized with two nodes, for this example.

       

      The desired behavior is that the timer is initialized only once. And run on any node (just one by time).

       

      But for my current configuration, it does not. For each servlet initialized at each node, the lookup by JNDI name results on two different ejb beans, so that two timers running on the corresponding node individually. I have drawn this figure below to illustrate the behavior:

       

      OsfNW.jpg

       

      And the code:

      TimedBean.java

          public interface TimedBean extends Serializable {
              public void startTimer();
          }
      
      
      
      
      
      
      
      
      
      
      

       

      TimedBeanImpl.java

          @Stateless(name = "TimedEjb")
          @Clustered
          @Remote(TimedBean.class)
          @Interceptors(SpringBeanAutowiringInterceptor.class)
          public class TimedBeanImpl implements TimedBean {
      
              private static final long serialVersionUID = 1684152846073889080L;
      
              @Resource
              private SessionContext ctx;
      
              @Override
              public void startTimer() {
                  ...
                  this.ctx.getTimerService().createCalendarTimer(se, new TimerConfig("TimedEjb", false));
              }
      
              @Timeout
              public void handleTimeout(Timer timer) {
                  doSomeWork();
              }
              ...
          }
      
      
      
      
      
      
      
      
      
      
      
      
      
      

       

      LoadTimer.java

              public class LoadTimer implements ServletContextListener {
      
                  @EJB(lookup = "java:global/webapp-01.00.00/sync-01.00.00/timedEjb")
                  private TimedBean timerBean;
      
                  @Override
                  public void contextInitialized(ServletContextEvent servletcontextevent) {
                      this.timerBean.startTimer();
                  }
                  ...
              }
      
      
      
      
      

       

      web.xml

          <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
               <display-name>Sync</display-name>
               <context-param>
                    <param-name>contextConfigLocation</param-name>
                    <param-value>classpath:applicationContext.xml</param-value>
               </context-param>
               <listener>
                    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
               </listener>
               <listener>
                   <listener-class>com.tanooki.test01.sync.client.LoadTimer</listener-class>
               </listener>
          </web-app>
      
      

       

      The first possible solution onto which have been researching is to get the lookup always resolves the same bean, keeping control initialization. Something like a singleton bean (not stateless) clusterized. But either is not possible or in spite of my efforts have failed to find this possible fix.

       

      I do not know if it would be possible to have one common context to the entire application for the cluster environment. It would be a solution, but did not think possible.

       

      Right now I am confused and my only alternative would be a run control through a flag persisted in database. Which would be undesirable.

       

      Any suggestions would be happy to try it.

       

      Greetings!