114 lines
4.6 KiB
Java
114 lines
4.6 KiB
Java
package eu.bitfield.recipes.api;
|
|
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
import org.springframework.context.MessageSourceResolvable;
|
|
import org.springframework.core.MethodParameter;
|
|
import org.springframework.http.ProblemDetail;
|
|
import org.springframework.util.MultiValueMap;
|
|
import org.springframework.validation.FieldError;
|
|
import org.springframework.validation.ObjectError;
|
|
import org.springframework.validation.method.ParameterValidationResult;
|
|
import org.springframework.web.ErrorResponse;
|
|
import org.springframework.web.ErrorResponseException;
|
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
|
import org.springframework.web.bind.support.WebExchangeBindException;
|
|
import org.springframework.web.method.annotation.HandlerMethodValidationException;
|
|
import org.springframework.web.server.ServerWebInputException;
|
|
|
|
import java.lang.reflect.Executable;
|
|
import java.lang.reflect.Parameter;
|
|
import java.util.List;
|
|
|
|
import static eu.bitfield.recipes.util.CollectionUtils.*;
|
|
import static org.springframework.http.HttpStatus.*;
|
|
|
|
public interface ErrorResponseHandling {
|
|
Logger log = LoggerFactory.getLogger(ErrorResponseHandling.class);
|
|
|
|
private static void addMethodParameter(ProblemDetail problemDetail, MethodParameter methodParam) {
|
|
Executable executable = methodParam.getExecutable();
|
|
Parameter param = methodParam.getParameter();
|
|
String method = executable.toGenericString();
|
|
String argument = param.getType().getCanonicalName() + " " + param.getName();
|
|
problemDetail.setProperty("method", method);
|
|
problemDetail.setProperty("argument", argument);
|
|
}
|
|
|
|
@ExceptionHandler
|
|
default ErrorResponse handleError(HandlerMethodValidationException e) {
|
|
log.debug("""
|
|
Handling {}:
|
|
method: {}
|
|
errors: {}""",
|
|
e.getClass().getName(), e.getMethod(), e.getAllErrors(), e);
|
|
|
|
ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(BAD_REQUEST, e.getReason());
|
|
|
|
String method = e.getMethod().toGenericString();
|
|
problemDetail.setProperty("method", method);
|
|
|
|
MultiValueMap<String, String> errors = multiValueMap();
|
|
for (ParameterValidationResult result : e.getParameterValidationResults()) {
|
|
Parameter param = result.getMethodParameter().getParameter();
|
|
String errorKey = param.getName();
|
|
List<String> errorValues = result.getResolvableErrors()
|
|
.stream()
|
|
.map(MessageSourceResolvable::getDefaultMessage)
|
|
.toList();
|
|
errors.addAll(errorKey, errorValues);
|
|
}
|
|
problemDetail.setProperty("errors", errors);
|
|
|
|
return ErrorResponse.builder(e, problemDetail).build();
|
|
}
|
|
|
|
@ExceptionHandler
|
|
default ErrorResponse handleError(WebExchangeBindException e) {
|
|
List<ObjectError> objectErrors = e.getAllErrors();
|
|
log.debug("""
|
|
Handling {}:
|
|
methodParameter: {}
|
|
errors: {}""",
|
|
e.getClass().getName(), e.getMethodParameter(), e.getAllErrors(), e);
|
|
|
|
ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(BAD_REQUEST, e.getReason());
|
|
|
|
MethodParameter methodParam = e.getMethodParameter();
|
|
if (methodParam != null) addMethodParameter(problemDetail, methodParam);
|
|
|
|
MultiValueMap<String, String> errors = multiValueMap();
|
|
for (ObjectError objectError : objectErrors) {
|
|
String errorKey = objectError.getObjectName();
|
|
if (objectError instanceof FieldError fieldError) {
|
|
errorKey += "." + fieldError.getField();
|
|
}
|
|
errors.add(errorKey, objectError.getDefaultMessage());
|
|
}
|
|
problemDetail.setProperty("errors", errors);
|
|
|
|
return ErrorResponse.builder(e, problemDetail).build();
|
|
}
|
|
|
|
@ExceptionHandler
|
|
default ErrorResponse handleError(ServerWebInputException e) {
|
|
log.debug("""
|
|
Handling {}:
|
|
methodParameter: {}""",
|
|
e.getClass().getName(), e.getMethodParameter(), e);
|
|
|
|
ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(BAD_REQUEST, e.getReason());
|
|
|
|
MethodParameter methodParam = e.getMethodParameter();
|
|
if (methodParam != null) addMethodParameter(problemDetail, methodParam);
|
|
|
|
return ErrorResponse.builder(e, problemDetail).build();
|
|
}
|
|
|
|
@ExceptionHandler
|
|
default ErrorResponse handleError(ErrorResponseException e) {
|
|
log.debug("Handling {}", e.getClass().getName(), e);
|
|
return e;
|
|
}
|
|
}
|