【问题标题】:Kotlin based Spring RabbitListener produces endlessloop trying to send back `kotlin.Unit`基于 Kotlin 的 Spring RabbitListener 产生无限循环,试图发回 `kotlin.Unit`
【发布时间】:2021-04-16 14:56:45
【问题描述】:

我们在 Kotlin 中实现了一个 RabbitListener。该方法返回 Unit,所以我不希望 Spring 发送结果,但我们收到以下错误消息。看起来 Spring 尝试将 Unit 解释为结果并返回一个兔子消息:

2021-04-16 16:39:21 
msg="Execution of Rabbit message listener failed." thread="org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#0-2" level=WARN logger="org.springframework.amqp.rabbit.listener.ConditionalRejectingErrorHandler" exception="org.springframework.amqp.rabbit.support.ListenerExecutionFailedException: Listener threw exception
    at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.wrapToListenerExecutionFailedExceptionIfNeeded(AbstractMessageListenerContainer.java:1746)
    at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:1636)
    at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.actualInvokeListener(AbstractMessageListenerContainer.java:1551)
    at jdk.internal.reflect.GeneratedMethodAccessor64.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.base/java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at brave.spring.rabbit.TracingRabbitListenerAdvice.invoke(TracingRabbitListenerAdvice.java:108)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215)
    at org.springframework.amqp.rabbit.listener.$Proxy146.invokeListener(Unknown Source)
    at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:1539)
    at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:1530)
    at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:1474)
    at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:967)
    at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:913)
    at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$1600(SimpleMessageListenerContainer.java:83)
    at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.mainLoop(SimpleMessageListenerContainer.java:1288)
    at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1194)
    at java.base/java.lang.Thread.run(Unknown Source)
Caused by: org.springframework.amqp.rabbit.listener.adapter.ReplyFailureException: Failed to send reply with payload 'InvocationResult [returnValue=kotlin.Unit, returnType=class java.lang.Object, bean=com.xxx.EventHandler@4aaf6902, method=public java.lang.Object com.xxx.EventHandler.receiveMessage(org.springframework.amqp.core.Message)]'
    at org.springframework.amqp.rabbit.listener.adapter.AbstractAdaptableMessageListener.doHandleResult(AbstractAdaptableMessageListener.java:476)
    at org.springframework.amqp.rabbit.listener.adapter.AbstractAdaptableMessageListener.handleResult(AbstractAdaptableMessageListener.java:400)
    at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandlerAndProcessResult(MessagingMessageListenerAdapter.java:152)
    at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:135)
    at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:1632)
    ... 20 common frames omitted
Caused by: java.lang.IllegalArgumentException: SimpleMessageConverter only supports String, byte[] and Serializable payloads, received: kotlin.Unit
    at org.springframework.amqp.support.converter.SimpleMessageConverter.createMessage(SimpleMessageConverter.java:164)
    at org.springframework.amqp.support.converter.AbstractMessageConverter.createMessage(AbstractMessageConverter.java:88)
    at org.springframework.amqp.support.converter.AbstractMessageConverter.toMessage(AbstractMessageConverter.java:70)
    at org.springframework.amqp.rabbit.listener.adapter.AbstractAdaptableMessageListener.convert(AbstractAdaptableMessageListener.java:519)
    at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.buildMessage(MessagingMessageListenerAdapter.java:257)
    at org.springframework.amqp.rabbit.listener.adapter.AbstractAdaptableMessageListener.doHandleResult(AbstractAdaptableMessageListener.java:464)
    ... 24 common frames omitted
" time="2021-04-16 14:39:21,726"

这里是 RabbitLister 的简化版本:

@Component
class EventHandler {

    @RabbitListener(queues = ["someQueue"])
    fun receiveMessage(message: Message): Unit {
        log.debug("Received message")
    }
}

我们使用 Spring Boot 2.4.4、Spring Rabbit 2.3.6 和 Spring Framework 5.3.6

调试问题,得到如下结果:

【问题讨论】:

  • 就这样吧:fun receiveMessage(message: Message) {!明确指定Unit 有什么意义?
  • 即使: Unit 我在 IntelliJ 中看到 void 作为返回类型。
  • 我添加了版本
  • 在这种情况下,Kotlin 版本比 Spring 版本更重要。

标签: spring kotlin rabbitmq spring-rabbit


【解决方案1】:

你用的是什么版本?

这对我来说很好用(有和没有Unit 返回类型)...

@RabbitListener(queues = ["foo"])
open fun listen(data: String?): Unit {
    println(data)
}

即使使用: Unit,我也看到void 作为返回类型,null:

【讨论】:

  • 这是使用 spring-rabbit 2.3.6 和 Kotlin 1.4.32 的。
  • 我将它调试到抛出异常的地步,并将结果添加到我的问题中。我也得到了返回类型void,但返回值是kotlin.Unit
猜你喜欢
  • 2015-12-25
  • 2011-06-26
  • 1970-01-01
  • 2021-12-19
  • 2023-01-03
  • 1970-01-01
  • 1970-01-01
  • 2015-05-28
  • 2021-03-23
相关资源
最近更新 更多