I was working on a test in my Spring-Boot app and noticed that the timestamps in JSON output were sometimes formatted incorrectly. Luckily I was able to identify the issue and fix it.
During an integration test I noticed that an expected JSON output of "2019-08-26T08:22:21Z"
was actually 1566807741.000000000
even though in other tests in my application the automatic conversion from java.time.Instant
to an ISO8601-formatted string was working just fine. As is the default for Spring-Boot, Jackson’s ObjectMapper
was used for the conversion. So what could make Jackson work correctly in one case but not another?
First I thought that I did something wrong with configuring so I did a lot of googling in order to find out what I was doing wrong. I added jackson-datatype-jsr310
to my project’s dependencies, I disabled Jackson’s “write dates as timestamps†serializer feature in four different ways but the error would persist. I dug into how the ObjectMapper
used by Spring was created; maybe the feature was not disabled correctly? No, it was disabled just fine but Jackson still would not format the Instant
properly.
During my research on how to create your own ObjectMapper
and have Spring use it, I stumbled upon this question. It had nothing to do with my immediate problem but it mentioned that when using a @Configuration class extending WebMvcConfigurationSupport
in conjunction with @EnableWebMvc Spring-Boot’s auto-configuration would be disabled. A disabled auto-configuration could explain an ObjectMapper
that can not format Instant
s properly!
As it turns out, I had a SwaggerConfiguration
class that extended WebMvcConfigurationSupport
. Following the hints in the StackOverflow post I replaced the superclass by WebMvcConfigurerAdapter
only to discover that it was deprecated. Fixing that was easy, though, as the interface WebMvcConfigurer
could (and should!) be used instead. And this made my integration test work…
…although at this point I am still not 100% sure why. I am not using @EnableWebMvc anywhere (just @SpringBootApplication) so I do not yet know why the SwaggerConfiguration
class extending WebMvcConfigurationSupport
would disable Spring-Boot’s auto-configuration mechanisms. Spring’s usually excellent documentation is rather unclear as to what happens if you only do one of those things.
I also don’t know why the Jackson mapper in the working test had its “write dates as timestamps†serializer feature disabled but the one in the other test had not. From my understanding it must have been disabled so that Jackson’s jackson-datatype-jsr310
module was used—it was already a part of my dependencies without me knowing so explicitely adding it to my project’s build file did not actually change anything.
And even though my mental model of some things involving Spring has been improved by getting this to work I will not investigate this any further. My integration tests work and that shall be good enough for me, for today.