Apache ActiveMQ Spring Boot Example

Apache ActiveMQ Spring Boot Example | We have seen what is message queue and the types of communication (P2P & Pub/Sub). See more:- Message Queues Using Spring Boot. Let us see the Spring Boot Message queues example using Apache ActiveMQ.

ActiveMQ Setup

  • Download Apache ActiveMQ
  • Click on OS based link: Windows apache-activemq-5.18.5-bin.zip
  • Extract to a folder ex: ‘apache-activemq-5.18.5’
  • Open folder location ‘\apache-activemq-5.18.5\bin\win64’
  • Click on activemq.bat file
  • Enter URL: http://127.0.0.1:8161/admin

Username: admin
Password: admin

ActiveMQ Dashboard

For username & password, Check \apache-activemq-5.18.5\conf\users.properties file. There we can update the username and password.

username=password

Press CTRL + C to terminate the batch.

JMS (Java Message Service)

To work with Apache ActiveMQ we will use JMS API.

  • JMS stands for Java Message Service.
  • This API is given by Sun/Oracle.
  • It is part of J2EE.
  • By using this API we can transfer data between two machines(apps) by using the Protocol ‘TCP = Transmission Control Protocol’.
TopicDescriptionTechnology
TCP MQsMessage QueuesApache Kafka
FTP Files TransferFile Transfer ProtocolApache Camel
HTTP Web AppsWeb ApplicationWeb API + Server
  • JMS is used for continuous data flow between two systems using a mediator.
  • There should be at least two Applications:-
  1. Producer Application. JmsTemplate#send(destinationName, messageCreator)
  2. Consumer Application.
@JmsListener(destination="")
read message

These two applications communicate with each other using TCP protocol for data exchange.

JMS API contains the following interfaces:-

  • Session
  • Message
    • TextMessage

ActiveMQ contains the following implementations:-

JMS InterfacesActiveMQ Implementation
SessionActiveMQSession
TextMessageActiveMQTextMessage

Spring Boot Example using Apache ActiveMQ

Steps:-

  1. ActiveMQ Setup:- We have already set up ActiveMQ by downloading Apache ActiveMQ. Start ActiveMQ by clicking on the activemq.bat file of ‘\apache-activemq-5.18.5\bin\win64’ folder. Enter URL: http://127.0.0.1:8161/admin; Use username: admin, password: admin. Go to the “Queues” section.
  2. Producer Application
  3. Consumer Application

Producer Application

  1. Create a Spring starter project “ActiveMQProducerEx”, and add dependency:- Spring for Apache ActiveMQ 5 (spring-boot-starter-activemq).
  2. For connectivity property, in the application.properties file:-
spring.activemq.broker-url=tcp://localhost:61616
spring.activemq.user=admin
spring.activemq.password=admin

# for P2P communication
spring.jms.pub-sub-domain=false

# for PUB/SUB communication
# spring.jms.pub-sub-domain=true

If we use spring.jms.pub-sub-domain=false then code behaves like P2P communication, if it is set to true then it is PUB/SUB Communication.

  1. ProducerService:-
package com.knowprogram.demo.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Component;

@Component
public class ProducerService {

    @Autowired
    JmsTemplate jmsTemplate;

    public void send(String destination, String message) {
        jmsTemplate.send(destination, (session) -> session.createTextMessage(message));
    }

}
  1. Runner class to call the ProducerService.
package com.knowprogram.demo.runner;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import com.knowprogram.demo.service.ProducerService;

@Component
public class TestProducerRunner implements CommandLineRunner {

    @Autowired
    ProducerService producerService;

