Skip to content

Commit f98a6c6

Browse files
committed
Support expression in @sendto
The attributes of @JmsListener allows to specify the reference to a key in the Environment but @sendto did not. This commit fixes this inconsistency so that response destinations are now also externally configurable. Issue: SPR-12899
1 parent 2c7d2d3 commit f98a6c6

File tree

4 files changed

+42
-5
lines changed

4 files changed

+42
-5
lines changed

spring-jms/src/main/java/org/springframework/jms/annotation/JmsListenerAnnotationBeanPostProcessor.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -247,6 +247,7 @@ protected void processJmsListener(JmsListener jmsListener, Method method, Object
247247
endpoint.setBean(bean);
248248
endpoint.setMethod(method);
249249
endpoint.setMessageHandlerMethodFactory(this.messageHandlerMethodFactory);
250+
endpoint.setBeanFactory(this.beanFactory);
250251
endpoint.setId(getEndpointId(jmsListener));
251252
endpoint.setDestination(resolve(jmsListener.destination()));
252253
if (StringUtils.hasText(jmsListener.selector())) {

spring-jms/src/main/java/org/springframework/jms/config/MethodJmsListenerEndpoint.java

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121

2222
import org.springframework.aop.framework.AopProxyUtils;
2323
import org.springframework.aop.support.AopUtils;
24+
import org.springframework.beans.factory.BeanFactory;
25+
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
2426
import org.springframework.core.annotation.AnnotationUtils;
2527
import org.springframework.jms.listener.MessageListenerContainer;
2628
import org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter;
@@ -46,6 +48,8 @@ public class MethodJmsListenerEndpoint extends AbstractJmsListenerEndpoint {
4648

4749
private MessageHandlerMethodFactory messageHandlerMethodFactory;
4850

51+
private BeanFactory beanFactory;
52+
4953

5054
/**
5155
* Set the object instance that should manage this endpoint.
@@ -78,6 +82,12 @@ public void setMessageHandlerMethodFactory(MessageHandlerMethodFactory messageHa
7882
this.messageHandlerMethodFactory = messageHandlerMethodFactory;
7983
}
8084

85+
/**
86+
* Set the {@link BeanFactory} to use to resolve expressions (can be null).
87+
*/
88+
public void setBeanFactory(BeanFactory beanFactory) {
89+
this.beanFactory = beanFactory;
90+
}
8191

8292
@Override
8393
protected MessagingMessageListenerAdapter createMessageListener(MessageListenerContainer container) {
@@ -110,7 +120,10 @@ protected MessagingMessageListenerAdapter createMessageListenerInstance() {
110120
return new MessagingMessageListenerAdapter();
111121
}
112122

113-
private String getDefaultResponseDestination() {
123+
/**
124+
* Return the default response destination, if any.
125+
*/
126+
protected String getDefaultResponseDestination() {
114127
Method specificMethod = getMostSpecificMethod();
115128
SendTo ann = AnnotationUtils.getAnnotation(specificMethod, SendTo.class);
116129
if (ann != null) {
@@ -119,11 +132,23 @@ private String getDefaultResponseDestination() {
119132
throw new IllegalStateException("Invalid @" + SendTo.class.getSimpleName() + " annotation on '"
120133
+ specificMethod + "' one destination must be set (got " + Arrays.toString(destinations) + ")");
121134
}
122-
return (String) destinations[0];
135+
return resolve((String) destinations[0]);
123136
}
124137
return null;
125138
}
126139

140+
/**
141+
* Resolve the specified value if possible.
142+
* @see ConfigurableBeanFactory#resolveEmbeddedValue
143+
*/
144+
private String resolve(String value) {
145+
if (this.beanFactory instanceof ConfigurableBeanFactory) {
146+
return ((ConfigurableBeanFactory) this.beanFactory).resolveEmbeddedValue(value);
147+
}
148+
return value;
149+
}
150+
151+
127152
private Method getMostSpecificMethod() {
128153
if (AopUtils.isAopProxy(this.bean)) {
129154
Class<?> target = AopProxyUtils.ultimateTargetClass(this.bean);

spring-jms/src/test/java/org/springframework/jms/annotation/AbstractJmsAnnotationDrivenTests.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.jms.annotation;
1818

19+
import java.lang.reflect.Method;
1920
import javax.jms.JMSException;
2021
import javax.jms.Session;
2122

@@ -32,7 +33,9 @@
3233
import org.springframework.jms.config.SimpleJmsListenerEndpoint;
3334
import org.springframework.jms.listener.SimpleMessageListenerContainer;
3435
import org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter;
36+
import org.springframework.messaging.handler.annotation.SendTo;
3537
import org.springframework.stereotype.Component;
38+
import org.springframework.util.ReflectionUtils;
3639
import org.springframework.validation.Errors;
3740
import org.springframework.validation.Validator;
3841
import org.springframework.validation.annotation.Validated;
@@ -111,13 +114,19 @@ public void testFullConfiguration(ApplicationContext context) {
111114
assertEquals("mySelector", endpoint.getSelector());
112115
assertEquals("mySubscription", endpoint.getSubscription());
113116
assertEquals("1-10", endpoint.getConcurrency());
117+
118+
Method m = ReflectionUtils.findMethod(endpoint.getClass(), "getDefaultResponseDestination");
119+
ReflectionUtils.makeAccessible(m);
120+
Object destination = ReflectionUtils.invokeMethod(m, endpoint);
121+
assertEquals("queueOut", destination);
114122
}
115123

116124
@Component
117125
static class FullBean {
118126

119127
@JmsListener(id = "listener1", containerFactory = "simpleFactory", destination = "queueIn",
120128
selector = "mySelector", subscription = "mySubscription", concurrency = "1-10")
129+
@SendTo("queueOut")
121130
public String fullHandle(String msg) {
122131
return "reply";
123132
}
@@ -129,6 +138,7 @@ static class FullConfigurableBean {
129138
@JmsListener(id = "${jms.listener.id}", containerFactory = "${jms.listener.containerFactory}",
130139
destination = "${jms.listener.destination}", selector = "${jms.listener.selector}",
131140
subscription = "${jms.listener.subscription}", concurrency = "${jms.listener.concurrency}")
141+
@SendTo("${jms.listener.sendTo}")
132142
public String fullHandle(String msg) {
133143
return "reply";
134144
}

spring-jms/src/test/resources/org/springframework/jms/annotation/jms-listener.properties

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ jms.listener.containerFactory=simpleFactory
33
jms.listener.destination=queueIn
44
jms.listener.selector=mySelector
55
jms.listener.subscription=mySubscription
6-
jms.listener.concurrency=1-10
6+
jms.listener.concurrency=1-10
7+
jms.listener.sendTo=queueOut

0 commit comments

Comments
 (0)