How to use the Spring Boot Starter for Azure Service Bus JMS

This article demonstrates how to use Spring Boot Starter for Azure Service Bus JMS to send messages to and receive messages from Service Bus queues and topics.

Azure provides an asynchronous messaging platform called Azure Service Bus ("Service Bus") that is based on the Advanced Message Queueing Protocol 1.0 ("AMQP 1.0") standard. Service Bus can be used across the range of supported Azure platforms.

The Spring Boot Starter for Azure Service Bus JMS provides Spring JMS integration with Service Bus.

The following video describes how to integrate Spring JMS applications with Azure Service Bus using JMS 2.0.


Prerequisites

The following prerequisites are required for this article:

  1. An Azure subscription; if you don't already have an Azure subscription, you can activate your MSDN subscriber benefits or sign up for a free account.

  2. A supported Java Development Kit (JDK), version 8 or later. For more information about the JDKs available for use when developing on Azure, see Java support on Azure and Azure Stack.

  3. Apache Maven, version 3.2 or later.

  4. If you already have a configured Service Bus queue or topic, ensure that the Service Bus namespace meets the following requirements:

    1. Allows access from all networks
    2. Is Premium (or higher)
    3. Has an access policy with read/write access for your queue and topic
  5. If you don't have a configured Service Bus queue or topic, use the Azure portal to create a Service Bus queue or create a Service Bus topic. Ensure that the namespace meets the requirements specified in the previous step. Also, make note of the connection string in the namespace as you need it for this tutorial's test app.

  6. If you don't have a Spring Boot application, create a Maven project with the Spring Initializr. Remember to select Maven Project and, under Dependencies, add the Web dependency.

Use the Azure Service Bus JMS starter

  1. Locate the pom.xml file in the parent directory of your app; for example:

    C:\SpringBoot\servicebus\pom.xml

    -or-

    /users/example/home/servicebus/pom.xml

  2. Open the pom.xml file in a text editor.

  3. Add the Spring Boot Azure Service Bus JMS starter to the list of <dependencies>:

    <dependency>
        <groupId>com.azure.spring</groupId>
        <artifactId>azure-spring-boot-starter-servicebus-jms</artifactId>
        <version>3.12.0</version>
    </dependency>
    
  4. Save and close the pom.xml file.

Configure the app for your service bus

In this section, you see how to configure your app to use either a Service Bus queue or topic.

Use a Service Bus queue

  1. Locate the application.properties in the resources directory of your app; for example:

    C:\SpringBoot\servicebus\application.properties

    -or-

    /users/example/home/servicebus/application.properties

  2. Open the application.properties file in a text editor.

  3. Append the following code to the end of the application.properties file. Replace the placeholder values with the appropriate values for your service bus, and do not put quotes around the values.

    spring.jms.servicebus.connection-string=<ServiceBusNamespaceConnectionString>
    spring.jms.servicebus.idle-timeout=<IdleTimeout>
    spring.jms.servicebus.pricing-tier=<ServiceBusPricingTier> 
    

    Field descriptions

    Field Description
    spring.jms.servicebus.connection-string Specify the connection string you obtained in your Service Bus namespace from the Azure portal.
    spring.jms.servicebus.idle-timeout Specify the idle timeout in milliseconds. The recommended value for this tutorial is 1800000.
    spring.jms.servicebus.pricing-tier Specify the pricing tier of your service bus. Supported values are premium, standard, and basic. Premium uses Java Message Service (JMS) 2.0, while standard and basic use JMS 1.0 to interact with Azure Service Bus.
  4. Save and close the application.properties file.

