This guide walks you through the process of publishing and subscribing to messages using a JMS broker.
You will build an application that uses Spring’s JmsTemplate
to post a single message and subscribes to it with a @JmsListener
annotated method of a managed bean.
If you use Maven, visit the Spring Initializr to generate a new project with the required dependency (Spring for Apache ActiveMQ 5).
The following listing shows the pom.xml
file that is created when you choose Maven:
link:complete/pom.xml[role=include]
If you use Gradle, visit the Spring Initializr to generate a new project with the required dependency (Spring for Apache ActiveMQ 5).
The following listing shows the build.gradle
file that is created when you choose Gradle:
link:complete/build.gradle[role=include]
If you want to initialize the project manually rather than use the links shown earlier, follow the steps given below:
-
Navigate to https://start.spring.io. This service pulls in all the dependencies you need for an application and does most of the setup for you.
-
Choose either Gradle or Maven and the language you want to use. This guide assumes that you chose Java.
-
Click Dependencies and select Spring for Apache ActiveMQ 5.
-
Click Generate.
-
Download the resulting ZIP file, which is an archive of a web application that is configured with your choices.
Note
|
If your IDE has the Spring Initializr integration, you can complete this process from your IDE. |
Spring provides the means to publish messages to any POJO (Plain Old Java Object).
This guide describes how to send a message out over a JMS message broker. To start things off, create a simple POJO that embodies the details of an email message. Note that we are not sending an email message. We send the details from one place to another about WHAT to send in a message.
src/main/java/hello/Email.java
link:complete/src/main/java/hello/Email.java[role=include]
This POJO is quite simple, containing two fields (to and body), along with the presumed set of getters and setters.
From here, you can define a message receiver:
src/main/java/hello/Receiver.java
link:complete/src/main/java/hello/Receiver.java[role=include]
Receiver
is also known as a message-driven POJO. As the code shows, there is no need to implement any particular interface or for the method to have any particular name. Besides, the method may have a flexible signature. Note, in particular, that this class has no import of the JMS API.
The JmsListener
annotation defines the name of the Destination
that this method should listen to and the reference to the JmsListenerContainerFactory
to use to create the underlying message listener container. Strictly speaking, that last attribute is not necessary unless you need to customize the way the container is built, as Spring Boot registers a default factory if necessary.
The reference documentation covers this in more detail.
Next, wire up a sender and a receiver.
src/main/java/hello/Application.java
link:complete/src/main/java/hello/Application.java[role=include]
@EnableJms
triggers the discovery of methods annotated with @JmsListener
, creating the message listener container under the covers.
For clarity, we have also defined a myFactory
bean that is referenced in the JmsListener
annotation of the receiver. Because we use the DefaultJmsListenerContainerFactoryConfigurer
infrastructure provided by Spring Boot, that JmsMessageListenerContainer
is identical to the one that Boot creates by default.
The default MessageConverter
can convert only basic types (such as String
, Map
, Serializable
), and our Email
is not Serializable
on purpose. We want to use Jackson and serialize the content to JSON in text format (that is, as a TextMessage
). Spring Boot detects the presence of a MessageConverter
and associates it to both the default JmsTemplate
and any JmsListenerContainerFactory
created by DefaultJmsListenerContainerFactoryConfigurer
.
JmsTemplate
makes it simple to send messages to a JMS destination. In the main
runner method, after starting things up, you can use jmsTemplate
to send an Email
POJO. Because our custom MessageConverter
has been automatically associated to it, a JSON document is generated in a TextMessage
only.
Two beans that you do not see defined are JmsTemplate
and ConnectionFactory
. These are created automatically by Spring Boot. In this case, the ActiveMQ broker runs embedded.
By default, Spring Boot creates a JmsTemplate
configured to transmit to queues by having pubSubDomain
set to false
. The JmsMessageListenerContainer
is also configured the same way.
To override, set spring.jms.isPubSubDomain=true
through Boot’s property settings (either inside application.properties
or by setting an environment variable). Then make sure the receiving container
has the same setting.
Note
|
Spring’s JmsTemplate can receive messages directly through its receive method, but that works only synchronously, meaning that it blocks. That is why we recommend that you use a listener container such as DefaultMessageListenerContainer with a cache-based connection factory, so you can consume messages asynchronously and with maximum connection efficiency.
|
When it runs, buried amidst all the logging, you should see these messages:
Sending an email message. Received <Email{to=info@example.com, body=Hello}>
Congratulations! You have developed a publisher and consumer of JMS-based messages.