SpringBoot @DateTimeFormat and custom error message via MessageSource

721 views Asked by At

I'm trying to avoid return this kind of error to the client when the Spring fails to convert a date using @DateTimeFormat

Failed to convert property value of type 'java.lang.String' to required type 'java.time.LocalDateTime' for property 'myDate'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [@org.springframework.format.annotation.DateTimeFormat java.time.LocalDateTime] for value '2023-01-01 00:00'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [2023-01-01 00:00]

This is what I tried.

public class MyDTO {

  @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
  private LocalDateTime myDate;
}

A Controller

@GetMapping("/hello")
public String test(@ParameterObject MyDTO myDTO) {
    return "hello";
}

In the messages.properties file I have added (added different combinations just to test)

typeMismatch.java.time.LocalDateTime=Date is not correctly formatted
typeMismatch=Date is not correctly formatted

I also have a Controller advice

@ControllerAdvice
public class MyControllerAdvice {

@ExceptionHandler(BindException.class)
  public ResponseEntity<....> handleBindException(BindException e) {
   // I break point in here to see what's inside e and verify my custom error code is in there somewhere
  }
}

If I call the controller with a wrong date such has 2023-01-01 00:00, Spring correctly throws a BindException containing the original exception details and the following error codes

typeMismatch.java.time.LocalDateTime
typeMismatch.MyDTO.myDate
typeMismatch.myDate
typeMismatch

But my custom error message is no where to be seen. The only way to get it is to manually @Autowired MessageSource messageSource (which is automatically created by SpringBoot using the ResourceBundleMessageSource implementation and call messageSource.getMessage(code, args, locale) OR messageSource.get((MessageSourceResolvable) e.getBindingResult().getFieldError().getArguments()[0], locale)

Now from reading various SO on the subject, people seem to say that by just adding the custom error message in the messages.properties it should magically adds these error message somewhere in the exception but I cannot see this kind of code anywhere in the spring code base (DefaultMessageCodesResolver? DefaultBindingErrorProcessor ? org.springframework.format.datetime.standard.TemporalAccessParser where the actual DateTimeParseException is thrown ?

Did I just read these answers wrong and whatever we add in the messages.properties needs to be manually fetched using messageSource.getMessage(code, args, locale) from the Controller Advice ?

0

There are 0 answers