Skip to content

Commit d9e17a6

Browse files
committed
Refine SyncInvocableHandlerMethod error handling
Ensure the error is wrapped as ServerErrorException
1 parent 912c270 commit d9e17a6

File tree

4 files changed

+60
-16
lines changed

4 files changed

+60
-16
lines changed

spring-web/src/main/java/org/springframework/web/server/ServerErrorException.java

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2018 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.
@@ -19,18 +19,22 @@
1919
import org.springframework.core.MethodParameter;
2020
import org.springframework.http.HttpStatus;
2121
import org.springframework.lang.Nullable;
22+
import org.springframework.web.method.HandlerMethod;
2223

2324
/**
24-
* Exception for errors that fit response status 500 (bad request) for use in
25-
* Spring Web applications. The exception provides additional fields (e.g.
26-
* an optional {@link MethodParameter} if related to the error).
25+
* Exception for an {@link HttpStatus#INTERNAL_SERVER_ERROR} that exposes extra
26+
* information about a controller method that failed, or a controller method
27+
* argument that could not be resolved.
2728
*
2829
* @author Rossen Stoyanchev
2930
* @since 5.0
3031
*/
3132
@SuppressWarnings("serial")
3233
public class ServerErrorException extends ResponseStatusException {
3334

35+
@Nullable
36+
private final HandlerMethod handlerMethod;
37+
3438
@Nullable
3539
private final MethodParameter parameter;
3640

@@ -39,27 +43,60 @@ public class ServerErrorException extends ResponseStatusException {
3943
* Constructor with an explanation only.
4044
*/
4145
public ServerErrorException(String reason) {
42-
this(reason, null, null);
46+
super(HttpStatus.INTERNAL_SERVER_ERROR, reason, null);
47+
this.handlerMethod = null;
48+
this.parameter = null;
4349
}
4450

4551
/**
46-
* Constructor for a 500 error linked to a specific {@code MethodParameter}.
52+
* Constructor with a reason and root cause.
53+
* @since 5.0.5
4754
*/
48-
public ServerErrorException(String reason, MethodParameter parameter) {
49-
this(reason, parameter, null);
55+
public ServerErrorException(String reason, Throwable cause) {
56+
super(HttpStatus.INTERNAL_SERVER_ERROR, reason, cause);
57+
this.handlerMethod = null;
58+
this.parameter = null;
5059
}
5160

5261
/**
53-
* Constructor for a 500 error with a root cause.
62+
* Constructor for a 500 error with a {@link MethodParameter}.
5463
*/
55-
public ServerErrorException(String reason, @Nullable MethodParameter parameter, @Nullable Throwable cause) {
64+
public ServerErrorException(String reason, MethodParameter parameter, @Nullable Throwable cause) {
5665
super(HttpStatus.INTERNAL_SERVER_ERROR, reason, cause);
66+
this.handlerMethod = null;
5767
this.parameter = parameter;
5868
}
5969

70+
/**
71+
* Constructor for a 500 error with a root cause.
72+
*/
73+
public ServerErrorException(String reason, HandlerMethod handlerMethod, @Nullable Throwable cause) {
74+
super(HttpStatus.INTERNAL_SERVER_ERROR, reason, cause);
75+
this.handlerMethod = handlerMethod;
76+
this.parameter = null;
77+
}
78+
79+
/**
80+
* Constructor for a 500 error linked to a specific {@code MethodParameter}.
81+
* @deprecated in favor of {@link #ServerErrorException(String, MethodParameter, Throwable)}
82+
*/
83+
@Deprecated
84+
public ServerErrorException(String reason, MethodParameter parameter) {
85+
this(reason, parameter, null);
86+
}
87+
88+
89+
/**
90+
* Return the controller method associated with the error, if any.
91+
* @since 5.0.5
92+
*/
93+
@Nullable
94+
public HandlerMethod getHandlerMethod() {
95+
return this.handlerMethod;
96+
}
6097

6198
/**
62-
* Return the {@code MethodParameter} associated with this error, if any.
99+
* Return the controller method argument associated with this error, if any.
63100
*/
64101
@Nullable
65102
public MethodParameter getMethodParameter() {

spring-webflux/src/main/java/org/springframework/web/reactive/BindingContext.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2018 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.
@@ -21,6 +21,7 @@
2121
import org.springframework.validation.support.BindingAwareConcurrentModel;
2222
import org.springframework.web.bind.support.WebBindingInitializer;
2323
import org.springframework.web.bind.support.WebExchangeDataBinder;
24+
import org.springframework.web.server.ServerErrorException;
2425
import org.springframework.web.server.ServerWebExchange;
2526

2627
/**
@@ -75,6 +76,7 @@ public Model getModel() {
7576
* @param target the object to create a data binder for
7677
* @param name the name of the target object
7778
* @return the created data binder
79+
* @throws ServerErrorException if {@code @InitBinder} method invocation fails
7880
*/
7981
public WebExchangeDataBinder createDataBinder(ServerWebExchange exchange, @Nullable Object target, String name) {
8082
WebExchangeDataBinder dataBinder = new WebExchangeDataBinder(target, name);
@@ -86,6 +88,7 @@ public WebExchangeDataBinder createDataBinder(ServerWebExchange exchange, @Nulla
8688

8789
/**
8890
* Initialize the data binder instance for the given exchange.
91+
* @throws ServerErrorException if {@code @InitBinder} method invocation fails
8992
*/
9093
protected WebExchangeDataBinder initDataBinder(WebExchangeDataBinder binder, ServerWebExchange exchange) {
9194
return binder;
@@ -97,6 +100,7 @@ protected WebExchangeDataBinder initDataBinder(WebExchangeDataBinder binder, Ser
97100
* @param exchange the current exchange
98101
* @param name the name of the target object
99102
* @return the created data binder
103+
* @throws ServerErrorException if {@code @InitBinder} method invocation fails
100104
*/
101105
public WebExchangeDataBinder createDataBinder(ServerWebExchange exchange, String name) {
102106
return createDataBinder(exchange, null, name);

spring-webflux/src/main/java/org/springframework/web/reactive/result/method/SyncInvocableHandlerMethod.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.springframework.web.method.HandlerMethod;
3030
import org.springframework.web.reactive.BindingContext;
3131
import org.springframework.web.reactive.HandlerResult;
32+
import org.springframework.web.server.ServerErrorException;
3233
import org.springframework.web.server.ServerWebExchange;
3334

3435
/**
@@ -95,6 +96,7 @@ public ParameterNameDiscoverer getParameterNameDiscoverer() {
9596
* @param bindingContext the binding context to use
9697
* @param providedArgs optional list of argument values to match by type
9798
* @return Mono with a {@link HandlerResult}.
99+
* @throws ServerErrorException if method argument resolution or method invocation fails
98100
*/
99101
@Nullable
100102
public HandlerResult invokeForHandlerResult(ServerWebExchange exchange,
@@ -104,9 +106,10 @@ public HandlerResult invokeForHandlerResult(ServerWebExchange exchange,
104106
this.delegate.invoke(exchange, bindingContext, providedArgs).subscribeWith(processor);
105107

106108
if (processor.isTerminated()) {
107-
Throwable error = processor.getError();
108-
if (error != null) {
109-
throw (RuntimeException) error;
109+
Throwable ex = processor.getError();
110+
if (ex != null) {
111+
throw (ex instanceof ServerErrorException ? (ServerErrorException) ex :
112+
new ServerErrorException("Failed to invoke: " + getShortLogMessage(), this, ex));
110113
}
111114
return processor.peek();
112115
}

spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/PathVariableMethodArgumentResolver.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ protected Object resolveNamedValue(String name, MethodParameter parameter, Serve
9292

9393
@Override
9494
protected void handleMissingValue(String name, MethodParameter parameter) {
95-
throw new ServerErrorException(name, parameter);
95+
throw new ServerErrorException(name, parameter, null);
9696
}
9797

9898
@Override

0 commit comments

Comments
 (0)