From 39c9c44caf0982234d6835cc4eecfecd8c609b9b Mon Sep 17 00:00:00 2001 From: Gary Russell Date: Wed, 25 Nov 2020 13:08:59 -0500 Subject: [PATCH] GH-1269: @RabbitListener: Allow other Annotations Resolves https://github.com/spring-projects/spring-amqp/issues/1269 Previously, a parameter annotated with a "foreign" annoation (e.g. `@Validated`) would not be considered as an eligible payload conversion target; it must also have been annotated with `@Payload`. - remove the check for zero annotations - add a check that the method is not annotated with both `@Payload` and `@Header` - ignore if it does, with a warn log, to be consistent with previous behavior. - in a future release we might consider this to be fatal. **cherry-pick to 2.2.x** --- .../MessagingMessageListenerAdapter.java | 16 +++++++++++--- .../EnableRabbitIntegrationTests.java | 21 ++++++++++++++++--- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/listener/adapter/MessagingMessageListenerAdapter.java b/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/listener/adapter/MessagingMessageListenerAdapter.java index 15dfc40c..a614715e 100644 --- a/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/listener/adapter/MessagingMessageListenerAdapter.java +++ b/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/listener/adapter/MessagingMessageListenerAdapter.java @@ -34,6 +34,7 @@ import org.springframework.core.MethodParameter; import org.springframework.lang.Nullable; import org.springframework.messaging.Message; import org.springframework.messaging.MessagingException; +import org.springframework.messaging.handler.annotation.Header; import org.springframework.messaging.handler.annotation.Payload; import org.springframework.messaging.support.MessageBuilder; import org.springframework.remoting.support.RemoteInvocationResult; @@ -333,12 +334,21 @@ public class MessagingMessageListenerAdapter extends AbstractAdaptableMessageLis for (int i = 0; i < this.method.getParameterCount(); i++) { MethodParameter methodParameter = new MethodParameter(this.method, i); /* - * We're looking for a single non-annotated parameter, or one annotated with @Payload. + * We're looking for a single parameter, or one annotated with @Payload. * We ignore parameters with type Message because they are not involved with conversion. */ + boolean isHeader = methodParameter.hasParameterAnnotation(Header.class); + boolean isPayload = methodParameter.hasParameterAnnotation(Payload.class); + if (isHeader && isPayload) { + if (MessagingMessageListenerAdapter.this.logger.isWarnEnabled()) { + MessagingMessageListenerAdapter.this.logger.warn(this.method.getName() + + ": Cannot annotate a parameter with both @Header and @Payload; " + + "ignored for payload conversion"); + } + } if (isEligibleParameter(methodParameter) - && (methodParameter.getParameterAnnotations().length == 0 - || methodParameter.hasParameterAnnotation(Payload.class))) { + && (!isHeader || isPayload) && !(isHeader && isPayload)) { + if (genericParameterType == null) { genericParameterType = extractGenericParameterTypFromMethodParameter(methodParameter); } diff --git a/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/annotation/EnableRabbitIntegrationTests.java b/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/annotation/EnableRabbitIntegrationTests.java index 3ed5d4bc..8c1b555c 100644 --- a/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/annotation/EnableRabbitIntegrationTests.java +++ b/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/annotation/EnableRabbitIntegrationTests.java @@ -131,6 +131,7 @@ import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.ErrorHandler; +import org.springframework.validation.annotation.Validated; import com.rabbitmq.client.Channel; import com.rabbitmq.http.client.Client; @@ -1148,8 +1149,9 @@ public class EnableRabbitIntegrationTests { } - @RabbitListener(id = "different", queues = "differentTypes", containerFactory = "jsonListenerContainerFactory") - public void handleDifferent(Foo2 foo) { + @RabbitListener(id = "different", queues = "differentTypes", + containerFactory = "jsonListenerContainerFactoryNoClassMapper") + public void handleDifferent(@Validated Foo2 foo) { foos.add(foo); latch.countDown(); } @@ -1592,6 +1594,19 @@ public class EnableRabbitIntegrationTests { return factory; } + @Bean + public SimpleRabbitListenerContainerFactory jsonListenerContainerFactoryNoClassMapper() { + SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory(); + factory.setConnectionFactory(rabbitConnectionFactory()); + factory.setErrorHandler(errorHandler()); + factory.setConsumerTagStrategy(consumerTagStrategy()); + Jackson2JsonMessageConverter messageConverter = new Jackson2JsonMessageConverter(); + factory.setMessageConverter(messageConverter); + factory.setReceiveTimeout(10L); + factory.setConcurrentConsumers(2); + return factory; + } + @Bean public MeterRegistry meterRegistry() { return new SimpleMeterRegistry(); @@ -2189,7 +2204,7 @@ public class EnableRabbitIntegrationTests { } @RabbitListener(queues = "test.converted.args2") - public String foo2a(@Payload Foo2 foo2, @Header("amqp_consumerQueue") String queue) { + public String foo2a(Foo2 foo2, @Header("amqp_consumerQueue") String queue) { return foo2 + queue; }