Introduce base exception class for arg resolution
Issue: SPR-11584
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.messaging.handler.annotation.support;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessagingException;
|
||||
|
||||
/**
|
||||
* Base class for exceptions resulting from the invocation of
|
||||
* {@link org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 4.0.3
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public abstract class AbstractMethodArgumentResolutionException extends MessagingException {
|
||||
|
||||
private final MethodParameter parameter;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new instance providing the invalid {@code MethodParameter}.
|
||||
*/
|
||||
protected AbstractMethodArgumentResolutionException(Message<?> message, MethodParameter parameter) {
|
||||
this(message, parameter, getMethodParamMessage(parameter));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance providing the invalid {@code MethodParameter} and
|
||||
* a prepared description. Sub-classes should prepend the description with
|
||||
* the help of {@link #getMethodParamMessage(org.springframework.core.MethodParameter)}.
|
||||
*/
|
||||
protected AbstractMethodArgumentResolutionException(Message<?> message,
|
||||
MethodParameter parameter, String description) {
|
||||
|
||||
super(message, description);
|
||||
this.parameter = parameter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the MethodParameter that was rejected.
|
||||
*/
|
||||
public MethodParameter getMethodParameter() {
|
||||
return this.parameter;
|
||||
}
|
||||
|
||||
protected static String getMethodParamMessage(MethodParameter param) {
|
||||
return new StringBuilder("Could not resolve method parameter at index ")
|
||||
.append(param.getParameterIndex()).append(" in method: ")
|
||||
.append(param.getMethod().toGenericString()).toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,6 +21,8 @@ import org.springframework.core.ResolvableType;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* A {@link HandlerMethodArgumentResolver} for {@link Message} parameters. Validates
|
||||
* that the generic type of the payload matches with the message value.
|
||||
@@ -39,28 +41,30 @@ public class MessageMethodArgumentResolver implements HandlerMethodArgumentResol
|
||||
|
||||
@Override
|
||||
public Object resolveArgument(MethodParameter parameter, Message<?> message) throws Exception {
|
||||
// Validate the message type is assignable
|
||||
if (!parameter.getParameterType().isAssignableFrom(message.getClass())) {
|
||||
throw new MethodArgumentTypeMismatchException(message,
|
||||
"Could not resolve Message parameter: invalid message type:"
|
||||
+ "expected [" + message.getClass().getName() + "] but got ["
|
||||
+ parameter.getParameterType().getName() + "]");
|
||||
|
||||
Class<?> paramType = parameter.getParameterType();
|
||||
|
||||
if (!paramType.isAssignableFrom(message.getClass())) {
|
||||
throw new MethodArgumentTypeMismatchException(message, parameter,
|
||||
"The actual message type [" + message.getClass().getName() + "] " +
|
||||
"does not match the expected type [" + paramType.getName() + "]");
|
||||
}
|
||||
|
||||
// validate that the payload type matches
|
||||
Class<?> effectivePayloadType = getPayloadType(parameter);
|
||||
if (effectivePayloadType != null && !effectivePayloadType.isInstance(message.getPayload())) {
|
||||
throw new MethodArgumentTypeMismatchException(message,
|
||||
"Could not resolve Message parameter: invalid payload type: "
|
||||
+ "expected [" + effectivePayloadType.getName() + "] but got ["
|
||||
+ message.getPayload().getClass().getName() + "]");
|
||||
Class<?> expectedPayloadType = getPayloadType(parameter);
|
||||
Object payload = message.getPayload();
|
||||
|
||||
if (expectedPayloadType != null && !expectedPayloadType.isInstance(payload)) {
|
||||
throw new MethodArgumentTypeMismatchException(message, parameter,
|
||||
"The expected Message<?> payload type [" + expectedPayloadType.getClass().getName() +
|
||||
"] does not match the actual payload type [" + payload.getClass().getName() + "]");
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
private Class<?> getPayloadType(MethodParameter parameter) {
|
||||
ResolvableType resolvableType = ResolvableType
|
||||
.forType(parameter.getGenericParameterType()).as(Message.class);
|
||||
Type genericParamType = parameter.getGenericParameterType();
|
||||
ResolvableType resolvableType = ResolvableType.forType(genericParamType).as(Message.class);
|
||||
return resolvableType.getGeneric(0).resolve(Object.class);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,22 +18,19 @@ package org.springframework.messaging.handler.annotation.support;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessagingException;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.validation.ObjectError;
|
||||
|
||||
/**
|
||||
* Exception to be thrown when a method argument is not valid. For instance, this
|
||||
* can be issued if a validation on a method parameter annotated with
|
||||
* {@code @Valid} fails.
|
||||
* Exception to be thrown when a method argument fails validation perhaps as a
|
||||
* result of {@code @Valid} style validation, or perhaps because it is required.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 4.0.1
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class MethodArgumentNotValidException extends MessagingException {
|
||||
|
||||
private final MethodParameter parameter;
|
||||
public class MethodArgumentNotValidException extends AbstractMethodArgumentResolutionException {
|
||||
|
||||
private final BindingResult bindingResult;
|
||||
|
||||
@@ -41,7 +38,6 @@ public class MethodArgumentNotValidException extends MessagingException {
|
||||
/**
|
||||
* Create a new instance with the invalid {@code MethodParameter}.
|
||||
*/
|
||||
|
||||
public MethodArgumentNotValidException(Message<?> message, MethodParameter parameter) {
|
||||
this(message, parameter, null);
|
||||
}
|
||||
@@ -53,19 +49,13 @@ public class MethodArgumentNotValidException extends MessagingException {
|
||||
public MethodArgumentNotValidException(Message<?> message, MethodParameter parameter,
|
||||
BindingResult bindingResult) {
|
||||
|
||||
super(message, generateMessage(parameter, bindingResult));
|
||||
this.parameter = parameter;
|
||||
super(message, parameter, getMethodParamMessage(parameter) +
|
||||
getValidationErrorMessage(parameter, bindingResult));
|
||||
|
||||
this.bindingResult = bindingResult;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the MethodParameter that was rejected.
|
||||
*/
|
||||
public MethodParameter getMethodParameter() {
|
||||
return this.parameter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the BindingResult if the failure is validation-related or {@code null}.
|
||||
*/
|
||||
@@ -74,21 +64,18 @@ public class MethodArgumentNotValidException extends MessagingException {
|
||||
}
|
||||
|
||||
|
||||
private static String generateMessage(MethodParameter parameter, BindingResult bindingResult) {
|
||||
|
||||
StringBuilder sb = new StringBuilder("Invalid parameter at index ")
|
||||
.append(parameter.getParameterIndex()).append(" in method: ")
|
||||
.append(parameter.getMethod().toGenericString());
|
||||
|
||||
|
||||
private static String getValidationErrorMessage(MethodParameter parameter, BindingResult bindingResult) {
|
||||
if (bindingResult != null) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(", with ").append(bindingResult.getErrorCount()).append(" error(s): ");
|
||||
for (ObjectError error : bindingResult.getAllErrors()) {
|
||||
sb.append("[").append(error).append("] ");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
else {
|
||||
return "";
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.messaging.handler.annotation.support;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessagingException;
|
||||
|
||||
@@ -26,9 +27,14 @@ import org.springframework.messaging.MessagingException;
|
||||
* @author Stephane Nicoll
|
||||
* @since 4.0.3
|
||||
*/
|
||||
public class MethodArgumentTypeMismatchException extends MessagingException {
|
||||
@SuppressWarnings("serial")
|
||||
public class MethodArgumentTypeMismatchException extends AbstractMethodArgumentResolutionException {
|
||||
|
||||
public MethodArgumentTypeMismatchException(Message<?> message, String description) {
|
||||
super(message, description);
|
||||
|
||||
/**
|
||||
* Create a new instance with the invalid {@code MethodParameter}.
|
||||
*/
|
||||
public MethodArgumentTypeMismatchException(Message<?> message, MethodParameter parameter, String description) {
|
||||
super(message, parameter, getMethodParamMessage(parameter) + description);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user