Red Hat Training

A Red Hat training course is available for Red Hat JBoss Enterprise Application Platform

10.3. Implement an HA Singleton


The following procedure demonstrates how to deploy a service that is wrapped with the SingletonService decorator and used as a cluster-wide singleton service. The service activates a scheduled timer, which is started only once in the cluster.

Procedure 10.3. Implement an HA Singleton Service

  1. Write the HA singleton service application.
    The following is a simple example of a Service that is wrapped with the SingletonService decorator to be deployed as a singleton service. A complete example can be found in the cluster-ha-singleton quickstart that ships with Red Hat JBoss Enterprise Application Platform 6. This quickstart contains all the instructions to build and deploy the application.
    1. Create a service.
      The following listing is an example of a service:
      import java.util.Date;
      import java.util.concurrent.atomic.AtomicBoolean;
      import javax.naming.InitialContext;
      import javax.naming.NamingException;
      import org.jboss.logging.Logger;
      import org.jboss.msc.service.Service;
      import org.jboss.msc.service.ServiceName;
      import org.jboss.msc.service.StartContext;
      import org.jboss.msc.service.StartException;
      import org.jboss.msc.service.StopContext;
       * @author <a href="">Wolf-Dieter Fink</a>
      public class HATimerService implements Service<String> {
          private static final Logger LOGGER = Logger.getLogger(HATimerService.class);
          public static final ServiceName SINGLETON_SERVICE_NAME = ServiceName.JBOSS.append("quickstart", "ha", "singleton", "timer");
           * A flag whether the service is started.
          private final AtomicBoolean started = new AtomicBoolean(false);
           * @return the name of the server node
          public String getValue() throws IllegalStateException, IllegalArgumentException {
              LOGGER.infof("%s is %s at %s", HATimerService.class.getSimpleName(), (started.get() ? "started" : "not started"), System.getProperty(""));
              return "";
          public void start(StartContext arg0) throws StartException {
              if (!started.compareAndSet(false, true)) {
                  throw new StartException("The service is still started!");
    "Start HASingleton timer service '" + this.getClass().getName() + "'");
              final String node = System.getProperty("");
              try {
                  InitialContext ic = new InitialContext();
                  ((Scheduler) ic.lookup("global/jboss-cluster-ha-singleton-service/SchedulerBean!")).initialize("HASingleton timer @" + node + " " + new Date());
              } catch (NamingException e) {
                  throw new StartException("Could not initialize timer", e);
          public void stop(StopContext arg0) {
              if (!started.compareAndSet(true, false)) {
                  LOGGER.warn("The service '" + this.getClass().getName() + "' is not active!");
              } else {
        "Stop HASingleton timer service '" + this.getClass().getName() + "'");
                  try {
                      InitialContext ic = new InitialContext();
                      ((Scheduler) ic.lookup("global/jboss-cluster-ha-singleton-service/SchedulerBean!")).stop();
                  } catch (NamingException e) {
                      LOGGER.error("Could not stop timer", e);
    2. Create an activator that installs the Service as a clustered singleton.
      The following listing is an example of a Service activator that installs the HATimerService as a clustered singleton service:
      import org.jboss.logging.Logger;
      import org.jboss.msc.service.DelegatingServiceContainer;
      import org.jboss.msc.service.ServiceActivator;
      import org.jboss.msc.service.ServiceActivatorContext;
      import org.jboss.msc.service.ServiceController;
       * Service activator that installs the HATimerService as a clustered singleton service
       * during deployment.
       * @author Paul Ferraro
      public class HATimerServiceActivator implements ServiceActivator {
          private final Logger log = Logger.getLogger(this.getClass());
          public void activate(ServiceActivatorContext context) {
    "HATimerService will be installed!");
              HATimerService service = new HATimerService();
              SingletonService<String> singleton = new SingletonService<String>(service, HATimerService.SINGLETON_SERVICE_NAME);
               * To pass a chain of election policies to the singleton, for example, 
               * to tell JGroups to prefer running the singleton on a node with a
               * particular name, uncomment the following line:
              // singleton.setElectionPolicy(new PreferredSingletonElectionPolicy(new SimpleSingletonElectionPolicy(), new NamePreference("node1/singleton")));
     DelegatingServiceContainer(context.getServiceTarget(), context.getServiceRegistry()))


      The above code example uses a class,, that is part of the JBoss EAP private API. A public API will become available in the JBoss EAP 7 release and the private class will be deprecated, but these classes will be maintained and available for the duration of the JBoss EAP 6.x release cycle.
    3. Create a ServiceActivator File
      Create a file named org.jboss.msc.service.ServiceActivator in the application's resources/META-INF/services/ directory. Add a line containing the fully qualified name of the ServiceActivator class created in the previous step. 
    4. Create a Singleton bean that implements a timer to be used as a cluster-wide singleton timer.
      This Singleton bean must not have a remote interface and you must not reference its local interface from another EJB in any application. This prevents a lookup by a client or other component and ensures the SingletonService has total control of the Singleton.
      1. Create the Scheduler interface
         * @author <a href="">Wolf-Dieter Fink</a>
        public interface Scheduler {
            void initialize(String info);
            void stop();
      2. Create the Singleton bean that implements the cluster-wide singleton timer.
        import javax.annotation.Resource;
        import javax.ejb.ScheduleExpression;
        import javax.ejb.Singleton;
        import javax.ejb.Timeout;
        import javax.ejb.Timer;
        import javax.ejb.TimerConfig;
        import javax.ejb.TimerService;
        import org.jboss.logging.Logger;
         * A simple example to demonstrate a implementation of a cluster-wide singleton timer.
         * @author <a href="">Wolf-Dieter Fink</a>
        public class SchedulerBean implements Scheduler {
            private static Logger LOGGER = Logger.getLogger(SchedulerBean.class);
            private TimerService timerService;
            public void scheduler(Timer timer) {
      "HASingletonTimer: Info=" + timer.getInfo());
            public void initialize(String info) {
                ScheduleExpression sexpr = new ScheduleExpression();
                // set schedule to every 10 seconds for demonstration
                // persistent must be false because the timer is started by the HASingleton service
                timerService.createCalendarTimer(sexpr, new TimerConfig(info, false));
            public void stop() {
      "Stop all existing HASingleton timers");
                for (Timer timer : timerService.getTimers()) {
                    LOGGER.trace("Stop HASingleton timer: " + timer.getInfo());
  2. Start each JBoss EAP 6 instance with clustering enabled.
    To enable clustering for standalone servers, you must start each server with the HA profile, using a unique node name and port offset for each instance.
    • For Linux, use the following command syntax to start the servers:
      EAP_HOME/bin/ --server-config=standalone-ha.xml -Djboss.socket.binding.port-offset=PORT_OFFSET

      Example 10.4. Start multiple standalone servers on Linux

      $ EAP_HOME/bin/ --server-config=standalone-ha.xml
      $ EAP_HOME/bin/ --server-config=standalone-ha.xml -Djboss.socket.binding.port-offset=100
    • For Microsoft Windows, use the following command syntax to start the servers:
      EAP_HOME\bin\standalone.bat --server-config=standalone-ha.xml -Djboss.socket.binding.port-offset=PORT_OFFSET

      Example 10.5. Start multiple standalone servers on Microsoft Windows

      C:> EAP_HOME\bin\standalone.bat --server-config=standalone-ha.xml
      C:> EAP_HOME\bin\standalone.bat --server-config=standalone-ha.xml -Djboss.socket.binding.port-offset=100


    If you prefer not to use command line arguments, you can configure the standalone-ha.xml file for each server instance to bind on a separate interface.
  3. Deploy the application to the servers
    The following Maven command deploys the application to a standalone server running on the default ports.
    mvn clean install jboss-as:deploy
    To deploy to additional servers, pass the server name. if it is on a different host, pass the host name and port number on the command line:
    mvn clean package jboss-as:deploy -Djboss-as.hostname=localhost -Djboss-as.port=10099
    See the cluster-ha-singleton quickstart that ships with JBoss EAP 6 for Maven configuration and deployment details.