2010-09-09 22 views
6

Tengo una clase de recurso que intenta devolver un tipo de interfaz, dicen "Shape":¿Puede una solicitud GET de Jersey devolver una entidad polimórfica?

public interface Shape {...} 

@XmlRootElement 
public class Circle implements Shape {...} 

@Path("/api/shapes") 
public class ShapeResource { 
    @GET 
    @Path("/{shapeId}") 
    public Shape get(@PathParam("shapeId") String shapeId) { 
     .... 
     return new Circle(); 
    } 
} 

Experimentando con lo anterior, veo que el servidor está volviendo XML, así:

<?xml version="1.0" encoding="UTF-8"?> 
<circle> 
... 
</circle> 

Hasta ahora todo bien. El problema es que el cliente no sabe cómo deshacer esto. Estoy recibiendo:

com.sun.jersey.api.client.ClientHandlerException: A message body for Java type, interface Shape, and MIME media type, application/xml, was not found 

dado un WebResource, y pidiendo un tipo de entidad de Shape.class produce una excepción.

Parece que el servidor está haciendo lo correcto. He estado luchando durante horas sobre cómo lograr que el Cliente deserialice esta clase. Incluso traté de envolver la interfaz. Estoy tratando de ponerme en un contenedor como se describe aquí: https://jaxb.dev.java.net/guide/Mapping_interfaces.html. Eso tampoco funcionó.

Mi código de cliente es el siguiente:

ClientResponse response = get(wr, ClientResponse.class); // wr == WebResource 
    try { 
     return response.getEntity(Shape.class); // <-- FAIL  
    } catch (Exception e) { 
     e.printStackTrace(); 
     // com.sun.jersey.api.client.ClientHandlerException: A message body reader for Java type, interface Shape, and MIME media type, application/xml, was not found 
    } 
    try { 
     return response.getEntity(Circle.class); // <-- WIN, but hacky and forces me to try every concrete type 
    } catch (Exception e) {} 
    return null; 

Cualquier idea o guía es muy apreciada. Gracias de antemano.

+0

Esto debería funcionar. Lo he hecho con la suficiente frecuencia. Creo que es un error en tu código de cliente. ¿Puedes publicarlo? –

+0

He actualizado la publicación original – Erik

+0

Hmm, ¿qué sucede cuando agrega '@ XmlRootElement' a' Shape'? –

Respuesta

2

El problema probablemente no es con la implementación de JAXB que está utilizando, ya que el mensaje se está organizando correctamente.

En cambio, el problema es con la siguiente llamada:

return response.getEntity(Shape.class); 

No estoy seguro de cómo esto se lleva a cabo, pero puedo imaginar que hace algo como lo siguiente, que sería válido:

jaxbContext.createUnmarshaller.unmarshal(xmlSource, Shape.class); 

Dado que parece que todas las implementaciones de la forma son anotados con @XmlRootElement, necesitamos una forma de desencadenar la siguiente llamada a JAXB:

jaxbContext.createUnmarshaller.unmarshal(xmlSource); 

Se podría Doe esta fuera de las API de cliente Jersey:

URL url = new URL("http://www.example.com/api/shapes/123"); 
HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 
connection.setRequestMethod("GET"); 
connection.setRequestProperty("Accept", "application/xml"); 

JAXBContext jaxbContext = JAXBContext.newInstance(Circle.class, Square.class, Triangle.class); 
Shape shape = (Shape) jaxbContext.createUnmarshaller().unmarshal(connection.getInputStream()); 

connection.disconnect(); 

Así que debe haber una manera de hacerlo con API de cliente Jersey.

Cuestiones relacionadas