Connect Glassfish 3 to external ActiveMQ 5 broker
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.
Reference: How to connect Glassfish 3 to an external ActiveMQ 5 broker from our JCG partner Geert Schuring at the Geert Schuring blog.