Home > OS >  Spring Boot unable to set global date format for REST API input
Spring Boot unable to set global date format for REST API input

Time:01-05

I am trying to set a global format for date-time, so that I don't have to annotate each and every method or on DTO fields.

I have tried to configure it globally, the only impact it had was on API response, it is formatting the date in specific pattern.

But it does not accept it as an input format.

@Configuration
public class DateFormatConfig {

    public DateFormatConfig() {
        TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
    }

    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() {
        return builder -> {
            builder.simpleDateFormat("yyyy-MM-dd HH:mm:ss");
            builder.serializers(new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            builder.serializers(new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        };
    }
}

Exception message

org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: 
    Failed to convert value of type 'java.lang.String' to required type 'java.util.Date'; 
nested exception is org.springframework.core.convert.ConversionFailedException: 
    Failed to convert from type [java.lang.String] to type [@org.springframework.web.bind.annotation.RequestParam 
    java.util.Date] for value '2022-01-03 19:32:22'; nested exception is java.lang.IllegalArgumentException
....
Caused by: java.lang.IllegalArgumentException: null
    at java.base/java.util.Date.parse(Date.java:616) ~[na:na]
    at java.base/java.util.Date.<init>(Date.java:274) ~[na:na]
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:na]
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490) ~[na:na]

A REST controller method where the call lands is as follow

public Response update(@PathVariable("id") 
                            Long id,
                       @RequestParam(value = "someTime", required = false) 
                            Date someTime)

My expectaion from above configuration is, it should work for both input and output of the API

  1. It must accept the format I specificy for input
  2. It must accept null as value

Everything works fine if I use @DateTimeFormat annotation, which means for each field I have to make such changes

@RequestParam(value = "someTime", required = false)
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date someTime

CodePudding user response:

Can you try with below code.It should work.

@PostConstruct
    public void init() {
        // Setting Spring Boot SetTimeZone
        TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
    }

CodePudding user response:

you should use

@Bean
public Converter<String, Date> stringDateConverter() {
    return new Converter<String, Date>() {
        final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        @Override
        public Date convert(@NonNull String source) {
            return Date.from(formatter.parse(source, LocalDateTime::from).toInstant(ZoneOffset.UTC));
        }
    };
}

AbstractNamedValueMethodArgumentResolver#resolveArgument use WebDataBinder,WebDataBinder use ConversionService registered in WebMvcAutoConfiguration.EnableWebMvcConfiguration#mvcConversionService, and this converter will be registered in org.springframework.boot.convert.ApplicationConversionService#addBeans

  •  Tags:  
  • Related