Skip to main content

Tomitribe supports a lot of clients that use ActiveMQ and JMS in production. This post introduces you to both ActiveMQ and JMS. If you already understand the fundamental concepts behind JMS messaging, skip ahead to “A Short ActiveMQ and JMS Tutorial”. It should take five minutes or less. If you are new to JMS than keep reading!

JMS Concepts

A messaging system is composed of a JMS Broker (middleware), Queues and Topics, and Producers and Consumers.

The JMS Broker

There is a common misunderstanding that JMS messages are sent directly from one application to another; that the application sending is connected directly to the application receiving. This could not be further from the truth.

Between the sender and receiver (aka producers and consumers) is a broker – an application server – that receives messages from producers and sends messages to consumers. The producers and consumers are completely decoupled. In principle, the producer has no idea who is getting its messages and the consumer has no idea who is sending them.

It’s the broker to which producers are sending the messages using a kind of address called a Topic or Queue. After receiving a message, the broker forwards the message to consumers who have subscribed to the Topic or Queue. Transactions with producers and consumers are transactions between the producer and the broker or between the broker and the consumers, but never between the producer and the consumer.

JMS Topic vs. Queues

With JMS you have the option of publishing messages to a Topic or Queue. There is a fundamental difference between the two which is illustrated below. A Topic forwards a message from the producer to many consumers at once. It’s a broadcast. This is often called Publish-and-Subscribe (Pub/Sub) messaging. A Queue may also have many consumers, but it forwards each message to only one consumer. The consumers wait in line, in a queue, taking turns getting new messages from the Queue. This often called Point-to-Point (P2P) messaging.

A Short ActiveMQ and JMS Tutorial

The purpose of this tutorial is to show you how easy it is to set up ActiveMQ for simple messaging, but it also demonstrates the difference in the distribution of messages when using Topics vs Queues. We can demonstrate the difference by setting up a single producer, a broker, and multiple consumers, but before we do that we need a JMS broker to manage the sending and receiving of messages. That’s where ActiveMQ comes in.

Step 1: Download and start ActiveMQ

1. Download ActiveMQ 5 “Classic”
You will find the link to download further down the page.

2. Copy to Desktop and Unzip it
You should get Desktop/apache-activemq-5.a.b directory (where a.b is minor and point version e.g. Desktop/apache-activemq-5.15.9)

3. Open a console window and navigate ActiveMQ directory

$ cd Desktop/apache-activemq-5.a.b/

4. Start the server and then minimize the window so it’s not in your way

$ cd Desktop/apache-activemq-5.a.b/
$ bin/activemq console

Step 2: Download the JMS Example file

1. Go to GitHub and download the example zip file to your “Desktop” and Unpackage it.

2. Rename the directory from “JMS-1.1-PubSub-Queue-Example-with-ActiveMQ” to simply “JmsExample”.

Step 4: Open three additional console windows

In addition to the console window that ActiveMQ is running in, you’ll need three more console windows so that you can have one Java application producing (sending) JMS messages to two other applications consuming (receiving) them. You can either open new standalone console windows for each application, open one console window and two more tabs, or open one console window and split it into three consoles. As long as you have three separate console command-lines any option is fine.

With the three console windows open, navigate each one to the JmsExample directory on your Desktop.

$ cd Desktop/JmsExample

When you are done, your Desktop should look something like the one pictured below.

Step 3: Do the Maven Install

1. In one of three console windows that you just opened, run the $ mvn install console to build the example.

$ mvn install

Step 4: Start the JMS Consumers and Producer for Topic-based Messaging

1. In two of the three console windows enter $ java -cp target/jms-example-SNAPSHOT.jar example.Consumer Topic to start the consumers.

$ java -cp target/jms-example-SNAPSHOT.jar example.Consumer Topic

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

2. In the third console window enter $ java -cp target/jms-example-SNAPSHOT.jar example.Producer Topic to start the producer.

$ java -cp target/jms-example-SNAPSHOT.jar example.Producer Topic

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

Enter message: 

3. With all the console windows set up, it should look something like this:

Step 5: Send JMS messages to the Topic

1. The producer window should say Enter message: At this prompt type in the message you want to send and hit Enter.

$ java -cp target/jms-example-SNAPSHOT.jar example.Producer Topic

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

Enter message: Hi!
Enter message: 

2. The other two console windows are running the consumers. You should see the text entered at the producer prompt appear in both of the consumer windows.

