Why Messaging Matters in Modern Applications
In a distributed system, services often need to communicate asynchronously to ensure decoupling, scalability and resilience. Messaging systems enable this by allowing services to send and receive messages without needing to know about each otherâs existence or availability in real time. This pattern is crucial in microservices, event-driven architectures and systems requiring reliable data exchange.
What is Apache ActiveMQ Artemis?
Apache ActiveMQ Artemis is a high-performance, embeddable, multi-protocol message broker. Itâs the next-generation version of ActiveMQ, designed to support modern messaging needs with improved performance, scalability and features like:
- Support for JMS 2.0 API
- Core messaging protocol (AMQP, MQTT, STOMP, OpenWire)
- High throughput and low latency
- Built-in clustering and persistence
Why Use ArtemisMQ with Spring Boot?
Spring Boot simplifies the setup and integration of messaging with ArtemisMQ through auto-configuration, sensible defaults and tight JMS support. Combined, they provide:
- Rapid development with minimal boilerplate
- Easy testing with embedded brokers
- Seamless JSON serialization with
MessageConverter
- Robust error handling and observability with Spring Boot Actuator
Project Setup
pom.xml
Dependencies
Here are the essential dependencies to get started:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-artemis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-jms-server</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<scope>test</scope>
</dependency></dependencies>
Embedded ArtemisMQ Setup
Spring Boot can auto-configure an embedded Artemis server when no external broker is specified. Just add this to your application.properties
:
spring.artemis.mode=embedded
spring.artemis.embedded.enabled=true
This allows you to run and test your messaging app without external infrastructure.
The embedded Artemis isn’t suitable for production, since it lacks some important Artemis features, but it’s great for connecting to a ActiveMQ server and testing. But in this example we will be using the embedded to demonstrate its capabilities.
â Embedded Artemis (Spring Boot auto-config)
Good for:
- Local development
- Demos and testing
- Simpler projects with no broker deployment needs
Bad for:
- Production use
- Scalability and clustering
- Monitoring and management
- Reliability (you lose messages if the app crashes)
Embedded Artemis runs in-process, so if your Spring Boot app crashes or restarts, your broker goes down tooâand takes your messages with it.
Creating a Simple Messaging Flow
1. Define a DTO
public class NotificationMessage {
private String title;
private String body;
// Getters and setters
}
2. Send Messages with JmsTemplate
@Service
public class NotificationSender {
private final JmsTemplate jmsTemplate;
public NotificationSender(JmsTemplate jmsTemplate) {
this.jmsTemplate = jmsTemplate;
}
public void send(NotificationMessage message) {
jmsTemplate.convertAndSend("notification.queue", message);
}
}
3. Receive Messages with @JmsListener
@Component
public class NotificationReceiver {
@JmsListener(destination = "notification.queue")
public void receive(NotificationMessage message) {
System.out.println("Received message: " + message.getTitle());
}
}
4. Configure MessageConverter
for JSON
@Configuration
public class MessagingConfig {
@Bean
public MessageConverter jacksonJmsMessageConverter() {
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.setTargetType(MessageType.TEXT);
converter.setTypeIdPropertyName("_type");
return converter;
}
}
This ensures that your messages are automatically converted to/from JSON when using JmsTemplate
or @JmsListener
.
â Write the Integration Test
@SpringBootTest
class MessagingIntegrationTest {
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(basePackages = "vmfvmf.com")
static class TestConfig {}
@Autowired
private NotificationSender sender;
@SpyBean
private NotificationReceiver receiver;
@Test
void testMessageSendAndReceive() {
NotificationMessage message = new NotificationMessage();
message.setTitle("Hello");
message.setBody("This is a test message");
sender.send(message);
waitAtMost(2, TimeUnit.SECONDS).untilAsserted(() -> {
verify(receiver, times(1)).receive(argThat(argument -> argument.getBody().contentEquals("This is a test message")));
});
}
}
This test verifies that a NotificationMessage
is successfully sent and received using Spring Boot, ActiveMQ Artemis, and JMS. It uses JmsTemplate to send the message and a @JmsListener-based receiver to consume it. The test leverages Mockito to verify the receiver was called with the expected content, and Awaitility to wait for the asynchronous processing to complete within a timeout, ensuring reliable behavior testing in a message-driven flow.

In this case we had a success, the received message had the same content of the sent message, but if change the validation…

We will got an error telling that the arguments are different.
This test approach, using an embedded Artemis broker, is well-suited for local development and integration testing. It allows for fast, isolated, and repeatable tests without requiring an external broker. Combining Spring Boot, JMS, Awaitility, and Mockito provides a robust way to validate asynchronous messaging behavior in real time. However, while embedded Artemis is convenient for testing, it’s not recommended for production, as it doesn’t reflect a distributed, secured, or tuned broker environment. For production-grade scenarios, tests should also be validated against an external broker setup to ensure compatibility and performance under realistic conditions.
â Conclusion
In this first part, we explored the importance of messaging in modern applications and introduced Apache ActiveMQ Artemis as a powerful broker solution. We saw how effortlessly it integrates with Spring Boot, offering a fast path to building robust messaging flows using JMS, JmsTemplate and @JmsListener. With just a few configurations and components, you can set up a fully working asynchronous communication channel between servicesâcomplete with JSON serialization out of the box.
This foundation is not just functionalâit’s production-ready with the right enhancements.
đ Whatâs Next?
In the next parts, weâll level up the integration by diving into:
- Custom error handling and how to gracefully manage message failures.
- Retry strategies, dead-letter queues and avoiding message loss.
- Delayed and priority messaging, giving you more control over how and when messages are processed.
- Exposing messaging functionality through REST endpoints with springdoc-openapi, so your services are not just reactiveâbut also transparent and well-documented.
- Testing strategies using dockerized Artemis and Spring Boot testing utilities.
Stay tuned as we continue building a full-featured messaging layer thatâs resilient, observable and ready for scale.
Here is a LINK with the running code in case you couldn’t follow this tutorial and not managed to test.