Home > ActiveMQ, Application Servers, Glassfish, Java > How to connect Glassfish 3 to an external ActiveMQ 5 broker

How to connect Glassfish 3 to an external ActiveMQ 5 broker

Introduction

Here at ONVZ we’re using Glassfish 3 as our development and production application server, and we’re quite happy with its performance and stability, as well as the large community surrounding it. I rarely run into a problem that does not have a matching solution on stackoverflow or java.net. As part of our open source strategy we also run a customized ActiveMQ cluster called “ONVZ Message Bus”.

To enable Message Driven Beans and other EJBs to consume and produce messages to and from the ActiveMQ message brokers, ignoring the internal OpenMQ broker that comes shipped with Glassfish, an ActiveMQ Resource Adapter has to be installed. Luckily for me Sven Hafner wrote a blog post about running an embedded ActiveMQ 5 broker in Glassfish 3, and I was able to distill the information I needed to connect to an external broker instead. This blog post describes what I did to get it to work.

Install the ActiveMQ Resource Adapter

  • Before you start Glassfish copy the following libraries from an ActiveMQ installation directory or elsewhere to Glassfish
    • Copy “slf4j-api-1.5.11.jar” from the ActiveMQ “lib” directory to the Glassfish “lib” directory
    • Copy “slf4j-log4j12-1.5.11.jar” and “log4j-1.2.14.jar” from the ActiveMQ “lib/optional” directory to the Glassfish “lib” directory. Note: Instead of these two you can also download “slf4j-jdk14-1.5.11.jar” from the maven repo to the Glassfish “lib” directory.
  • Download the resource adapter (activemq-rar-5.5.1.rar) from the following location
  • Deploy the resource adapter in Glassfish
    • In the Glassfish Admin Console, go to “Applications”, and click on “Deploy”
    • Click “Choose file” and select the rar file you just downloaded.
    • Notice how the page recognized the selected rar file and automatically selected the correct Type and Application Name and finally click “Ok”
  • Create the Resource Adapter Config
    • In the Glassfish Admin Console, go to “Resources”, and click on “Resource Adapter Configs”
    • Click “New”, and select the ActiveMQ Resource Adapter we just depoyed, and select a Thread Pool. (“thread-pool-1″ for instance)
    • Set the property “ServerUrl”, “UserName” and “Password”, leave the rest untouched and click “OK”.
  • Create the Connector Connection Pool
    • In the Glassfish Admin Console, go to “Resources”, “Connectors”, “Connector Connection Pools”
    • Click “New”, fill in a pool name like “jms/connectionFactory” and select the ActiveMQ Resource Adapter. The Connection Definition will default to “javax.jms.ConnectionFactory”, which is correct, so click “Next”.
    • Enable the “Ping” checkbox and click “Finish”.
  • Create the Admin Object Resource
    • In the Glassfish Admin Console, go to “Resources”, “Connectors”, “Admin Object Resources”
    • Click “New”, set a JNDI Name such as “jms/queue/incoming” and select the ActiveMQ Resource Adapter
    • Again, the other fields don’t need to be changed so click “OK”

We now have everything in place (in JNDI actually) to start processing messages using a standard Java EE Message Driven Bean. The “Connector Connection Pool” you just created has resulted in a ConnectionFactory being registered in JNDI, and the “Admin Object Resource” resulted in a JMS Destination. You can find these objects in the admin console when you go to “Resources”, “JMS Resources”. In the Glassfish version I’m using (3.1.1) the admin console has a bug which results in the connection factory and destinations being only visible in the menu, and not on the right side of the page.

Create and deploy a Message Driven Bean

  • Create a new Java Enterprise project in your favorite IDE, and create a Message Driven Bean with the following contents:

package com.example.activemq.glassfish;

import javax.ejb.*;
import javax.jms.*;

@MessageDriven(
        activationConfig = {
            @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
            @ActivationConfigProperty(propertyName = "destination", propertyValue = "jms/queue/incoming")
        }
)
public class ExampleMessageBean implements MessageListener {

