Closed holgerstolzenberg closed 10 years ago
I have been able to get the gradle eclipse
plugin to work with your sample application so I have tried to create a simplified project to reproduce the problem.
Unfortunately, I've not been able to fully replicate the issue. If I run the application the com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer
class does kick-in and the JSON is rendered correctly as three fields:
{
"birthday": [
2014,
9,
25
]
}
If I completely manage the HttpMessageConverters
(see commented out code in Repro1620Application
) then no custom serialization occurs:
{
"birthday": {
"year": 2014,
"month": "SEPTEMBER",
"dayOfMonth": 25,
"dayOfWeek": "THURSDAY",
"era": "CE",
"dayOfYear": 268,
"leapYear": false,
"monthValue": 9,
"chronology": {
"id": "ISO",
"calendarType": "iso8601"
}
}
}
What do you mean by "birthday property is correctly mapped to a string representation"? I'm not really sure which part of the JSON serialization process would cause this to happen. Could you update the issues project that I created to show me how you would expect the String representation to be marshaled?
Please excuse, my description was a bit unprecise. I mean exactly the behaviour you described. With the overridden mappers, the birthday property is (correctly) rendered in JSON:
{
"birthday": [
2014,
9,
25
]
}
Commenting out the override causes the birthday property to be rendered as JSON representation of the LocalDate
class (incorrect).
The point is: Why are these overrides necessary? I do not change anything to the mappingJackson2HttpMessageConverter
, because it is setup correctly by spring boot.
I have managed to reproduce the issue with your simplified sample application. Adding @EnableWebMvc
breaks the JSON rendering behaviour. I have created a pull request at spring-boot-issues
project that showcases that. I had to change the parent POM version to 1.1.6.RELEASE.
The above references are invalid as they have been hooked up because I accidentally committed a fix for gh-1619 on a branch for gh-1620. The invalid gh-1620 branch has been removed, therefore the above references are invalid. They can be deleted by someone with write access.
Indeed, with your PR and additional explanations, I have been able to reproduce this behavior. In fact, when @EnableWebMvc
is used, Spring Framework (and not Spring Boot) is responsible to create the message converters.
Up to Spring Framework 4.1.0, MappingJackson2HttpMessageConverter
was using the default Jackson ObjectMapper
constructor, which has not JSR-310 module automatically enabled.
Fortunately, the recently released Spring Framework 4.1.1 now uses Jackson2ObjectMapperBuilder
to create the ObjectMapper
and it is JSR-310 aware. Spring Boot 1.2.0.BUILD-SNAPSHOT already has the right behavior since it depends on the latest Spring Framework version and is Jackson2ObjectMapper
aware (see commit 315213ea4e2fb3b4dd42c056b0a0da5f05d9f01a for more details).
So with Spring Boot 1.1.x, you should use @EnableAutoConfiguration
without @EnableWebMvc
in order to allow Spring Boot to autoconfigure your ObjectMapper
instance. If you want to use @EnableWebMvc
and still would like to have your ObjectMapper
instance autoconfigured, you should specify <spring.version>4.1.1.RELEASE</spring.version>
in your Maven properties.
I used @EnableWebMvc
on the WebConfig
, and created a custome @Configuration for ObjectMapper
, it does not work.
@Configuration public class Jackson2ObjectMapperConfig { @Bean @Primary public ObjectMapper objectMapper() { Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); builder.serializationInclusion(Include.NON_EMPTY); builder.featuresToDisable( SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); builder.featuresToEnable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY); builder.modulesToInstall(JSR310Module.class); return builder.build(); } }
Using @EnableWebMvc
turns off Spring Boot's auto-configuration of Spring MVC, is that what you intended? Also, it's not clear what you mean by "it does not work".
If you'd like some help, please post on Stackoverflow using the spring-boot
tag, describing the behaviour that you expected to see and what the actual behaviour was. A small sample that reproduces the problem would also help.
Using @EnableWebMvc
disable Spring Boot web autoconfiguration, so the ObjectMapper
bean is not used anymore. In order to make it work, remove @EnableWebMvc
. If you need to use Spring MVC JavaConfig, you can declare a WebMvcConfigurer
bean instead, and return a WebMvcConfigurerAdapter
instance.
@sdeleuze I used custom WebMvcConfigurerAdpter
class(WebConfig
) which annotated withEnableWebMvc
and @Configuration
. And a standalone Jackson2ObjectMapperConfig
for ObjectMapper
(listed above). All of these are ported from my before projects(none spring boot project), but these did not work as exptected, the new Jdk 8 jsr310 jackson serialization configuration is not applied. As an end user of Spring boot, I hope my custom configuration owns high priority other than auto configuration provided by Spring Boot, thus I can move to Spring Boot painlessly.
Thanks for your help, @sdeleuze , and @wilkinsona
@hantsy As proposed by @wilkinsona , feel free to post a Stackoverflow question link, I will answer you there.
Please see
https://github.com/ewerk/sample_spring-boot-camel-mongo-jdk8/blob/features/jsr310/prototype-app/src/main/java/com/ewerk/prototype/api/ApiConfiguration.java
that illustrates the problem. The
ApiConfiguration
class does nothing special then overriding the HttpMessageConverters used by WebMVC. I am not configuring anything special to the JacksonObjectMapper
. The jackson JSR-310 module is on the classpath.If you launch the app and access the URL
http://localhost:9090/prototype/api/persons/all
you can see that the person beans birthday property is correctly mapped to a string representationCommenting out the code within
ApiConfiguration
and running the app again shows that the birthday property is rendered as a JSON object.Debugging the app shows that all autoconfiguration related stuff is honoring the JSR-310 module, which then gets registered in the
@PostConstruct
method ofJacksonAutoConfiguration
. But something in bean creation order is messed up or the Jackson message converter created as default does not use theObjectMapper
instance created by spring boot autoconfiguration.