Reputation: 631
I have a projectDTO which accepts a project name and start date. See below
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ProjectDTO {
@NotBlank(message = "project name is required")
private String projectName;
@NotNull(message = "project start date is required")
@Pattern(regexp = "^\\d{4}\\-(0[1-9]|1[012])\\-(0[1-9]|[12][0-9]|3[01])$", message = "date format should be yyyy-MM-dd")
private LocalDate startDate;
}
Below is my ExceptionHandler class
@RestControllerAdvice
public class ApplicationExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
private ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex) {
List<String> errors = ex.getBindingResult()
.getFieldErrors()
.stream()
.map(DefaultMessageSourceResolvable::getDefaultMessage)
.collect(Collectors.toList());
ApiException apiException = ApiException.builder()
.errors(errors)
.httpStatus(HttpStatus.BAD_REQUEST)
.timestamp(ZonedDateTime.now(ZoneId.of("Z")))
.build();
return new ResponseEntity<>(apiException, HttpStatus.BAD_REQUEST);
}
}
If I add a null value for the project name it validates as expected and give the custom error response as below.
{
"errors": [
"project name is required"
],
"httpStatus": "BAD_REQUEST",
"timestamp": "2023-02-17T05:06:08.9362836Z"
}
But if I provide a wrong format for the start date (e.g. - 2023/12-17) the validation is not working. Getting below error
{
"timestamp": "2023-02-17T05:21:07.004+00:00",
"status": 400,
"error": "Bad Request",
"path": "/api/projects"
}
In the console
Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `java.time.LocalDate` from String "2023/02-17": Failed to deserialize java.time.LocalDate: (java.time.format.DateTimeParseException) Text '2023/02-17' could not be parsed at index 4; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.time.LocalDate` from String "2023/02-17": Failed to deserialize java.time.LocalDate: (java.time.format.DateTimeParseException) Text '2023/02-17' could not be parsed at index 4<LF> at [Source: (PushbackInputStream); line: 5, column: 25] (through reference chain: com.theravado.donationservice.dto.ProjectRequest["projects"]->java.util.ArrayList[0]->com.theravado.donationservice.dto.ProjectDTO["startDate"])]
Can you give my some input on how to get this date format validation can be fixed for @Pattern so that I can output an informative error message like in project name?
Cheers
Edited
Thanks @times29. I feel like my validation is not applied at all for the start date here. exquisitely meantioning that "date format should be yyyy-MM-dd" rather than JSON parse error: Cannot deserialize value of type java.time.LocalDate
from String "2023/02-17"
@Pattern(regexp = "^\\d{4}\\-(0[1-9]|1[012])\\-(0[1-9]|[12][0-9]|3[01])$", message = "date format should be yyyy-MM-dd")
Upvotes: 0
Views: 1125
Reputation: 631
Actually the issue was @Pattern cannot be used for LocalDate. When I changed the type to String in my projectDTO this started working
@NotNull(message = "project start date is required")
@Pattern(regexp = "^\\d{4}\\-(0[1-9]|1[012])\\-(0[1-9]|[12][0-9]|3[01])$", message = "date format should be yyyy-MM-dd")
private String startDate;
Upvotes: 0
Reputation: 3373
You need a separate @ExceptionHandler
for the HttpMessageNotReadableException
. Your current @ExceptionHandler(MethodArgumentNotValidException.class)
will only handle MethodArgumentNotValidException
exceptions, but when a HttpMessageNotReadableException
occurrs like in your case, it won't be handled by the handleMethodArgumentNotValid
method.
@ExceptionHandler(HttpMessageNotReadableException.class)
private ResponseEntity<Object> handleHttpMessageNotReadableException(HttpMessageNotReadableException ex) {
List<String> errors = ...; // Extract info from the exception
ApiException apiException = ApiException.builder()
.errors(errors)
.httpStatus(HttpStatus.BAD_REQUEST)
.timestamp(ZonedDateTime.now(ZoneId.of("Z")))
.build();
return new ResponseEntity<>(apiException, HttpStatus.BAD_REQUEST);
}
Upvotes: 0