Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jersey serialization/deserialization issue: abstract types can only be instantiated with additional type information

I'm using jersey for both serialization and deserialization. I've made REST channel on WebLogic using jersey. I have result object with contains abstract class. Jersey adds to the result metadata with this class'es implementation name:

{"order":{"@type":"installationOrder",

However, the same jersey, when using to deserialize this data, is screaming the following:

Caused by: org.codehaus.jackson.map.JsonMappingException: Can not construct instance of ocl.mobile.service.data.order.DetailedOrder, problem: abstract types can only be instantiated with additional type information
 at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@97eded; line: 1, column: 2] (through reference chain: ocl.mobile.service.OrderDetailsResult["order"])
    at org.codehaus.jackson.map.JsonMappingException.from(JsonMappingException.java:163)
    at org.codehaus.jackson.map.deser.StdDeserializationContext.instantiationException(StdDeserializationContext.java:212)
    at org.codehaus.jackson.map.deser.AbstractDeserializer.deserialize(AbstractDeserializer.java:97)
    at org.codehaus.jackson.map.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:252)
    at org.codehaus.jackson.map.deser.SettableBeanProperty$MethodProperty.deserializeAndSet(SettableBeanProperty.java:356)
    at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:494)
    at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:350)
    at org.codehaus.jackson.map.ObjectMapper._readValue(ObjectMapper.java:2376)
    at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1166)
    at org.codehaus.jackson.jaxrs.JacksonJsonProvider.readFrom(JacksonJsonProvider.java:410)
    at com.sun.jersey.json.impl.provider.entity.JacksonProviderProxy.readFrom(JacksonProviderProxy.java:139)
    at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:553)
    ... 5 more

but he himself have provided this additional information in the JSON he has serialized.

So, how to make jersey to read and understand this "@type" annotations he have created?

This is how I'm using jersey to read data from channel:

private static Client client;

private static void initClient() {
    if (client == null) {
        ClientConfig clientConfig = new DefaultClientConfig();
        clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING,
                Boolean.TRUE);
        client = Client.create(clientConfig);
    }
}

private static <T> T jsonForResult(String addr, Class<T> expectedClass) {
    initClient();
    WebResource r = client.resource(addr);
    try {
        T result = r.get(expectedClass);
    return result;
        } catch (UniformInterfaceException e) {
        log.error(e.getMessage(), e);
        return null;
    }
}

The expectedClass is in my case the class of result, which contains status and the abstract class "order", which has implementations such as "installationOrder".

like image 207
Danubian Sailor Avatar asked Jan 30 '12 15:01

Danubian Sailor


2 Answers

try this it works

@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = ExchangeFormat.class, name = "ExchangeFormat"),
@JsonSubTypes.Type(value = TypeStatus.class, name = "TypeStatus"),
})
public abstract class MapperJsonXml <T>

it's the same with xml

@XmlSeeAlso({ExchangeFormat.class,TypeStatus.class})
like image 61
nizar ouerghi Avatar answered Nov 05 '22 04:11

nizar ouerghi


Jersey (or more specifically, Jackson JSON lib it uses with POJO mapping) does not add @type unless type information inclusion is enabled, usually by adding @JsonTypeInfo on an abstract type. So something must have enabled this. Maybe you can share definition DetailOrder class?

As to problem itself: this is usually caused by incompatible types used -- type used for deserialization (reading JSON value into POJO) must be such that @JsonTypeInfo annotation is visible. You can not, for example, just ask for value of type java.lang.Object, since it does not have such annotation. Without knowing actual class definitions it is not possible to point to specific cause, but this is the most likely explanation.

like image 35
StaxMan Avatar answered Nov 05 '22 06:11

StaxMan