    @Override
    public void run(String... args) throws Exception {
        producerService.send("my-q1", "Hello Data Sample");
        System.out.println("Data Sent");
    }
}
  1. Start the application, and check the ActiveMQ dashboard “Queues” section (http://127.0.0.1:8161/admin/queues.jsp). There we can find the “my-q1” queue with the Number of pending message=1 and the Number of Consumer=0.
ActiveMQ Dashboard Queues

Click on “my-q1”.

ActiveMQ Queue Detail

Click on the given message ID.

ActiveMQ Queue Message Details

Consumer Application.

  1. Choose a different workspace for consumer applications.
  2. Create a Spring starter project “JMSConsumerApp”, and add the dependency:- Spring for Apache ActiveMQ 5 (spring-boot-starter-activemq).
  3. In starter class:- @EnableJms
  4. For connectivity property, in the application.properties file:-
spring.activemq.broker-url=tcp://localhost:61616
spring.activemq.user=admin
spring.activemq.password=admin
# for P2P communication
spring.jms.pub-sub-domain=false
  1. MessageConsumer:-
package com.example.demo.consumer;

import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

@Component
public class MessageConsumer {

    @JmsListener(destination = "my-q1")

    public void readMessage(String message) {
        System.out.println("At consumer: " + message);
    }
}
  1. Run the application. On console:-

Notice that the Consumer is never going to directly communicate with the producer. ActiveMQ MOM will work as a mediator between the producer and consumer. The producer application will send data to the MOM, and the MOM will send data to the consumer application.

ActiveMQ

  • It is a mediator server.
  • It will transfer data using Protocol TCP (Port:61616). We can find the port details in apache-activemq-5.18.5\conf folder, open activemq.xml file and search for, it contains:- <transportConnector name="openwire" uri="tcp://0.0.0.0:61616? .../>.
  • It provides a GUI (HTTP 8161) that provides information on sent messages, Consumers, Queue/Topic Names, etc.
  • Both Producer and Consumer communicate with MOM (Message Oriented Middleware) software only.
  • Data is stored in a Destination(Queue/Topic).
  • The producer destination name and consumer destination must be the same. If destination names are not matching then NO ERROR/ NO EXCEPTION/ NO OUTPUT.
  • On Receiving a message to the destination, MOM software will send a message to the Consumer.
  • Consumer App, need not make any request (it is always listening).

Sending Object through ActiveMQ

Q) How can we send/transfer Object/Collection data?
We can not send Java objects as it is. It must be converted into one global Format String (JSON/XML).

  1. Add Lombok & Jackson dependencies in the producer application:-
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
  1. Create a model class.
package com.knowprogram.demo.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class GameInfo {
    private String matchId;
    private String op1;
    private String op2;
    private Integer op1Score;
    private Integer op2Score;
    private String winner;
}
  1. Create a MessageConverter class:-
package com.knowprogram.demo.converter;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class MessageConverter {
    public static String convertObjectToString(Object object) {
        try {
            return new ObjectMapper().writeValueAsString(object);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }

}
  1. Modify TestProducerRunner to send Object data:-
package com.knowprogram.demo.runner;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import com.knowprogram.demo.converter.MessageConverter;
import com.knowprogram.demo.model.GameInfo;
import com.knowprogram.demo.service.ProducerService;

@Component
public class TestProducerRunner implements CommandLineRunner {

    @Autowired
    ProducerService producerService;

    @Override
    public void run(String... args) throws Exception {
        producerService.send("my-q1",
                MessageConverter.convertObjectToString(
                        new GameInfo("ABC15246", "ABC", "IND", 251, 252, "IND-WINNER")
                        )
                );
        System.out.println("Data Sent");
    }
}
  1. Re-run the producer application, no need to do anything with the consumer application. The consumer is already in listening mode.
  2. Check output in consumer application.

Pub/Sub Communication using JMS

  • By default every Producer and Consumer app is P2P Communication as internally key: spring.jms.pub-sub-domain is set to false.
  • To convert the P2P Application into Pub/Sub, modify the key: spring.jms.pub-sub-domain with value true in both producer and consumer.
  • Producer/Consumer code is the same for both P2P and Pub/Sub. Just define another consumer Application.
  • The topic is created if spring.jms.pub-sub-domain=true
  • Based on the number of consumers, actual Message cloning is done, [Clone – Create a copy of actual message].
  • Considering the number of consumers is 10 then one message is delivered to 10 consumers from MOM.
  1. Create one more consumer by copying the existing consumer application
  2. In all Producer and consumer applications, modify the below property in the application.properties file:-
spring.jms.pub-sub-domain=true
  1. Run the producer and consumers.
  2. Change data in the producer and rerun the producer. We can see the modified data in all consumers.

Advantages of ActiveMQ

  • MOM software will store data to avoid message loss until the consumer receives it.
  • MOM software can support sending data in Global Format (JSON/XML)
  • It is good to use for simple and less data transfer between multiple systems.

Limitations of ActiveMQ

  • In case of data is too large (like GBs) then MOM becomes slow even data loss may occur.
  • In case of number of consumers increases it may become very slow.
  • Here, MOM contains a single broker instance. If it is down or not responding then data loss may occur. It does not support the Load Balancer concept.
  • It is fully protocol-dependent (TCP).

To overcome these limitations we can work with Apache Kafka.

If you enjoyed this post, share it with your friends. Do you want to share more information about the topic discussed above or do you find anything incorrect? Let us know in the comments. Thank you!

Leave a Comment

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