What is Spring's JmsTemplate, and what do convertAndSend and receiveAndConvert do?
answer
- template pattern — manages Connection/Session/Producer
- convertAndSend = object -> Message via MessageConverter
- receiveAndConvert = blocking receive -> object
- SimpleMessageConverter default (String/Map/Serializable/byte[])
- needs caching/pooled ConnectionFactory
basics
~20 sJmsTemplate is a Spring helper that hides raw JMS boilerplate (opening connections, sessions, producers). convertAndSend turns a Java object into a JMS message and sends it; receiveAndConvert reads a message and converts it back to a Java object.
solid answer
~40 sJmsTemplate is Spring's central class for synchronous JMS access. It follows the template pattern: you give it a ConnectionFactory, and it manages the Connection, Session, MessageProducer/MessageConsumer lifecycle for each call, so you never write try/finally cleanup. convertAndSend(destination, object) uses a MessageConverter (default SimpleMessageConverter) to marshal your object into a javax/jakarta.jms.Message and send it. receiveAndConvert(destination) does the reverse: it blocks waiting for a message, then converts the payload back to an object. Both accept either a Destination object or a String destination name resolved via a DestinationResolver. Because each operation opens and closes resources, JmsTemplate is meant to be used with a caching or pooled ConnectionFactory in production. It is thread-safe once configured.
code
java · 18 lines@Service
public class OrderSender {
private final JmsTemplate jmsTemplate;
public OrderSender(JmsTemplate jmsTemplate) {
this.jmsTemplate = jmsTemplate;
}
// convert Java object -> JMS message and send to a named queue
public void send(Order order) {
jmsTemplate.convertAndSend("orders.queue", order);
}
// blocking pull-style receive, converted back to an object
public Order poll() {
return (Order) jmsTemplate.receiveAndConvert("orders.queue");
}
}go deeper
Know that JmsTemplate removes JMS boilerplate and that convertAndSend sends an object, receiveAndConvert reads one.
Explain the default SimpleMessageConverter mappings and swapping in Jackson for JSON.
Discuss the per-call resource lifecycle and why a CachingConnectionFactory is mandatory, plus receiveTimeout pitfalls.
Frame when polling receive is the wrong tool vs. listener containers, and the operational cost model of synchronous JMS.
**JMS background.** JMS (Java/Jakarta Message Service) is the standard API for sending messages through a broker (ActiveMQ, Artemis, IBM MQ, etc.). Raw JMS is verbose: you obtain a `ConnectionFactory`, call `createConnection()`, `createSession()`, `createProducer()`/`createConsumer()`, `send`/`receive`, then close each resource in the right order inside try/finally. Getting the cleanup wrong leaks connections. **What JmsTemplate is.** `org.springframework.jms.core.JmsTemplate` implements the *template method* pattern (same idea as `JdbcTemplate`). You configure it once with a `ConnectionFactory`; each call internally does the open-session/create-producer/send/close dance for you and translates checked `JMSException`s into Spring's unchecked `JmsException` hierarchy (via `JmsTemplate`'s exception translation). Configure once (usually a Spring bean) and reuse — it is thread-safe. **Sending.** - `send(destination, MessageCreator)` — lowest level; you build the `Message` yourself in the callback. - `convertAndSend(destination, Object)` — the common path: a `MessageConverter` turns your object into a `Message`. The default is `SimpleMessageConverter`, which maps `String`→`TextMessage`, `Map`→`MapMessage`, `Serializable`→`ObjectMessage`, `byte[]`→`BytesMessage`. For JSON you swap in `MappingJackson2MessageConverter`. - `convertAndSend(dest, obj, MessagePostProcessor)` — convert, then tweak the `Message` (e.g. set a header/property) before sending. **Receiving (synchronous / polling).** - `receive(destination)` — blocks until a message arrives or `receiveTimeout` elapses, returns the raw `Message`. - `receiveAndConvert(destination)` — same, then runs the payload back through the `MessageConverter` to give you an object. - `receiveSelected(dest, selector)` — filter with a JMS selector string. This is *pull*-style consumption. For high-throughput push-style listening you normally use `@JmsListener` / `DefaultMessageListenerContainer` instead, not `JmsTemplate.receive`. **Key config knobs.** - `receiveTimeout` — default is `RECEIVE_TIMEOUT_INDEFINITE_WAIT` (0 = block forever). Almost always set a finite value, or a receive can hang a thread indefinitely. - `pubSubDomain` — `false` (default) means Queue (point-to-point); `true` means Topic (pub/sub). This flag changes how a *destination name string* is resolved. - `defaultDestination`/`defaultDestinationName` — used by the no-destination overloads. - `messageConverter`, `destinationResolver`, `sessionTransacted`, `deliveryMode`, `priority`, `timeToLive` (the last three need `explicitQosEnabled=true` to take effect). **Gotcha — connection churn.** Every send/receive opens and closes a Connection+Session against the broker. Doing that per call is expensive, so wrap the raw broker `ConnectionFactory` in a `CachingConnectionFactory` (Spring) or a pooled one (e.g. `JmsPoolConnectionFactory`) that caches connections/sessions/producers. Spring Boot auto-wires a `CachingConnectionFactory` by default. **Gotcha — receiveTimeout with caching.** A blocking `receive` holds a cached session busy; combining long/indefinite receives with a small session cache can starve producers. Prefer listener containers for continuous consumption. **When to use.** `JmsTemplate` for *request-driven, synchronous* sends and occasional polling receives; message-driven listeners for continuous async consumption.
- What is the default MessageConverter and how do you send JSON instead?The default is SimpleMessageConverter (String→TextMessage, Map→MapMessage, Serializable→ObjectMessage, byte[]→BytesMessage). For JSON, register a MappingJackson2MessageConverter bean (set target type TEXT and a type-id property name); Spring Boot picks up a MessageConverter bean automatically.
- Why should JmsTemplate not be used with the raw broker ConnectionFactory in production?Because each send/receive opens and closes a Connection and Session; against the raw factory that means constant connect/disconnect overhead. Wrap it in a CachingConnectionFactory (or pooled factory) so connections, sessions, and producers are reused.
saying these in an interview costs you the question
- Thinking JmsTemplate keeps a long-lived open connection per instance (it opens/closes per operation unless the factory caches)
- Believing receive() by default times out after a few seconds (default is block forever, 0 = indefinite)
- Assuming convertAndSend serializes to JSON by default (default SimpleMessageConverter uses ObjectMessage/Java serialization for beans)