Skip to content

Commit

Permalink
GH-2890: Fix MessagingMessageListenerAdapter for batch in Kotlin
Browse files Browse the repository at this point in the history
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

**Auto-cherry-pick to `3.1.x`**
  • Loading branch information
artembilan committed Nov 11, 2024
1 parent 0c72649 commit a2ac767
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.util.Assert;
import org.springframework.util.TypeUtils;

import com.rabbitmq.client.Channel;

Expand Down Expand Up @@ -456,17 +457,18 @@ private Type extractGenericParameterTypFromMethodParameter(MethodParameter metho
if (parameterizedType.getRawType().equals(Message.class)) {
genericParameterType = ((ParameterizedType) genericParameterType).getActualTypeArguments()[0];
}
else if (this.isBatch
&& ((parameterizedType.getRawType().equals(List.class)
|| parameterizedType.getRawType().equals(Collection.class))
&& parameterizedType.getActualTypeArguments().length == 1)) {
else if (this.isBatch &&
(parameterizedType.getRawType().equals(List.class) ||
(parameterizedType.getRawType().equals(Collection.class) &&
parameterizedType.getActualTypeArguments().length == 1))) {

this.isCollection = true;
Type paramType = parameterizedType.getActualTypeArguments()[0];
boolean messageHasGeneric = paramType instanceof ParameterizedType pType
&& pType.getRawType().equals(Message.class);
this.isMessageList = paramType.equals(Message.class) || messageHasGeneric;
this.isAmqpMessageList = paramType.equals(org.springframework.amqp.core.Message.class);
this.isMessageList = TypeUtils.isAssignable(paramType, Message.class) || messageHasGeneric;
this.isAmqpMessageList =
TypeUtils.isAssignable(paramType, org.springframework.amqp.core.Message.class);
if (messageHasGeneric) {
genericParameterType = ((ParameterizedType) paramType).getActualTypeArguments()[0];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ package org.springframework.amqp.rabbit.annotation
import assertk.assertThat
import assertk.assertions.containsOnly
import assertk.assertions.isEqualTo
import assertk.assertions.isInstanceOf
import assertk.assertions.isTrue
import org.junit.jupiter.api.Test
import org.springframework.amqp.core.AcknowledgeMode
import org.springframework.amqp.core.Message
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory
import org.springframework.amqp.rabbit.core.RabbitTemplate
Expand Down Expand Up @@ -77,7 +79,8 @@ class EnableRabbitKotlinTests {
template.convertAndSend("kotlinBatchQueue", "test1")
template.convertAndSend("kotlinBatchQueue", "test2")
assertThat(this.config.batchReceived.await(10, TimeUnit.SECONDS)).isTrue()
assertThat(this.config.batch).containsOnly("test1", "test2")
assertThat(this.config.batch[0]).isInstanceOf(Message::class.java)
assertThat(this.config.batch.map { m -> String(m.body) }).containsOnly("test1", "test2")
}

@Test
Expand All @@ -100,11 +103,11 @@ class EnableRabbitKotlinTests {

val batchReceived = CountDownLatch(1)

lateinit var batch: List<String>
lateinit var batch: List<Message>

@RabbitListener(id = "batch", queues = ["kotlinBatchQueue"],
containerFactory = "batchRabbitListenerContainerFactory")
suspend fun receiveBatch(messages: List<String>) {
suspend fun receiveBatch(messages: List<Message>) {
batch = messages
batchReceived.countDown()
}
Expand Down

0 comments on commit a2ac767

Please sign in to comment.