Skip to content

Commit 0cf9371

Browse files
committed
Fix race condition in AnntationMethodHER
Issue: SPR-9138 Backport-Issue: SPR-9147 Backport-Commit: 0b02933
1 parent 8faa2e6 commit 0cf9371

File tree

2 files changed

+35
-35
lines changed

2 files changed

+35
-35
lines changed

org.springframework.web.portlet/src/main/java/org/springframework/web/portlet/mvc/annotation/AnnotationMethodHandlerExceptionResolver.java

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,7 @@
7575
public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExceptionResolver {
7676

7777
// dummy method placeholder
78-
private static final Method NO_METHOD_FOUND = ClassUtils
79-
.getMethodIfAvailable(System.class, "currentTimeMillis", null);
78+
private static final Method NO_METHOD_FOUND = ClassUtils.getMethodIfAvailable(System.class, "currentTimeMillis", (Class<?>[]) null);
8079

8180
private WebArgumentResolver[] customArgumentResolvers;
8281

@@ -134,10 +133,9 @@ protected ModelAndView doResolveException(
134133
private Method findBestExceptionHandlerMethod(Object handler, final Exception thrownException) {
135134
final Class<?> handlerType = handler.getClass();
136135
final Class<? extends Throwable> thrownExceptionType = thrownException.getClass();
137-
138136
Method handlerMethod = null;
139-
Map<Class<? extends Throwable>, Method> handlers = exceptionHandlerCache
140-
.get(handlerType);
137+
138+
Map<Class<? extends Throwable>, Method> handlers = exceptionHandlerCache.get(handlerType);
141139

142140
if (handlers != null) {
143141
handlerMethod = handlers.get(thrownExceptionType);
@@ -173,7 +171,9 @@ public void doWith(Method method) {
173171
}
174172
});
175173

176-
return getBestMatchingMethod(resolverMethods, thrownException);
174+
handlerMethod = getBestMatchingMethod(resolverMethods, thrownException);
175+
handlers.put(thrownExceptionType, (handlerMethod == null ? NO_METHOD_FOUND : handlerMethod));
176+
return handlerMethod;
177177
}
178178

179179
/**
@@ -204,19 +204,19 @@ protected List<Class<? extends Throwable>> getHandledExceptions(Method method) {
204204
}
205205

206206
/**
207-
* Returns the best matching method. Uses the {@link DepthComparator}.
207+
* Uses the {@link DepthComparator} to find the best matching method
208+
* @return the best matching method or {@code null}.
208209
*/
209210
private Method getBestMatchingMethod(
210211
Map<Class<? extends Throwable>, Method> resolverMethods, Exception thrownException) {
211212

212-
if (!resolverMethods.isEmpty()) {
213-
Class<? extends Throwable> closestMatch =
214-
ExceptionDepthComparator.findClosestMatch(resolverMethods.keySet(), thrownException);
215-
return resolverMethods.get(closestMatch);
216-
}
217-
else {
213+
if (resolverMethods.isEmpty()) {
218214
return null;
219215
}
216+
Class<? extends Throwable> closestMatch =
217+
ExceptionDepthComparator.findClosestMatch(resolverMethods.keySet(), thrownException);
218+
Method method = resolverMethods.get(closestMatch);
219+
return ((method == null) || (NO_METHOD_FOUND == method)) ? null : method;
220220
}
221221

222222
/**
@@ -225,13 +225,13 @@ private Method getBestMatchingMethod(
225225
private Object[] resolveHandlerArguments(Method handlerMethod, Object handler,
226226
NativeWebRequest webRequest, Exception thrownException) throws Exception {
227227

228-
Class[] paramTypes = handlerMethod.getParameterTypes();
228+
Class<?>[] paramTypes = handlerMethod.getParameterTypes();
229229
Object[] args = new Object[paramTypes.length];
230230
Class<?> handlerType = handler.getClass();
231231
for (int i = 0; i < args.length; i++) {
232232
MethodParameter methodParam = new MethodParameter(handlerMethod, i);
233233
GenericTypeResolver.resolveParameterType(methodParam, handlerType);
234-
Class paramType = methodParam.getParameterType();
234+
Class<?> paramType = methodParam.getParameterType();
235235
Object argValue = resolveCommonArgument(methodParam, webRequest, thrownException);
236236
if (argValue != WebArgumentResolver.UNRESOLVED) {
237237
args[i] = argValue;
@@ -267,7 +267,7 @@ protected Object resolveCommonArgument(MethodParameter methodParameter, NativeWe
267267
}
268268

269269
// Resolution of standard parameter types...
270-
Class paramType = methodParameter.getParameterType();
270+
Class<?> paramType = methodParameter.getParameterType();
271271
Object value = resolveStandardArgument(paramType, webRequest, thrownException);
272272
if (value != WebArgumentResolver.UNRESOLVED && !ClassUtils.isAssignableValue(paramType, value)) {
273273
throw new IllegalStateException("Standard argument type [" + paramType.getName() +
@@ -287,7 +287,7 @@ protected Object resolveCommonArgument(MethodParameter methodParameter, NativeWe
287287
* @param thrownException the exception thrown
288288
* @return the argument value, or {@link org.springframework.web.bind.support.WebArgumentResolver#UNRESOLVED}
289289
*/
290-
protected Object resolveStandardArgument(Class parameterType, NativeWebRequest webRequest,
290+
protected Object resolveStandardArgument(Class<?> parameterType, NativeWebRequest webRequest,
291291
Exception thrownException) throws Exception {
292292

293293
if (parameterType.isInstance(thrownException)) {

org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerExceptionResolver.java

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,10 @@
8484
public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExceptionResolver {
8585

8686
// dummy method placeholder
87-
private static final Method NO_METHOD_FOUND = ClassUtils.getMethodIfAvailable(System.class, "currentTimeMillis", null);
88-
89-
private final Map<Class<?>, Map<Class<? extends Throwable>, Method>> exceptionHandlerCache =
90-
new ConcurrentHashMap<Class<?>, Map<Class<? extends Throwable>, Method>>();
87+
private static final Method NO_METHOD_FOUND = ClassUtils.getMethodIfAvailable(System.class, "currentTimeMillis", (Class<?>[]) null);
88+
89+
private final Map<Class<?>, Map<Class<? extends Throwable>, Method>> exceptionHandlerCache =
90+
new ConcurrentHashMap<Class<?>, Map<Class<? extends Throwable>, Method>>();
9191

9292
private WebArgumentResolver[] customArgumentResolvers;
9393

@@ -157,7 +157,7 @@ private Method findBestExceptionHandlerMethod(Object handler, final Exception th
157157
final Class<?> handlerType = ClassUtils.getUserClass(handler);
158158
final Class<? extends Throwable> thrownExceptionType = thrownException.getClass();
159159
Method handlerMethod = null;
160-
160+
161161
Map<Class<? extends Throwable>, Method> handlers = exceptionHandlerCache.get(handlerType);
162162

163163
if (handlers != null) {
@@ -170,7 +170,7 @@ private Method findBestExceptionHandlerMethod(Object handler, final Exception th
170170
handlers = new ConcurrentHashMap<Class<? extends Throwable>, Method>();
171171
exceptionHandlerCache.put(handlerType, handlers);
172172
}
173-
173+
174174
final Map<Class<? extends Throwable>, Method> resolverMethods = handlers;
175175

176176
ReflectionUtils.doWithMethods(handlerType, new ReflectionUtils.MethodCallback() {
@@ -228,19 +228,19 @@ protected List<Class<? extends Throwable>> getHandledExceptions(Method method) {
228228
}
229229

230230
/**
231-
* Returns the best matching method. Uses the {@link DepthComparator}.
231+
* Uses the {@link DepthComparator} to find the best matching method
232+
* @return the best matching method or {@code null}.
232233
*/
233234
private Method getBestMatchingMethod(
234235
Map<Class<? extends Throwable>, Method> resolverMethods, Exception thrownException) {
235236

236-
if (!resolverMethods.isEmpty()) {
237-
Class<? extends Throwable> closestMatch =
238-
ExceptionDepthComparator.findClosestMatch(resolverMethods.keySet(), thrownException);
239-
return resolverMethods.get(closestMatch);
240-
}
241-
else {
237+
if (resolverMethods.isEmpty()) {
242238
return null;
243239
}
240+
Class<? extends Throwable> closestMatch =
241+
ExceptionDepthComparator.findClosestMatch(resolverMethods.keySet(), thrownException);
242+
Method method = resolverMethods.get(closestMatch);
243+
return ((method == null) || (NO_METHOD_FOUND == method)) ? null : method;
244244
}
245245

246246
/**
@@ -249,13 +249,13 @@ private Method getBestMatchingMethod(
249249
private Object[] resolveHandlerArguments(Method handlerMethod, Object handler,
250250
NativeWebRequest webRequest, Exception thrownException) throws Exception {
251251

252-
Class[] paramTypes = handlerMethod.getParameterTypes();
252+
Class<?>[] paramTypes = handlerMethod.getParameterTypes();
253253
Object[] args = new Object[paramTypes.length];
254254
Class<?> handlerType = handler.getClass();
255255
for (int i = 0; i < args.length; i++) {
256256
MethodParameter methodParam = new MethodParameter(handlerMethod, i);
257257
GenericTypeResolver.resolveParameterType(methodParam, handlerType);
258-
Class paramType = methodParam.getParameterType();
258+
Class<?> paramType = methodParam.getParameterType();
259259
Object argValue = resolveCommonArgument(methodParam, webRequest, thrownException);
260260
if (argValue != WebArgumentResolver.UNRESOLVED) {
261261
args[i] = argValue;
@@ -290,7 +290,7 @@ protected Object resolveCommonArgument(MethodParameter methodParameter, NativeWe
290290
}
291291

292292
// Resolution of standard parameter types...
293-
Class paramType = methodParameter.getParameterType();
293+
Class<?> paramType = methodParameter.getParameterType();
294294
Object value = resolveStandardArgument(paramType, webRequest, thrownException);
295295
if (value != WebArgumentResolver.UNRESOLVED && !ClassUtils.isAssignableValue(paramType, value)) {
296296
throw new IllegalStateException(
@@ -311,7 +311,7 @@ protected Object resolveCommonArgument(MethodParameter methodParameter, NativeWe
311311
* @param thrownException the exception thrown
312312
* @return the argument value, or {@link WebArgumentResolver#UNRESOLVED}
313313
*/
314-
protected Object resolveStandardArgument(Class parameterType, NativeWebRequest webRequest,
314+
protected Object resolveStandardArgument(Class<?> parameterType, NativeWebRequest webRequest,
315315
Exception thrownException) throws Exception {
316316

317317
if (parameterType.isInstance(thrownException)) {
@@ -395,7 +395,7 @@ else if (returnValue instanceof Model) {
395395
return new ModelAndView().addAllObjects(((Model) returnValue).asMap());
396396
}
397397
else if (returnValue instanceof Map) {
398-
return new ModelAndView().addAllObjects((Map) returnValue);
398+
return new ModelAndView().addAllObjects((Map<String, Object>) returnValue);
399399
}
400400
else if (returnValue instanceof View) {
401401
return new ModelAndView((View) returnValue);

0 commit comments

Comments
 (0)