#122 - Fixed parameter binding for optional request parameters.
If the method arguments handed into a dummy controller method invocation are required but null we now throw an exception as we cannot build a URI that hits the very same method in the very same way. Based on that, we now inspect @RequestParam annotated parameters for null values, allow them but don't bind a parameter for them anymore.
This commit is contained in:
@@ -65,12 +65,41 @@ class AnnotatedParametersParameterAccessor {
|
||||
List<BoundMethodParameter> result = new ArrayList<BoundMethodParameter>();
|
||||
|
||||
for (MethodParameter parameter : parameters.getParametersWith(attribute.getAnnotationType())) {
|
||||
result.add(new BoundMethodParameter(parameter, arguments[parameter.getParameterIndex()], attribute));
|
||||
|
||||
Object value = arguments[parameter.getParameterIndex()];
|
||||
Object verifiedValue = verifyParameterValue(parameter, value);
|
||||
|
||||
if (verifiedValue != null) {
|
||||
result.add(new BoundMethodParameter(parameter, value, attribute));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to verifiy the parameter values given for a dummy invocation. Default implementation rejects
|
||||
* {@literal null} values as they indicate an invalid dummy call.
|
||||
*
|
||||
* @param parameter will never be {@literal null}.
|
||||
* @param value could be {@literal null}.
|
||||
* @return the verified value.
|
||||
*/
|
||||
protected Object verifyParameterValue(MethodParameter parameter, Object value) {
|
||||
|
||||
if (value == null) {
|
||||
|
||||
Object indexOrName = StringUtils.hasText(parameter.getParameterName()) ? parameter.getParameterName() : parameter
|
||||
.getParameterIndex();
|
||||
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Required controller parameter %s of method %s found but null value given!", indexOrName,
|
||||
parameter.getMethod()));
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a {@link MethodParameter} alongside the value it has been bound to.
|
||||
*
|
||||
|
||||
@@ -56,8 +56,7 @@ public class ControllerLinkBuilderFactory implements MethodLinkBuilderFactory<Co
|
||||
private static final MappingDiscoverer DISCOVERER = new AnnotationMappingDiscoverer(RequestMapping.class);
|
||||
private static final AnnotatedParametersParameterAccessor PATH_VARIABLE_ACCESSOR = new AnnotatedParametersParameterAccessor(
|
||||
new AnnotationAttribute(PathVariable.class));
|
||||
private static final AnnotatedParametersParameterAccessor REQUEST_PARAM_ACCESSOR = new AnnotatedParametersParameterAccessor(
|
||||
new AnnotationAttribute(RequestParam.class));
|
||||
private static final AnnotatedParametersParameterAccessor REQUEST_PARAM_ACCESSOR = new RequestParamParameterAccessor();
|
||||
|
||||
private List<UriComponentsContributor> uriComponentsContributors = new ArrayList<UriComponentsContributor>();
|
||||
|
||||
@@ -169,4 +168,28 @@ public class ControllerLinkBuilderFactory implements MethodLinkBuilderFactory<Co
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom extension of {@link AnnotatedParametersParameterAccessor} for {@link RequestParam} to allow {@literal null}
|
||||
* values handed in for optional request parameters.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private static class RequestParamParameterAccessor extends AnnotatedParametersParameterAccessor {
|
||||
|
||||
public RequestParamParameterAccessor() {
|
||||
super(new AnnotationAttribute(RequestParam.class));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.hateoas.mvc.AnnotatedParametersParameterAccessor#verifyParameterValue(org.springframework.core.MethodParameter, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected Object verifyParameterValue(MethodParameter parameter, Object value) {
|
||||
|
||||
RequestParam annotation = parameter.getParameterAnnotation(RequestParam.class);
|
||||
return annotation.required() ? super.verifyParameterValue(parameter, value) : value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user