@SendTo support for jms listener endpoints

This commit replaces the "responseDestination" attribute on the
JmsListener annotation by a support of the standard SendTo annotation.

Issue: SPR-11707
This commit is contained in:
Stephane Nicoll
2014-04-24 15:33:24 +03:00
parent 4b0aba63df
commit bded025d9f
9 changed files with 153 additions and 45 deletions

View File

@@ -61,7 +61,9 @@ import org.springframework.messaging.handler.annotation.MessageMapping;
*
* <p>Annotated method may have a non {@code void} return type. When they do, the result of the
* method invocation is sent as a JMS reply to the destination defined by either the
* {@code JMSReplyTO} header of the incoming message or the value of {@link #responseDestination()}.
* {@code JMSReplyTO} header of the incoming message. When this value is not set, a default
* destination can be provided by adding @{@link org.springframework.messaging.handler.annotation.SendTo
* SendTo} to the method declaration.
*
* @author Stephane Nicoll
* @since 4.1
@@ -111,14 +113,4 @@ public @interface JmsListener {
*/
String selector() default "";
/**
* The name of the default response destination to send response messages to.
* <p>This will be applied in case of a request message that does not carry
* a "JMSReplyTo" field. The type of this destination will be determined
* by the listener-container's "destination-type" attribute.
* <p>Note: This only applies to a listener method with a return value,
* for which each result object will be converted into a response message.
*/
String responseDestination() default "";
}

View File

@@ -182,9 +182,6 @@ public class JmsListenerAnnotationBeanPostProcessor implements BeanPostProcessor
if (StringUtils.hasText(jmsListener.subscription())) {
endpoint.setSubscription(jmsListener.subscription());
}
if (StringUtils.hasText(jmsListener.responseDestination())) {
endpoint.setResponseDestination(jmsListener.responseDestination());
}
JmsListenerContainerFactory<?> factory = null;
String containerFactoryBeanName = jmsListener.containerFactory();

View File

@@ -17,12 +17,16 @@
package org.springframework.jms.config;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.jms.listener.MessageListenerContainer;
import org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter;
import org.springframework.jms.support.converter.MessageConverter;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.handler.invocation.InvocableHandlerMethod;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* A {@link JmsListenerEndpoint} providing the method to invoke to process
@@ -37,8 +41,6 @@ public class MethodJmsListenerEndpoint extends AbstractJmsListenerEndpoint {
private Method method;
private String responseDestination;
private JmsHandlerMethodFactory jmsHandlerMethodFactory;
/**
@@ -64,20 +66,6 @@ public class MethodJmsListenerEndpoint extends AbstractJmsListenerEndpoint {
return method;
}
/**
* Set the name of the default response destination to send response messages to.
*/
public void setResponseDestination(String responseDestination) {
this.responseDestination = responseDestination;
}
/**
* Return the name of the default response destination to send response messages to.
*/
public String getResponseDestination() {
return responseDestination;
}
/**
* Set the {@link DefaultJmsHandlerMethodFactory} to use to build the
* {@link InvocableHandlerMethod} responsible to manage the invocation
@@ -91,12 +79,12 @@ public class MethodJmsListenerEndpoint extends AbstractJmsListenerEndpoint {
protected MessagingMessageListenerAdapter createMessageListener(MessageListenerContainer container) {
Assert.state(jmsHandlerMethodFactory != null,
"Could not create message listener, message listener factory not set.");
MessagingMessageListenerAdapter messageListener = new MessagingMessageListenerAdapter();
MessagingMessageListenerAdapter messageListener = createMessageListenerInstance();
InvocableHandlerMethod invocableHandlerMethod =
jmsHandlerMethodFactory.createInvocableHandlerMethod(getBean(), getMethod());
messageListener.setHandlerMethod(invocableHandlerMethod);
String responseDestination = getResponseDestination();
if (responseDestination != null) {
String responseDestination = getDefaultResponseDestination();
if (StringUtils.hasText(responseDestination)) {
if (isQueue()) {
messageListener.setDefaultResponseQueueName(responseDestination);
}
@@ -111,6 +99,26 @@ public class MethodJmsListenerEndpoint extends AbstractJmsListenerEndpoint {
return messageListener;
}
/**
* Create an empty {@link MessagingMessageListenerAdapter} instance.
*/
protected MessagingMessageListenerAdapter createMessageListenerInstance() {
return new MessagingMessageListenerAdapter();
}
private String getDefaultResponseDestination() {
SendTo ann = AnnotationUtils.getAnnotation(getMethod(), SendTo.class);
if (ann != null) {
Object[] destinations = ann.value();
if (destinations.length != 1) {
throw new IllegalStateException("Invalid @" + SendTo.class.getSimpleName() + " annotation on '"
+ getMethod() + "' one destination must be set (got " + Arrays.toString(destinations) + ")");
}
return (String) destinations[0];
}
return null;
}
@Override
protected StringBuilder getEndpointDescription() {
return super.getEndpointDescription()

View File

@@ -51,47 +51,82 @@ public class JmsMessageHeaderAccessor extends NativeMessageHeaderAccessor {
}
@Override
public Object getReplyChannel() {
return getReplyTo();
}
/**
* Return the {@link JmsHeaders#CORRELATION_ID correlationId}.
* @see JmsHeaders#CORRELATION_ID
*/
public String getCorrelationId() {
return (String) getHeader(JmsHeaders.CORRELATION_ID);
}
/**
* Return the {@link JmsHeaders#DESTINATION destination}.
* @see JmsHeaders#DESTINATION
*/
public Destination getDestination() {
return (Destination) getHeader(JmsHeaders.DESTINATION);
}
/**
* Return the {@link JmsHeaders#DELIVERY_MODE delivery mode}.
* @see JmsHeaders#DELIVERY_MODE
*/
public Integer getDeliveryMode() {
return (Integer) getHeader(JmsHeaders.DELIVERY_MODE);
}
/**
* Return the message {@link JmsHeaders#EXPIRATION expiration}.
* @see JmsHeaders#EXPIRATION
*/
public Long getExpiration() {
return (Long) getHeader(JmsHeaders.EXPIRATION);
}
/**
* Return the {@link JmsHeaders#MESSAGE_ID message id}.
* @see JmsHeaders#MESSAGE_ID
*/
public String getMessageId() {
return (String) getHeader(JmsHeaders.MESSAGE_ID);
}
/**
* Return the {@link JmsHeaders#PRIORITY}.
* @see JmsHeaders#PRIORITY
*/
public Integer getPriority() {
return (Integer) getHeader(JmsHeaders.PRIORITY);
}
/**
* Return the {@link JmsHeaders#REPLY_TO reply to}.
* @see JmsHeaders#REPLY_TO
*/
public Destination getReplyTo() {
return (Destination) getHeader(JmsHeaders.REPLY_TO);
}
/**
* Return the {@link JmsHeaders#REDELIVERED redelivered} flag.
* @see JmsHeaders#REDELIVERED
*/
public Boolean getRedelivered() {
return (Boolean) getHeader(JmsHeaders.REDELIVERED);
}
/**
* Return the {@link JmsHeaders#TYPE type}.
* @see JmsHeaders#TYPE
*/
public String getType() {
return (String) getHeader(JmsHeaders.TYPE);
}
/**
* Return the {@link JmsHeaders#TIMESTAMP timestamp}.
* @see JmsHeaders#TIMESTAMP
*/
public Long getTimestamp() {
return (Long) getHeader(JmsHeaders.TIMESTAMP);
}