Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to return Response with message, jax rs

I have a web service rest using jax-rs, my service return a List of objects but y don't know how to add custom status values to response, for example the result that I want to build is the following:

If its ok:

{
   "status": "success",
   "message": "list ok!!",
   "clients": [{
        "name": "john",
        "age": 23
    },
    {
        "name": "john",
        "age": 23
    }]
}

If is error:

{
   "status": "error",
   "message": "not found records",
   "clients": []
}

my rest service:

 @POST
 @Path("/getById")
 @Consumes(MediaType.APPLICATION_JSON)
 @Produces(MediaType.APPLICATION_JSON)
 public List<Client> getById(Client id) {

  try {

       return Response.Ok(new ClientLogic().getById(id)).build();
       //how to add status = success, and message = list! ?

    } catch (Exception ex) {
       return  ??   
       // ex.getMessage() = "not found records"
       //i want return json with satus = error and message from exception
    }
    } 
like image 863
Alonso Contreras Avatar asked Sep 13 '17 14:09

Alonso Contreras


People also ask

What is response return type in Java?

The Response class is an abstract class that contains three simple methods. The getEntity() method returns the Java object you want converted into an HTTP message body. The getStatus() method returns the HTTP response code. The getMetadata() method is a MultivaluedMap of response headers.

How do you create a response to an object in Java?

Create a new ResponseBuilder for a created resource, set the location header using the supplied value. Create a new ResponseBuilder by performing a shallow copy of an existing Response. Return the response entity. Get metadata associated with the response as a map.

How do you get entity from response object?

You can use: public abstract <T> T readEntity(Class<T> entityType) - Read the message entity input stream as an instance of specified Java type using a MessageBodyReader that supports mapping the message entity stream onto the requested type.


2 Answers

If you want full control on your output JSON structure, use a JsonObjectBuilder (as explained here, then convert your final json to String and write (for example for the success json):

return Response.Ok(jsonString,MediaType.APPLICATION_JSON).build();

and change your return value to a Response object.

However please note that you are trying to send redundant (and not standard) piece of information, which is already encoded into the HTTP error codes. When you use Response.Ok, the response will have code "200 OK", and you can study the Response class methods for returning any HTTP code you desire. In your case it would be:

return Response.status(Response.Status.NOT_FOUND).entity(ex.getMessage()).build();

returning a 404 HTTP code (look at Response.Status list of codes).

like image 158
Nicola Pellicanò Avatar answered Oct 11 '22 01:10

Nicola Pellicanò


I was facing the same problem and here is how I solved it. If your service method succeeds, return Response with status 200 and with your desired entities. If your service method throws an exception, return Response with different status and with exception message bind to your RestError class.

@POST
@Path("/getById")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response getById(Client id) {
  try {    
    return Response.Ok(new ClientLogic().getById(id)).build();
  } catch (Exception ex) {
    return Response.status(201) // 200 means OK, I want something different
                   .entity(new RestError(status, msg))
                   .build();   
  }
}

In client, I am using these utility methods to read entity from Response. If there is an error, I throw an exception containing status and msg of that error.

public class ResponseUtils {

  public static <T> T convertToEntity(Response response, 
                                      Class<T> target)
                          throws RestResponseException {
    if (response.getStatus() == 200) {
      return response.readEntity(target);
    } else {
      RestError err = response.readEntity(RestError.class);
      // my exception class
      throw new RestResponseException(err);
    }
  }

  // this method is for reading Set<> and List<> from Response
  public static <T> T convertToGenericType(Response response,
                                           GenericType<T> target)
                          throws RestResponseException {
    if (response.getStatus() == 200) {
      return response.readEntity(target);
    } else {
      RestDTOError err = response.readEntity(RestError.class);
      // my exception class
      throw new RestResponseException(err);
    }
  }

}

My client method will call (through proxy object) service method

public List<Client> getById(Client id) 
                        throws RestResponseException {
  return ResponseUtils.convertToGenericType(getProxy().getById(id),
                                            new GenericType<List<Client>>() {});
} 
like image 28
Jan Lochman Avatar answered Oct 10 '22 23:10

Jan Lochman