|
18 | 18 |
|
19 | 19 | import java.lang.reflect.AnnotatedElement; |
20 | 20 | import java.lang.reflect.Method; |
| 21 | +import java.lang.reflect.Type; |
21 | 22 | import java.nio.charset.Charset; |
22 | 23 | import java.nio.charset.StandardCharsets; |
23 | 24 | import java.util.ArrayList; |
|
28 | 29 | import java.util.HashSet; |
29 | 30 | import java.util.List; |
30 | 31 | import java.util.Map; |
| 32 | +import java.util.Optional; |
31 | 33 | import java.util.Set; |
32 | 34 | import java.util.concurrent.ConcurrentHashMap; |
33 | 35 | import java.util.concurrent.ConcurrentMap; |
|
73 | 75 | import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; |
74 | 76 | import org.springframework.context.EnvironmentAware; |
75 | 77 | import org.springframework.context.expression.StandardBeanExpressionResolver; |
| 78 | +import org.springframework.core.MethodParameter; |
76 | 79 | import org.springframework.core.Ordered; |
77 | 80 | import org.springframework.core.annotation.AnnotationUtils; |
78 | 81 | import org.springframework.core.annotation.MergedAnnotations; |
|
82 | 85 | import org.springframework.core.convert.support.DefaultConversionService; |
83 | 86 | import org.springframework.core.env.Environment; |
84 | 87 | import org.springframework.core.task.TaskExecutor; |
| 88 | +import org.springframework.format.support.DefaultFormattingConversionService; |
85 | 89 | import org.springframework.lang.Nullable; |
| 90 | +import org.springframework.messaging.Message; |
| 91 | +import org.springframework.messaging.converter.GenericMessageConverter; |
86 | 92 | import org.springframework.messaging.handler.annotation.support.DefaultMessageHandlerMethodFactory; |
87 | 93 | import org.springframework.messaging.handler.annotation.support.MessageHandlerMethodFactory; |
| 94 | +import org.springframework.messaging.handler.annotation.support.MethodArgumentNotValidException; |
| 95 | +import org.springframework.messaging.handler.annotation.support.PayloadMethodArgumentResolver; |
88 | 96 | import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver; |
89 | 97 | import org.springframework.messaging.handler.invocation.InvocableHandlerMethod; |
90 | 98 | import org.springframework.util.Assert; |
91 | 99 | import org.springframework.util.ClassUtils; |
92 | 100 | import org.springframework.util.CollectionUtils; |
93 | 101 | import org.springframework.util.ReflectionUtils; |
94 | 102 | import org.springframework.util.StringUtils; |
| 103 | +import org.springframework.validation.ObjectError; |
95 | 104 | import org.springframework.validation.Validator; |
96 | 105 |
|
97 | 106 | /** |
@@ -980,6 +989,9 @@ private String resolve(String value) { |
980 | 989 | */ |
981 | 990 | private class RabbitHandlerMethodFactoryAdapter implements MessageHandlerMethodFactory { |
982 | 991 |
|
| 992 | + private final DefaultFormattingConversionService defaultFormattingConversionService = |
| 993 | + new DefaultFormattingConversionService(); |
| 994 | + |
983 | 995 | private MessageHandlerMethodFactory factory; |
984 | 996 |
|
985 | 997 | RabbitHandlerMethodFactoryAdapter() { |
@@ -1008,20 +1020,70 @@ private MessageHandlerMethodFactory createDefaultMessageHandlerMethodFactory() { |
1008 | 1020 | defaultFactory.setValidator(validator); |
1009 | 1021 | } |
1010 | 1022 | defaultFactory.setBeanFactory(RabbitListenerAnnotationBeanPostProcessor.this.beanFactory); |
1011 | | - DefaultConversionService conversionService = new DefaultConversionService(); |
1012 | | - conversionService.addConverter( |
| 1023 | + this.defaultFormattingConversionService.addConverter( |
1013 | 1024 | new BytesToStringConverter(RabbitListenerAnnotationBeanPostProcessor.this.charset)); |
1014 | | - defaultFactory.setConversionService(conversionService); |
| 1025 | + defaultFactory.setConversionService(this.defaultFormattingConversionService); |
1015 | 1026 |
|
1016 | | - List<HandlerMethodArgumentResolver> customArgumentsResolver = |
1017 | | - new ArrayList<>(RabbitListenerAnnotationBeanPostProcessor.this.registrar.getCustomMethodArgumentResolvers()); |
| 1027 | + List<HandlerMethodArgumentResolver> customArgumentsResolver = new ArrayList<>( |
| 1028 | + RabbitListenerAnnotationBeanPostProcessor.this.registrar.getCustomMethodArgumentResolvers()); |
1018 | 1029 | defaultFactory.setCustomArgumentResolvers(customArgumentsResolver); |
| 1030 | + GenericMessageConverter messageConverter = new GenericMessageConverter( |
| 1031 | + this.defaultFormattingConversionService); |
| 1032 | + defaultFactory.setMessageConverter(messageConverter); |
| 1033 | + // Has to be at the end - look at PayloadMethodArgumentResolver documentation |
| 1034 | + customArgumentsResolver.add(new OptionalEmptyAwarePayloadArgumentResolver(messageConverter, validator)); |
1019 | 1035 | defaultFactory.afterPropertiesSet(); |
1020 | 1036 | return defaultFactory; |
1021 | 1037 | } |
1022 | 1038 |
|
1023 | 1039 | } |
1024 | 1040 |
|
| 1041 | + private static class OptionalEmptyAwarePayloadArgumentResolver extends PayloadMethodArgumentResolver { |
| 1042 | + |
| 1043 | + OptionalEmptyAwarePayloadArgumentResolver( |
| 1044 | + org.springframework.messaging.converter.MessageConverter messageConverter, |
| 1045 | + @Nullable Validator validator) { |
| 1046 | + |
| 1047 | + super(messageConverter, validator); |
| 1048 | + } |
| 1049 | + |
| 1050 | + @Override |
| 1051 | + public Object resolveArgument(MethodParameter parameter, Message<?> message) throws Exception { // NOSONAR |
| 1052 | + Object resolved = null; |
| 1053 | + try { |
| 1054 | + resolved = super.resolveArgument(parameter, message); |
| 1055 | + } |
| 1056 | + catch (MethodArgumentNotValidException ex) { |
| 1057 | + if (message.getPayload().equals(Optional.empty())) { |
| 1058 | + Type type = parameter.getGenericParameterType(); |
| 1059 | + List<ObjectError> allErrors = ex.getBindingResult().getAllErrors(); |
| 1060 | + if (allErrors.size() == 1 |
| 1061 | + && allErrors.get(0).getDefaultMessage().equals("Payload value must not be empty")) { |
| 1062 | + return Optional.empty(); |
| 1063 | + } |
| 1064 | + } |
| 1065 | + throw ex; |
| 1066 | + } |
| 1067 | + /* |
| 1068 | + * Replace Optional.empty() list elements with null. |
| 1069 | + */ |
| 1070 | + if (resolved instanceof List) { |
| 1071 | + List<?> list = ((List<?>) resolved); |
| 1072 | + for (int i = 0; i < list.size(); i++) { |
| 1073 | + if (list.get(i).equals(Optional.empty())) { |
| 1074 | + list.set(i, null); |
| 1075 | + } |
| 1076 | + } |
| 1077 | + } |
| 1078 | + return resolved; |
| 1079 | + } |
| 1080 | + |
| 1081 | + @Override |
| 1082 | + protected boolean isEmptyPayload(Object payload) { |
| 1083 | + return payload == null || payload.equals(Optional.empty()); |
| 1084 | + } |
| 1085 | + |
| 1086 | + } |
1025 | 1087 | /** |
1026 | 1088 | * The metadata holder of the class with {@link RabbitListener} |
1027 | 1089 | * and {@link RabbitHandler} annotations. |
|
0 commit comments