Skip to content

Payload value must not be empty

Posted on:June 6, 2023 at 09:48 AM

背景

生产环境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 字段
        ...
    }

查看源码

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

	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和条件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)