About Piotr Nowicki

Piotr is a Java fascinate since his computer science studies (2007). He's currently working as a senior Java EE developer in utilities and industry sector. He's mostly interested in designing and development of web applications using Java EE technology stack.

Using JGroups Directly From JBoss AS 7 Component

JGroups is Bela Ban‘s piece of software for reliable message exchange that is highly configurable and can use either TCP or UDP as a transport protocol. Basically – you run the JGroups on number of clients, they form a cluster and they can send and receive messages within the cluster.

JGroups is used internally by JBoss Infinispan. Infinispan, however, unlike JGroups adds the distributed cache semantics (replicated / distributed modes, entries invalidation, transactional behavior, Map access API, etc.) It even allows you to use the cluster as a compute grid.
 
 
 
Infinispan in turn is used to provide JBoss AS 7 clustering functionalities. Therefore, it means that the underlying JGroups subsystem can and is configured using a standard JBoss AS 7 standalone*.xml file. You can access Infinispan cache from your Java EE component (e.g. EJB) without any problems as described here.

However, there are cases when you’d like to use just the underlying JGroups messaging instead of all the cache semantics Infinispan gives you. And here’s the place things are becoming more complicated. You can always use JGroups directly and store the configuration for it as an application-local resources. It might become arguable if this is or isn’t a violation of the Java EE spec which says that an application should not manage low-level connections, spawn threads, open sockets, etc. This is something that is better to be left to the application server – it also allows us to use one configuration file instead of spreading it across multiple places. So, the question is – how to access the JGroups subsystem from our EJB application? The whole solution involves few steps which will be described below. If you want to check the whole working project – take a look at my JGroups AS7 Github project.

1. Write Custom JBoss AS 7 Service Activator

This activator (JGroupsChannelServiceActivator.java) will do two things:

  • create the actual JGroups channel using JBoss protocol configuration,
  • bind the newly created JGroups channel to the JNDI.

First part is done in JGroupsChannelServiceActivator#createChannel(-). I don’t know the ServiceActivator nor other internals of the JBoss AS 7 modules but from what you can read:

InjectedValue<ChannelFactory> channelFactory = new InjectedValue<>();
ServiceName serviceName = ChannelFactoryService.getServiceName(STACK_NAME);
ChannelService channelService = new ChannelService(CHANNEL_NAME, channelFactory);

target.addService(channelServiceName, channelService)
      .addDependency(serviceName, ChannelFactory.class, channelFactory).install();  

it seems that it creates a new service (ChannelService) and let the JBoss MSC automatically inject its dependent ChannelFactory during the installation. The ChannelFactory will use the UDP protocol stack. The second part is done in JGroupsChannelServiceActivator#bindChannelToJNDI(-) and it binds the newly created Channel instance to the JNDI under user-defined location. In our case it is java:jboss/channel/myChannel.

2. Register the Activator

We now need to tell JBoss AS 7 to invoke our custom Activator. It is done using standardized JDK ServiceLoader API. In a nutshell it means we need to provide a META-INF/services/org.jboss.msc.service.ServiceActivator file with fully qualified name of our activator class. Take a look at this example.

3. Add Required Modules to our Application

Ok, so we have an activator that should do the magic. If we’d try to deploy it as such we’ll get a bunch of ClassNotFoundExceptions. It is because the JBoss Modules. Our application is not packed with all those JBoss artifacts like JGroups, ServiceActivator API and the JNDI related classes. We don’t want to clutter our app with those libraries – we just want to define the dependencies on modules provided by JBoss AS 7 itself. We do it in the META-INF/jboss-deployment-structure.xml. Note that we could do it in MANIFEST.MF Dependencies: section but Intellij IDEA doesn’t seem to be working with Maven generated MANIFEST.MF:

<?xml version='1.0' encoding='UTF-8'?>
<jboss-deployment-structure>
    <deployment>
        <dependencies>
            <module name='org.jgroups'/>
            <module name='org.jboss.as.naming'/>
            <module name='org.jboss.as.clustering.jgroups'/>
        </dependencies>
    </deployment>
</jboss-deployment-structure>

JGroups modules are required for accessing the JChannel, ChannelService, etc. The naming module is required for the JNDI binding code.

4. Develop the EJB Using JGroups Channel

JGroupsSampleDataProducer is a Singleton EJB that shows how to access the JGroups channel. It’s rather simple because of the JNDI binding. We can just use:

@Resource(lookup = 'java:jboss/channel/myChannel')
private JChannel channel;   

and there it is. This EJB registers a timer that is invoked every 2 seconds and sends some random String message.

Note we didn’t have to explicitly start the JChannel. We just inject it and use it straightaway. Take a look at the ChannelService used in our activator from step 1. Its start method looks like:

@Override
protected void start() throws Exception {
    (...)
    if (this.channel.getProtocolStack().findProtocol(STATE_TRANSFER.class, STATE.class, STATE_SOCK.class) != null) {
        this.channel.connect(this.id, null, STATE_TRANSFER_TIMEOUT);
    } else {
        this.channel.connect(this.id);
    }

So this service will connect to our channel automatically. Instead of using ChannelService we could develop our own service that will be responsible for starting and stopping our channel or we could even move this responsibility to the actual user of the channel.

5. Deploy the EJB-JAR

We are now ready to deploy our application to JBoss AS 7 server. The most important part here is to make sure our server will be running with the appropriate configuration, which means one with JGroups protocol stack defined. It is done using <subsystem xmlns='urn:jboss:domain:jgroups:1.1'>. I am using JBoss AS 7.1.1 and standalone-full-ha.xml config.

**Note: ** Because the Intellij IDEA doesn’t allow you to easily change the configuration file for your JBoss AS as the Eclipse does, we will need to specify it using VM options: -Djboss.server.default.config=standalone-full-ha.xml.

We also need to make sure JGroups will use IPv4 (it sometimes chooses the IPv6 which can lead to some weird and hard to solve problems.) To do so, add the -Djava.net.preferIPv4Stack=true option to the Server configuration.

6. Run the Client Application

You can find a rather simple Client code here. It just connects to JGroups cluster using specified configuration file. Mind that multicast port number and address should be set to the same values for server and client. Also remember to add -Djava.net.preferIPv4Stack=true VM option while running your client. Hope you’ll find this tutorial helpful and it’ll save you some configuration time. Great thanks to Bela Ban for a lot of important advice and Paul Ferraro for pointing me to relavant forum topics (like this or this one) regarding similar problems.
 

Reference: Using JGroups Directly From JBoss AS 7 Component from our JCG partner Piotr Nowicki at the Piotr Nowicki’s Homepage 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!  

Leave a Reply


× four = 24



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use
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

15,153 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
Get tutored by the Geeks! JCG Academy is a fact... Join Now
Hello. Add your message here.