3. When you are done with the example, send the “shutdown” message from the producer console to exit all three programs (the ActiveMQ broker will keep running).

Enter message: shutdown
$ 

The shutdown message is sent the consumers just like any other message, but when that keyword, “shutdown”, is received it triggers the consumer applications to exit. After the message is sent to the broker, the producer application will also exit.

During this part of the tutorial, you should have observed that, when using a Topic, every message goes to all the clients that are subscribed to that topic. It’s a broadcast.

Step 6: Repeat Steps 4 and 5 for JMS Queue-based Messaging

At this point, you can either reuse the producer and two consumers console windows (make sure they have exited to the command line prompt), or you can open three new console windows.

1. In two console windows enter the $ java -cp target/jms-example-SNAPSHOT.jar example.Consumer queue to start the consumers.

$ java -cp target/jms-example-SNAPSHOT.jar example.Consumer queue

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

2. In the remaining console windows enter $ java -cp target/jms-example-SNAPSHOT.jar example.Producer queue to start the producer.

$ java -cp target/jms-example-SNAPSHOT.jar example.Producer queue

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

Enter message: 

3. At the prompt send these text messages.

Enter message: First
Enter message: Second
Enter message: Third
Enter message: Fourth
Enter message: 

4. Observer the consumers.

You should have noticed that messages sent to a Queue are only delivered to one client at a time and that clients take turns receiving messages. Every message goes to one consumer when using a Queue.

5. Send the “shutdown” message.

$ Enter message: shutdown

Did you notice that when you sent the “shutdown” message that only the producer and one of the consumers actually did exit; That one consumer is still running? Why do you think that is the case? If you know the answer then you understand the fundamental difference between Topics and Queues. If you do not know the answer, then you may want to read the “JMS Concepts” section again.

Wrapping Up

Hopefully, this tutorial allowed you to see not only how easy it is to get started with ActiveMQ, but the fundamental difference between a Queue and Topic in JMS messaging. Queues forward messages to one consumer at a time. Topics forward messages to many consumers at once.

The source code included with this tutorial contains detailed information, in the form of comments about the specific JMS API calls used to send and receive messages. You can learn a lot just reading those comments while looking at the example source code.

Richard Monson-Haefel

Richard Monson-Haefel

Richard has more the 24 years of experience as a professional software developer and architect. He has written five books on enterprise Java including EJB, JMS, web services, and software architecture. He has served on the JCP executive committee and multiple expert groups, is the co-founder of OpenEJB and Apache Geronimo, was a Sr. Analyst for Burton Group (aka Gartner), and is a celebrated public speaker.
rmonson

15 Comments

  • narayan says:

    It helped me to learn the basic concepts of JMS and Kafka

  • EuropaCoder says:

    My message is getting published only to one of the consumers, Its not reaching the other. I am getting the following exception: Exception in thread “main” javax.jms.JMSException: Transport closed due to the peer exceeding our requested idle-timeout

  • EuropaCoder says:

    My message is getting published only to one of the consumers, Its not reaching the other. I am getting the following exception: Exception in thread “main” javax.jms.JMSException: Transport closed due to the peer exceeding our requested idle-timeout

  • Richard Monson-Haefel says:

    @EuropaCoder. Please zip up your project and send it to me at [email protected]. I’m happy to look it over and see if I can replicate the timeout condition. Without the source code it’s difficult to triage the problem.

  • misterchaos says:

    really good tutorial for a beginer

  • Tharinda Wickramaarachchi says:

    Clearly explained the basics. Thanks

  • Oliver Yao says:

    Really good article, easy and clear. Thanks.

  • Sam says:

    Keep up the good work. Fantastic stuff for beginners!

  • Marlo says:

    Thanks for this easy to understand mini tutorial. A better explaination I can’t imagine, thanks!

    I have spend some hours to understand this concepts, now I understand it.

  • Russ says:

    Thank you for a simple ‘hello world’ example. All to often these example offerings try to do a bit of everything and get overly complicated.

  • Marek says:

    I have apache-activemq-5.16.0 and there was no options like $activemq console so used $activemq start and then everything worked well.
    (With the option ‘console’ I got this error when I wanted to run consumer or producer ‘Exception in thread “main” javax.jms.JMSException: Connection refused: no further information: localhost/127.0.0.1:5672’)

  • Umadhar M says:

    Its really fun by running the examples after reading this article, Very simple and nice article to inject concept into our brain 🙂 Thank you.

  • Turan says:

    Thanks, great tutorial.

Leave a Reply