Every computer system frequently exchanges data, either locally, within the system or perhaps over the Internet. When we take a closer look, this is actually the data that is exchanged between processes running on the same machine or different machines. We call this data messages, which can vary in length and type. When two processes communicate with each other, it is a good idea to use a queue for messaging, because messages placed onto the queue are stored until the recipient retrieves them. This ensures robustness and reliability through persistence strategies. To maintain a high reliability level of the messages, message queues are used.
Today, there are a lot of message queues to choose from. In fact, there are dozens of message queues with different features and various pros and cons, and Apache ActiveMQ is one of them. Lets explore it.
What is ActiveMQ?
Apache ActiveMQ is a popular and powerful open source message-oriented middleware (software for communication between distributed applications). It supports the J2EE feature called JMS (Java Messaging Service). Apache ActiveMQ is released under the Apache 2.0 License. Apart from Java Apache, ActiveMQ supports cross-language clients such as Perl, PHP, Python, C/C++, C#, Ruby and more. ActiveMQ is widely used with ESBs (Enterprise Service Bus) such as Apache ServiceMix, JBoss Fuse and Mule. It is also used with Apache Camel, a very powerful EIP (Enterprise Integration Pattern).
Features
Described below are a few of the features of Apache ActiveMQ:
1. Supports a variety of cross-language clients. Apart from the obvious Java support via JMS, it also supports Perl, PHP, Python, C/C++, C#, Ruby and more.
2. Full support for EIP (Enterprise Integration Pattern); Apache ActiveMQ is used with Apache Camel to support EIP.
3. Fully supports JMS 1.1 and J2EE 1.4.
4. RESTful API support messaging directly from Web browsers using regular HTTP GET or POST.
5. Support for clustering; uses a network of brokers for scalability purposes.
6. Security can be customised for various types of authentication and authorisation.
7. Provides a wide range of connectivity options such as SSL, TCP, UDP, XMPP, multi-cast and more.
8. Easy for administration; does not require dedicated administrators. It provides very powerful monitoring tools.
Why use ActiveMQ?
Technologies using RPC (Remote Procedure Calls) are called tightly coupled distributed applications. Using RPC, one application can call the other application. There are many disadvantages of tightly coupled technologies, a higher maintenance cost being the most common. Another disadvantage is when one application calls another application through RPC, the other application must be available to receive the call or else the whole architecture fails. Figure 1 shows the architecture of two tightly coupled distributed applications.
To overcome the problems related to tightly coupled RPC, MOM (Message-Oriented Middleware) is used where one application sends messages to MOM and, on the other side, the other application receives the messages from MOM. Loosely coupled applications have greater advantages compared to tightly coupled ones when considering distributed applications. Figure 2 shows the architecture of two loosely coupled distributed applications.
ActiveMQ is used to overcome the disadvantages of RPC based tightly coupled distributed applications. The application relies on ActiveMQ and there is a guaranteed delivery of messages. ActiveMQ acts as a middleman between distributed applications and interacts in an asynchronous manner.
Installation of ActiveMQ
To install ActiveMQ, download the application from http://activemq.apache.org/download-archives.html. Extract and run the activemq script from the bin directory to start the ActiveMQ server as shown in Figure 3. Next, check if http://localhost:8161 is accessible from the browser. The ActiveMQ web console shown in Figure 4 is used to monitor ActiveMQ.
Heres an example of how ActiveMQ is used.
ActiveMQ uses a notation called Producer/Publisher and Consumer/Subscriber. Producer produces the messages and Consumer consumes it. A Producer can produce messages both on queues (messages have to be delivered to only one consumer) and topics (a distributed mechanism for publishing multiple messages that are delivered to multiple consumers).
Application 1 (Consumer): To connect to the ActiveMQ server, ActiveMQ client libraries have to be added. Create a Maven project as shown in Figure 5 and add the Maven dependency in pom.xml as follows:
<dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-core</artifactId> <version>5.7.0</version> </dependency> Consumer Class - import javax.jms.Connection; import javax.jms.Destination; import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.Session; import javax.jms.TextMessage; import org.apache.activemq.ActiveMQConnectionFactory; public class Consumer implements Runnable { public static void main(String[] args) throws InterruptedException { Consumer consumer = new Consumer(); Thread t1 = new Thread(consumer); t1.start(); } public void run() { while (true) { try { // Create a ConnectionFactory ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory( tcp://localhost:61616); // Create a Connection Connection connection = connectionFactory.createConnection(); connection.start(); // Create a Session Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); // Create the destination (Topic or Queue) Destination destination = session.createQueue(TEST); // Create a MessageConsumer from the Session to the Topic or // Queue MessageConsumer consumer = session.createConsumer(destination); // Wait for a message Message message = consumer.receive(1000); if (message instanceof TextMessage) { TextMessage textMessage = (TextMessage) message; String text = textMessage.getText(); System.out.println(Received: + text); } consumer.close(); session.close(); connection.close(); } catch (Exception e) { System.out.println(Caught: + e); e.printStackTrace(); } } } }
Application 2 (Producer): Create a Maven project as shown in Figure 6 and add the same Maven dependency in pom.xml as Consumer Application.
Producer Class - import javax.jms.Connection; import javax.jms.DeliveryMode; import javax.jms.Destination; import javax.jms.MessageProducer; import javax.jms.Session; import javax.jms.TextMessage; import org.apache.activemq.ActiveMQConnectionFactory; public class Producer { public static void main(String[] args) { try { // Create a ConnectionFactory ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(tcp://localhost:61616); // Create a Connection Connection connection = connectionFactory.createConnection(); connection.start(); // Create a Session Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); // Create the destination (Topic or Queue) Destination destination = session.createQueue(TEST); // Create a MessageProducer from the Session to the Topic or Queue MessageProducer producer = session.createProducer(destination); producer.setDeliveryMode(DeliveryMode.PERSISTENT); // Create a messages String text = Hello world!; TextMessage message = session.createTextMessage(text); producer.send(message); // Clean up session.close(); connection.close(); } catch (Exception e) { System.out.println(Caught: + e); e.printStackTrace(); } } }
In the above example, the delivery mode is set to PERSISTENT, which means that even if the ActiveMQ server goes down, the Producer data persists.
Now, run the Consumer application. The Consumer will keep checking whether there is any message to consume from ActiveMQ.
Next, run the Producer application to send messages to the ActiveMQ. Each run of the Producer will send a Hello World!message to ActiveMQ and, in turn, the Consumer will consume the message from ActiveMQ.