HornetQ is the former JBoss EAP 6 / AS 7 messaging broker. It has been now deprecated. We recommend checking Artemis MQ which is the new version of the Messaging Broker that is included in WildFly application server. Getting started with ActiveMQ Artemis
HornetQ is an open source project to build a multi-protocol, embeddable, very high performance, clustered, asynchronous messaging system.
Why learning another messaging system ? here are a few good reasons:
- Hornet Q is an open source messaging system which can be used as standalone or on any application server or even embedded in your applications.
- HornetQ delivers amazing messaging performance.
- HornetQ provides seamless clustering capabilities.
- It’s the default Messaging system in JBoss EAP 6 and WildFly 8/9.
Since WildFly 10 and JBoss EAP 7 Apache Artemis MQ is the default Messagins system. This project, however, is derived from the HornetQ project, recently donated to the Apache foundation. The new messaging provides retains compatibility with the former HornetQ while providing several new features.
It takes just a few minutes to be operative, let’s start:
Download the latest stable release from http://www.jboss.org/hornetq/downloads.html and unzip in a convenient location.
Starting HornetQ
HornetQ can be started in 3 ways:
- Standalone server
- Inside an application server
- Embedded in your applications
#1 Standalone HornetQ server
Launching HornetQ as standalone server is fairly trivial: reach the “bin” folder in your HornetQ distribution and launch run.bat/run.sh
#2 Inside JBoss EAP 6 / WildFly 8
HornetQ is the JBoss EAP 6 and WildFly 8 messasing broker. To be more specific, the messaging suite of the application server is based on two core building blocks which let you create and consume JMS messages:
- HornetQ itself is the JBoss EAP’s messaging provider featuring a multi-protocol, embeddable, very high performance, clusterable messaging implementation.
- Netty project (http://netty.io/index.html) is an asynchronous event-driven network application framework which is used by HornetQ to transport messages from one JVM to another.
Please note that the messaging subsystem is not included in the default server configuration, therefore in order to use it you have to point to one of the standalone-full.xml or standalone-full-ha.xml configurations.So, for example, if you plan to run JMS applications on a non- clustered EAP server all you have to do is starting it like that:
$ ./standalone.sh –c standalone-full.xml
#3 Embedded in your Java code
HornetQ can be started as well in embedded mode. This can be particularly useful for testing purposes if you don’t want to start/stop manually the server on your machine.
An example of how to start an embedded HornetQ server is contained in the examples/core/embedded which can be found in the HornetQ distribution:
package org.hornetq.core.example; import java.util.Date; import org.hornetq.api.core.TransportConfiguration; import org.hornetq.api.core.client.ClientConsumer; import org.hornetq.api.core.client.ClientMessage; import org.hornetq.api.core.client.ClientProducer; import org.hornetq.api.core.client.ClientSession; import org.hornetq.api.core.client.ClientSessionFactory; import org.hornetq.api.core.client.HornetQClient; import org.hornetq.api.core.client.ServerLocator; import org.hornetq.core.config.Configuration; import org.hornetq.core.config.impl.ConfigurationImpl; import org.hornetq.core.remoting.impl.invm.InVMAcceptorFactory; import org.hornetq.core.remoting.impl.invm.InVMConnectorFactory; import org.hornetq.core.server.HornetQServer; import org.hornetq.core.server.HornetQServers; /** * * This example shows how to run a HornetQ core client and server embedded in your * own application * * @author Tim Fox * */ public class EmbeddedExample { public static void main(final String[] args) throws Exception { try { // Step 1. Create the Configuration, and set the properties accordingly Configuration configuration = new ConfigurationImpl(); //we only need this for the server lock file configuration.setJournalDirectory("target/data/journal"); configuration.setPersistenceEnabled(false); configuration.setSecurityEnabled(false); configuration.getAcceptorConfigurations().add(new TransportConfiguration(InVMAcceptorFactory.class.getName())); // Step 2. Create and start the server HornetQServer server = HornetQServers.newHornetQServer(configuration); server.start(); // Step 3. As we are not using a JNDI environment we instantiate the objects directly ServerLocator serverLocator = HornetQClient.createServerLocatorWithoutHA(new TransportConfiguration(InVMConnectorFactory.class.getName())); ClientSessionFactory sf = serverLocator.createSessionFactory(); // Step 4. Create a core queue ClientSession coreSession = sf.createSession(false, false, false); final String queueName = "queue.exampleQueue"; coreSession.createQueue(queueName, queueName, true); coreSession.close(); ClientSession session = null; try { // Step 5. Create the session, and producer session = sf.createSession(); ClientProducer producer = session.createProducer(queueName); // Step 6. Create and send a message ClientMessage message = session.createMessage(false); final String propName = "myprop"; message.putStringProperty(propName, "Hello sent at " + new Date()); System.out.println("Sending the message."); producer.send(message); // Step 7. Create the message consumer and start the connection ClientConsumer messageConsumer = session.createConsumer(queueName); session.start(); // Step 8. Receive the message. ClientMessage messageReceived = messageConsumer.receive(1000); System.out.println("Received TextMessage:" + messageReceived.getStringProperty(propName)); } finally { // Step 9. Be sure to close our resources! if (sf != null) { sf.close(); } // Step 10. Stop the server server.stop(); } } catch (Exception e) { e.printStackTrace(); throw e; } } }
Inspecting HornetQ configuration
The configuration of HornetQ is split in several files. The following table resumes the basics of its configuration.
File | Content |
hornetq-beans.xml | The core MBean server and Port settings. |
hornetq-configuration.xml | Main configuration file. Used to change JMS Storage directories and Message settings. |
hornetq-jms.xml | JMS Queue/Topic configuration. |
hornetq-users.xml | Users configuration |
logging.properties | The JUL configuration of the Server |
As a developer you are likely to be interested to uodate the hornetq-jms.xml file to add/remove new Queue/Topics.
Deploying a simple MDB
Here is an example of MDB from the example suite which demonstrate sending a message and the MDB consuming only the message that matches the message selector.
package org.hornetq.javaee.example.server; import org.jboss.ejb3.annotation.ResourceAdapter; import javax.ejb.ActivationConfigProperty; import javax.ejb.MessageDriven; import javax.ejb.TransactionAttribute; import javax.ejb.TransactionAttributeType; import javax.ejb.TransactionManagement; import javax.ejb.TransactionManagementType; import javax.jms.Message; import javax.jms.MessageListener; import javax.jms.TextMessage; /** * @author Andy Taylor */ @MessageDriven(name = "MDBMessageSelectorExample", activationConfig = { @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/testQueue"), @ActivationConfigProperty(propertyName = "messageSelector", propertyValue = "color = 'RED'") }) @TransactionManagement(value= TransactionManagementType.CONTAINER) @TransactionAttribute(value= TransactionAttributeType.REQUIRED) @ResourceAdapter("hornetq-ra.rar") public class MDBMessageSelectorExample implements MessageListener { public void onMessage(Message message) { try { //Step 11. We know the client is sending a text message so we cast TextMessage textMessage = (TextMessage)message; //Step 12. get the text from the message. String text = textMessage.getText(); //Step 13. We check we received the right color of message String color = textMessage.getStringProperty("color"); System.out.println("message " + text + " received color=" + color); } catch (Exception e) { e.printStackTrace(); } } }
Ok. In order to connect to the MDB, you have to provide the following exports in your messaging configuration:
<jms-connection-factories> . . . . . <connection-factory name="RemoteConnectionFactory"> <connectors> <connector-ref connector-name="netty"/> </connectors> <entries> <entry name="RemoteConnectionFactory"/> <entry name="java:jboss/exported/jms/RemoteConnectionFactory"/> </entries> </connection-factory> </jms-connection-factories> <jms-destinations> <jms-queue name="testQueue"> <entry name="queue/test"/> <entry name="java:jboss/exported/jms/queues/testQueue"/> </jms-queue> </jms-destinations>
And finally here’s a generic test client which can be used to send messages to the “testQueue”:
package org.hornetq.javaee.example; import javax.jms.Connection; import javax.jms.ConnectionFactory; import javax.jms.MessageProducer; import javax.jms.Queue; import javax.jms.Session; import javax.jms.TextMessage; import javax.naming.Context; import javax.naming.InitialContext; import java.util.Properties; /** * @author Andy Taylor */ public class MDBMessageSelectorClientExample { public static void main(String[] args) throws Exception { Connection connection = null; InitialContext initialContext = null; try { //Step 1. Create an initial context to perform the JNDI lookup. final Properties env = new Properties(); env.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory"); env.put(Context.PROVIDER_URL, "remote://localhost:4447"); env.put(Context.SECURITY_PRINCIPAL, "guest"); env.put(Context.SECURITY_CREDENTIALS, "password"); initialContext = new InitialContext(env); //Step 2. Perfom a lookup on the queue Queue queue = (Queue) initialContext.lookup("jms/queues/testQueue"); //Step 3. Perform a lookup on the Connection Factory ConnectionFactory cf = (ConnectionFactory) initialContext.lookup("jms/RemoteConnectionFactory"); //Step 4.Create a JMS Connection connection = cf.createConnection("guest", "password"); //Step 5. Create a JMS Session Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); //Step 6. Create a JMS Message Producer MessageProducer producer = session.createProducer(queue); //Step 7. Create a Text Message and set the color property to blue TextMessage blueMessage = session.createTextMessage("This is a text message"); blueMessage.setStringProperty("color", "BLUE"); System.out.println("Sent message: " + blueMessage.getText() + " color=BLUE"); //Step 8. Send the Message producer.send(blueMessage); //Step 9. create another message and set the color property to red TextMessage redMessage = session.createTextMessage("This is a text message"); redMessage.setStringProperty("color", "RED"); System.out.println("Sent message: " + redMessage.getText() + " color=RED"); //Step 10. Send the Message producer.send(redMessage); //Step 10,11 and 12 in MDBMessageSelectorExample } finally { //Step 13. Be sure to close our JMS resources! if (initialContext != null) { initialContext.close(); } if(connection != null) { connection.close(); } } } }
Your example is completed.In order to build the example, the following dependencies need to be set in your Maven project:
<hornetq.client.version>2.4.0-SNAPSHOT</hornetq.client.version> <dependencies> <dependency> <groupId>org.jboss.spec.javax.jms</groupId> <artifactId>jboss-jms-api_2.0_spec</artifactId> </dependency> <dependency> <groupId>org.jboss.spec</groupId> <artifactId>jboss-javaee-6.0</artifactId> <version>1.0.0.Final</version> <type>pom</type> <scope>provided</scope> </dependency> <dependency> <groupId>org.hornetq</groupId> <artifactId>hornetq-core-client</artifactId> <version>${hornetq.client.version}</version> </dependency> <dependency> <groupId>org.hornetq</groupId> <artifactId>hornetq-jms-client</artifactId> <version>${hornetq.client.version}</version> </dependency> <dependency> <groupId>org.hornetq</groupId> <artifactId>hornetq-ra</artifactId> <version>${hornetq.client.version}</version> </dependency> <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>${netty.version}</version> </dependency> <dependency> <groupId>org.jboss.ejb3</groupId> <artifactId>jboss-ejb3-ext-api</artifactId> <version>2.0.0-beta-2</version> </dependency> </dependencies>