Search code examples
javaspring-bootobjectmapper

Configure JavaTimeModule in ObjectMapper globally instead of using @datetimeformat


Hi I try to create a controller which will accept request-parameter as LocalDateTime.

ex: /api/actions?page=0&size=10&from=2018-05-02T20:20:20&to=2018-06-02T20:20:20

at controller if I using code bellow it work:

@RequestParam(value = "from")
        @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
                LocalDateTime from,
        @RequestParam(value = "to")
        @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
                LocalDateTime to

But I want to move @DateTimeFormat to globally configuration, and I choose ObjectMapper:

I create a bean in configuration:

@Bean
public ObjectMapper jacksonObjectMapper() {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    JavaTimeModule javaTimeModule = new JavaTimeModule();
    javaTimeModule.addSerializer(
            LocalDateTime.class,
            new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(dateTimeFormat)));
    objectMapper.registerModule(javaTimeModule);
    return objectMapper;
}

And try

@Bean
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
    ObjectMapper objectMapper = builder.createXmlMapper(false).build();
    objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    JavaTimeModule javaTimeModule = new JavaTimeModule();
    javaTimeModule.addSerializer(
            LocalDateTime.class,
            new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(dateTimeFormat)));
    objectMapper.registerModule(javaTimeModule);
    return objectMapper;
}

This is dateTimeFormat value: yyyy-MM-dd'T'HH:mm:ss.SS

Both of 2 ways above are not working, It said:

class org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'java.time.LocalDateTime'; 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.time.LocalDateTime] for value '2018-05-02T20:20:20'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [2018-05-02T20:20:20]

My jackson version:

<dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-jsr310</artifactId>
        <version>2.8.8</version>
    </dependency>

Am I missing something? Thank you for your time.


Solution

  • Problem is I pass LocalDateTime at requestParam, but I using ObjectMapper which only work with request's body.

    And to resolve my issue I create new component LocalDateTimeConverter and remove bean of ObjectMapper.

    @Component
    public class LocalDateTimeConverter implements Converter<String, LocalDateTime> {
    private final DateTimeFormatter formatter;
    
    @Autowired
    public LocalDateTimeConverter(@Value("${dateTime.format}") String dateTimeFormat) {
        this.formatter = DateTimeFormatter.ofPattern(dateTimeFormat);
    }
    
    @Override
    public LocalDateTime convert(String source) {
        if (source == null || source.isEmpty()) {
            return null;
        }
    
        return LocalDateTime.parse(source, formatter);
    }
    }