feat!: initial prototype
This commit is contained in:
113
src/main/java/eu/bitfield/recipes/api/ErrorResponseHandling.java
Normal file
113
src/main/java/eu/bitfield/recipes/api/ErrorResponseHandling.java
Normal file
@@ -0,0 +1,113 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user