Tuesday, April 14, 2015

Configure a Spring JMS application with Spring Boot and annotation support

1   Introduction


In previous posts we learned how to configure a project using Spring JMS. If you check the article introduction to messaging with Spring JMS, you will notice that it is configured using XML. This article will take advantage of the improvements introduced in Spring 4.1 version, and configure a JMS project using Java config only.

In this example we will also see how easy it can be to configure the project by using Spring Boot.

Before we get started, just note that as usual, you can take a look at the source code of the project used in the examples below.

See the example project at github.

Sections:
  1. Introduction.
  2. The example application.
  3. Setting up the project.
  4. A simple example with JMS listener.
  5. Sending a response to another queue with @SendTo.
  6. Conclusion.

2   The example application


The application uses a Client service to send orders to a JMS queue, where a JMS listener will be registered and handle these orders. Once received, the listener will store the order through the Store service:



We will use the Order class to create orders:

Before moving on to the first example, we will first explore how the project structure is built.


3   Setting up the project


3.1   Configuring pom.xml

The first thing to do is to define the artifact spring-boot-starter-parent as our parent pom.

This parent basically sets several Maven defaults and provides the dependency management for the main dependencies that we will use, like the Spring version (which is 4.1.6).

It is important to note that this parent pom defines the version of many libraries but it does not add any dependency to our project. So don’t worry about getting libraries you won’t use.

The next step is to set the basic dependencies for Spring Boot:

In addition to the core Spring libraries, this dependency will bring the auto configuration functionality of Spring Boot. This will allow the framework to try to automatically set up the configuration based on the dependencies you add.

Finally, we will add the Spring JMS dependency and the ActiveMQ message broker, leaving the whole pom.xml as follows:

3.2   Spring Configuration with Java Config

We used @SpringBootApplication instead of the usual @Configuration annotation. This Spring Boot annotation is also annotated with @Configuration. In addition, it sets other configuration like Spring Boot auto configuration:

The configuration class does not need to define any bean. All the configuration is automatically set by Spring Boot. Regarding the connection factory, Spring Boot will detect that I included the ActiveMQ dependency on the classpath and will start and configure an embedded broker.

If you need to specify a different broker url, you can declare it in the properties. Check ActiveMQ support section for further detail.

It is all set now. We will see how to configure a JMS listener in the example in the next section, since it is configured with an annotation.


4   A simple example with JMS listener


4.1   Sending an order to a JMS queue

The ClientService class is responsible for sending a new order to the JMS queue. In order to accomplish this, it uses a JmsTemplate:

Here, we use a JmsTemplate to convert our Order instance and send it to the JMS queue. If you prefer to directly send a message through the send message, you can instead use the new JmsMessagingTemplate. This is preferable since it uses the more standardized Message class.


4.2   Receiving an order sent to the JMS queue

Registering a JMS listener to a JMS listener container is as simple as adding the @JmsListener annotation to the method we want to use. This will create a JMS listener container under the covers that will receive messages sent to the specified queue and delegate them to our listener class:

The StoreService receives the order and saves it to a list of received orders:

4.3   Testing the application

Now let’s add a test to check if we did everything correctly:


5   Sending a response to another queue with @SendTo


Another addition to Spring JMS is the @SendTo annotation. This annotation allows a listener to send a message to another queue. For example, the following listener receives an order from the “in.queue” and after storing the order, sends a confirmation to the “out.queue”.

There, we have another listener registered that will process this confirmation id:


6   Conclusion


With annotation support, it is now much easier to configure a Spring JMS application, taking advantage of asynchronous message retrieval using annotated JMS listeners.

I'm publishing my new posts on Google plus and Twitter. Follow me if you want to be updated with new content.

10 comments:

  1. both the client service and store service are running in same jvm....what if we need to run them in separate jvm

    ReplyDelete
    Replies
    1. You would only need to specify a different broker URL (default is embedded). At the end of section 3.2 there's a link showing how to do this.

      Delete
  2. will @JmsListener work in Tibco queue as well?

    ReplyDelete
    Replies
    1. I have never worked with Tibco, but I think you would just need to configure a JNDI ConnectionFactory. The @JmsListener should work well once the configuration is set. Check the following link to see how to configure it:

      http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-messaging.html#boot-features-jms-jndi

      Delete
  3. Hi,

    I need to integrate Rest with ActiveMQ.

    Can you provide me a sample code

    ReplyDelete
    Replies
    1. What does that even mean? REST calls to populate ActiveMQ? REST to read ActiveMQ?

      Either way, quit being lazy and at read some documentation. It's really not that hard, especially since you're a software developer.

      Delete
  4. i have used Tibco queue for @JmsListener , use "TibjmsQueueConnectionFactory".
    read more: http://sarkarinaukrijobfair.blogspot.in

    ReplyDelete
  5. bad solution, had a bad perfomance ..

    ReplyDelete
    Replies
    1. Why? Could you provide a better alternative/example?

      Delete
  6. Hi, i want to ask, in your method with @JmsListener annotations, you were executing storeService, is it working sync or asynchronously? I have similar codes and i noticed the performance is very poor

    ReplyDelete