Skip to content

Commit 9942e3c

Browse files
committed
GH-2890: Fix MessagingMessageListenerAdapter for batch in Kotlin
Fixes: #2890 Issue link: #2890 The Kotlin function with signature `receiveBatch(messages: List<Message>)` produced a `WildCardType` for the generic of the `List` argument. * Fix `MessagingMessageListenerAdapter` to use `TypeUtils.isAssignable()` to determine if the `Type` has a part as expected type # Conflicts: # spring-rabbit/src/main/java/org/springframework/amqp/rabbit/listener/adapter/MessagingMessageListenerAdapter.java # spring-rabbit/src/test/kotlin/org/springframework/amqp/rabbit/annotation/EnableRabbitKotlinTests.kt
1 parent ad20705 commit 9942e3c

File tree

2 files changed

+22
-19
lines changed

2 files changed

+22
-19
lines changed

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

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import java.util.List;
2525
import java.util.Optional;
2626

27+
import com.rabbitmq.client.Channel;
28+
2729
import org.springframework.amqp.core.MessageProperties;
2830
import org.springframework.amqp.rabbit.listener.api.RabbitListenerErrorHandler;
2931
import org.springframework.amqp.rabbit.support.ListenerExecutionFailedException;
@@ -43,8 +45,7 @@
4345
import org.springframework.messaging.handler.annotation.Payload;
4446
import org.springframework.messaging.support.MessageBuilder;
4547
import org.springframework.util.Assert;
46-
47-
import com.rabbitmq.client.Channel;
48+
import org.springframework.util.TypeUtils;
4849

4950
/**
5051
* A {@link org.springframework.amqp.core.MessageListener MessageListener}
@@ -240,9 +241,9 @@ private void returnOrThrow(org.springframework.amqp.core.Message amqpMessage, Ch
240241
Object payload = message == null ? null : message.getPayload();
241242
try {
242243
handleResult(new InvocationResult(new RemoteInvocationResult(throwableToReturn), null,
243-
payload == null ? Object.class : this.handlerAdapter.getReturnTypeFor(payload),
244-
this.handlerAdapter.getBean(),
245-
payload == null ? null : this.handlerAdapter.getMethodFor(payload)),
244+
payload == null ? Object.class : this.handlerAdapter.getReturnTypeFor(payload),
245+
this.handlerAdapter.getBean(),
246+
payload == null ? null : this.handlerAdapter.getMethodFor(payload)),
246247
amqpMessage, channel, message);
247248
}
248249
catch (ReplyFailureException rfe) {
@@ -405,8 +406,8 @@ private Type determineInferredType() { // NOSONAR - complexity
405406
boolean isPayload = methodParameter.hasParameterAnnotation(Payload.class);
406407
if (isHeaderOrHeaders && isPayload && MessagingMessageListenerAdapter.this.logger.isWarnEnabled()) {
407408
MessagingMessageListenerAdapter.this.logger.warn(this.method.getName()
408-
+ ": Cannot annotate a parameter with both @Header and @Payload; "
409-
+ "ignored for payload conversion");
409+
+ ": Cannot annotate a parameter with both @Header and @Payload; "
410+
+ "ignored for payload conversion");
410411
}
411412
if (isEligibleParameter(methodParameter) // NOSONAR
412413
&& (!isHeaderOrHeaders || isPayload) && !(isHeaderOrHeaders && isPayload)) {
@@ -416,7 +417,7 @@ private Type determineInferredType() { // NOSONAR - complexity
416417
if (this.isBatch && !this.isCollection) {
417418
throw new IllegalStateException(
418419
"Mis-configuration; a batch listener must consume a List<?> or "
419-
+ "Collection<?> for method: " + this.method);
420+
+ "Collection<?> for method: " + this.method);
420421
}
421422

422423
}
@@ -467,15 +468,16 @@ private Type extractGenericParameterTypFromMethodParameter(MethodParameter metho
467468
}
468469
else if (this.isBatch
469470
&& ((parameterizedType.getRawType().equals(List.class)
470-
|| parameterizedType.getRawType().equals(Collection.class))
471-
&& parameterizedType.getActualTypeArguments().length == 1)) {
471+
|| parameterizedType.getRawType().equals(Collection.class))
472+
&& parameterizedType.getActualTypeArguments().length == 1)) {
472473

473474
this.isCollection = true;
474475
Type paramType = parameterizedType.getActualTypeArguments()[0];
475476
boolean messageHasGeneric = paramType instanceof ParameterizedType pType
476477
&& pType.getRawType().equals(Message.class);
477-
this.isMessageList = paramType.equals(Message.class) || messageHasGeneric;
478-
this.isAmqpMessageList = paramType.equals(org.springframework.amqp.core.Message.class);
478+
this.isMessageList = TypeUtils.isAssignable(paramType, Message.class) || messageHasGeneric;
479+
this.isAmqpMessageList =
480+
TypeUtils.isAssignable(paramType, org.springframework.amqp.core.Message.class);
479481
if (messageHasGeneric) {
480482
genericParameterType = ((ParameterizedType) paramType).getActualTypeArguments()[0];
481483
}
@@ -487,6 +489,7 @@ else if (this.isBatch
487489
}
488490
return genericParameterType;
489491
}
492+
490493
}
491494

492495
}

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ class EnableRabbitKotlinTests {
6666
assertThat(result).isEqualTo("TEST")
6767
val listener = registry.getListenerContainer("single").messageListener
6868
assertThat(TestUtils.getPropertyValue(listener, "messagingMessageConverter.inferredArgumentType").toString())
69-
.isEqualTo("class java.lang.String")
69+
.isEqualTo("class java.lang.String")
7070
}
7171

7272
@Test
@@ -83,17 +83,17 @@ class EnableRabbitKotlinTests {
8383
class Config {
8484

8585
@RabbitListener(id = "single", queues = ["kotlinQueue"])
86-
suspend fun handle(@Suppress("UNUSED_PARAMETER") data: String) : String? {
86+
suspend fun handle(@Suppress("UNUSED_PARAMETER") data: String): String? {
8787
return data.uppercase()
8888
}
8989

9090
@Bean
9191
fun rabbitListenerContainerFactory(cf: CachingConnectionFactory) =
92-
SimpleRabbitListenerContainerFactory().also {
93-
it.setAcknowledgeMode(AcknowledgeMode.MANUAL)
94-
it.setReceiveTimeout(10)
95-
it.setConnectionFactory(cf)
96-
}
92+
SimpleRabbitListenerContainerFactory().also {
93+
it.setAcknowledgeMode(AcknowledgeMode.MANUAL)
94+
it.setReceiveTimeout(10)
95+
it.setConnectionFactory(cf)
96+
}
9797

9898
@Bean
9999
fun cf() = CachingConnectionFactory(RabbitAvailableCondition.getBrokerRunning().connectionFactory)

0 commit comments

Comments
 (0)