Skip to content

Commit aa75131

Browse files
committed
Refactoring in AbstractMethodMessageHandler
Split out the mechanics of invoking a HandlerMethod and handling the result into a separate helper class. See spring-projectsgh-21987
1 parent 0546793 commit aa75131

File tree

3 files changed

+208
-121
lines changed

3 files changed

+208
-121
lines changed

spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/AbstractExceptionHandlerMethodResolver.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -85,7 +85,7 @@ public boolean hasExceptionMappings() {
8585
* @return a Method to handle the exception, or {@code null} if none found
8686
*/
8787
@Nullable
88-
public Method resolveMethod(Exception exception) {
88+
public Method resolveMethod(Throwable exception) {
8989
Method method = resolveMethodByExceptionType(exception.getClass());
9090
if (method == null) {
9191
Throwable cause = exception.getCause();

spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/AbstractMethodMessageHandler.java

+28-119
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -24,7 +24,6 @@
2424
import java.util.List;
2525
import java.util.Map;
2626
import java.util.Set;
27-
import java.util.concurrent.ConcurrentHashMap;
2827
import java.util.function.Predicate;
2928

3029
import org.apache.commons.logging.Log;
@@ -35,11 +34,9 @@
3534
import org.springframework.context.ApplicationContext;
3635
import org.springframework.context.ApplicationContextAware;
3736
import org.springframework.core.MethodIntrospector;
38-
import org.springframework.core.MethodParameter;
3937
import org.springframework.core.ReactiveAdapterRegistry;
4038
import org.springframework.lang.Nullable;
4139
import org.springframework.messaging.Message;
42-
import org.springframework.messaging.MessageHandlingException;
4340
import org.springframework.messaging.MessagingException;
4441
import org.springframework.messaging.ReactiveMessageHandler;
4542
import org.springframework.messaging.handler.HandlerMethod;
@@ -82,20 +79,15 @@ public abstract class AbstractMethodMessageHandler<T>
8279
protected final Log logger = LogFactory.getLog(getClass());
8380

8481

82+
@Nullable
83+
private Predicate<Class<?>> handlerPredicate;
84+
8585
private ArgumentResolverConfigurer argumentResolverConfigurer = new ArgumentResolverConfigurer();
8686

8787
private ReturnValueHandlerConfigurer returnValueHandlerConfigurer = new ReturnValueHandlerConfigurer();
8888

89-
private final HandlerMethodArgumentResolverComposite argumentResolvers =
90-
new HandlerMethodArgumentResolverComposite();
91-
92-
private final HandlerMethodReturnValueHandlerComposite returnValueHandlers =
93-
new HandlerMethodReturnValueHandlerComposite();
94-
95-
private ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance();
96-
97-
@Nullable
98-
private Predicate<Class<?>> handlerPredicate;
89+
private final InvocableHandlerMethodHelper handlerMethodHelper =
90+
new InvocableHandlerMethodHelper(this::createExceptionMethodResolverFor);
9991

10092
@Nullable
10193
private ApplicationContext applicationContext;
@@ -104,12 +96,24 @@ public abstract class AbstractMethodMessageHandler<T>
10496

10597
private final MultiValueMap<String, T> destinationLookup = new LinkedMultiValueMap<>(64);
10698

107-
private final Map<Class<?>, AbstractExceptionHandlerMethodResolver> exceptionHandlerCache =
108-
new ConcurrentHashMap<>(64);
10999

110-
private final Map<MessagingAdviceBean, AbstractExceptionHandlerMethodResolver> exceptionHandlerAdviceCache =
111-
new LinkedHashMap<>(64);
100+
/**
101+
* Configure a predicate to decide if which beans in the Spring context
102+
* should be checked to see if they have message handling methods.
103+
* <p>By default this is not set and sub-classes should configure it in
104+
* order to enable auto-detection of message handling methods.
105+
*/
106+
public void setHandlerPredicate(@Nullable Predicate<Class<?>> handlerPredicate) {
107+
this.handlerPredicate = handlerPredicate;
108+
}
112109

110+
/**
111+
* Return the {@link #setHandlerPredicate configured} handler predicate.
112+
*/
113+
@Nullable
114+
public Predicate<Class<?>> getHandlerPredicate() {
115+
return this.handlerPredicate;
116+
}
113117

114118
/**
115119
* Configure custom resolvers for handler method arguments.
@@ -141,39 +145,20 @@ public ReturnValueHandlerConfigurer getReturnValueHandlerConfigurer() {
141145
return this.returnValueHandlerConfigurer;
142146
}
143147

144-
/**
145-
* Configure a predicate to decide if which beans in the Spring context
146-
* should be checked to see if they have message handling methods.
147-
* <p>By default this is not set and sub-classes should configure it in
148-
* order to enable auto-detection of message handling methods.
149-
*/
150-
public void setHandlerPredicate(@Nullable Predicate<Class<?>> handlerPredicate) {
151-
this.handlerPredicate = handlerPredicate;
152-
}
153-
154-
/**
155-
* Return the {@link #setHandlerPredicate configured} handler predicate.
156-
*/
157-
@Nullable
158-
public Predicate<Class<?>> getHandlerPredicate() {
159-
return this.handlerPredicate;
160-
}
161-
162148
/**
163149
* Configure the registry for adapting various reactive types.
164150
* <p>By default this is an instance of {@link ReactiveAdapterRegistry} with
165151
* default settings.
166152
*/
167153
public void setReactiveAdapterRegistry(ReactiveAdapterRegistry registry) {
168-
Assert.notNull(registry, "ReactiveAdapterRegistry is required");
169-
this.reactiveAdapterRegistry = registry;
154+
this.handlerMethodHelper.setReactiveAdapterRegistry(registry);
170155
}
171156

172157
/**
173158
* Return the configured registry for adapting reactive types.
174159
*/
175160
public ReactiveAdapterRegistry getReactiveAdapterRegistry() {
176-
return this.reactiveAdapterRegistry;
161+
return this.handlerMethodHelper.getReactiveAdapterRegistry();
177162
}
178163

179164
@Override
@@ -193,7 +178,7 @@ public ApplicationContext getApplicationContext() {
193178
protected void registerExceptionHandlerAdvice(
194179
MessagingAdviceBean bean, AbstractExceptionHandlerMethodResolver resolver) {
195180

196-
this.exceptionHandlerAdviceCache.put(bean, resolver);
181+
this.handlerMethodHelper.registerExceptionHandlerAdvice(bean, resolver);
197182
}
198183

199184
/**
@@ -219,13 +204,13 @@ public void afterPropertiesSet() {
219204
if (resolvers.isEmpty()) {
220205
resolvers = new ArrayList<>(this.argumentResolverConfigurer.getCustomResolvers());
221206
}
222-
this.argumentResolvers.addResolvers(resolvers);
207+
this.handlerMethodHelper.getArgumentResolvers().addResolvers(resolvers);
223208

224209
List<? extends HandlerMethodReturnValueHandler> handlers = initReturnValueHandlers();
225210
if (handlers.isEmpty()) {
226211
handlers = new ArrayList<>(this.returnValueHandlerConfigurer.getCustomHandlers());
227212
}
228-
this.returnValueHandlers.addHandlers(handlers);
213+
this.handlerMethodHelper.getReturnValueHandlers().addHandlers(handlers);
229214

230215
initHandlerMethods();
231216
}
@@ -379,21 +364,7 @@ public Mono<Void> handleMessage(Message<?> message) throws MessagingException {
379364
return Mono.empty();
380365
}
381366
HandlerMethod handlerMethod = match.getHandlerMethod().createWithResolvedBean();
382-
InvocableHandlerMethod invocable = new InvocableHandlerMethod(handlerMethod);
383-
invocable.setArgumentResolvers(this.argumentResolvers.getResolvers());
384-
if (logger.isDebugEnabled()) {
385-
logger.debug("Invoking " + invocable.getShortLogMessage());
386-
}
387-
return invocable.invoke(message)
388-
.flatMap(value -> {
389-
MethodParameter returnType = invocable.getReturnType();
390-
return this.returnValueHandlers.handleReturnValue(value, returnType, message);
391-
})
392-
.onErrorResume(throwable -> {
393-
Exception ex = (throwable instanceof Exception) ? (Exception) throwable :
394-
new MessageHandlingException(message, "HandlerMethod invocation error", throwable);
395-
return processHandlerException(message, handlerMethod, ex);
396-
});
367+
return this.handlerMethodHelper.invoke(handlerMethod, message);
397368
}
398369

399370
@Nullable
@@ -482,68 +453,6 @@ protected void handleNoMatch(@Nullable String destination, Message<?> message) {
482453
logger.debug("No handlers for destination '" + destination + "'");
483454
}
484455

485-
486-
private Mono<Void> processHandlerException(Message<?> message, HandlerMethod handlerMethod, Exception ex) {
487-
InvocableHandlerMethod exceptionInvocable = findExceptionHandler(handlerMethod, ex);
488-
if (exceptionInvocable == null) {
489-
logger.error("Unhandled exception from message handling method", ex);
490-
return Mono.error(ex);
491-
}
492-
exceptionInvocable.setArgumentResolvers(this.argumentResolvers.getResolvers());
493-
if (logger.isDebugEnabled()) {
494-
logger.debug("Invoking " + exceptionInvocable.getShortLogMessage());
495-
}
496-
return exceptionInvocable.invoke(message, ex)
497-
.flatMap(value -> {
498-
MethodParameter returnType = exceptionInvocable.getReturnType();
499-
return this.returnValueHandlers.handleReturnValue(value, returnType, message);
500-
});
501-
}
502-
503-
/**
504-
* Find an exception handling method for the given exception.
505-
* <p>The default implementation searches methods in the class hierarchy of
506-
* the HandlerMethod first and if not found, it continues searching for
507-
* additional handling methods registered via
508-
* {@link #registerExceptionHandlerAdvice(MessagingAdviceBean, AbstractExceptionHandlerMethodResolver)}.
509-
* @param handlerMethod the method where the exception was raised
510-
* @param exception the raised exception
511-
* @return a method to handle the exception, or {@code null}
512-
*/
513-
@Nullable
514-
protected InvocableHandlerMethod findExceptionHandler(HandlerMethod handlerMethod, Exception exception) {
515-
if (logger.isDebugEnabled()) {
516-
logger.debug("Searching for methods to handle " + exception.getClass().getSimpleName());
517-
}
518-
Class<?> beanType = handlerMethod.getBeanType();
519-
AbstractExceptionHandlerMethodResolver resolver = this.exceptionHandlerCache.get(beanType);
520-
if (resolver == null) {
521-
resolver = createExceptionMethodResolverFor(beanType);
522-
this.exceptionHandlerCache.put(beanType, resolver);
523-
}
524-
InvocableHandlerMethod exceptionHandlerMethod = null;
525-
Method method = resolver.resolveMethod(exception);
526-
if (method != null) {
527-
exceptionHandlerMethod = new InvocableHandlerMethod(handlerMethod.getBean(), method);
528-
}
529-
else {
530-
for (MessagingAdviceBean advice : this.exceptionHandlerAdviceCache.keySet()) {
531-
if (advice.isApplicableToBeanType(beanType)) {
532-
resolver = this.exceptionHandlerAdviceCache.get(advice);
533-
method = resolver.resolveMethod(exception);
534-
if (method != null) {
535-
exceptionHandlerMethod = new InvocableHandlerMethod(advice.resolveBean(), method);
536-
break;
537-
}
538-
}
539-
}
540-
}
541-
if (exceptionHandlerMethod != null) {
542-
exceptionHandlerMethod.setArgumentResolvers(this.argumentResolvers.getResolvers());
543-
}
544-
return exceptionHandlerMethod;
545-
}
546-
547456
/**
548457
* Create a concrete instance of {@link AbstractExceptionHandlerMethodResolver}
549458
* that finds exception handling methods based on some criteria, e.g. based

0 commit comments

Comments
 (0)