Skip to content

Commit b5d6b92

Browse files
rstoyanchevlxbzmy
authored andcommitted
missingAfterConversion flag for missing request values
Closes spring-projectsgh-26679
1 parent c2aa4ba commit b5d6b92

12 files changed

+206
-32
lines changed

spring-web/src/main/java/org/springframework/web/bind/MissingMatrixVariableException.java

Lines changed: 19 additions & 5 deletions
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-2021 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.
@@ -28,7 +28,7 @@
2828
* @see MissingPathVariableException
2929
*/
3030
@SuppressWarnings("serial")
31-
public class MissingMatrixVariableException extends ServletRequestBindingException {
31+
public class MissingMatrixVariableException extends MissingRequestValueException {
3232

3333
private final String variableName;
3434

@@ -41,16 +41,30 @@ public class MissingMatrixVariableException extends ServletRequestBindingExcepti
4141
* @param parameter the method parameter
4242
*/
4343
public MissingMatrixVariableException(String variableName, MethodParameter parameter) {
44-
super("");
44+
this(variableName, parameter, false);
45+
}
46+
47+
/**
48+
* Constructor for use when a value was present but converted to {@code null}.
49+
* @param variableName the name of the missing matrix variable
50+
* @param parameter the method parameter
51+
* @param missingAfterConversion whether the value became null after conversion
52+
* @since 5.3.6
53+
*/
54+
public MissingMatrixVariableException(
55+
String variableName, MethodParameter parameter, boolean missingAfterConversion) {
56+
57+
super("", missingAfterConversion);
4558
this.variableName = variableName;
4659
this.parameter = parameter;
4760
}
4861

4962

5063
@Override
5164
public String getMessage() {
52-
return "Missing matrix variable '" + this.variableName +
53-
"' for method parameter of type " + this.parameter.getNestedParameterType().getSimpleName();
65+
return "Required matrix variable '" + this.variableName + "' for method parameter type " +
66+
this.parameter.getNestedParameterType().getSimpleName() + " is " +
67+
(isMissingAfterConversion() ? "present but converted to null" : "not present");
5468
}
5569

5670
/**

spring-web/src/main/java/org/springframework/web/bind/MissingPathVariableException.java

Lines changed: 19 additions & 5 deletions
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-2021 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.
@@ -30,7 +30,7 @@
3030
* @see MissingMatrixVariableException
3131
*/
3232
@SuppressWarnings("serial")
33-
public class MissingPathVariableException extends ServletRequestBindingException {
33+
public class MissingPathVariableException extends MissingRequestValueException {
3434

3535
private final String variableName;
3636

@@ -43,16 +43,30 @@ public class MissingPathVariableException extends ServletRequestBindingException
4343
* @param parameter the method parameter
4444
*/
4545
public MissingPathVariableException(String variableName, MethodParameter parameter) {
46-
super("");
46+
this(variableName, parameter, false);
47+
}
48+
49+
/**
50+
* Constructor for use when a value was present but converted to {@code null}.
51+
* @param variableName the name of the missing path variable
52+
* @param parameter the method parameter
53+
* @param missingAfterConversion whether the value became null after conversion
54+
* @since 5.3.6
55+
*/
56+
public MissingPathVariableException(
57+
String variableName, MethodParameter parameter, boolean missingAfterConversion) {
58+
59+
super("", missingAfterConversion);
4760
this.variableName = variableName;
4861
this.parameter = parameter;
4962
}
5063

5164

5265
@Override
5366
public String getMessage() {
54-
return "Missing URI template variable '" + this.variableName +
55-
"' for method parameter of type " + this.parameter.getNestedParameterType().getSimpleName();
67+
return "Required URI template variable '" + this.variableName + "' for method parameter type " +
68+
this.parameter.getNestedParameterType().getSimpleName() + " is " +
69+
(isMissingAfterConversion() ? "present but converted to null" : "not present");
5670
}
5771

5872
/**

spring-web/src/main/java/org/springframework/web/bind/MissingRequestCookieException.java

Lines changed: 19 additions & 5 deletions
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-2021 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.
@@ -28,7 +28,7 @@
2828
* @see MissingRequestHeaderException
2929
*/
3030
@SuppressWarnings("serial")
31-
public class MissingRequestCookieException extends ServletRequestBindingException {
31+
public class MissingRequestCookieException extends MissingRequestValueException {
3232

3333
private final String cookieName;
3434

@@ -41,16 +41,30 @@ public class MissingRequestCookieException extends ServletRequestBindingExceptio
4141
* @param parameter the method parameter
4242
*/
4343
public MissingRequestCookieException(String cookieName, MethodParameter parameter) {
44-
super("");
44+
this(cookieName, parameter, false);
45+
}
46+
47+
/**
48+
* Constructor for use when a value was present but converted to {@code null}.
49+
* @param cookieName the name of the missing request cookie
50+
* @param parameter the method parameter
51+
* @param missingAfterConversion whether the value became null after conversion
52+
* @since 5.3.6
53+
*/
54+
public MissingRequestCookieException(
55+
String cookieName, MethodParameter parameter, boolean missingAfterConversion) {
56+
57+
super("", missingAfterConversion);
4558
this.cookieName = cookieName;
4659
this.parameter = parameter;
4760
}
4861

4962

5063
@Override
5164
public String getMessage() {
52-
return "Missing cookie '" + this.cookieName +
53-
"' for method parameter of type " + this.parameter.getNestedParameterType().getSimpleName();
65+
return "Required cookie '" + this.cookieName + "' for method parameter type " +
66+
this.parameter.getNestedParameterType().getSimpleName() + " is " +
67+
(isMissingAfterConversion() ? "present but converted to null" : "not present");
5468
}
5569

5670
/**

spring-web/src/main/java/org/springframework/web/bind/MissingRequestHeaderException.java

Lines changed: 19 additions & 5 deletions
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-2021 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.
@@ -28,7 +28,7 @@
2828
* @see MissingRequestCookieException
2929
*/
3030
@SuppressWarnings("serial")
31-
public class MissingRequestHeaderException extends ServletRequestBindingException {
31+
public class MissingRequestHeaderException extends MissingRequestValueException {
3232

3333
private final String headerName;
3434

@@ -41,16 +41,30 @@ public class MissingRequestHeaderException extends ServletRequestBindingExceptio
4141
* @param parameter the method parameter
4242
*/
4343
public MissingRequestHeaderException(String headerName, MethodParameter parameter) {
44-
super("");
44+
this(headerName, parameter, false);
45+
}
46+
47+
/**
48+
* Constructor for use when a value was present but converted to {@code null}.
49+
* @param headerName the name of the missing request header
50+
* @param parameter the method parameter
51+
* @param missingAfterConversion whether the value became null after conversion
52+
* @since 5.3.6
53+
*/
54+
public MissingRequestHeaderException(
55+
String headerName, MethodParameter parameter, boolean missingAfterConversion) {
56+
57+
super("", missingAfterConversion);
4558
this.headerName = headerName;
4659
this.parameter = parameter;
4760
}
4861

4962

5063
@Override
5164
public String getMessage() {
52-
return "Missing request header '" + this.headerName +
53-
"' for method parameter of type " + this.parameter.getNestedParameterType().getSimpleName();
65+
String typeName = this.parameter.getNestedParameterType().getSimpleName();
66+
return "Required request header '" + this.headerName + "' for method parameter type " + typeName + " is " +
67+
(isMissingAfterConversion() ? "present but converted to null" : "not present");
5468
}
5569

5670
/**
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright 2002-2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.web.bind;
17+
18+
/**
19+
* Base class for {@link ServletRequestBindingException} exceptions that could
20+
* not bind because the request value is required but is either missing or
21+
* otherwise resolves to {@code null} after conversion.
22+
*
23+
* @author Rossen Stoyanchev
24+
* @since 5.3.6
25+
*/
26+
@SuppressWarnings("serial")
27+
public class MissingRequestValueException extends ServletRequestBindingException {
28+
29+
private final boolean missingAfterConversion;
30+
31+
32+
public MissingRequestValueException(String msg) {
33+
this(msg, false);
34+
}
35+
36+
public MissingRequestValueException(String msg, boolean missingAfterConversion) {
37+
super(msg);
38+
this.missingAfterConversion = missingAfterConversion;
39+
}
40+
41+
42+
/**
43+
* Whether the request value was present but converted to {@code null}, e.g. via
44+
* {@code org.springframework.core.convert.support.IdToEntityConverter}.
45+
*/
46+
public boolean isMissingAfterConversion() {
47+
return this.missingAfterConversion;
48+
}
49+
50+
}

spring-web/src/main/java/org/springframework/web/bind/MissingServletRequestParameterException.java

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2021 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.
@@ -23,7 +23,7 @@
2323
* @since 2.0.2
2424
*/
2525
@SuppressWarnings("serial")
26-
public class MissingServletRequestParameterException extends ServletRequestBindingException {
26+
public class MissingServletRequestParameterException extends MissingRequestValueException {
2727

2828
private final String parameterName;
2929

@@ -36,15 +36,30 @@ public class MissingServletRequestParameterException extends ServletRequestBindi
3636
* @param parameterType the expected type of the missing parameter
3737
*/
3838
public MissingServletRequestParameterException(String parameterName, String parameterType) {
39-
super("");
39+
this(parameterName, parameterType, false);
40+
}
41+
42+
/**
43+
* Constructor for use when a value was present but converted to {@code null}.
44+
* @param parameterName the name of the missing parameter
45+
* @param parameterType the expected type of the missing parameter
46+
* @param missingAfterConversion whether the value became null after conversion
47+
* @since 5.3.6
48+
*/
49+
public MissingServletRequestParameterException(
50+
String parameterName, String parameterType, boolean missingAfterConversion) {
51+
52+
super("", missingAfterConversion);
4053
this.parameterName = parameterName;
4154
this.parameterType = parameterType;
4255
}
4356

4457

4558
@Override
4659
public String getMessage() {
47-
return "Required " + this.parameterType + " parameter '" + this.parameterName + "' is not present";
60+
return "Required request parameter '" + this.parameterName + "' for method parameter type " +
61+
this.parameterType + " is " +
62+
(isMissingAfterConversion() ? "present but converted to null" : "not present");
4863
}
4964

5065
/**

spring-web/src/main/java/org/springframework/web/method/annotation/AbstractCookieValueMethodArgumentResolver.java

Lines changed: 8 additions & 1 deletion
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-2021 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,6 +24,7 @@
2424
import org.springframework.web.bind.ServletRequestBindingException;
2525
import org.springframework.web.bind.WebDataBinder;
2626
import org.springframework.web.bind.annotation.CookieValue;
27+
import org.springframework.web.context.request.NativeWebRequest;
2728

2829
/**
2930
* A base abstract class to resolve method arguments annotated with
@@ -70,6 +71,12 @@ protected void handleMissingValue(String name, MethodParameter parameter) throws
7071
throw new MissingRequestCookieException(name, parameter);
7172
}
7273

74+
@Override
75+
protected void handleMissingValueAfterConversion(
76+
String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
77+
78+
throw new MissingRequestCookieException(name, parameter, true);
79+
}
7380

7481
private static final class CookieValueNamedValueInfo extends NamedValueInfo {
7582

spring-web/src/main/java/org/springframework/web/method/annotation/AbstractNamedValueMethodArgumentResolver.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 the original author or authors.
2+
* Copyright 2002-2021 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.
@@ -135,7 +135,7 @@ else if ("".equals(arg) && namedValueInfo.defaultValue != null) {
135135
// Check for null value after conversion of incoming argument value
136136
if (arg == null && namedValueInfo.defaultValue == null &&
137137
namedValueInfo.required && !nestedParameter.isOptional()) {
138-
handleMissingValue(namedValueInfo.name, nestedParameter, webRequest);
138+
handleMissingValueAfterConversion(namedValueInfo.name, nestedParameter, webRequest);
139139
}
140140
}
141141

@@ -237,6 +237,19 @@ protected void handleMissingValue(String name, MethodParameter parameter) throws
237237
"' for method parameter of type " + parameter.getNestedParameterType().getSimpleName());
238238
}
239239

240+
/**
241+
* Invoked when a named value is present but becomes {@code null} after conversion.
242+
* @param name the name for the value
243+
* @param parameter the method parameter
244+
* @param request the current request
245+
* @since 5.3.6
246+
*/
247+
protected void handleMissingValueAfterConversion(String name, MethodParameter parameter, NativeWebRequest request)
248+
throws Exception {
249+
250+
handleMissingValue(name, parameter, request);
251+
}
252+
240253
/**
241254
* A {@code null} results in a {@code false} value for {@code boolean}s or an exception for other primitives.
242255
*/

spring-web/src/main/java/org/springframework/web/method/annotation/RequestHeaderMethodArgumentResolver.java

Lines changed: 7 additions & 1 deletion
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-2021 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.
@@ -87,6 +87,12 @@ protected void handleMissingValue(String name, MethodParameter parameter) throws
8787
throw new MissingRequestHeaderException(name, parameter);
8888
}
8989

90+
@Override
91+
protected void handleMissingValueAfterConversion(
92+
String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
93+
94+
throw new MissingRequestHeaderException(name, parameter, true);
95+
}
9096

9197
private static final class RequestHeaderNamedValueInfo extends NamedValueInfo {
9298

0 commit comments

Comments
 (0)