2010-09-09 6 views
6

У меня есть класс ресурса, который пытается вернуть тип интерфейса, скажем, «Форма»:Может ли запрос Джерси GET возвратить полиморфный объект?

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

Экспериментируя с вышеизложенным, я вижу, что сервер возвращает XML следующим образом:

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

Пока все хорошо. Проблема в том, что клиент не знает, как отменить это. Я получаю:

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

Учитывая WebResource и просить типа сущности из Shape.class вызывает исключение.

Сервер, похоже, делает правильную вещь. Я много часов боролся о том, как заставить Клиента десериализовать этот класс. Я даже попробовал обернуть интерфейс, который я действительно пытаюсь получить в обертке, как описано здесь: https://jaxb.dev.java.net/guide/Mapping_interfaces.html. Это тоже не сработало.

Мой код клиента выглядит следующим образом:

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; 

Любое понимание или руководство высоко ценится. Спасибо заранее.

+0

Это должно сработать. Я делал это достаточно часто. Я думаю, что это ошибка в вашем клиентском коде. Можете ли вы опубликовать его? –

+0

Я обновил исходное сообщение – Erik

+0

Хм, что происходит, когда вы добавляете '@ XmlRootElement' в' Shape'? –

ответ

2

Проблема, вероятно, связана не с реализацией JAXB, которую вы используете, поскольку сообщение правильно сортируется.

Вместо проблема со следующим вызовом:

return response.getEntity(Shape.class); 

Я не знаю, как это реализовано, но я могу себе представить, что он делает что-то вроде следующего, который был бы недействителен:

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

Поскольку кажется, что все ваши реализации Shape аннотируется @XmlRootElement, нам нужен способ, чтобы вызвать следующий вызов JAXB:

jaxbContext.createUnmarshaller.unmarshal(xmlSource); 

Вы можете лань это вне клиентских интерфейсов Джерси:

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

Так что должен быть способ сделать это с клиентскими API, Джерси.