2010-09-09 15 views
6

Mam klasę zasobu, który próbuje wrócić typ interfejsu, powiedzieć „Shape”:Czy żądanie GET z Jersey może zwrócić obiekt polimorficzny?

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(); 
    } 
} 

Eksperymentowanie z powyższym, widzę, że serwer zwraca XML tak:

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

Jak dotąd tak dobrze. Problem polega na tym, że klient nie wie, jak to usunąć. Otrzymuję:

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

Biorąc pod uwagę WebResource, prosząc o podanie typu obiektu Shape.class, spowoduje to wyjątek.

Wygląda na to, że serwer działa prawidłowo. Od wielu godzin walczę o to, jak skłonić Klienta do deserializacji tej klasy. Próbowałem nawet owijać interfejs, który naprawdę próbuję uzyskać w opakowaniu, jak tutaj: https://jaxb.dev.java.net/guide/Mapping_interfaces.html. To też nie działa.

Mój kod klienta wygląda następująco:

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; 

Każdy wgląd lub poradnictwo jest mile widziana. Z góry dzięki.

+0

To powinno zadziałać. Zrobiłem to dość często. Myślę, że to błąd w kodzie klienta. Czy możesz to opublikować? –

+0

Zaktualizowałem oryginalny post – Erik

+0

Hmm, co się stanie, gdy dodasz '@ XmlRootElement' do' Shape'? –

Odpowiedz

2

Problem prawdopodobnie nie jest związany z implementacją JAXB, którego używasz, ponieważ wiadomość jest poprawnie porządkowana.

Zamiast problem jest z następującego połączenia:

return response.getEntity(Shape.class); 

Nie jestem pewien, jak to jest realizowane, ale mogę sobie wyobrazić, że robi coś jak poniżej, który byłby nieważny:

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

Ponieważ wydaje się, że wszystkie implementacje kształt są opatrzone @XmlRootElement, musimy znaleźć sposób, aby powodować następujące wezwanie do JAXB:

jaxbContext.createUnmarshaller.unmarshal(xmlSource); 

Można doe to poza API klienta 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(); 

więc nie powinno być jakiś sposób, aby to zrobić z API klienta Jersey.

Powiązane problemy