I have an application that uses Spring Boot to provide REST capability. I'm running into a problem deserializing a POST response into a POJO. The exception is as follows:
org.springframework.http.converter.HttpMessageConversionException: Type definition error: [collection type; class uci.BoundedList, contains [simple type, class java.lang.Object]]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `uci.BoundedList` (no Creators, like default construct, exist): no default no-arguments constructor found
The BoundedList
type is part of an API that is generated from an XML schema using XJC. I have no control over how this class is generated. It turns out that it's a subclass of java.util.ArrayList
and has only one constructor defined:
public BoundedList(int minOccurs, int maxOccurs) {
super();
this.minOccurs = minOccurs;
this.maxOccurs = maxOccurs;
}
It does not define a no argument constructor, which is what the exception seems to be complaining about.
Since I cannot modify this class and it is an integral part of the API I'm using, what can I do to get around this problem? Can I supply some sort of customized class/interface that will satisfy the Jackson data binding? Some other possible solution?
UPDATE:
I have tried a number of suggestions based upon answers provided below. None of them work. I'm investigating the "mix-in" approach and I'll admit I don't quite understand how it's supposed to work. The many articles I've read are written simply, but it still seems to be a little "black magic".
In any case, below are snippets of what I've tried to do based on what I've read:
The "mix-in" class:
public abstract class BoundedListMixin {
@JsonCreator
public BoundedListMixin(@JsonProperty("minOccurs") int minOccurs,
@JsonProperty("maxOccurs") int maxOccurs) {}
}
What was added to an existing configuration class:
@Configuration
@EnableAsync
@EnableScheduling
@ComponentScan("<package>")
public class ServiceConfigurer {
@Bean
@Primary
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper mapper = builder.createXmlMapper(false).build();
mapper.addMixIn(BoundedList.class, BoundedListMixin.class);
return mapper;
}
}
I can confirm that the objectMapper()
method in the configuration class is being called via the debugger.
This link (https://dzone.com/articles/jackson-mixin-to-the-rescue) introduces another facet, but alas, that does not work either.
UPDATE:
I have replaced the objectMapper()
method in ServiceConfigurer
(above) with the following:
@Bean
public Jackson2ObjectMapperBuilderCustomizer objectMapperCustomizer() {
return new Jackson2ObjectMapperBuilderCustomizer() {
@Override
public void customize(Jackson2ObjectMapperBuilder builder) {
builder.mixIn(BoundedList.class, BoundedListMixin.class);
}
};
}
I STILL get the same problem. The problem has to be related to some other issue.
NOTE:
I should also clarify that this issue manifests when I made a GET
call. I have a simple REST endpoint that just requests a service return a POJO. Oddly, I if send the request from a browser, the object is returned as JSON and rendered. But, when it's called from the code, I get the exception above.
The GET call:
RequestStatus statusMsg = template.getForObject("http://localhost:8080/rst/missionPlanning/data", RequestStatus.class);