DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Distributed Tracing System (Spring Cloud Sleuth + OpenZipkin)
  • Using Kong Ingress Controller with Spring Boot Services
  • Component Tests for Spring Cloud Microservices
  • Migration of Microservice Applications From WebLogic to Openshift

Trending

  • How Large Tech Companies Architect Resilient Systems for Millions of Users
  • Java Virtual Threads and Scaling
  • My LLM Journey as a Software Engineer Exploring a New Domain
  • Concourse CI/CD Pipeline: Webhook Triggers
  1. DZone
  2. Coding
  3. Frameworks
  4. Event-Driven Microservices With Spring Boot and ActiveMQ

Event-Driven Microservices With Spring Boot and ActiveMQ

A guide to using Spring Boot and ActiveMQ for event-driven microservices.

By 
Swathi Prasad user avatar
Swathi Prasad
·
Aug. 13, 19 · Analysis
Likes (16)
Comment
Save
Tweet
Share
41.1K Views

Join the DZone community and get the full member experience.

Join For Free

Most communications between microservices are either via HTTP request-response APIs or asynchronous messaging. While these two mechanisms are most commonly used, yet they’re quite different. It is important to know when to use which mechanism.

Event-driven communication is important when propagating changes across several microservices and their related domain models. This means that when changes occur, we need some way to coordinate changes across the different models. This ensures reliable communication as well as loose coupling between microservices.

There are multiple patterns to achieve event-driven architecture. One of the common and popular patterns is the messaging pattern. It is extremely scalable, flexible, and guarantees delivery of messages. There are several tools that can be used for messaging pattern such as RabbitMQ, ActiveMQ, Apache Kafka and so on.

Messaging Pattern

In this article, we are going to build microservices using Spring Boot and we will set up the ActiveMQ message broker to communicate between microservices asynchronously.

Building Microservices

Let us create two Spring Boot projects ‘ activemq-sender ’ and ‘ activemq-receiver ’. Here is the sample project structure.

                                                                     Sample Project Structure

We need to add maven dependency spring-boot-starter-activemq to enable ActiveMQ. Here is a sample pom.xml.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.techshard.activemqsender</groupId>
    <artifactId>activemq-sender</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
        <relativePath />
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-activemq</artifactId>
        </dependency>
    </dependencies>

</project>

Configuring Publisher

In the project activemq-sender, we will first configure a queue. Create a JmsConfig class as follows.

package com.techshard.activemq.configuration;

import org.apache.activemq.command.ActiveMQQueue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.annotation.EnableJms;

import javax.jms.Queue;

@Configuration
public class JmsConfig {

    @Bean
    public Queue queue(){
        return new ActiveMQQueue("test-queue");
    }
}

The above class just declares a bean Queue and our queue name would be test-queue. Note: queue names can also be read from application properties. This is just an example.

Now, let’s create a REST API which will be used to publish the message to the queue.

package com.techshard.activemq.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.jms.Queue;

@RestController
@RequestMapping("/api")
public class MessageController {

    @Autowired
    private Queue queue;

    @Autowired
    private JmsTemplate jmsTemplate;

    @GetMapping("message/{message}")
    public ResponseEntity<String> publish(@PathVariable("message") final String message){
        jmsTemplate.convertAndSend(queue, message);
        return new ResponseEntity(message, HttpStatus.OK);
    }

}

In the controller, we will inject the bean Queue which we declared before and we will also inject  JmsTemplate.

To send or receive messages through JMS, we need to establish a connection to the JMS provider and obtain a session.  JmsTemplate is a helper class that simplifies sending and receiving of messages through JMS and gets rid of boilerplate code.

We have now created a simple API endpoint that will accept a string as a parameter and puts it in the queue.

Configuring Consumer

In the project  activemq-receiver, create a component class as follows:

package com.techshard.activemq.consumer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

@Component
@EnableJms
public class MessageConsumer {

    private final Logger logger = LoggerFactory.getLogger(MessageConsumer.class);

    @JmsListener(destination = "test-queue")
    public void listener(String message){
        logger.info("Message received {} ", message);
    }
}

In this class, we have an annotated method with  @JmsListenerand we have passed the queue name test-queue which we configured in the publisher. @JmsListener is used for listening to any messages that are put on the queue test-queue.

Notice that we have an annotated class with @EnableJms. As Spring documentation says “@EnableJms enables detection of JmsListener annotations on any Spring-managed bean in the container.”

The interesting point here is that Spring Boot detects the methods even without @EnableJms annotation. This issue has been reported on Stackoverflow.

Creating Spring Boot Applications

In both the projects, create an "Application" class annotated with @SpringBootApplication as below.

package com.techshard.activemq;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

@SpringBootApplication
public class Application extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}


Installing ActiveMQ

I have installed ActiveMQ by downloading here. We can also use Spring Boot’s embedded ActiveMQ for testing purposes. Once you have installed, the ActiveMQ server should be available at http://localhost:8161/admin and we will see the following welcome page.

                                                                    ActiveMQ Home Page

Configuring ActiveMQ

In both the projects, create application.properties file and add the following properties.

spring.activemq.broker-url=tcp://localhost:61616
spring.activemq.user=admin
spring.activemq.password=admin

ActiveMQ supports multiple protocols to connect to the message broker. In this example, we will be using the OpenWire protocol.

That’s it!

Testing ActiveMQ

Before running the applications, make sure to change the server port for one of the projects. The embedded tomcat server runs on the port 8080 by default.

Run both the applications and run the URL http://localhost:8080/api/message/Welcome to ActiveMQ! in browser or any REST API testing tool.

In the consumer application, we will see the following log in console.

2019-08-06 22:29:57.667 INFO 17608 — [enerContainer-2] c.t.activemq.consumer.MessageConsumer : Message received Welcome to ActiveMQ!

´What just happened is that the message was put on the queue. The consumer application that was listening to the queue read the message from the queue.

In the ActiveMQ dashboard, navigate to the Queue tab. We can see the details such as a number of consumers to a queue, the number is messages pending, queued and dequeued.

At the beginning of this article, I mentioned that message brokers guarantee delivery of messages. Imagine that the consumer service is down, and the message was put on the queue by publisher service.

Stop the application  activemq-receiver . Run this URL again http://localhost:8080/api/message/Welcome to ActiveMQ! In browser.

Navigate to the ActiveMQ dashboard and notice the queue state.

We can see that one message is pending and enqueued. Start the application activemq-receiver again.

As soon as the application is started, we will the following message in console.

2019-08-06 22:54:32.667 INFO 17608 — [enerContainer-2] c.t.activemq.consumer.MessageConsumer : Message received Welcome to ActiveMQ!

The number of pending messages is now set to zero and the number of dequeued messages is set to two. The message broker guarantees the delivery of messages.

Conclusion

We just saw a simple example of a messaging pattern in this article. The messaging system takes the responsibility of transferring data from one service to another, so the services can focus on what data they need to share but not worry about how to share it.

I hope you enjoyed this article. Feel free to let me know if you have any comments or suggestions.

Spring Framework Spring Boot microservice

Published at DZone with permission of Swathi Prasad, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Distributed Tracing System (Spring Cloud Sleuth + OpenZipkin)
  • Using Kong Ingress Controller with Spring Boot Services
  • Component Tests for Spring Cloud Microservices
  • Migration of Microservice Applications From WebLogic to Openshift

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!