Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple return type in Jersey Client request

I'm using Jersey Client API in the following way :-

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

So I'm expecting the response in object of User class which is a JAXB annotated class. However, at times I might also get an error xml and for that I've created a JAXB class ErrorResponse.

Now the problem is that if my request returns an object of ErrorResponse instead of User how can I handle that ?

I tried like this -

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

But when I try to use getEntity() in catch block, it throws following exception

[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) .....

Seems like after calling getEntity() once, the inputstream is exhausted.

like image 979
netlogger Avatar asked Jan 08 '10 06:01

netlogger


2 Answers

I think you missed a point in the whole "REST way of thinking".
Short answer: yes, you can only call getEntity once. You need to check the returned HTTP status to know what entity you should get.

On the server side:

  1. When designing a REST API, one should always use appropriate status codes regarding the HTTP RFC.
  2. For that matter, please consider using the ExceptionMapper interface (here's an example with a "NotFoundException"

So, now your server returns either "HTTP status OK - 200" with a User object, or an error status with an error object.

On the client side:

You need to check the return status and adapt your behavior according to the API spec. here's a quick and dirty code sample:

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

NB: depending on the status code returned, this error could be very different (thus needing very different behavior):

  • client error 40X: your client request is wrong
  • server error 500: an unexpected error occured on the server side
like image 126
Brian Clozel Avatar answered Nov 18 '22 19:11

Brian Clozel


This kind of code could be used to manage Error message or business message in the response :

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



}
like image 20
Stj Avatar answered Nov 18 '22 18:11

Stj