1 16 17 package org.springframework.jms.listener.adapter; 18 19 import java.lang.reflect.InvocationTargetException ; 20 21 import javax.jms.Destination ; 22 import javax.jms.InvalidDestinationException ; 23 import javax.jms.JMSException ; 24 import javax.jms.Message ; 25 import javax.jms.MessageListener ; 26 import javax.jms.MessageProducer ; 27 import javax.jms.Session ; 28 29 import org.apache.commons.logging.Log; 30 import org.apache.commons.logging.LogFactory; 31 32 import org.springframework.jms.listener.SessionAwareMessageListener; 33 import org.springframework.jms.support.JmsUtils; 34 import org.springframework.jms.support.converter.MessageConversionException; 35 import org.springframework.jms.support.converter.MessageConverter; 36 import org.springframework.jms.support.converter.SimpleMessageConverter; 37 import org.springframework.jms.support.destination.DestinationResolver; 38 import org.springframework.jms.support.destination.DynamicDestinationResolver; 39 import org.springframework.util.Assert; 40 import org.springframework.util.MethodInvoker; 41 import org.springframework.util.ObjectUtils; 42 43 136 public class MessageListenerAdapter implements MessageListener , SessionAwareMessageListener { 137 138 141 public static final String ORIGINAL_DEFAULT_LISTENER_METHOD = "handleMessage"; 142 143 144 145 protected final Log logger = LogFactory.getLog(getClass()); 146 147 private Object delegate; 148 149 private String defaultListenerMethod = ORIGINAL_DEFAULT_LISTENER_METHOD; 150 151 private Object defaultResponseDestination; 152 153 private DestinationResolver destinationResolver = new DynamicDestinationResolver(); 154 155 private MessageConverter messageConverter; 156 157 158 161 public MessageListenerAdapter() { 162 initDefaultStrategies(); 163 this.delegate = this; 164 } 165 166 169 public MessageListenerAdapter(Object delegate) { 170 initDefaultStrategies(); 171 setDelegate(delegate); 172 } 173 174 175 182 public void setDelegate(Object delegate) { 183 Assert.notNull(delegate, "Delegate must not be null"); 184 this.delegate = delegate; 185 } 186 187 190 protected Object getDelegate() { 191 return this.delegate; 192 } 193 194 200 public void setDefaultListenerMethod(String defaultListenerMethod) { 201 this.defaultListenerMethod = defaultListenerMethod; 202 } 203 204 207 protected String getDefaultListenerMethod() { 208 return this.defaultListenerMethod; 209 } 210 211 223 public void setDefaultResponseDestination(Destination destination) { 224 this.defaultResponseDestination = destination; 225 } 226 227 235 public void setDefaultResponseQueueName(String destinationName) { 236 this.defaultResponseDestination = new DestinationNameHolder(destinationName, false); 237 } 238 239 247 public void setDefaultResponseTopicName(String destinationName) { 248 this.defaultResponseDestination = new DestinationNameHolder(destinationName, true); 249 } 250 251 259 public void setDestinationResolver(DestinationResolver destinationResolver) { 260 Assert.notNull(destinationResolver, "DestinationResolver must not be null"); 261 this.destinationResolver = destinationResolver; 262 } 263 264 267 protected DestinationResolver getDestinationResolver() { 268 return this.destinationResolver; 269 } 270 271 280 public void setMessageConverter(MessageConverter messageConverter) { 281 this.messageConverter = messageConverter; 282 } 283 284 289 protected MessageConverter getMessageConverter() { 290 return this.messageConverter; 291 } 292 293 294 307 public void onMessage(Message message) { 308 try { 309 onMessage(message, null); 310 } 311 catch (Throwable ex) { 312 handleListenerException(ex); 313 } 314 } 315 316 325 public void onMessage(Message message, Session session) throws JMSException { 326 Object convertedMessage = extractMessage(message); 327 String methodName = getListenerMethodName(message, convertedMessage); 328 329 if (methodName == null) { 330 Object delegate = getDelegate(); 331 if (delegate != this) { 332 if (delegate instanceof SessionAwareMessageListener) { 333 if (session != null) { 334 ((SessionAwareMessageListener) delegate).onMessage(message, session); 335 return; 336 } 337 else if (!(delegate instanceof MessageListener )) { 338 throw new javax.jms.IllegalStateException ("MessageListenerAdapter cannot handle a " + 339 "SessionAwareMessageListener delegate if it hasn't been invoked with a Session itself"); 340 } 341 } 342 if (delegate instanceof MessageListener ) { 343 ((MessageListener ) delegate).onMessage(message); 344 return; 345 } 346 } 347 throw new javax.jms.IllegalStateException ("No default listener method specified: " + 348 "Either specify a non-null value for the 'defaultListenerMethod' property or " + 349 "override the 'getListenerMethodName' method."); 350 } 351 352 Object [] listenerArguments = buildListenerArguments(convertedMessage); 353 Object result = invokeListenerMethod(methodName, listenerArguments); 354 if (result != null) { 355 handleResult(result, message, session); 356 } 357 else { 358 logger.debug("No result object given - no result to handle"); 359 } 360 } 361 362 363 368 protected void initDefaultStrategies() { 369 setMessageConverter(new SimpleMessageConverter()); 370 } 371 372 381 protected void handleListenerException(Throwable ex) { 382 logger.error("Listener execution failed", ex); 383 } 384 385 392 protected Object extractMessage(Message message) throws JMSException { 393 MessageConverter converter = getMessageConverter(); 394 if (converter != null) { 395 return converter.fromMessage(message); 396 } 397 return message; 398 } 399 400 412 protected String getListenerMethodName(Message originalMessage, Object extractedMessage) throws JMSException { 413 return getDefaultListenerMethod(); 414 } 415 416 431 protected Object [] buildListenerArguments(Object extractedMessage) { 432 return new Object [] {extractedMessage}; 433 } 434 435 444 protected Object invokeListenerMethod(String methodName, Object [] arguments) throws JMSException { 445 try { 446 MethodInvoker methodInvoker = new MethodInvoker(); 447 methodInvoker.setTargetObject(getDelegate()); 448 methodInvoker.setTargetMethod(methodName); 449 methodInvoker.setArguments(arguments); 450 methodInvoker.prepare(); 451 return methodInvoker.invoke(); 452 } 453 catch (InvocationTargetException ex) { 454 throw new ListenerExecutionFailedException( 455 "Listener method '" + methodName + "' threw exception", ex.getTargetException()); 456 } 457 catch (Throwable ex) { 458 throw new ListenerExecutionFailedException("Failed to invoke target method '" + methodName + 459 "' with arguments " + ObjectUtils.nullSafeToString(arguments), ex); 460 } 461 } 462 463 464 476 protected void handleResult(Object result, Message request, Session session) throws JMSException { 477 if (session != null) { 478 if (logger.isDebugEnabled()) { 479 logger.debug("Listener method returned result [" + result + 480 "] - generating response message for it"); 481 } 482 Message response = buildMessage(session, result); 483 postProcessResponse(request, response); 484 Destination destination = getResponseDestination(request, response, session); 485 sendResponse(session, destination, response); 486 } 487 else { 488 if (logger.isDebugEnabled()) { 489 logger.debug("Listener method returned result [" + result + 490 "]: not generating response message for it because of no JMS Session given"); 491 } 492 } 493 } 494 495 503 protected Message buildMessage(Session session, Object result) throws JMSException { 504 MessageConverter converter = getMessageConverter(); 505 if (converter != null) { 506 return converter.toMessage(result, session); 507 } 508 else { 509 if (!(result instanceof Message )) { 510 throw new MessageConversionException( 511 "No MessageConverter specified - cannot handle message [" + result + "]"); 512 } 513 return (Message ) result; 514 } 515 } 516 517 526 protected void postProcessResponse(Message request, Message response) throws JMSException { 527 response.setJMSCorrelationID(request.getJMSCorrelationID()); 528 } 529 530 547 protected Destination getResponseDestination(Message request, Message response, Session session) 548 throws JMSException { 549 550 Destination replyTo = request.getJMSReplyTo(); 551 if (replyTo == null) { 552 replyTo = resolveDefaultResponseDestination(session); 553 if (replyTo == null) { 554 throw new InvalidDestinationException ("Cannot determine response destination: " + 555 "Request message does not contain reply-to destination, and no default response destination set."); 556 } 557 } 558 return replyTo; 559 } 560 561 571 protected Destination resolveDefaultResponseDestination(Session session) throws JMSException { 572 if (this.defaultResponseDestination instanceof Destination ) { 573 return (Destination ) this.defaultResponseDestination; 574 } 575 if (this.defaultResponseDestination instanceof DestinationNameHolder) { 576 DestinationNameHolder nameHolder = (DestinationNameHolder) this.defaultResponseDestination; 577 return getDestinationResolver().resolveDestinationName(session, nameHolder.name, nameHolder.isTopic); 578 } 579 return null; 580 } 581 582 592 protected void sendResponse(Session session, Destination destination, Message response) throws JMSException { 593 MessageProducer producer = session.createProducer(destination); 594 try { 595 postProcessProducer(producer, response); 596 producer.send(response); 597 } 598 finally { 599 JmsUtils.closeMessageProducer(producer); 600 } 601 } 602 603 610 protected void postProcessProducer(MessageProducer producer, Message response) throws JMSException { 611 } 612 613 614 618 private static class DestinationNameHolder { 619 620 public final String name; 621 622 public final boolean isTopic; 623 624 public DestinationNameHolder(String name, boolean isTopic) { 625 this.name = name; 626 this.isTopic = isTopic; 627 } 628 } 629 630 } 631 | Popular Tags |