From f6d46f69b36cdbc3a0a3203518273b98cace9812 Mon Sep 17 00:00:00 2001 From: Gary Russell Date: Tue, 3 Oct 2023 10:58:32 -0400 Subject: [PATCH] GH-2532: Ignore Kotlin Continuation Parameter Resolves https://github.com/spring-projects/spring-amqp/issues/2532 The presence of the parameter caused the inferred type to be set to `null` due to ambiguous parameters present. It must be considered an ineligible type when inferring conversion types. **cherry-pick to 3.0.x (#2533), 2.4.x (#2534)** --- .../MessagingMessageListenerAdapter.java | 3 ++- .../annotation/EnableRabbitKotlinTests.kt | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/listener/adapter/MessagingMessageListenerAdapter.java b/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/listener/adapter/MessagingMessageListenerAdapter.java index 473d2b5bd3..60a67e3075 100644 --- a/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/listener/adapter/MessagingMessageListenerAdapter.java +++ b/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/listener/adapter/MessagingMessageListenerAdapter.java @@ -447,7 +447,8 @@ private boolean isEligibleParameter(MethodParameter methodParameter) { Type parameterType = methodParameter.getGenericParameterType(); if (parameterType.equals(Channel.class) || parameterType.equals(MessageProperties.class) - || parameterType.equals(org.springframework.amqp.core.Message.class)) { + || parameterType.equals(org.springframework.amqp.core.Message.class) + || parameterType.getTypeName().startsWith("kotlin.coroutines.Continuation")) { return false; } if (parameterType instanceof ParameterizedType parameterizedType && diff --git a/spring-rabbit/src/test/kotlin/org/springframework/amqp/rabbit/annotation/EnableRabbitKotlinTests.kt b/spring-rabbit/src/test/kotlin/org/springframework/amqp/rabbit/annotation/EnableRabbitKotlinTests.kt index 2fc695faf2..8eadd20341 100644 --- a/spring-rabbit/src/test/kotlin/org/springframework/amqp/rabbit/annotation/EnableRabbitKotlinTests.kt +++ b/spring-rabbit/src/test/kotlin/org/springframework/amqp/rabbit/annotation/EnableRabbitKotlinTests.kt @@ -21,12 +21,15 @@ import assertk.assertions.isEqualTo import assertk.assertions.isTrue import org.junit.jupiter.api.Test import org.springframework.amqp.core.AcknowledgeMode +import org.springframework.amqp.core.MessageListener import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory import org.springframework.amqp.rabbit.connection.CachingConnectionFactory import org.springframework.amqp.rabbit.core.RabbitTemplate import org.springframework.amqp.rabbit.junit.RabbitAvailable import org.springframework.amqp.rabbit.junit.RabbitAvailableCondition +import org.springframework.amqp.rabbit.listener.RabbitListenerEndpointRegistry import org.springframework.amqp.rabbit.listener.api.RabbitListenerErrorHandler +import org.springframework.amqp.utils.test.TestUtils import org.springframework.aop.framework.ProxyFactory import org.springframework.beans.BeansException import org.springframework.beans.factory.annotation.Autowired @@ -57,17 +60,20 @@ class EnableRabbitKotlinTests { private lateinit var config: Config @Test - fun `send and wait for consume`() { + fun `send and wait for consume`(@Autowired registry: RabbitListenerEndpointRegistry) { val template = RabbitTemplate(this.config.cf()) template.convertAndSend("kotlinQueue", "test") - assertThat(this.config.latch.await(10, TimeUnit.SECONDS)).isTrue(); + assertThat(this.config.latch.await(10, TimeUnit.SECONDS)).isTrue() + val listener = registry.getListenerContainer("single").messageListener + assertThat(TestUtils.getPropertyValue(listener, "messagingMessageConverter.inferredArgumentType").toString()) + .isEqualTo("class java.lang.String") } @Test fun `send and wait for consume with EH`() { val template = RabbitTemplate(this.config.cf()) template.convertAndSend("kotlinQueue1", "test") - assertThat(this.config.ehLatch.await(10, TimeUnit.SECONDS)).isTrue(); + assertThat(this.config.ehLatch.await(10, TimeUnit.SECONDS)).isTrue() val reply = template.receiveAndConvert("kotlinReplyQueue", 10_000) assertThat(reply).isEqualTo("error processed"); } @@ -78,7 +84,7 @@ class EnableRabbitKotlinTests { val latch = CountDownLatch(1) - @RabbitListener(queues = ["kotlinQueue"]) + @RabbitListener(id = "single", queues = ["kotlinQueue"]) suspend fun handle(@Suppress("UNUSED_PARAMETER") data: String) { this.latch.countDown() } @@ -121,12 +127,12 @@ class EnableRabbitKotlinTests { } - @RabbitListener(queues = ["kotlinQueue1"], errorHandler = "#{eh}") + @RabbitListener(id = "multi", queues = ["kotlinQueue1"], errorHandler = "#{eh}") @SendTo("kotlinReplyQueue") open class Multi { @RabbitHandler - suspend fun handle(@Suppress("UNUSED_PARAMETER") data: String) { + fun handle(@Suppress("UNUSED_PARAMETER") data: String) { throw RuntimeException("fail") }