Use Service Bus topic

  1. Locate the application.properties in the resources directory of your app; for example:

    C:\SpringBoot\servicebus\application.properties

    -or-

    /users/example/home/servicebus/application.properties

  2. Open the application.properties file in a text editor.

  3. Append the following code to the end of the application.properties file. Replace the placeholder values with the appropriate values for your service bus, and do not put quotes around the values.

    spring.jms.servicebus.connection-string=<ServiceBusNamespaceConnectionString>
    spring.jms.servicebus.topic-client-id=<ServiceBusSubscriptionID>
    spring.jms.servicebus.idle-timeout=<IdleTimeout>
    spring.jms.servicebus.pricing-tier=<ServiceBusPricingTier> 
    

    Field descriptions

    Field Description
    spring.jms.servicebus.connection-string Specify the connection string you obtained in your Service Bus namespace from the Azure portal.
    spring.jms.servicebus.topic-client-id Specify the JMS client ID, which is your Service Bus Subscription ID in the Azure portal.
    spring.jms.servicebus.idle-timeout Specify the idle timeout in milliseconds. The recommended value for this tutorial is 1800000.
    spring.jms.servicebus.pricing-tier Specify the pricing tier of your service bus. Supported values are premium, standard, and basic. Premium uses Java Message Service (JMS) 2.0, while standard and basic use JMS 1.0 to interact with Azure Service Bus.
  4. Save and close the application.properties file.

Implement basic Service Bus functionality

In this section, you create the necessary Java classes for sending messages to your Service Bus queue or topic and receive messages from your corresponding queue or topic subscription.

Modify the main application class

  1. Locate the main application Java file in the package directory of your app; for example:

    C:\SpringBoot\servicebus\src\main\java\com\wingtiptoys\servicebus\ServiceBusJmsStarterApplication.java

    -or-

    /users/example/home/servicebus/src/main/java/com/wingtiptoys/servicebus/ServiceBusJmsStarterApplication.java

  2. Open the main application Java file in a text editor.

  3. Add the following code to the file:

     package com.wingtiptoys.servicebus;
    
     import org.springframework.boot.SpringApplication;
     import org.springframework.boot.autoconfigure.SpringBootApplication;
    
     @SpringBootApplication
     public class ServiceBusJmsStarterApplication {
    
         public static void main(String[] args) {
             SpringApplication.run(ServiceBusJmsStarterApplication.class, args);
         }
     }
    
  4. Save and close the file.

