Jax-Rs - How to Return JSON and Http Status Code Together

JAX-RS — How to return JSON and HTTP status code together?

Here's an example:

@GET
@Path("retrieve/{uuid}")
public Response retrieveSomething(@PathParam("uuid") String uuid) {
if(uuid == null || uuid.trim().length() == 0) {
return Response.serverError().entity("UUID cannot be blank").build();
}
Entity entity = service.getById(uuid);
if(entity == null) {
return Response.status(Response.Status.NOT_FOUND).entity("Entity not found for UUID: " + uuid).build();
}
String json = //convert entity to json
return Response.ok(json, MediaType.APPLICATION_JSON).build();
}

Take a look at the Response class.

Note that you should always specify a content type, especially if you are passing multiple content types, but if every message will be represented as JSON, you can just annotate the method with @Produces("application/json")

Error - Returning JSON along with HTTP status code error JAX-RS

Your client is expecting to get JSON but you have set a plain string in the Response entity and application/json as content-type. You need to return a valid JSON. For example

return Response
.status(Response.Status.BAD_REQUEST)
.entity("{\"error\":\"Device cannot be null or empty.\"}")
.build();

You can also build the json response string using your preferred mapper (you will need to add a dependency). This is an example using Jackson

Jackson using API

ObjectMapper mapper  = new ObjectMapper();
ObjectNode objectNode = mapper.createObjectNode();
objectNode.put("error", "Device cannot be null or empty.");
String json = mapper.writeValueAsString(objectNode);

Jackson using POJO

class ErrorBean{
private String error;
//getters and setters
}

ObjectMapper mapper = new ObjectMapper();
ErrorBeanerrorBean = new ErrorBean();
errorBean.setError ("Device cannot be null or empty.");
String json = mapper.writeValueAsString(errorBean);

You can also return POJO from your service method and let the JAX-RS implementation to convert them to JSON (this means change the response type). See https://www.mkyong.com/webservices/jax-rs/json-example-with-jersey-jackson/

Spring Rest return a JSON response with a certain http response code

How I do it

Here is how I do JSON returns from a Spring Handler method.
My techniques are somewhat out-of-date,
but are still reasonable.

Configure Jackson
Add the following to the spring configuration xml file:

<bean name="jsonView"
class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">
</bean>

With that,
Spring will convert return values to JSON and place them in the body of the response.

Create a utility method to build the ResponseEntity
Odds are good that you will have multiple handler methods.
Instead of boilerplate code,
create a method to do the standard work.
ResponseEntity is a Spring class.

protected ResponseEntity<ResponseJson> buildResponse(
final ResponseJson jsonResponseBody,
final HttpStatus httpStatus)
{
final ResponseEntity<ResponseJson> returnValue;

if ((jsonResponseBody != null) &&
(httpStatus != null))
{
returnValue = new ResponseEntity<>(
jsonResponseBody,
httpStatus);
}

return returnValue;
}

Annotate the handler method

@RequestMapping(value = "/webServiceUri", method = RequestMethod.POST)

you can also use the @PostMethod annotation

@PostMethod("/webServiceUri")

Return ResponseEntity from the handler method
Call the utility method to build the ResponseEntity

public ResponseEntity<ResponseJson> handlerMethod(
... params)
{
... stuff

return buildResponse(json, httpStatus);
}

Annotate the handler parameters
Jackson will convert from json to the parameter type when you use the @RequestBody annotation.

public ResponseEntity<ResponseJson> handlerMethod(
final WebRequest webRequest,
@RequestBody final InputJson inputJson)
{
... stuff
}

A different story

You can use the @JsonView annotation.
Check out the Spring Reference for details about this.
Browse to the ref page and search for @JsonView.

How to return Response with message, jax rs

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

Setting Http Status Code and customized status message and returning JSON output using Jersey in RESTful Service

the mistakes are :

1. if status is set to NO_content (HTTP204) the norm is to have an entity empty. so entity will be returned as empty to your client. This is not what you want to do in all case, if found return details, if not found return 404.

2.Produces( { MediaType.APPLICATION_JSON }) tells that you will return a json content, and the content of entity is not a json. You will have to return a json. You will see I use jackson as it's part of Jersey.


  1. set a @Path("/user") to set a endpoint path at least at Resource level.
    Need to set a path in order to adress your resource (endpoint)

  2. use a bean in order to pass multiple things. I've made an example bean for you.

  3. as improvement caution with HTTP return, use the proper one
    404 :not found resource
    204 : empty....
    take a look at the norm: http://www.wikiwand.com/en/List_of_HTTP_status_codes

Take a look the complete code in Gist: https://gist.github.com/jeorfevre/260067c5b265f65f93b3

Enjoy :)

How do I return the HTTP status code when I'm making a JSON post in C#?

It should be easy as

var client = new HttpClient();
var results = await client.GetAsync("https://stackoverflow.com");
Console.WriteLine(results.StatusCode);

What to return for different HTTP methods in JAX-RS?

  1. GET - The client is trying to retrieve a resource or in other words, get a resource. So yes, you should return an entity with a status code of "200 OK" In most cases, it will either be a single resource or a collection resource; in your example, either a single book or all of the books

  2. POST - When you create a new resource, generally the client will send the representation of the new book to be created. What the client doesn't have is the identifier for the resource or how to access the resource later. What is generally done is a Location header is sent back to the client so the client can later access the resource. The status of this response should be "201 Created" Optionally, you can send back the same representation the client sent, but including the newly created identifier. You can see an example in this post.

  3. PUT - This is a complete update. So whatever the client sends completely overwrites the current resource (excluding the identifier). So ultimately, the client has all the information already; no need to send anything back. You can just respond back with a "204 No Content" status. In code terms, you can simply have a void method or return a Response to explicitly set the status.

  4. DELETE - If everything goes well with the delete, there is no need to send anything but to let the client know that everything is OK. So simply sending a "200 OK" response is suitable. Optionally, including the deleted representation may be OK.

These are very general guidelines. Everyone has their own style, but most try to follow standards. Below are some resources you can dig into to learn more

  • RFC 7231 - Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content
  • Roy Fielding dissertation - Architectural Styles and
    the Design of Network-based Software Architectures
  • MDN Web Docs

Aside

I was looking at how your service layer implementation (your BookService class) and there are some design flaws. Generally, in a tiered application, the lower tiers should not know anything about the tier above it. Here is an example of tiers

  WEB

SERVICE

DAO
  • The WEB layer is the REST layer (the JAX-RS code)
  • The SERVICE layer is the BookService where the business happens
  • The DAO layer is data later where data access happens

In this architecture, the DAO layer should not know about the SERVICE layer and SERVICE layer should not know about the WEB layer. In your example though, your service knows about Response objects. The Response should be only used in the WEB layer. A better implementation might look something like

public Response getBook(@PathParam("id") long id) {
Book book = bookService.findBook(id);
if (book == null) {
throw new NotFoundException();
}
return book;
}

Now the BookService only has the responsibility of finding the book and the resource method handles all of the web logic.



Related Topics



Leave a reply



Submit