There are some issues with the ObjectMapper generated by the default configuration in the Spring context. When using the readerWithView() method to deserialize objects, it results in an error (all properties of the generated object are null). This directly affects Spring Messaging because MappingJackson2MessageConverter uses this method for deserialization, causing failures in Spring Messaging. However, when I use an ObjectMapper created with Jackson's default configuration, the issue does not occur. I created a Test project kotlin , java to verify this, and below is the simplified code for the test:
Different: Spring ObjectMapper: MapperFeature.DEFAULT_VIEW_INCLUSION is false Default ObjectMapper: MapperFeature.DEFAULT_VIEW_INCLUSION is true I don't know this a wrong configuration or Jackson's bug!
Spring boot version is 3.3.4
@ExtendWith({SpringExtension.class})
@SpringBootTest(classes = Main.class)
public class JsonTest {
static class SimpleStockFreezeStatusMessage {
private Long businessId;
private Boolean success;
private String tenantId;
// getter and setter ...
}
public void testSpringJsonMessage(ObjectMapper objectMapper) throws IOException {
var json = "{\"businessId\":1336504106360835,\"tenantId\":\"first\",\"success\":false}";
var value = objectMapper.readValue(json, SimpleStockFreezeStatusMessage.class);
System.out.println("message ser by readValue : " + value.tenantId);
// success
assertEquals(value.tenantId, "first");
Class<?> view = SimpleStockFreezeStatusMessage.class;
JavaType javaType = objectMapper.constructType(new TypeReference<SimpleStockFreezeStatusMessage>() {});
//this is Spring message Usage
var value2 = (SimpleStockFreezeStatusMessage)objectMapper.readerWithView(view).forType(javaType).readValue(json);
System.out.println("message ser by readerWithView: " + value2.tenantId);
// tenantId is null
assertEquals(value2.tenantId, "first");
}
@Autowired
private ObjectMapper objectMapper;
//Fails
@Test
public void testBySpringMapper() throws IOException {
testSpringJsonMessage(objectMapper);
}
//Success
@Test
public void testByDefaultMapper() throws IOException {
testSpringJsonMessage(new ObjectMapper());
}
}
The same issue also exists in version 3.2.9
Comment From: quaff
Different: Spring ObjectMapper: MapperFeature.DEFAULT_VIEW_INCLUSION is false Default ObjectMapper: MapperFeature.DEFAULT_VIEW_INCLUSION is true I don't know this a wrong configuration or Jackson's bug!
Spring Framework set DEFAULT_VIEW_INCLUSION to false by default.
https://github.com/spring-projects/spring-framework/blob/b3cc9a219e79cd7c99c528229be502f55fa9c97b/spring-web/src/main/java/org/springframework/http/converter/json/Jackson2ObjectMapperBuilder.java#L814
You can enable it by configuration properties:
spring.jackson.mapper.default-view-inclusion: true
Comment From: cooperlyt
Different: Spring ObjectMapper: MapperFeature.DEFAULT_VIEW_INCLUSION is false Default ObjectMapper: MapperFeature.DEFAULT_VIEW_INCLUSION is true I don't know this a wrong configuration or Jackson's bug!
Spring Framework set
DEFAULT_VIEW_INCLUSIONtofalseby default.https://github.com/spring-projects/spring-framework/blob/b3cc9a219e79cd7c99c528229be502f55fa9c97b/spring-web/src/main/java/org/springframework/http/converter/json/Jackson2ObjectMapperBuilder.java#L814
You can enable it by configuration properties:
yaml spring.jackson.mapper.default-view-inclusion: true
I believe that unless there's a specific reason, Spring Boot should set the default value of DEFAULT_VIEW_INCLUSION to true. When it is set to false, the org.springframework.messaging.converter.MappingJackson2MessageConverter will fail. It took me two days of debugging to find this configuration, and it posed an obstacle for using Spring Messaging.
However, setting spring.jackson.mapper.default-view-inclusion: true has solved my problem.
Thanks
Comment From: mdeinum
There is a specific reason, which can be found here (in a migrated issue from 2014).
Comment From: wilkinsona
Thanks for the report, but as explained above, Spring Boot is just picking up Spring Framework's default configuration and we don't want to override that as it is false for good reason. If you disagree with this default in Spring Framework, you may want to open a Spring Framework issue.
Comment From: cooperlyt
Oh, that sounds reasonable. We should expect Jackson-databind's readerWithView() method to work even when DEFAULT_VIEW_INCLUSION is set to false. I believe this is a bug in Jackson-databind. Thanks for all!
Comment From: quaff
Oh, that sounds reasonable. We should expect Jackson-databind's readerWithView() method to work even when DEFAULT_VIEW_INCLUSION is set to false. I believe this is a bug in Jackson-databind. Thanks for all!
It's designed feature, why do you think it's a bug of jackson-databind?
Comment From: cooperlyt
Oh, that sounds reasonable. We should expect Jackson-databind's readerWithView() method to work even when DEFAULT_VIEW_INCLUSION is set to false. I believe this is a bug in Jackson-databind. Thanks for all!
It's designed feature, why do you think it's a bug of jackson-databind?
Class<?> view = SimpleStockFreezeStatusMessage.class;
JavaType javaType = objectMapper.constructType(new TypeReference<SimpleStockFreezeStatusMessage>() {});
//this is Spring message Usage
var value2 = (SimpleStockFreezeStatusMessage)objectMapper.readerWithView(view).forType(javaType).readValue(json);
System.out.println("message ser by readerWithView: " + value2.tenantId);
//fail tenantId is null
assertEquals(value2.tenantId, "first");
In this code, I have explicitly specified the "View", so even with DEFAULT_VIEW_INCLUSION set to false, it should successfully return the object. However, right now, the returned object has all its properties as null. Isn't this a bug?
And this is exactly how org.springframework.messaging.converter.MappingJackson2MessageConverter is implemented!
Comment From: cooperlyt
Oh, that sounds reasonable. We should expect Jackson-databind's readerWithView() method to work even when DEFAULT_VIEW_INCLUSION is set to false. I believe this is a bug in Jackson-databind. Thanks for all!
It's designed feature, why do you think it's a bug of jackson-databind?
You're right, I made a mistake; I misunderstood readerWithView(),This is indeed not a bug, but it's still quite puzzling that Spring Messaging doesn't work correctly by default. It's especially challenging when using Java instead of Kotlin, as there are no null checks, and without any exceptions being thrown, it makes troubleshooting much more difficult.
Comment From: quaff
Class<?> view = SimpleStockFreezeStatusMessage.class;
I think you misunderstood @JsonView, SimpleStockFreezeStatusMessage seems not like a view.