Define a test Java class

  1. Using a text editor, create a Java file named User.java in the package directory of your app.

  2. Define a generic user class that stores and retrieves user's name:

    package com.wingtiptoys.servicebus;
    
    import java.io.Serializable;
    
    // Define a generic User class.
    public class User implements Serializable {
    
        private static final long serialVersionUID = -295422703255886286L;
    
        private String name;
    
        public User() {
        }
    
        public User(String name) {
            setName(name);
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
    }
    

    Serializable is implemented to use the send method in JmsTemplate in the Spring framework. Otherwise, a customized MessageConverter bean should be defined to serialize the content to json in text format. For more information about MessageConverter, see the official Spring JMS starter project.

  3. Save and close the User.java file.

Create a new class for the message send controller

  1. Using a text editor, create a Java file named SendController.java in the package directory of your app

  2. Add the following code to the new file:

    package com.wingtiptoys.servicebus;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.jms.core.JmsTemplate;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class SendController {
    
        private static final String DESTINATION_NAME = "<DestinationName>";
    
        private static final Logger logger = LoggerFactory.getLogger(SendController.class);
    
        @Autowired
        private JmsTemplate jmsTemplate;
    
        @PostMapping("/messages")
        public String postMessage(@RequestParam String message) {
            logger.info("Sending message");
            jmsTemplate.convertAndSend(DESTINATION_NAME, new User(message));
            return message;
        }
    }
    

    Note

    Replace <DestinationName> with your own queue name or topic name configured in your Service Bus namespace.

  3. Save and close the SendController.java.

Create a class for the message receive controller

Receive messages from a Service Bus queue

  1. Use a text editor to create a Java file named QueueReceiveController.java in the package directory of your app

  2. Add the following code to the new file:

    package com.wingtiptoys.servicebus;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.jms.annotation.JmsListener;
    import org.springframework.stereotype.Component;
    
    @Component
    public class QueueReceiveController {
    
        private static final String QUEUE_NAME = "<ServiceBusQueueName>";
    
        private final Logger logger = LoggerFactory.getLogger(QueueReceiveController.class);
    
        @JmsListener(destination = QUEUE_NAME, containerFactory = "jmsListenerContainerFactory")
        public void receiveMessage(User user) {
            logger.info("Received message: {}", user.getName());
        }
    }
    

    Note

    Replace <ServiceBusQueueName> with your own queue name configured in your Service Bus namespace.

  3. Save and close the QueueReceiveController.java file.

Receive messages from a Service Bus subscription

  1. Using a text editor, create a Java file named TopicReceiveController.java in the package directory of your app.

  2. Add the following code to the new file. Replace the <ServiceBusTopicName> placeholder with your own topic name configured in your Service Bus namespace. Replace the <ServiceBusSubscriptionName> placeholder with your own subscription name for your Service Bus topic.

    package com.wingtiptoys.servicebus;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.jms.annotation.JmsListener;
    import org.springframework.stereotype.Component;
    
    @Component
    public class TopicReceiveController {
    
        private static final String TOPIC_NAME = "<ServiceBusTopicName>";
    
        private static final String SUBSCRIPTION_NAME = "<ServiceBusSubscriptionName>";
    
        private final Logger logger = LoggerFactory.getLogger(TopicReceiveController.class);
    
        @JmsListener(destination = TOPIC_NAME, containerFactory = "topicJmsListenerContainerFactory",
                subscription = SUBSCRIPTION_NAME)
        public void receiveMessage(User user) {
            logger.info("Received message: {}", user.getName());
        }
    }
    
  3. Save and close the TopicReceiveController.java file.

Optional Service Bus Functionality

You can use a customized MessageConverter bean to convert between Java objects and JMS messages.

Set the content-type of messages

The following code example sets the BytesMessage content-type to application/json. For more information, see Messages, payloads, and serialization.

package com.wingtiptoys.servicebus;

import com.fasterxml.jackson.databind.ObjectWriter;
import org.apache.qpid.jms.message.JmsBytesMessage;
import org.apache.qpid.jms.provider.amqp.message.AmqpJmsMessageFacade;
import org.apache.qpid.proton.amqp.Symbol;
import org.springframework.jms.support.converter.MappingJackson2MessageConverter;
import org.springframework.jms.support.converter.MessageType;
import org.springframework.stereotype.Component;

import javax.jms.BytesMessage;
import javax.jms.JMSException;
import javax.jms.Session;
import java.io.IOException;

@Component
public class CustomMessageConverter extends MappingJackson2MessageConverter {

    private static final String TYPE_ID_PROPERTY = "_type";
    private static final Symbol CONTENT_TYPE = Symbol.valueOf("application/json");

    public CustomMessageConverter() {
        this.setTargetType(MessageType.BYTES);
        this.setTypeIdPropertyName(TYPE_ID_PROPERTY);
    }

    @Override
    protected BytesMessage mapToBytesMessage(Object object, Session session, ObjectWriter objectWriter)
        throws JMSException, IOException {
        final BytesMessage bytesMessage = super.mapToBytesMessage(object, session, objectWriter);
        JmsBytesMessage jmsBytesMessage = (JmsBytesMessage) bytesMessage;
        AmqpJmsMessageFacade facade = (AmqpJmsMessageFacade) jmsBytesMessage.getFacade();
        facade.setContentType(CONTENT_TYPE);
        return jmsBytesMessage;
    }
}

For more information about MessageConverter, see the official Spring JMS guide.

Build and test your application

  1. Open a command prompt and change directory to the location of your pom.xml; for example:

    cd C:\SpringBoot\servicebus 
    

    -or-

    cd /users/example/home/servicebus 
    
  2. Build your Spring Boot application with Maven and run it:

    mvn clean spring-boot:run
    
  3. Once your application is running, you can use curl to test your application:

    curl -X POST localhost:8080/messages?message=hello
    

    You should see "Sending message" and "hello" posted to your application log:

    [nio-8080-exec-1] com.wingtiptoys.servicebus.SendController : Sending message
    [enerContainer-1] com.wingtiptoys.servicebus.ReceiveController : Received message: hello
    

Clean up resources

When no longer needed, use the Azure portal to delete the resources created in this article to avoid unexpected charges.

Next steps