    public void onMessage(Message message) {
        try {
        	System.out.println("We've received a message: " + message.getJMSMessageID());
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
}

Glassfish will hookup your bean to the configured queue but it will try to do so with the default ConnectionFactory which connects to the embedded OpenMQ broker. This is not what we want, so we’ll instruct Glassfish which ConnectionFactory to use.

  • Add a file called glassfish-ejb-jar.xml to the META-INF folder, and insert the following contents:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glassfish-ejb-jar PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 EJB 3.1//EN" "http://glassfish.org/dtds/glassfish-ejb-jar_3_1-1.dtd">
<glassfish-ejb-jar>
    <enterprise-beans>
        <ejb>
            <ejb-name>ExampleMessageBean</ejb-name>
            <mdb-connection-factory>
                <jndi-name>jms/connectionFactory</jndi-name>
            </mdb-connection-factory>
            <mdb-resource-adapter>
                <resource-adapter-mid>activemq-rar-5.5.1</resource-adapter-mid>
            </mdb-resource-adapter>
        </ejb>
    </enterprise-beans>
</glassfish-ejb-jar>
  • Deploy the MDB to glassfish

Glassfish now uses the ActiveMQ ConnectionFactory and all is well. Use the ActiveMQ webconsole to send a message to a queue called “jms/queue/incoming”, or use some other tool to send a message. Glassfish catches all the sysout statements and prints those in it’s default glassfish log file.

References:

Sven Hafner – http://javadude.wordpress.com/2011/07/21/glassfish-v3-1-running-embedded-activemq-for-jms-part-1

About these ads
  1. Ant B
    April 27, 2012 at 3:21 pm

    Hi Geert,

    Nice post. I had similar experiences “distilling” the steps required to consume messages from ActiveMQ in Glassfish 3. I posted to the ActiveMQ forum:

    http://activemq.2283324.n4.nabble.com/Consume-Topic-messages-from-remote-MDB-ActiveMQ-5-5-1-amp-Glassfish-3-1-1-td4319980.html

    I recently moved to a linux dev environment, and noticed what may be a bug – I cannot use a JNDI name which matches the names of the ActiveMQ destinations (e.g. my.topic.xml). The admin console displays error, and the server logs state that their was an error at the intended end-point.

    Have you encountered any similar issues?

    Ant

  2. Leonid Kogan
    June 25, 2012 at 4:10 pm

    Hi there and thanks for the great article!
    Everything works, however, the dequeueing performance is just unthinkably slow. Something about 10 messaged per second. The standalone consumer does something like 1000 per second. Any ideas?

    Thanks in advance,
    LK

  3. July 11, 2012 at 7:34 pm

    Do you know how I could override the ra.xml and activemq-config.xml configuration without mucking with the contents of the RAR file (seems a bit clumsy to do so)? I need to add transports, customize clustering and connect to a remote broker on another GF instance.

    Thanks in advance.

  4. Cristian
    September 4, 2012 at 5:05 pm

    Hi Geert,

    Thank you for the article!

    ¿Can provide your Glassfish 3 server version (3.x or build) at the moment that you write this tutorial? I am having problems to follow this guide with the actual Glassfish 3 versions.

    Thank you!

    Chris

  5. October 23, 2012 at 4:26 pm

    Can ‘Producing’ through ActiveMQ be documented similarly? I found ourselves going to the native ActiveMQ calls in order to produce messages, and I”d rather use the EJB-way of producing messages.
    i.e. ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(user, password, url); etc.

    • Bob
      November 5, 2012 at 7:10 pm

      Any update and/or ideas on producing jms messages in GlassFish 3.1 to ActiveMQ without using native ActiveMQConnectionFactory?

      • November 5, 2012 at 10:33 pm

        Nothing yet, our dev’s are using the native ActiveMQ calls still.

      • November 6, 2012 at 11:36 am

        I’m currently at ApacheCon so I’ll take a look at it next week. It should be easy to define an ActiveMQ connection factory and have it inserted into your EJB.

    • Rick
      December 11, 2012 at 12:23 am

      It is easy to do. Just create a new “Connector Resource”. Navigate to “connectors->Connector Resources”, click on the “New” button, Give a JNDI name, Choose the Pool Name which you just created in this blog, and save it.

      Create a new EJB which can send message to the queue.

      @Resource(mappedName=””)
      private ConnectionFactory queueConnectionFactory;

      Connection connection =queueConnectionFactory.createConnection();
      Session session =connection.createSession(Boolean.TRUE, Session.SESSION_TRANSACTED);
      Destination dest=session.createQueue(“”);
      MessageProducer producer=session.createProducer(dest);
      Message messages=session.createTextMessage(“This is a testing message”);
      producer.send(messages);

      • Rick
        December 11, 2012 at 12:24 am

        mappedName= “The Connector Resource JNDI Name which you just created”

  6. Rene
    November 14, 2012 at 2:32 pm

    This post helped me a lot.

    1) Adding an ejb-jar.xml seems necessary (see e.g.: Sven Hafner’s post)

    I tried to deploy the mdb as a war-file. It resulted in adding the following jvm-option to my Glassfish server-config:
    -Dcom.sun.enterprise.connectors.inbound.ramid=activemq-rar-5.7.0

    As a result of this, the glassfish-ejb-jar.xml was no longer needed.

    2) Restarting activeMQ requires also reloading the war-application in order to make the mdb consuming messages again. I think this is unacceptable behavior when in production use.
    What is the recommended resolution for this issue?

  7. December 21, 2012 at 2:33 pm

    I followed this nice guide and got MDB working, thanks! I also tried implementing a servlet which would send to the queue but I ran into some problems where the queu resource in my servlet would not get injected. After some testing and googling I realised that the Admin Object Resource was not reachable over JNDI! Creating it using Glassfish asadmin command instead solved my problem.

    I wrote down my findings here: http://codelevain.wordpress.com/2012/12/21/glassfish_activemq/

  1. December 21, 2012 at 2:25 pm

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: