REST method return type - Best practicee - rest

Is it a good idea to always use Response as a return type for all your REST services.
For example, let's say I have a method that gets all customers
First way:
public List <customer> getAllCustomers(){
// select all customers from database
}
Second Way:
public Response getAllCustomers(){
// user Response.ResponseBuilder.entity(customer)
}
enter code here
Which is a better approach. Is is advisable for all methods to return Response as return type (as in the Second way).

I would create your own response object. This will let you pass information to the client about the operation, number of records updated, error messages, etc. Also your service will behave consistently to your clients.
I would say you do not have to return any response data, but you should set your HTTP response codes appropriately. Like setting a 204 (No Content) response code for a simple acknowledgement of an operation.

Related

What is the correct status code to return for a successful PUT operation performed by a RESTful API?

In Visual Studio 2017, when creating a new controller for a .Net Core 2.1 Web API, and using the "Add Scaffold - API Controller with actions, using Entity Framework" wizard, the generated controller code returns a NoContent() for the PUT action, and a CreatedAtAction() for the POST action.
// POST: api/Items
[HttpPost]
public async Task<IActionResult> PostItem([FromBody] Item item)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
_context.Item.Add(item);
await _context.SaveChangesAsync();
return CreatedAtAction("GetItem", new { id = item.Id }, item);
}
// PUT: api/Items/5
[HttpPut("{id}")]
public async Task<IActionResult> PutItem([FromRoute] int id, [FromBody] Item item)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
if (id != item.Id)
return BadRequest();
_context.Entry(item).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!ItemExists(id))
return NotFound();
else
throw;
}
return NoContent();
}
I completely agree with the return value for the POST action. But regarding the PUT action returning a NoContent() with an empty body, is this "best practice" for RESTful APIs? I mean, I understand that it is returning a NoContent() status code because the body is empty, but would it not make more sense if it returned an Ok() to signal that everything went fine? It seems a bit ambiguous as to whether the action succeeded or not when receiving a NoContent() status code. Or is it more correct to return NoContent(), to let the consuming app know that it should ignore the body, and assume that, because no error code was returned, everything went fine?
Just wondering what RESTful best practice dictates in this situation...
Returning no content status still falls within the 2xx status code range which all indicate successful processing of the request. Returning 200 would now be just a matter of choice rather than what best practice dictates in this situation.
Reference Learn REST: A RESTful Tutorial - Using HTTP Methods for RESTful Services
PUT is most-often utilized for update capabilities, PUT-ing to a
known resource URI with the request body containing the newly-updated
representation of the original resource.
However, PUT can also be used to create a resource in the case where
the resource ID is chosen by the client instead of by the server. In
other words, if the PUT is to a URI that contains the value of a
non-existent resource ID. Again, the request body contains a resource
representation. Many feel this is convoluted and confusing.
Consequently, this method of creation should be used sparingly, if at
all.
Alternatively, use POST to create new resources and provide the
client-defined ID in the body representation—presumably to a URI that
doesn't include the ID of the resource (see POST below).
On successful update, return 200 (or 204 if not returning any content
in the body) from a PUT. If using PUT for create, return HTTP status
201 on successful creation. A body in the response is
optional—providing one consumes more bandwidth. It is not necessary to
return a link via a Location header in the creation case since the
client already set the resource ID.
PUT is not a safe operation, in that it modifies (or creates) state on
the server, but it is idempotent. In other words, if you create or
update a resource using PUT and then make that same call again, the
resource is still there and still has the same state as it did with
the first call.
If, for instance, calling PUT on a resource increments a counter
within the resource, the call is no longer idempotent. Sometimes that
happens and it may be enough to document that the call is not
idempotent. However, it's recommended to keep PUT requests idempotent.
It is strongly recommended to use POST for non-idempotent requests.

Controller return type and httpStatus best practice and production/consumption on method in REST WS

