spring-hateoas: @EnableHypermediaSupport is not compatible with Spring Boot's Jackson2ObjectMapperBuilder
I am trying to customize Jackson serialization for ISO dates. Per Spring Boot instructions, I created a @Bean of type Jackson2ObjectMapperBuilder:
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.featuresToDisable(
SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,
DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
return builder;
}
However, I find that these settings are not applied when using @EnableHypermediaSupport. When I remove the annotation, I see the effects of the Jackson serialization settings.
About this issue
- Original URL
- State: closed
- Created 9 years ago
- Comments: 49 (11 by maintainers)
To take the comment from @gregturn a bit further, I agree that the best solution is to work off of Spring Boot’s auto-configuration instead of creating your own custom
ObjectMapper. However, in your code, it doesn’t seem that you are addressing the issue of using@EnableHypermediaSupport. For most cases (i.e. serializing) this doesn’t seem to be needed, and putting all settings for Jackson inapplication.ymletc. works perfectly fine. On the other hand, in the case where you want to deserialize json responses, we need to use the_halObjectMapperin Spring HATEOAS to get this to work properly.Here is an example of a very simple solution which worked for me (using Spring Boot 1.5.2 and Spring HATEOAS 0.23.0, and it is also using Spring Boot’s own API for customizing the auto-configured
ObjectMapper(just like @gregturn shows in his code):In Application.java:
@EnableHypermediaSupport(type = HypermediaType.HAL)In
application.yml:@Configuration-annotated class:It’s clean and simple, and not very invasive either.
To expand on @thebignet’s solution you can apply the default configuration from Boot’s Jackson2ObjectMapperBuilder by injecting it and using its configure method.
Update
Section 27.1.8 - Spring HATEOAS in the Spring Boot docs indicates that simply leaving off the @EnableHypermediaSupport annotation will let Boot’s autoconfiguration kick in for HATEOAS and create a proper ObjectMapper with the standard modules loaded and properties and features applied.
Are you using HAL? If so, we found that Spring HATEOAS constructs its own object mapper. In order to address this in our project, we did the following to get the whole application using the same configuration.
Resolved via #719 and #723.
You are right. Its more the other way round (Spring Data REST is using HATEOAS). So this make no sense. Anyway to provide a third workaround, I use a BeanPostProcessor to configure my ObjectMapper:
Would be nice to have this one documented as a “gotcha” in the docs.
I had a similar issue with spring boot and HATEOAS. The workaround was to register a bean post processor, rather than creating multiple beans of the same type.
I just updated to Spring Boot 2.0.4 and Spring HATEOAS 0.25.0 which lead to a failing Jackson configuration as _halObjectMapper is no longer available.
I was trying to refactor my code according to the changes in #719, but to no avail.
With 0.25.0, what would be a simple way to configure the ObjectMapper that is being used by Spring HATEOAS?
I’ve sifted through all the comments, and have an example github repo (Spring Boot 1.5.4 + Spring HATEOS 0.23) that covers this in detail (https://github.com/gregturn/spring-hateoas-customize-jackson).
If you read the Spring Boot docs, you have multiple options:
spring.jackson.serialization.indent-output=true). You can uncomment what I have insrc/main/resources/application.properties, and see that by starting up my app, this works.Jackson2ObjectMapperBuilderCustomizerbean, which is handed a copy of Boot’s autoconfiguredJackson2ObjectMapperBuilderafter applying Boot’s defaults. If you uncomment the@Beanannotation inside my repo’sCustomizeJacksonconfiguration class, you can see this behavior applied.Both of these solutions appear simpler to plug in your custom
ObjectMappersettings than the other presented mechanisms.It’s also possible to create your own
Jackson2ObjectMapperBuilder, but there are actually a handful of other things you must undertake should you take this approach. As stated in the docs,Notice the last sentence in that quote: “You will disable all autoconfiguration of the ObjectMapper”. That’s why this is NOT recommended.
I haven’t reconciled this with Spring Data REST’s HAL-based object mapper (yet). But I wanted to clarify the proper approach.
P.S. This probably would make good material for Spring HATEOAS’s reference docs.
None of the workarounds in this ticket seem to be working any longer with spring-hateoas 0.23 and boot 1.5.3.
The
objectMappermethod is never called (verified with debugger).@pleimann thanx for the suggested workaround, it works. I would also suggest to declare the
@Bean(name = "objectMapper")as@Primary; this is how Spring Boot’s autoconf works, see JacksonAutoConfigurationIf it’s any help, I ended up mixing @gpaul-idexx and @thomasletsch solutions
This might be a more Spring-Boot approach to rendering Java8 dates with the HAL Jackson Object Mapper.
I’m also loosing the Java 8
com.fasterxml.jackson.datatype.jsr310.JavaTimeModuleif using@EnableHypermediaSupportwith spring boot 1.3.1 Thanks to @thomasletsch for the BeanPostProcessor workaround!I believe this is because Spring HATEOAS uses its own object mapper. You will have to set these flags on that instance. You can access the object mapper using the bean factory: