Skip to content

Commit 1d669cd

Browse files
artembilangaryrussell
authored andcommitted
Fix missing class-level @SendTo for CGLib proxy
Similar to spring-projects/spring-kafka#1631 The `DelegatingInvocableHandler` doesn't take into account a possible proxy nature of the listener class. * Fix `DelegatingInvocableHandler.setupReplyTo()` to deal with user class which is origin for possible CGLib proxy for the proper annotations search **Cherry-pick to 2.2.x**
1 parent e2414fa commit 1d669cd

File tree

2 files changed

+32
-7
lines changed

2 files changed

+32
-7
lines changed

spring-rabbit/src/main/java/org/springframework/amqp/rabbit/listener/adapter/DelegatingInvocableHandler.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2015-2019 the original author or authors.
2+
* Copyright 2015-2020 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.
@@ -164,8 +164,9 @@ private void setupReplyTo(InvocableHandlerMethod handler) {
164164
replyTo = extractSendTo(method.toString(), ann);
165165
}
166166
if (replyTo == null) {
167-
SendTo ann = AnnotationUtils.getAnnotation(this.bean.getClass(), SendTo.class);
168-
replyTo = extractSendTo(getBean().getClass().getSimpleName(), ann);
167+
Class<?> beanType = handler.getBeanType();
168+
SendTo ann = AnnotationUtils.getAnnotation(beanType, SendTo.class);
169+
replyTo = extractSendTo(beanType.getSimpleName(), ann);
169170
}
170171
if (replyTo != null) {
171172
this.handlerSendTo.put(handler, PARSER.parseExpression(replyTo, PARSER_CONTEXT));

spring-rabbit/src/test/kotlin/org/springframework/amqp/rabbit/annotation/EnableRabbitKotlinTests.kt

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2018-2019 the original author or authors.
2+
* Copyright 2018-2020 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.
@@ -17,6 +17,7 @@
1717
package org.springframework.amqp.rabbit.annotation
1818

1919
import assertk.assertThat
20+
import assertk.assertions.isEqualTo
2021
import assertk.assertions.isTrue
2122
import org.junit.jupiter.api.Test
2223
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory
@@ -25,9 +26,13 @@ import org.springframework.amqp.rabbit.core.RabbitTemplate
2526
import org.springframework.amqp.rabbit.junit.RabbitAvailable
2627
import org.springframework.amqp.rabbit.junit.RabbitAvailableCondition
2728
import org.springframework.amqp.rabbit.listener.api.RabbitListenerErrorHandler
29+
import org.springframework.aop.framework.ProxyFactory
30+
import org.springframework.beans.BeansException
2831
import org.springframework.beans.factory.annotation.Autowired
32+
import org.springframework.beans.factory.config.BeanPostProcessor
2933
import org.springframework.context.annotation.Bean
3034
import org.springframework.context.annotation.Configuration
35+
import org.springframework.messaging.handler.annotation.SendTo
3136
import org.springframework.test.annotation.DirtiesContext
3237
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig
3338
import java.util.concurrent.CountDownLatch
@@ -37,12 +42,13 @@ import java.util.concurrent.TimeUnit
3742
* Kotlin Annotated listener tests.
3843
*
3944
* @author Gary Russell
45+
* @author Artem Bilan
4046
*
4147
* @since 2.1
4248
*
4349
*/
4450
@SpringJUnitConfig
45-
@RabbitAvailable(queues = ["kotlinQueue", "kotlinQueue1"])
51+
@RabbitAvailable(queues = ["kotlinQueue", "kotlinQueue1", "kotlinReplyQueue"])
4652
@DirtiesContext
4753
class EnableRabbitKotlinTests {
4854

@@ -61,6 +67,8 @@ class EnableRabbitKotlinTests {
6167
val template = RabbitTemplate(this.config.cf())
6268
template.convertAndSend("kotlinQueue1", "test")
6369
assertThat(this.config.ehLatch.await(10, TimeUnit.SECONDS)).isTrue();
70+
val reply = template.receiveAndConvert("kotlinReplyQueue")
71+
assertThat(reply).isEqualTo("error processed");
6472
}
6573

6674
@Configuration
@@ -92,18 +100,34 @@ class EnableRabbitKotlinTests {
92100
return Multi()
93101
}
94102

103+
@Bean
104+
fun proxyListenerPostProcessor(): BeanPostProcessor? {
105+
return object : BeanPostProcessor {
106+
@Throws(BeansException::class)
107+
override fun postProcessBeforeInitialization(bean: Any, beanName: String): Any {
108+
if (bean is Multi) {
109+
val proxyFactory = ProxyFactory(bean)
110+
proxyFactory.isProxyTargetClass = true
111+
return proxyFactory.proxy
112+
}
113+
return bean
114+
}
115+
}
116+
}
117+
95118
val ehLatch = CountDownLatch(1)
96119

97120
@Bean
98121
fun eh() = RabbitListenerErrorHandler { _, _, _ ->
99122
this.ehLatch.countDown()
100-
null
123+
"error processed"
101124
}
102125

103126
}
104127

105128
@RabbitListener(queues = ["kotlinQueue1"], errorHandler = "#{eh}")
106-
class Multi {
129+
@SendTo("kotlinReplyQueue")
130+
open class Multi {
107131

108132
@RabbitHandler
109133
fun handle(@Suppress("UNUSED_PARAMETER") data: String) {

0 commit comments

Comments
 (0)