Многократный тип возврата в запросе клиента Джерси - PullRequest
4 голосов
/ 08 января 2010

Я использую Jersey Client API следующим образом: -

User user = webRsrc.accept(MediaType.APPLICATION_XML).post(User.class, usr);

Итак, я ожидаю ответа в объекте класса User, который является аннотированным классом JAXB. Тем не менее, иногда я мог бы получить XML-сообщение об ошибке, и для этого я создал JAXB-класс ErrorResponse.

Теперь проблема в том, что если мой запрос возвращает объект ErrorResponse вместо User, как я могу это обработать?

Я пытался так -

ClientResponse response=null;
try {

        response = webRsrc.accept(MediaType.APPLICATION_XML).post(ClientResponse.class,usr);
        User usr = response.getEntity(User.class);    
    }catch(Exception exp)
    {
       ErrorResponse err = response.getEntity(ErrorResponse.class);    
    }

Но когда я пытаюсь использовать getEntity () в блоке catch, выдается следующее исключение

[org.xml.sax.SAXParseException: Premature end of file.]
at com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider.readFrom(AbstractRootElementProvider.java:107)
at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:532)
at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:491) .....

Похоже, что после однократного вызова getEntity () входной поток исчерпан.

Ответы [ 2 ]

10 голосов
/ 04 марта 2010

Я думаю, вы упустили момент во всем "ОТДЫХНОМ мышлении".
Краткий ответ: да, вы можете вызвать getEntity только один раз. Вам нужно проверить возвращенный статус HTTP, чтобы узнать, какую сущность вы должны получить.

На стороне сервера:

  1. При разработке REST API всегда следует использовать соответствующие коды состояния относительно HTTP RFC .
  2. В этом отношении, пожалуйста, рассмотрите возможность использования интерфейса ExceptionMapper (вот пример с "NotFoundException"

Итак, теперь ваш сервер возвращает либо «HTTP status OK - 200» с объектом User, либо статус ошибки с объектом error.

На стороне клиента:

Вам необходимо проверить статус возврата и адаптировать свое поведение в соответствии со спецификацией API. Вот быстрый и грязный пример кода:

ClientResponse response=null;

response = webRsrc.accept(MediaType.APPLICATION_XML).post(ClientResponse.class,usr);

int status = response.getStatus();

if (Response.Status.OK.getStatusCode() == status) {

  // normal case, you receive your User object
  User usr = response.getEntity(User.class);

} else {

  ErrorResponse err = response.getEntity(ErrorResponse.class);
}

Примечание: в зависимости от возвращенного кода состояния, эта ошибка может сильно отличаться (поэтому требуется совсем другое поведение):

  • ошибка клиента 40X: ваш клиентский запрос неверен
  • ошибка сервера 500: на стороне сервера произошла непредвиденная ошибка
2 голосов
/ 08 декабря 2010

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

protected <T> T call(String uri, Class<T> c) throws  BusinessException {


    WebResource res = new Client().create().resource(url);
    ClientResponse cresp = res.get(ClientResponse.class);
    InputStream respIS = cresp.getEntityInputStream();


    try {
        // Managing business or error response
        JAXBContext jCtx = JAXBContext.newInstance(c, BeanError.class);
        Object entity = jCtx.createUnmarshaller().unmarshal(respIS);

        // If the response is an error, throw an exception
        if(entity instanceof  BeanError) {
            BeanError error = (BeanError) entity;
            throw new  BusinessException(error);

        // If this not an error, this is the business response
        } else {
            return (T) entity;
        }

    } catch (JAXBException e) {

        throw(new BusinessException(e));
    }



}
...