Playing with ActiveMQ using Maven

In this post I demonstrate how to get started with ActiveMQ. This is very much a simple beginners guide, and shows you just enough to get a message traveling between 2 separate applications.

I’ve separated the example up into 3 sections. The ‘producer’ section will create test messages on a queue, the ‘consumer’ will consume them, and the final section, ‘mq’, will host the ActiveMQ instance. It would be possible to do this in a single application using an embedded broker, however I think it’s useful to demonstrate them separately, as potentially the components could be on separate machines.

To get started, let’s create the 3 projects:

$ mvn --batch-mode archetype:generate -DarchetypeArtifactId=maven-archetype-quickstart -DgroupId=net.timico.messaging -DartifactId=producer -Dversion=0.1

$ mvn --batch-mode archetype:generate -DarchetypeArtifactId=maven-archetype-quickstart -DgroupId=net.timico.messaging -DartifactId=consumer -Dversion=0.1

$ mvn --batch-mode archetype:generate -DarchetypeArtifactId=maven-archetype-quickstart -DgroupId=net.timico.messaging -DartifactId=mq -Dversion=0.1

Setting up ActiveMQ

We’ll get the ActiveMQ broker up and running first. Change directory into 'mq' and modify the pom.xml file as below:


  4.0.0
  net.timico.messaging
  mq
  jar
  0.1
  mq
  http://maven.apache.org
  
    
      junit
      junit
      3.8.1
      test
    
  
  
    
      
        org.apache.activemq.tooling
        maven-activemq-plugin
        5.1
        
          xbean:file:./conf/activemq.xml
          false
          
            
              javax.net.ssl.keyStorePassword
              password
            
            
              org.apache.activemq.default.directory.prefix
              ./target/
            
          
        
        
          
            org.springframework
            spring
            2.5.5
          
          
            org.mortbay.jetty
            jetty-xbean
            6.1.11
          
          
            org.apache.camel
            camel-activemq
            1.1.0
          
        
      
    
  

We now need to create a configuration file for ActiveMQ, which will reside in conf/activemq.xml. Below you can see a very minimal config which will be sufficient for our needs.


  
    
    
      
    
  

That’s all we need! We can now launch ActiveMQ by simply running the following:

$ mvn org.apache.activemq.tooling:maven-activemq-plugin:5.2.0:run

Creating the Producer

We need to modify the pom.xml for the producer to include the JMS and ActiveMQ dependencies. I’ve also added the jboss repository so that JMS will download automatically without needing to manually install it into your local maven repository.


  4.0.0
  net.timico.messaging
  producer
  jar
  0.1
  producer
  http://maven.apache.org
  
    
      junit
      junit
      3.8.1
      test
    
    
      javax.jms
      jms
      1.1
    
    
      org.apache.activemq
     activemq-core
      5.2.0
    
  
  
    
      jboss
      http://repository.jboss.com/maven2
      
      
      
        false
      
    
  

I’ve decided to separate the Producer app into 2 files. There’s the App class, and the Producer class. The App class creates the ConnectionFactory, which is the only ActiveMQ specific bit of code, passes it to the constructor of the Producer class, calls the run method, and finally the close method.

src/main/java/net/timico/messaging/App.java
package net.timico.messaging;

import javax.jms.ConnectionFactory;
import org.apache.activemq.ActiveMQConnectionFactory;

public class App
{
    public static String brokerURL = "tcp://localhost:61616";

    public static void main( String[] args ) throws Exception
    {
        // setup the connection to ActiveMQ
        ConnectionFactory factory = new ActiveMQConnectionFactory(brokerURL);

        Producer producer = new Producer(factory, "test");
        producer.run();
        producer.close();
    }
}
src/main/java/net/timico/messaging/App.java
package net.timico.messaging;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageProducer;
import javax.jms.Session;

public class Producer
{
    private ConnectionFactory factory;
    private Connection connection;
    private Session session;
    private MessageProducer producer;

    public Producer(ConnectionFactory factory, String queueName) throws JMSException
    {
        this.factory = factory;
        connection = factory.createConnection();
        connection.start();
        session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        Destination destination = session.createQueue(queueName);
        producer = session.createProducer(destination);
    }

    public void run() throws JMSException
    {
        for (int i = 0; i < 100; i++)
        {
            System.out.println("Creating Message " + i);
            Message message = session.createTextMessage("Hello World!");
            producer.send(message);
        }
    }

    public void close() throws JMSException
    {
        if (connection != null)
        {
            connection.close();
        }
    }

}

This application can be run by executing the following:

$ mvn clean compile exec:java -Dexec.mainClass=net.timico.messaging.App

The Consumer

The consumer is pretty simple, and not that different from the producer. This class implements the MessageListener interface, causing the onMessage method to be called everytime a message is queued in the 'test' queue.

