001/* 002 * Copyright 2002-2017 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.jms.core; 018 019import java.util.Map; 020import javax.jms.ConnectionFactory; 021import javax.jms.Destination; 022import javax.jms.JMSException; 023import javax.jms.Session; 024 025import org.springframework.beans.factory.InitializingBean; 026import org.springframework.jms.InvalidDestinationException; 027import org.springframework.jms.JmsException; 028import org.springframework.jms.support.converter.MessageConverter; 029import org.springframework.jms.support.converter.MessagingMessageConverter; 030import org.springframework.jms.support.converter.SimpleMessageConverter; 031import org.springframework.messaging.Message; 032import org.springframework.messaging.MessagingException; 033import org.springframework.messaging.converter.MessageConversionException; 034import org.springframework.messaging.core.AbstractMessagingTemplate; 035import org.springframework.messaging.core.DestinationResolutionException; 036import org.springframework.messaging.core.MessagePostProcessor; 037import org.springframework.util.Assert; 038 039/** 040 * An implementation of {@link JmsMessageOperations}. 041 * 042 * @author Stephane Nicoll 043 * @author Juergen Hoeller 044 * @since 4.1 045 */ 046public class JmsMessagingTemplate extends AbstractMessagingTemplate<Destination> 047 implements JmsMessageOperations, InitializingBean { 048 049 private JmsTemplate jmsTemplate; 050 051 private MessageConverter jmsMessageConverter = new MessagingMessageConverter(); 052 053 private boolean converterSet; 054 055 private String defaultDestinationName; 056 057 058 /** 059 * Constructor for use with bean properties. 060 * Requires {@link #setConnectionFactory} or {@link #setJmsTemplate} to be called. 061 */ 062 public JmsMessagingTemplate() { 063 } 064 065 /** 066 * Create a {@code JmsMessagingTemplate} instance with the JMS {@link ConnectionFactory} 067 * to use, implicitly building a {@link JmsTemplate} based on it. 068 * @since 4.1.2 069 */ 070 public JmsMessagingTemplate(ConnectionFactory connectionFactory) { 071 this.jmsTemplate = new JmsTemplate(connectionFactory); 072 } 073 074 /** 075 * Create a {@code JmsMessagingTemplate} instance with the {@link JmsTemplate} to use. 076 */ 077 public JmsMessagingTemplate(JmsTemplate jmsTemplate) { 078 Assert.notNull(jmsTemplate, "JmsTemplate must not be null"); 079 this.jmsTemplate = jmsTemplate; 080 } 081 082 083 /** 084 * Set the ConnectionFactory to use for the underlying {@link JmsTemplate}. 085 * @since 4.1.2 086 */ 087 public void setConnectionFactory(ConnectionFactory connectionFactory) { 088 if (this.jmsTemplate != null) { 089 this.jmsTemplate.setConnectionFactory(connectionFactory); 090 } 091 else { 092 this.jmsTemplate = new JmsTemplate(connectionFactory); 093 } 094 } 095 096 /** 097 * Return the ConnectionFactory that the underlying {@link JmsTemplate} uses. 098 * @since 4.1.2 099 */ 100 public ConnectionFactory getConnectionFactory() { 101 return (this.jmsTemplate != null ? this.jmsTemplate.getConnectionFactory() : null); 102 } 103 104 /** 105 * Set the {@link JmsTemplate} to use. 106 */ 107 public void setJmsTemplate(JmsTemplate jmsTemplate) { 108 this.jmsTemplate = jmsTemplate; 109 } 110 111 /** 112 * Return the configured {@link JmsTemplate}. 113 */ 114 public JmsTemplate getJmsTemplate() { 115 return this.jmsTemplate; 116 } 117 118 /** 119 * Set the {@link MessageConverter} to use to convert a {@link Message} from 120 * the messaging to and from a {@link javax.jms.Message}. By default, a 121 * {@link MessagingMessageConverter} is defined using a {@link SimpleMessageConverter} 122 * to convert the payload of the message. 123 * <p>Consider configuring a {@link MessagingMessageConverter} with a different 124 * {@link MessagingMessageConverter#setPayloadConverter(MessageConverter) payload converter} 125 * for more advanced scenarios. 126 * @see org.springframework.jms.support.converter.MessagingMessageConverter 127 */ 128 public void setJmsMessageConverter(MessageConverter jmsMessageConverter) { 129 Assert.notNull(jmsMessageConverter, "MessageConverter must not be null"); 130 this.jmsMessageConverter = jmsMessageConverter; 131 this.converterSet = true; 132 } 133 134 /** 135 * Return the {@link MessageConverter} to use to convert a {@link Message} 136 * from the messaging to and from a {@link javax.jms.Message}. 137 */ 138 public MessageConverter getJmsMessageConverter() { 139 return this.jmsMessageConverter; 140 } 141 142 /** 143 * Configure the default destination name to use in send methods that don't have 144 * a destination argument. If a default destination is not configured, send methods 145 * without a destination argument will raise an exception if invoked. 146 * @see #setDefaultDestination(Object) 147 */ 148 public void setDefaultDestinationName(String defaultDestinationName) { 149 this.defaultDestinationName = defaultDestinationName; 150 } 151 152 /** 153 * Return the configured default destination name. 154 */ 155 public String getDefaultDestinationName() { 156 return this.defaultDestinationName; 157 } 158 159 @Override 160 public void afterPropertiesSet() { 161 Assert.notNull(this.jmsTemplate, "Property 'connectionFactory' or 'jmsTemplate' is required"); 162 if (!this.converterSet && this.jmsTemplate.getMessageConverter() != null) { 163 ((MessagingMessageConverter) this.jmsMessageConverter) 164 .setPayloadConverter(this.jmsTemplate.getMessageConverter()); 165 } 166 } 167 168 169 @Override 170 public void send(Message<?> message) { 171 Destination defaultDestination = getDefaultDestination(); 172 if (defaultDestination != null) { 173 send(defaultDestination, message); 174 } 175 else { 176 send(getRequiredDefaultDestinationName(), message); 177 } 178 } 179 180 @Override 181 public void convertAndSend(Object payload) throws MessagingException { 182 convertAndSend(payload, null); 183 } 184 185 @Override 186 public void convertAndSend(Object payload, MessagePostProcessor postProcessor) throws MessagingException { 187 Destination defaultDestination = getDefaultDestination(); 188 if (defaultDestination != null) { 189 convertAndSend(defaultDestination, payload, postProcessor); 190 } 191 else { 192 convertAndSend(getRequiredDefaultDestinationName(), payload, postProcessor); 193 } 194 } 195 196 @Override 197 public void send(String destinationName, Message<?> message) throws MessagingException { 198 doSend(destinationName, message); 199 } 200 201 @Override 202 public void convertAndSend(String destinationName, Object payload) throws MessagingException { 203 convertAndSend(destinationName, payload, (Map<String, Object>) null); 204 } 205 206 @Override 207 public void convertAndSend(String destinationName, Object payload, Map<String, Object> headers) 208 throws MessagingException { 209 210 convertAndSend(destinationName, payload, headers, null); 211 } 212 213 @Override 214 public void convertAndSend(String destinationName, Object payload, MessagePostProcessor postProcessor) 215 throws MessagingException { 216 217 convertAndSend(destinationName, payload, null, postProcessor); 218 } 219 220 @Override 221 public void convertAndSend(String destinationName, Object payload, Map<String, Object> headers, 222 MessagePostProcessor postProcessor) throws MessagingException { 223 224 Message<?> message = doConvert(payload, headers, postProcessor); 225 send(destinationName, message); 226 } 227 228 @Override 229 public Message<?> receive() { 230 Destination defaultDestination = getDefaultDestination(); 231 if (defaultDestination != null) { 232 return receive(defaultDestination); 233 } 234 else { 235 return receive(getRequiredDefaultDestinationName()); 236 } 237 } 238 239 @Override 240 public <T> T receiveAndConvert(Class<T> targetClass) { 241 Destination defaultDestination = getDefaultDestination(); 242 if (defaultDestination != null) { 243 return receiveAndConvert(defaultDestination, targetClass); 244 } 245 else { 246 return receiveAndConvert(getRequiredDefaultDestinationName(), targetClass); 247 } 248 } 249 250 @Override 251 public Message<?> receive(String destinationName) throws MessagingException { 252 return doReceive(destinationName); 253 } 254 255 @Override 256 public <T> T receiveAndConvert(String destinationName, Class<T> targetClass) throws MessagingException { 257 Message<?> message = doReceive(destinationName); 258 if (message != null) { 259 return doConvert(message, targetClass); 260 } 261 else { 262 return null; 263 } 264 } 265 266 @Override 267 public Message<?> sendAndReceive(Message<?> requestMessage) { 268 Destination defaultDestination = getDefaultDestination(); 269 if (defaultDestination != null) { 270 return sendAndReceive(defaultDestination, requestMessage); 271 } 272 else { 273 return sendAndReceive(getRequiredDefaultDestinationName(), requestMessage); 274 } 275 } 276 277 @Override 278 public Message<?> sendAndReceive(String destinationName, Message<?> requestMessage) throws MessagingException { 279 return doSendAndReceive(destinationName, requestMessage); 280 } 281 282 @Override 283 public <T> T convertSendAndReceive(String destinationName, Object request, Class<T> targetClass) 284 throws MessagingException { 285 286 return convertSendAndReceive(destinationName, request, null, targetClass); 287 } 288 289 @Override 290 public <T> T convertSendAndReceive(Object request, Class<T> targetClass) { 291 return convertSendAndReceive(request, targetClass, null); 292 } 293 294 @Override 295 public <T> T convertSendAndReceive(String destinationName, Object request, 296 Map<String, Object> headers, Class<T> targetClass) throws MessagingException { 297 298 return convertSendAndReceive(destinationName, request, headers, targetClass, null); 299 } 300 301 @Override 302 public <T> T convertSendAndReceive(Object request, Class<T> targetClass, MessagePostProcessor postProcessor) { 303 Destination defaultDestination = getDefaultDestination(); 304 if (defaultDestination != null) { 305 return convertSendAndReceive(defaultDestination, request, targetClass, postProcessor); 306 } 307 else { 308 return convertSendAndReceive(getRequiredDefaultDestinationName(), request, targetClass, postProcessor); 309 } 310 } 311 312 @Override 313 public <T> T convertSendAndReceive(String destinationName, Object request, Class<T> targetClass, 314 MessagePostProcessor requestPostProcessor) throws MessagingException { 315 316 return convertSendAndReceive(destinationName, request, null, targetClass, requestPostProcessor); 317 } 318 319 @SuppressWarnings("unchecked") 320 @Override 321 public <T> T convertSendAndReceive(String destinationName, Object request, Map<String, Object> headers, 322 Class<T> targetClass, MessagePostProcessor postProcessor) { 323 324 Message<?> requestMessage = doConvert(request, headers, postProcessor); 325 Message<?> replyMessage = sendAndReceive(destinationName, requestMessage); 326 return (replyMessage != null ? (T) getMessageConverter().fromMessage(replyMessage, targetClass) : null); 327 } 328 329 @Override 330 protected void doSend(Destination destination, Message<?> message) { 331 try { 332 this.jmsTemplate.send(destination, createMessageCreator(message)); 333 } 334 catch (JmsException ex) { 335 throw convertJmsException(ex); 336 } 337 } 338 339 protected void doSend(String destinationName, Message<?> message) { 340 try { 341 this.jmsTemplate.send(destinationName, createMessageCreator(message)); 342 } 343 catch (JmsException ex) { 344 throw convertJmsException(ex); 345 } 346 } 347 348 @Override 349 protected Message<?> doReceive(Destination destination) { 350 try { 351 javax.jms.Message jmsMessage = this.jmsTemplate.receive(destination); 352 return convertJmsMessage(jmsMessage); 353 } 354 catch (JmsException ex) { 355 throw convertJmsException(ex); 356 } 357 } 358 359 protected Message<?> doReceive(String destinationName) { 360 try { 361 javax.jms.Message jmsMessage = this.jmsTemplate.receive(destinationName); 362 return convertJmsMessage(jmsMessage); 363 } 364 catch (JmsException ex) { 365 throw convertJmsException(ex); 366 } 367 } 368 369 @Override 370 protected Message<?> doSendAndReceive(Destination destination, Message<?> requestMessage) { 371 try { 372 javax.jms.Message jmsMessage = this.jmsTemplate.sendAndReceive( 373 destination, createMessageCreator(requestMessage)); 374 return convertJmsMessage(jmsMessage); 375 } 376 catch (JmsException ex) { 377 throw convertJmsException(ex); 378 } 379 } 380 381 protected Message<?> doSendAndReceive(String destinationName, Message<?> requestMessage) { 382 try { 383 javax.jms.Message jmsMessage = this.jmsTemplate.sendAndReceive( 384 destinationName, createMessageCreator(requestMessage)); 385 return convertJmsMessage(jmsMessage); 386 } 387 catch (JmsException ex) { 388 throw convertJmsException(ex); 389 } 390 } 391 392 private MessagingMessageCreator createMessageCreator(Message<?> message) { 393 return new MessagingMessageCreator(message, getJmsMessageConverter()); 394 } 395 396 protected String getRequiredDefaultDestinationName() { 397 String name = getDefaultDestinationName(); 398 if (name == null) { 399 throw new IllegalStateException("No 'defaultDestination' or 'defaultDestinationName' specified. " + 400 "Check configuration of JmsMessagingTemplate."); 401 } 402 return name; 403 } 404 405 protected Message<?> convertJmsMessage(javax.jms.Message message) { 406 if (message == null) { 407 return null; 408 } 409 try { 410 return (Message<?>) getJmsMessageConverter().fromMessage(message); 411 } 412 catch (Exception ex) { 413 throw new MessageConversionException("Could not convert '" + message + "'", ex); 414 } 415 } 416 417 protected MessagingException convertJmsException(JmsException ex) { 418 if (ex instanceof org.springframework.jms.support.destination.DestinationResolutionException || 419 ex instanceof InvalidDestinationException) { 420 return new DestinationResolutionException(ex.getMessage(), ex); 421 } 422 if (ex instanceof org.springframework.jms.support.converter.MessageConversionException) { 423 return new MessageConversionException(ex.getMessage(), ex); 424 } 425 // Fallback 426 return new MessagingException(ex.getMessage(), ex); 427 } 428 429 430 private static class MessagingMessageCreator implements MessageCreator { 431 432 private final Message<?> message; 433 434 private final MessageConverter messageConverter; 435 436 public MessagingMessageCreator(Message<?> message, MessageConverter messageConverter) { 437 this.message = message; 438 this.messageConverter = messageConverter; 439 } 440 441 @Override 442 public javax.jms.Message createMessage(Session session) throws JMSException { 443 try { 444 return this.messageConverter.toMessage(this.message, session); 445 } 446 catch (Exception ex) { 447 throw new MessageConversionException("Could not convert '" + this.message + "'", ex); 448 } 449 } 450 } 451 452}