Introduction
In modern applications, messaging systems play a crucial role in enabling communication between different components and services. Apache ActiveMQ Artemis is a popular open-source messaging broker that supports multiple protocols, including AMQP. In this blog post, we will explore how to connect a Spring Boot 3 application to an Apache ActiveMQ Artemis broker using the AMQP protocol and configure it to support transactions.
Prerequisites
Before we begin, ensure you have the following:
- Java 17 or higher installed
- Apache ActiveMQ Artemis broker installed and running
- Basic knowledge of Spring Boot and JMS
Step 1: Set Up Dependencies
First, we need to add the necessary dependencies to our pom.xml
file. These dependencies include the Spring Boot starter for ActiveMQ and the Artemis JMS client.
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-jms-client</artifactId>
<version>2.17.0</version>
</dependency>
</dependencies>
Step 2: Configure Application Properties
Next, we need to configure the connection to the Apache ActiveMQ Artemis broker. Add the following properties to your application.properties
file:
spring.artemis.broker-url=amqp://localhost:5672
spring.artemis.user=your-username
spring.artemis.password=your-password
spring.artemis.mode=native
Replace your-username
and your-password
with your actual Artemis broker credentials.
Create a Custom Message Converter
First, create a custom message converter that implements the MessageConverter
interface. This converter will handle the conversion of messages to and from specific object types.
javaCopy codeimport javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import org.springframework.jms.support.converter.MessageConversionException;
import org.springframework.jms.support.converter.MessageConverter;
import org.springframework.jms.support.converter.SimpleMessageConverter;
public class CustomMessageConverter implements MessageConverter {
private final SimpleMessageConverter delegate = new SimpleMessageConverter();
@Override
public Message toMessage(Object object, Session session) throws JMSException, MessageConversionException {
// Add custom conversion logic if needed
return delegate.toMessage(object, session);
}
@Override
public Object fromMessage(Message message) throws JMSException, MessageConversionException {
// Add custom conversion logic if needed
return delegate.fromMessage(message);
}
}
Step 3: Create Configuration Class
To enable transactions and configure the connection to the broker, we need to create a configuration class. This class will set up the connection factory, transaction manager, and DefaultJmsListenerContainerFactory
.
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.connection.JmsTransactionManager;
import org.springframework.jms.core.JmsTemplate;
@Configuration
@EnableJms
public class ArtemisConfig {
@Bean
public ActiveMQConnectionFactory connectionFactory() {
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory();
connectionFactory.setBrokerURL("amqp://localhost:5672"); // tcp: for TCP protocol
connectionFactory.setUser("your-username");
connectionFactory.setPassword("your-password");
return connectionFactory;
}
@Bean
public JmsTransactionManager transactionManager() {
return new JmsTransactionManager(connectionFactory());
}
@Bean
public JmsTemplate jmsTemplate() {
JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory());
jmsTemplate.setSessionTransacted(true);
return jmsTemplate;
}
@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory());
factory.setTransactionManager(transactionManager());
factory.setConcurrency("1-1");
factory.setSessionTransacted(true);
factory.setMessageConverter(customMessageConverter());
return factory;
}
@Bean
public MessageConverter customMessageConverter() {
return new CustomMessageConverter();
}
}
Step 4: Sending Messages
To send messages to the broker, we will create a REST controller. This controller will use the JmsTemplate
to send messages to the specified queue.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.transaction.annotation.Transactional;
@RestController
public class MessageController {
@Autowired
private JmsTemplate jmsTemplate;
@GetMapping("/send")
@Transactional
public String sendMessage(@RequestParam String message) {
jmsTemplate.convertAndSend("test-queue", message);
return "Message sent!";
}
}
In this controller, the sendMessage
method is annotated with @Transactional
, ensuring that the message sending operation is wrapped in a transaction.
Step 5: Receiving Messages
To receive messages from the broker, we will create a message listener. This listener will use the DefaultJmsListenerContainerFactory
that we configured earlier.
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
@Component
public class MessageListener {
@JmsListener(destination = "test-queue", containerFactory = "jmsListenerContainerFactory")
public void onMessage(String message) {
System.out.println("Received message: " + message);
// Additional business logic can be added here
}
}
The @JmsListener
annotation specifies the destination queue and the container factory to use for this listener.
Step 6: Running the Application
With everything configured, we can now run the Spring Boot application. Start your Artemis broker if it is not already running, and then start your Spring Boot application. You can send messages by navigating to http://localhost:8080/send?message=HelloWorld
in your browser. The message will be sent to the test-queue
, and the message listener will receive and print it to the console.
Conclusion
In this blog post, we explored how to connect a Spring Boot 3 application to an Apache ActiveMQ Artemis broker using the AMQP protocol. We configured the connection factory, enabled transactions, and set up message sending and receiving. By following these steps, you can integrate Apache ActiveMQ Artemis into your Spring Boot applications, enabling robust messaging and transaction support.