About Jakub Kubrynski

I'm software developer by vocation. Java team leader at work and open source enthusiast at home. Strongly interested in new technologies. Fan of java.util.concurrent and sun.misc.Unsafe. My motto is "minimum code, maximum functionality.

Using HA Singleton in JBoss 7

Some time ago I had to change standard clustering behavior of Quartz Scheduler, and let it work without synchronizing over database. There are of course a lot of options to do that, but because I’m big fan of simplicity I’ve decided to use standard Spring @Scheduled configuration and totally skip thinking about cluster at this level. The idea was to just invoke “check that I’m on master node” method at the beginning of the scheduled method. The only problem was how to write such method. The choice was to use JBoss HA Singleton functionality. It’s available in JBoss 7.x but the big lack of documentation forces some experiments… nice!

First thing which we need to do is to provide proper dependency, containing few important classes. Of course remember about right version (here I’m using 7.1.1.Final because it’s available in public repositories and all next versions of 7 needs to be build manually).

<dependency>
  <groupid>org.jboss.as</groupid>
  <artifactid>jboss-as-clustering-singleton</artifactid>
  <version>7.1.1.Final</version>
  <scope>provided</scope>
</dependency>

Now it’s time to do some coding! Let’s start from class containing service that will be installed into application server. Its role is to set master status flag and expose it by simple static method.

package com.stackholder.jboss.ha;

import org.jboss.msc.service.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Serializable;
import java.util.concurrent.atomic.AtomicBoolean;

public class MasterStatusHaSingleton 
    extends AbstractService<Serializable> {

  private static final Logger LOGGER = 
      LoggerFactory.getLogger(MasterStatusHaSingleton.class);

  private static AtomicBoolean masterStatus = 
      new AtomicBoolean(false);

  @Override
  public void start(StartContext startContext) {
    LOGGER.info("MasterStatusHaSingleton started");
    masterStatus.set(true);
  }

  @Override
  public void stop(StopContext stopContext) {
    LOGGER.info("MasterStatusHaSingleton stopped");
    masterStatus.set(false);
  }

  public static boolean isMaster() {
    return masterStatus.get();
  }
}

Now we need to write class that will install prepared service into container.

package com.stackholder.jboss.ha;

import org.jboss.as.clustering.singleton.SingletonService;
import org.jboss.msc.service.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HaSingletonActivator implements ServiceActivator {

  private final static Logger LOGGER =
      LoggerFactory.getLogger(HaSingletonActivator.class);

  public static final ServiceName SINGLETON_SERVICE_NAME =
      ServiceName.JBOSS.append("ha", "singleton");

  @Override
  public void activate(ServiceActivatorContext context) 
      throws ServiceRegistryException {
    LOGGER.info("HaSingletonActivator will be installed");

    MasterStatusHaSingleton srv = new MasterStatusHaSingleton();
    SingletonService singleton = 
        new SingletonService(srv, SINGLETON_SERVICE_NAME);

    singleton.build(new DelegatingServiceContainer(
        context.getServiceTarget(),context.getServiceRegistry()))
        .setInitialMode(ServiceController.Mode.ACTIVE).install();
    LOGGER.info("HaSingletonActivator installation SUCCESSFUL");
  }
}

Remember that JBoss 7 is using OSGi, so we’ve to tell application server what modules we’re going to use in our application. The easiest way to do that is to add configuration into war or jar plugin:

<configuration>
  <archive>
    <manifestentries>
      <dependencies>
        org.jboss.msc,org.jboss.as.server,
        org.jboss.as.clustering.singleton
      </dependencies>
    </manifestentries>
  </archive>
</configuration>

Great – almost finished! Almost. Last thing we have to do is to activate proper modules in JBoss configuration. Just edit standalone-full-ha.xml file (or other configuration that you use of course) and add following modules into ee subsystem:

<subsystem xmlns="urn:jboss:domain:ee:1.0">
  <global-modules>
    <module name="org.jboss.msc" slot="main">
    <module name="org.jboss.as.clustering.singleton" slot="main">
  </global-modules>
</subsystem>

And finally you can execute your server and enjoy new, cool functionality.
 

Reference: Using HA Singleton in JBoss 7 from our JCG partner Jakub Kubrynski at the Java(B)Log blog.
Related Whitepaper:

Java Application Development on Linux

Linux is the fastest-growing Java development platform because it saves money and time by serving as a platform for both development and deployment. But developers face significant platform-specific challenges when managing and deploying Java applications in a controlled production environment.

This is the hands-on guide to the full Java application development lifecycle on Linux. It demonstrates the platform, tools, and application development by showing realistic, easy-to-follow examples. After a simple command-line application introduces basic tools, this program leads readers through business-logic object analysis, database design, Java servlet UIs, Java Server Pages (JSP) UIs, Swing GUIs, and Standard Widget Toolkit (SWT) GUIs. Scaling up to the enterprise level provides the opportunity to use both the JBoss Application Server and the Apache Geronimo Application Servers, and Enterprise JavaBeans (EJB).

Get it Now!  

2 Responses to "Using HA Singleton in JBoss 7"

  1. twain says:

    Nice tutorial, thanks. I have been looking for something like this for a long time now.
    How did you manage to start your Spring based @Scheduled annotation only on the Master Node?

  2. Hi,

    I decided to choose simpler way (following KISS rule) and at the begging of the @Scheduled method I’m checking if it’s started on master and only then continue execution.

    Kind regards,
    Kuba

Leave a Reply


× two = 8



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.

Sign up for our Newsletter

20,709 insiders are already enjoying weekly updates and complimentary whitepapers! Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

As an extra bonus, by joining you will get our brand new e-books, published by Java Code Geeks and their JCG partners for your reading pleasure! Enter your info and stay on top of things,

  • Fresh trends
  • Cases and examples
  • Research and insights
  • Two complimentary e-books