src/main/java/net/timico/messaging/App.java
package net.timico.messaging;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;

public class App implements MessageListener
{

    public static String brokerURL = "tcp://localhost:61616";

    private ConnectionFactory factory;
    private Connection connection;
    private Session session;
    private MessageConsumer consumer;

    public static void main( String[] args )
    {
        App app = new App();
        app.run();
    }

    public void run()
    {
        try
        {
            ConnectionFactory factory = new ActiveMQConnectionFactory(brokerURL);
            connection = factory.createConnection();
            connection.start();
            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            Destination destination = session.createQueue("test");
            consumer = session.createConsumer(destination);
            consumer.setMessageListener(this);
        }
        catch (Exception e)
        {
            System.out.println("Caught:" + e);
            e.printStackTrace();
        }
    }

    public void onMessage(Message message)
    {
        try
        {
            if (message instanceof TextMessage)
            {
                TextMessage txtMessage = (TextMessage)message;
                System.out.println("Message received: " + txtMessage.getText());
            }
            else
            {
                System.out.println("Invalid message received.");
            }
        }
        catch (JMSException e)
        {
            System.out.println("Caught:" + e);
            e.printStackTrace();
        }
    }
}

Assuming you're run the producer at least once, you should have messages on your queue ready to consume. When you run the consumer you will see a flood of messages.

$ mvn clean compile exec:java -Dexec.mainClass=net.timico.messaging.App

This process will not terminate, and will sit there waiting forever for messages - press CTRL-C to terminate.

To learn more about messaging, I strongly advise Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions.

Useful links

20 thoughts on “Playing with ActiveMQ using Maven”

  1. In a previous post, “Playing with ActiveMQ using Maven”, I showed how to produce and consume simple messages using Java. In this short post I show how to access these messages from PHP using STOMP. Assuming you are continuing from my previous a

  2. Really Sir, suberb.

    Just I copy and past code in my application and got running without changing a single line code. I only create one project and put Producer.java, Consumer.java and App.java.

    Thanks,

    Binod Suman

  3. thanks for this tutorial – i just played around with RabbitMQ and wanted to take a quick look at ActiveMQ and this is the article I’ve searched for 🙂

  4. I tried runing this tutorial. When I tried consumer, i do not see any messages. Also, the consumer process terminates nicely ( as opposed to the acertion “will not terminate” in the tutorial ). Any suggestion as to what might have gone wrong ?. As such I did not receive any errors during bulding 3 projects.

    1. Sorry, I figured out the problem myself. My modified source code App were in a different directory. Thank you for an excellent tutorial. This is one of the finest I have seen so far.

  5. hi. it is really great post.

    i copied and past the codes. getting error like this :

    —————————
    [ERROR] Failed to execute goal org.apache.activemq.tooling:maven-activemq-plugin:5.2.0:run (default-cli) on project jal-mq: Failed to start Activ
    eMQ Broker: Illegal character in opaque part at index 5: file: ./activemq.xml -> [Help 1]
    org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache.activemq.tooling:maven-activemq-plugin:5.2.0:run (defau
    lt-cli) on project jal-mq: Failed to start ActiveMQ Broker
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:217)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)
    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:319)
    at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156)
    at org.apache.maven.cli.MavenCli.execute(MavenCli.java:537)
    at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196)
    at org.apache.maven.cli.MavenCli.main(MavenCli.java:141)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:290)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:230)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:409)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:352)
    Caused by: org.apache.maven.plugin.MojoExecutionException: Failed to start ActiveMQ Broker
    at org.apache.activemq.maven.BrokerMojo.execute(BrokerMojo.java:107)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:209)
    … 19 more
    Caused by: java.net.URISyntaxException: Illegal character in opaque part at index 5: file: ./activemq.xml
    at java.net.URI$Parser.fail(URI.java:2809)
    at java.net.URI$Parser.checkChars(URI.java:2982)
    at java.net.URI$Parser.parse(URI.java:3019)
    at java.net.URI.(URI.java:578)
    at org.apache.activemq.broker.BrokerFactory.createBroker(BrokerFactory.java:85)
    at org.apache.activemq.maven.BrokerMojo.execute(BrokerMojo.java:90)
    … 21 more
    ———————-

  6. Very nice tutorial. Only one little hitch on the way (like javax.jms not found in the repository as shown in your example). And also you split the code for producer into two classes and the label for the second code listing is copy-paste from the first listing. tiniest little bit misleading. These are just ideas for improvement. Loved the simple way you constructed this example, now i can play with jms stuff 🙂 thanks

  7. Pingback: ActiveMQ and Maven
  8. If you get a compile error on the consumer, add the javax.jms and activemq dependencies, and the jboss repository to the consumer pom file.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.