У меня есть API для отдыха, который имеет 3 поля ввода, а именно EmployeeId, isActive и Name. EmployeeId определен как Long, isActive как логическое значение и имя как String. Мне нужно знать, когда кто-то передает недопустимые значения для этих полей, например: alphanumeri c значение для employeeId (число), как бы я обработал это и представил пользовательское сообщение об ошибке, говорящее «EmployeeId может быть только числом и должно иметь от 8 до 11 цифры "?
Я пытался определить пользовательский десериализатор и создать ControllerAdvice, но он не сработал. Ниже приведены классы.
JSON RequestDTO:
public class Address implements Serializable {
private static final long serialVersionUID = -1946551108793695733L;
@JsonDeserialize(using = NumberDeserializer.class)
@JsonSerialize(using =NumberSerializer.class)
private Long employeeId;
private Boolean isManager;
private String name;
//getters and setters
}
-----------------------------------------------------------------------------
Custom ControllerAdvice implelementation:`enter code here`
public class CustomControllerAdvice extends ResponseEntityExceptionHandler {
//other exception handlers
private static final String STRING_CONSTANT_VALIDATION_ERRORS = "Validation errors";
private static final String STRING_CONSTANT_APPLICATION_ERRORS = "Some error occured while processing the request. Please reach out to the customer service.";
@ExceptionHandler(DateFormatException.class)
@ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ResponseEntity<Object> handleDateFormatException(
DateFormatException ex) {
log.info("handling exception for DateFormatException");
ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, STRING_CONSTANT_VALIDATION_ERRORS);
apiError.setMessage(ex.getMessage());
return buildResponseEntity(apiError);
}
@ExceptionHandler(DateTimeFormatException.class)
@ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ResponseEntity<Object> handleDateTimeFormatException(
DateFormatException ex) {
log.info("handling exception for DateTimeFormatException");
ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, STRING_CONSTANT_VALIDATION_ERRORS);
apiError.setMessage(ex.getMessage());
return buildResponseEntity(apiError);
}
@ExceptionHandler(NullPointerException.class)
@ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ResponseEntity<Object> handleNullPointerException(
DateFormatException ex) {
log.info("handling exception for DateTimeFormatException");
ApiError apiError = new ApiError(HttpStatus.INTERNAL_SERVER_ERROR, STRING_CONSTANT_APPLICATION_ERRORS);
apiError.setMessage(ex.getMessage());
return buildResponseEntity(apiError);
}
@ExceptionHandler(InvalidNumberException.class)
@ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ResponseEntity<Object> handleInvalidNumberException(
DateFormatException ex) {
log.info("handling exception for DateFormatException");
ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, STRING_CONSTANT_VALIDATION_ERRORS);
apiError.setMessage(ex.getMessage());
return buildResponseEntity(apiError);
}
@ExceptionHandler(Exception.class)
@ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ResponseEntity<Object> handleAnyOtherException(
DateFormatException ex) {
log.info("handling any other type of exception");
ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, STRING_CONSTANT_VALIDATION_ERRORS);
apiError.setMessage(ex.getMessage());
return buildResponseEntity(apiError);
}
private ResponseEntity<Object> buildResponseEntity(ApiError apiError) {
return new ResponseEntity<>(apiError, apiError.getStatus());
}
}
-----------------------------------------------------------------------------
Desrializer implementation
public class NumberDeserializer extends JsonDeserializer<Long> {
@Override
public Long deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
JsonToken currentToken = jp.getCurrentToken();
boolean errorOccured = false;
Long retVal = 0l;
log.info("Inside the NumberDeserializer, supplied value being null? {}", currentToken == null || StringUtils.isBlank(currentToken.asString()));
if (currentToken == null || JsonToken.VALUE_NULL.equals(currentToken)) {
log.info("inside null");
retVal = null;
}
else if (!StringUtils.isBlank(currentToken.asString())) {
try {
log.info("inside not null");
retVal = Long.parseLong(currentToken.asString());
}catch(NumberFormatException nfe) {
errorOccured = true;
log.error("JSON desrialization error: invalid mumber "+currentToken.asString());
}
if(errorOccured) {
log.info("throwing the InvalidNumberFormatException for supplied value {}", currentToken.asString());
throw new InvalidNumberException("Invalid value "+ currentToken.asString()+" being passed for a numeric value");
}
}
log.info("return");
return retVal;
}
}
-----------------------------------------------------------------------------
Serializer Implementation:
@Slf4j
@JsonComponent
public class NumberSerializer extends JsonSerializer<Long> {
@Override
public void serialize(Long value, JsonGenerator jgen, SerializerProvider arg2) throws IOException {
log.info("inside the serializer start. Value being {}", value);
try {
if (value == null) {
jgen.writeNull();
}
else {
jgen.writeString(value.toString());
}
}catch (Exception e){
log.info("inside the serializer catch block");
jgen.writeString(StringUtils.EMPTY);
e.printStackTrace();
}
log.info("inside the serializer end");
}
-----------------------------------------------------------------------------
ApiError - это пользовательский класс для инкапсуляции сведений (httpStatus, сообщение об ошибке) для отправки в ответ.
В настоящее время я вижу только Http 400 в ответе с пустым содержимым:
Response Code
400
Response Headers
{
"content-length": "0",
"date": "Mon, 20 Jan 2020 15:44:14 GMT",
"content-type": null
}