I commence in REST and I have some questions:
What type must the controller return? Typically, I'm asking if my Rest #Controller must return Item object as it is or encapsulate it in ResponseEntity in order to specify http-status-code.
What http status code to use in a GET method on a particular item ("/items/2") if the given item does not exists: HttpMediaStatus.OK(200) and null return or HttpStatus.NO_CONTENT(204) and null return ?
Second part: I saw it was possible to specify #Produces and #Consumes on WS method but what the use of that? My application and my methods work so, why specify MediaType.APPLICATION_JSON_VALUE? Doesn't Spring/SpringBoot automatically convert Item or ResponseEntity into json?
Context: using Spring Boot, hibernate, REST webservice.
Thank you.
Many questions in one, I'll provide short answers with a bunch of link to relevant articles and the reference documentation.
What type must the controller return?
Depends on your annotation and the RESTful-ness of your service. There are three annotations you can use for controllers: #Controller, #RestController and #RepositoryRestController.
Controller is the base annotation to mark your class as a controller. The return type of the controller endpoint methods can be many things, I invite you to read this dedicated post to get a grasp of it.
When developing a pure-REST service, you will focus on using RestController and RepositoryRestController.
RestControlleris Controller + ResponseBody. It binds the return value of the endpoint method to the web response body:
#RestController
public ItemController {
#RequestMapping("/items/{id}")
public Item getItem(#PathVariable("id") String id) {
Item item = ...
return item;
}
}
With this, when you hit http:/.../api/items/foo, Spring does its magic, automatically converting the item to a ResponseEntity with a relevant 40X status code and some default HTTP headers.
At some point, you will need more control over the status code and headers, while still benefiting from Spring Data REST's settings. That's when you will use RepositoryRestController with a ResponseEntity<Item> as return type, see the example the Spring Data REST reference.
What http status code to use in a GET method on a particular item if the given item does not exists?
Bluntly said: use HttpStatus.NOT_FOUND. You're looking for a resource that does not exist, there's something wrong.
That being said, it is completely up to you to decide how to handle missing resources in your project. If your workflow justifies it, a missing resource could be something completely acceptable that indeed returns a 20X response, though you may expect users of your API to get confused if you haven't warned them or provided some documentation (we are creatures of habits and conventions). But I'd still start with a 404 status code.
(...) #Produces and #Consumes on WS method but what the use of that? My application and my methods work so, why specify MediaType.APPLICATION_JSON_VALUE? Doesn't Spring/SpringBoot automatically convert Item or ResponseEntity into json?
#Consumes and #Produces are respectively matched against content-type and accept headers from the request. It's a mean of restricting the input accepted and the output provided by your endpoint method.
Since we're talking about a REST service, communications between clients of the API and the service are expected to be JSON-formatted. Thanks to Spring HATEOAS, the answer are actually formatted with the application/hal+json content-type.
In that scenario, you can indeed not bother with those two annotations. You will need them if you develop a service that accepts different content-types (application/text, application/json, application/xml...) and provides, for instance, HTML views to users of your website and JSON or XML response to automated clients of your service.
For real life examples:
Facebook provides the Graph API for applications to read to/write from its graph, while users happily (?) surf on web pages
Google does the same with the Google Maps API

Should a RESFTful Web API return the modified entity on an Update operation (Put)?

I'm creating a new Web API and I'm having a doubt regarding the Update operation (it's a basic CRUD). Should I return a DTO with the updated entity data? I want my API to be RESTful.
have a read here
https://www.rfc-editor.org/rfc/rfc7231
it says and I quote:
For a state-changing request like PUT (Section 4.3.4) or POST
(Section 4.3.3), it implies that the server's response contains the
new representation of that resource, thereby distinguishing it from
representations that might only report about the action (e.g., "It
worked!"). This allows authoring applications to update their
local copies without the need for a subsequent GET request.
However, you do not need to be too fixed on this, return a 201 for example when you create something is perfectly OK as well and you probably want to add the the unique identifier of the created resource.
For updates, a 200 would be ok as well. 204 can be acceptable as well as already mentioned.
The bottom line is ... return only the data you need, if you need to see the whole updated object then return it. If you don't then don't do it. Keep in mind that some objects can be quite big and have a whole object graph below them, there's no point sending too much data down the wire.
I guess the most important thing is to choose one way of doing things and then be consistent and use the same thing everywhere
First of all, returning a DTO has nothing to do with RESTful.
It's true that DTO is a pattern created with the purpose of transferring data to remote interfaces (and web services can be a good fit for this pattern).
However using DTOs won't make your application more or less RESTful. Your application can use DTOs to have more control over the data exposed in the REST API. Just that.
If your update operation relies on the PUT HTTP method (which is designed to replace the state of a resource with a new representation), you may want to return 200 or 204 status code to indicate that the operation has succeeded.
If you go for 200, you can return a representation of the new state of the recently updated resource. If you go for 204, no representation must be returned.
By representation I mean a JSON document, a XML document or any other content that can be used to represent the state of a given resource.
We normally return NoContentResult after update is successful. For example,
[HttpPut("{id}", Name = "UpdateUser")]
public IActionResult UpdateUser(Guid id, [FromBody] UserUpdateDto user)
{
if (user == null)
{
return BadRequest();
}
if (!_repository.UserExists(id))
{
return NotFound();
}
var entity = _repository.GetUser(id);
Mapper.Map(user, entity);
_repository.UpdateUser(entity);
return NoContent();
}
NoContent basically returns status code 204. The following is the source code of NoContentResult.
public class NoContentResult : StatusCodeResult
{
public NoContentResult()
: base(204)
{
}
}
Returning data from a PUT operation is optional, though not necessary. If theres anything you wanted to calculate in the model which will be useful for the client then return them, but otherwise a 204.

In Spring's rest controller (marked with #RestController), functions can return both model objects and a ResponseEntity object, which is better?

As a Spring Boot noob, I just know that in the controller class, its public functions can return both model objects and ResponseEntity object. Something like
public List<Book> getBooks() {}
or
public ResponseEntity<Book> getBooks() {}
But my question is which is better when there are multiple choices?
Basically, you have control over the HTTP response status if you use ResponseEntity, in addition to the content of the object itself.
public ResponseEntity<Object> getObject() {
return new ResponseEntity<Object>(object, Httpstatus.OK);
}
For example, if you need to validate some data from the request before executing any action and you want to let your client know what happened through the HTTP status code you can choose between different options.
HttpStatus.CONFLICT
HttpStatus.CREATED
Here you can take a look on the different status codes:
HTTP Status Codes
Just to shed more light on what #lbpeppers has mentioned. Using a ResponseEntity has many advantages.
1. The client need not look into the body of the message if the status code is something like 400 or 404, which is quite helpful
2. In some cases the client is not interested in the body. All it needs is a status of the operation
3. There are a lot of handy methods like is1xxInformational, is2xxSuccessful, is3xxRedirection, is4xxClientError, is5xxServerError in HttpStatus calss which can be used like
response.getStatusCode().is2xxSuccessful()

How to create meaningful REST response messages?

I have created a REST service and I was wondering what the best practice was for sending meaningful messages to a GET request. Basically my GET request returns a specific object, something like this;
#GET
#Path("/examsple")
#Produces(MediaType.APPLICATION_JSON)
public List<SomeObject> retrieveSomeObjs() {
List<SomeObject> result = new ArrayList<>();
try {
result = ... Get SomeObjects ...;
} catch (Exception e) {
... Deal with exception ...
}
return result;
}
That works great except when there is an error the response just sends back an empty List! What would be more useful would be a message that explains what the problem is. However I cant send back a String message because the return type is List!
My current solution is to change the return type to a Map and then I can return the object wrapped in the Map along with any messages. However its a little messy on the client side and I was wondering if there was either an inbuilt solution or an 'accepted' solution for this.
If the client has made an error then use HTTP Response codes. If an item is not found then your response would be a 404 Not Found. If the user does not have permissions to access an object then return a 403 Forbidden. Currently you are responding with a 200 OK saying everything is OK when it's not.
If it's an error at the server side you don't really want to be sending that information to your clients. Catch the error on the server and do something meaningful with it (like log it) so you can change the code so it doesn't happen again.
You could return an HTTP error status code in the header and a JSON response body with an object describing the exception.
As already mentioned some common error codes for GET requests include:
301 Moved Permanently - If the resource has been moved
400 Bad Request - If the client request is unaccaptable, i.e. if the client sends none-sense parameters in the request
401 Unauthorized - If the client did not provide any valid credentials
403 Forbidden - If the client is authorized but not allowed to perform the request (you can also return a 404 in this case to conceal that this resource exists at all)
404 Not Found - If the requested resource could not be found
I usually create a POJO to represent these error messages and then return it using a Jersey Response object.
For example the error object could look like this:
public class ApiError {
private String status;
private String code;
private String message;
private String developerMessage;
// Getters and Setters here
}
To return it you can do the following (i.e. in your catch block or your custom ExceptionMapper):
ApiError error = new ApiError("409", "409-1", message, developerMessage);
return Response.status(Response.Status.CONFLICT).entity(error).build();
This way you can provide nicely formatted JSON/XML error messages containing custom error codes and further information for the developer. The error entities will get serialized according to your #Produces annotation.