Skip to content

Commit 7b2f218

Browse files
artembilanspring-builds
authored andcommitted
GH-2638: Fix for Kotlin suspend returns
Fixes: #2638 The `AbstractAdaptableMessageListener.asyncSuccess()` assumes only `Mono` & `CompletableFuture` return types. With Kotlin `suspend` it is just plain `Object`. * Fix `AbstractAdaptableMessageListener.asyncSuccess()` to check if `returnType` is not simple `Object.class` before going deep for its generic actual argument. (cherry picked from commit 08ead3b)
1 parent 33d489b commit 7b2f218

File tree

2 files changed

+9
-10
lines changed

2 files changed

+9
-10
lines changed

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2023 the original author or authors.
2+
* Copyright 2014-2024 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.
@@ -418,9 +418,10 @@ private void asyncSuccess(InvocationResult resultArg, Message request, Channel c
418418
}
419419
}
420420
else {
421-
// We only get here with Mono<?> and ListenableFuture<?> which have exactly one type argument
422421
Type returnType = resultArg.getReturnType();
423-
if (returnType != null) {
422+
// We only get here with Mono<?> and CompletableFuture<?> which have exactly one type argument
423+
// Otherwise it might be Kotlin suspend function
424+
if (returnType != null && !Object.class.getName().equals(returnType.getTypeName())) {
424425
Type[] actualTypeArguments = ((ParameterizedType) returnType).getActualTypeArguments();
425426
if (actualTypeArguments.length > 0) {
426427
returnType = actualTypeArguments[0]; // NOSONAR

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

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import assertk.assertions.isEqualTo
2121
import assertk.assertions.isTrue
2222
import org.junit.jupiter.api.Test
2323
import org.springframework.amqp.core.AcknowledgeMode
24-
import org.springframework.amqp.core.MessageListener
2524
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory
2625
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory
2726
import org.springframework.amqp.rabbit.core.RabbitTemplate
@@ -62,8 +61,9 @@ class EnableRabbitKotlinTests {
6261
@Test
6362
fun `send and wait for consume`(@Autowired registry: RabbitListenerEndpointRegistry) {
6463
val template = RabbitTemplate(this.config.cf())
65-
template.convertAndSend("kotlinQueue", "test")
66-
assertThat(this.config.latch.await(10, TimeUnit.SECONDS)).isTrue()
64+
template.setReplyTimeout(10_000)
65+
val result = template.convertSendAndReceive("kotlinQueue", "test")
66+
assertThat(result).isEqualTo("TEST")
6767
val listener = registry.getListenerContainer("single").messageListener
6868
assertThat(TestUtils.getPropertyValue(listener, "messagingMessageConverter.inferredArgumentType").toString())
6969
.isEqualTo("class java.lang.String")
@@ -82,11 +82,9 @@ class EnableRabbitKotlinTests {
8282
@EnableRabbit
8383
class Config {
8484

85-
val latch = CountDownLatch(1)
86-
8785
@RabbitListener(id = "single", queues = ["kotlinQueue"])
88-
suspend fun handle(@Suppress("UNUSED_PARAMETER") data: String) {
89-
this.latch.countDown()
86+
suspend fun handle(@Suppress("UNUSED_PARAMETER") data: String) : String? {
87+
return data.uppercase()
9088
}
9189

9290
@Bean

0 commit comments

Comments
 (0)