Skip to main content

Payload value must not be empty

· 3 min read

背景

生产环境rabbitmq遇到错误:Payload value must not be empty

Caused by: org.springframework.messaging.handler.annotation.support.MethodArgumentNotValidException: Could not resolve method parameter at index 0 in public void com.xxxx.consume(java.lang.String,org.springframework.amqp.core.Message,com.rabbitmq.client.Channel) throws java.lang.Exception: 1 error(s): [Error in object 'content': codes []; arguments []; default message [Payload value must not be empty]] 
at org.springframework.messaging.handler.annotation.support.PayloadMethodArgumentResolver.resolveArgument(PayloadMethodArgumentResolver.java:122)
at org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:117)
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:147)
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:115)
at org.springframework.amqp.rabbit.listener.adapter.HandlerAdapter.invoke(HandlerAdapter.java:75)
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:261)

解决方式

添加注解@Payload

    @RabbitListener(queues = "queue")
public void consume( @Payload(required = false) String content, Message message, Channel channel) throws Exception { // 将@Payload 塞到 content 字段
...
}

查看源码

扒了一下代码查看原因: 路径

  • org\springframework\messaging\handler\annotation\support\PayloadMethodArgumentResolver.java
	public Object resolveArgument(MethodParameter parameter, Message<?> message) throws Exception {
Payload ann = parameter.getParameterAnnotation(Payload.class);
if (ann != null && StringUtils.hasText(ann.expression())) {
throw new IllegalStateException("@Payload SpEL expressions not supported by this resolver");
}

Object payload = message.getPayload();
if (isEmptyPayload(payload)) { // 条件1
if (ann == null || ann.required()) { // 条件2
String paramName = getParameterName(parameter);
BindingResult bindingResult = new BeanPropertyBindingResult(payload, paramName);
bindingResult.addError(new ObjectError(paramName, "Payload value must not be empty")); // 在这里会校验空
throw new MethodArgumentNotValidException(message, parameter, bindingResult);
}
else {
return null;
}
}
}
  • 条件1 : payload 是空
  • 条件2 : 没有@Payload 注解或者 @Payload(required = ture)

原因: 满足条件1和条件2就会抛出异常

默认不加注解的时候会满足条件1和2 , 所以解决方案: 添加注解@Payload

    @RabbitListener(queues = "queue")
public void consume( @Payload(required = false) String content, Message message, Channel channel) throws Exception { // 将@Payload 塞到 content 字段
...
}

堆栈

resolveArgument:111, PayloadMethodArgumentResolver (org.springframework.messaging.handler.annotation.support)
resolveArgument:117, HandlerMethodArgumentResolverComposite (org.springframework.messaging.handler.invocation)
getMethodArgumentValues:147, InvocableHandlerMethod (org.springframework.messaging.handler.invocation)
invoke:115, InvocableHandlerMethod (org.springframework.messaging.handler.invocation)
invoke:75, HandlerAdapter (org.springframework.amqp.rabbit.listener.adapter)
invokeHandler:261, MessagingMessageListenerAdapter (org.springframework.amqp.rabbit.listener.adapter)
invokeHandlerAndProcessResult:207, MessagingMessageListenerAdapter (org.springframework.amqp.rabbit.listener.adapter)
onMessage:146, MessagingMessageListenerAdapter (org.springframework.amqp.rabbit.listener.adapter)
doInvokeListener:1665, AbstractMessageListenerContainer (org.springframework.amqp.rabbit.listener)
actualInvokeListener:1584, AbstractMessageListenerContainer (org.springframework.amqp.rabbit.listener)
invokeListener:-1, 1393414871 (org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer$$Lambda$1549)
invoke0:-1, NativeMethodAccessorImpl (jdk.internal.reflect)
invoke:62, NativeMethodAccessorImpl (jdk.internal.reflect)
invoke:43, DelegatingMethodAccessorImpl (jdk.internal.reflect)
invoke:566, Method (java.lang.reflect)
invokeJoinpointUsingReflection:344, AopUtils (org.springframework.aop.support)
invokeJoinpoint:198, ReflectiveMethodInvocation (org.springframework.aop.framework)
proceed:163, ReflectiveMethodInvocation (org.springframework.aop.framework)
doWithRetry:93, RetryOperationsInterceptor$1 (org.springframework.retry.interceptor)
doExecute:329, RetryTemplate (org.springframework.retry.support)
execute:225, RetryTemplate (org.springframework.retry.support)
invoke:116, RetryOperationsInterceptor (org.springframework.retry.interceptor)
proceed:186, ReflectiveMethodInvocation (org.springframework.aop.framework)
invoke:215, JdkDynamicAopProxy (org.springframework.aop.framework)
invokeListener:-1, $Proxy247 (org.springframework.amqp.rabbit.listener)
invokeListener:1572, AbstractMessageListenerContainer (org.springframework.amqp.rabbit.listener)
doExecuteListener:1563, AbstractMessageListenerContainer (org.springframework.amqp.rabbit.listener)
executeListener:1507, AbstractMessageListenerContainer (org.springframework.amqp.rabbit.listener)
doReceiveAndExecute:967, SimpleMessageListenerContainer (org.springframework.amqp.rabbit.listener)
receiveAndExecute:914, SimpleMessageListenerContainer (org.springframework.amqp.rabbit.listener)
access$1600:83, SimpleMessageListenerContainer (org.springframework.amqp.rabbit.listener)
mainLoop:1291, SimpleMessageListenerContainer$AsyncMessageProcessingConsumer (org.springframework.amqp.rabbit.listener)
run:1197, SimpleMessageListenerContainer$AsyncMessageProcessingConsumer (org.springframework.amqp.rabbit.listener)
run:834, Thread (java.lang)