DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workkloads.

Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Introducing Stalactite ORM
  • How Spring and Hibernate Simplify Web and Database Management
  • Functional Endpoints: Alternative to Controllers in WebFlux
  • Graceful Shutdown: Spring Framework vs Golang Web Services

Trending

  • Debugging Core Dump Files on Linux - A Detailed Guide
  • Segmentation Violation and How Rust Helps Overcome It
  • Emerging Data Architectures: The Future of Data Management
  • Setting Up Data Pipelines With Snowflake Dynamic Tables
  1. DZone
  2. Testing, Deployment, and Maintenance
  3. Deployment
  4. Don't Use JmsTemplate in Spring!

Don't Use JmsTemplate in Spring!

By 
Gordon Dickens user avatar
Gordon Dickens
·
Apr. 21, 11 · Opinion
Likes (0)
Comment
Save
Tweet
Share
84.5K Views

Join the DZone community and get the full member experience.

Join For Free

JmsTemplate is easy for simple message sending. What if we want to add headers, intercept or transform the message? Then we have to write more code. So, how do we solve this common task with more configurability in lieu of more code? First, lets review JMS in Spring.

Spring JMS Options

  1. JmsTemplate – either to send and receive messages inline
    1. Use send()/convertAndSend() methods to send messages
    2. Use receive()/receiveAndConvert() methods to receive messages. BEWARE: these are blocking methods! If there is no message on the Destination, it will wait until a message is received or times out.
  2. MessageListenerContainer – Async JMS message receipt by polling JMS Destinations and directing messages to service methods or MDBs

Both JmsTemplate and MessageListenerContainer have been successfully implemented in Spring applications, if we have to do something a little different, we introduce new code. What could possibly go wrong?


Future Extensibility?

On many projects new use-cases arise, such as:

  • Route messages to different destinations, based on header values or contents?
  • Log the message contents?
  • Add header values?
  • Buffer the messages?
  • Improved response and error handling?
  • Make configuration changes without having to recompile?
  • and more…

Now we have to refactor code and introduce new code and test cases, run it through QA, etc. etc.




A More Configurable Solution!

It is time to graduate Spring JmsTemplate and play with the big kids. We can easily do this with a Spring Integration flow.


How it is done with Spring Integration

Here we have a diagram illustrating the 3 simple components to Spring Integration replacing the JmsTemplate send.

  1. Create a Gateway interface – an interface defining method(s) that accept the type of data you wish to send and any optional header values.
  2. Define a Channel – the pipe connecting our endpoints
  3. Define an Outbound JMS Adapter – sends the message to your JMS provider (ActiveMQ, RabbitMQ, etc.)

Simply inject this into our service classes and invoke the methods.



Immediate Gains

  • Add header & header values via the methods defined in the interface
  • Simple invokation of Gateway methods from our service classes
  • Multiple Gateway methods
  • Configure method level or class level destinations



Future Gains

  • Change the JMS Adapter (one-way) to a JMS Gateway (two-way) to processes responses from JMS
  • We can change the channel to a queue (buffered) channel
  • We can wire in a transformer for message transformation
  • We can wire in additional destinations, and wire in a “header (key), header value, or content based” router and add another adapter
  • We can wire in other inbound adapters receiving data from another source, such as SMTP, FTP, File, etc.
  • Wiretap the channel to send a copy of the message elsewhere
  • Change the channel to a logging adapter channel which would provide us with logging of the messages coming through
  • Add the “message-history” option to our SI configuration to track the message along its route
  • and more…




Optimal JMS Send Solution

The Spring Integration Gateway Interface

Gateway provides a one or two way communication with Spring Integration. If the method returns void, it is inherently one-way.

The interface MyJmsGateway, has one Gateway method declared sendMyMessage(). When this method is invoked by your service class, the first argument will go into a message header field named “myHeaderKey”, the second argument goes into the payload.

package com.gordondickens.sijms; import org.springframework.integration.annotation.Gateway;import org.springframework.integration.annotation.Header; public interface MyJmsGateway {    @Gateway    public void sendMyMessage(@Header("myHeaderKey") String s, Object o);}

Spring Integration Configuration

Because the interface is proxied at runtime, we need to configure in the Gateway via XML.

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xmlns:jms="http://www.springframework.org/schema/integration/jms"        xmlns:si="http://www.springframework.org/schema/integration"        xsi:schemaLocation="http://www.springframework.org/schema/integration/jms http://www.springframework.org/schema/integration/jms/spring-integration-jms-2.0.xsd http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.0.xsd http://www.springframework.org/schema/beans           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">     <import resource="classpath:META-INF/spring/amq-context.xml"/>     <!-- Pickup the @Gateway annotation -->    <si:annotation-config/>     <si:poller default="true">      <si:interval-trigger interval="500"/>    </si:poller>     <!-- Define the channel (pipe) connecting the endpoints -->    <si:channel id="myRequestChannel"/>     <!-- Configure the Gateway to Send on the channel -->    <si:gateway id="myJmsGateway"        service-interface="com.gordondickens.sijms.MyJmsGateway"        default-request-channel="myRequestChannel"/>     <!-- Send message to JMS -->    <jms:outbound-channel-adapter channel="myRequestChannel"        connection-factory="connectionFactory"        destination="my.inbound.queue"/></beans>

Sending the Message

package com.gordondickens.sijms; import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @ContextConfiguration("classpath:/com/gordondickens/sijms/JmsSenderTests-context.xml")@RunWith(SpringJUnit4ClassRunner.class)public class JmsSenderTests {     @Autowired    MyJmsGateway myJmsGateway;     @Test    public void testJmsSend() {        myJmsGateway.sendMyMessage("myHeaderValue", "MY PayLoad");    }}




Summary

  • Simple implementation
  • Invoke a method to send a message to JMS – Very SOA eh?
  • Flexible configuration
  • Reconfigure & restart WITHOUT recompiling – SWEET!
Spring Framework Spring Integration

Opinions expressed by DZone contributors are their own.

Related

  • Introducing Stalactite ORM
  • How Spring and Hibernate Simplify Web and Database Management
  • Functional Endpoints: Alternative to Controllers in WebFlux
  • Graceful Shutdown: Spring Framework vs Golang Web Services

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!