I am building a REST API using Spring and implementing the PUT functionality. I am trying to handle the scenario in which the client tries to PUT to a uri where the resource does not already exist. In this scenario, per the PUT spec, a new resource should be created at that ID. However because of the ID generation strategy I am using (#GeneratedValue(strategy = GenerationType.IDENTITY)), I cannot create resources with IDs out of sequence. The database must use the next available value. However, according to the w3 spec on PUT...
If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI.
If the server desires that the request be applied to a different URI, it MUST send a 301 (Moved Permanently) response; the user agent MAY then make its own decision regarding whether or not to redirect the request.
In this case, I can do neither of these. I cannot create a new resource at the existing URI due to the ID generation restrictions, and I cannot send a 301 Moved Permanently response because according to How do I know the id before saving an object in jpa it is impossible to know the next ID in a sequence before actually persisting the object. So I would have no way of telling the client what URI to redirect to in order to properly create the new resource.
I would imagine this problem has been solved many times over because it is the standard PUT functionality, yet I am having trouble finding any other people who have tried to do this. It seems most people just ignore the "create new resource" part of PUT, and simply use it as update only.
What I want to do is just go ahead and create the new resource, and then send the 301 Moved Permanently to redirect the client to the true location of the created resource - but as we see above, this violates the definition of PUT.
Is there a spring-y way to solve this problem? Or is the problem unsolved, and the true standard practice is to simply not allow creation of new resources via PUT?
If the server cant processes the request due to an error in the request, just return a 400.
400 Bad Request -
The server cannot or will not process the request due to an apparent client error (e.g., malformed request syntax, size too large, invalid request message framing, or deceptive request routing).
Related
So I am building a REST APi that will be responsible for running various jobs on a special hardware.
So I understand that REST is used for accessing resources and not calling functions.
So what are the recommendations and best way to design an API for responsible for calling functions.
For example I will have an api job/run which will return the PID of job if job was sucesfully ran.
I'll also have a job/{pid} for accessing information about a given job. and job/cancel/{pid} for stopping said job.
So what are the recommendations and best way to design an API for
responsible for calling functions
Create a user: POST /users
Delete a user: DELETE /users/1
Get all users: GET /users
Get one user: GET /users/1
To GET Record
Bad designs
GET /FetchUsers // To fetch all records
GET /getAllUsers/12 // To fetch specific records
Preferred Designs
GET /users //To fetch all records
GET /users/12 // To fetch specific records
To Crete Record
Bad designs
POST /createUsers //To create users
GET /createrecordforUsers //To fetch all records
Preferred designs
POST /users //To create users records
To Update Record
Bad designs
PUT /updateUsersid // To update user
POST /id/modifyuser // To update users
Preferred designs
PUT /users/:id // To update users
To Delete Record
Bad designs
DELETE /deleteuser/id //To delete users
POST /id/removeusers //To delete users
Preferred designs
DELETE /users/:id // To delete users
Below points should be considered
Platform independence . (Any client should be able to call the API, regardless of how the API is implemented internally)
Service evolution .(The web API should be able to evolve and add functionality independently from client applications.)
A resource has an identifier, which is a URI that uniquely identifies that resource. For example, the URI for a particular customer order might be:
Request : GET -> https://domain/orders/1
Response :
JSON
{"orderId":1111,"amount":99.90,"productId":1,"quantity":1}
The most common operations are GET, POST, PUT, PATCH, and DELETE.
GET retrieves a representation of the resource at the specified URI. The body of the response message contains the details of the requested resource.
POST creates a new resource at the specified URI. The body of the request message provides the details of the new resource. Note that POST can also be used to trigger operations that don't actually create resources.
PUT either creates or replaces the resource at the specified URI. The body of the request message specifies the resource to be created or updated.
PATCH performs a partial update of a resource. The request body specifies the set of changes to apply to the resource.
DELETE removes the resource at the specified URI.
REST APIs use a stateless request model. HTTP requests should be independent and may occur in any order, so keeping transient state information between requests is not feasible.
We can return response with hypermedia links as spring boot having this feature
[Spring Boot:] https://spring.io/guides/gs/rest-hateoas/
https://domain/orders (Better)
https://domain/create-order (Avoid)
A resource doesn't have to be based on a single physical data item. For example, an order resource might be implemented internally as several tables in a relational database, but presented to the client as a single entity. Avoid creating APIs that simply mirror the internal structure of a database.
A client should not be exposed to the internal implementation.
Avoid requiring resource URIs more complex than (order/collection/item/details)
Summary
- Pagination Support : /orders?limit=25&offset=50
- Error handing :
- API Version (avoid as much as if possible)
Refer here https://www.openapis.org/blog/2017/03/01/openapi-spec-3-implementers-draft-released
My team had a discussion early this week about if HTTP Codes should represent Business Failures.
Imagine a scenario where we have a Customer REST API. Within that API, we have lots of operations, like:
POST - mydomain.com/customers (receive a JSON body and create a new Customer)
GET - mydomain.com/customers/{id} (search for a specific Customer)
PATCH - mydomain.com/customers/{id} (receive a JSON body and patch a specific Customer)
DELETE - mydomain.com;customers/{id} (deletes a specific Customer)
Now, imagine a situation where I'm looking for a Customer which has the id = 5.
There's no Customer with the id = 5. What should I do in terms of HTTP status code?
Customer not found is a Business Failure. Should I return a 404 - NOT FOUND? Should I return a 200 - OK (with a JSON body describing that the Customer with ID 5 do not exist)?
We had a discussion exactly on that behavior.
Controller.java (example)
#GetMapping("/customers/{id}")
public ResponseEntity<?> handleRequestOfRetrieveCustomerById(#PathVariable("id") Integer id) throws CustomerNotFoundException {
try {
ResponseEntity.ok(customerService.findCustomerById(id));
} catch(CustomerNotFoundException e) {
// log at Controller level and rethrow
throw e;
}
}
Handler.java (example)
#ExceptionHandler(BusinessResourceNotFoundException.class)
#ResponseBody
protected ResponseEntity<Fault> handleExceptionOfBusinessResourceNotFound(BusinessResourceNotFoundException exception) {
return new ResponseEntity<Fault>(exception.getFault(), HttpStatus.NOT_FOUND);
}
In this example, a 404 - NOT FOUND is returned with a body giving more details to the client.
From reading the HTTP/1.1 Specification:
404 Not Found
The server has not found anything matching the Request-URI. No
indication is given of whether the condition is temporary or
permanent. The 410 (Gone) status code SHOULD be used if the server
knows, through some internally configurable mechanism, that an old
resource is permanently unavailable and has no forwarding address.
This status code is commonly used when the server does not wish to
reveal exactly why the request has been refused, or when no other
response is applicable.
If "The server has not found anything matching the Request-URI...", I understand that returning a 404 - NOT FOUND would be the correct approach., since the /id composes my URI (mydomain.com/customers/id)
Am I right?
Which one is the better / right (if there's a wrong way) approach?
Status codes are meant to describe the result of the server's attempt to understand and satisfy the client's corresponding request.
Ultimately, if a client requests a representation of a resource that doesn't exist, the server should return 404 to indicate that. It's essentially a client error and should be reported as such.
Returning 200 would be misleading and would cause confusion to API clients.
Sometimes the HTTP status codes are not sufficient to convey enough information about an error to be helpful.
The RFC 7807 was created to define simple JSON and XML document formats to inform the client about a problem in a HTTP API. It's a great start point for reporting errors in your API. It also defines the application/problem+json and application/problem+xml media types.
Technically and from the http point of view, 404 should also be returned for any misspelling of the entity name (cutsomer instead of customer).
So even if you decide that "customer not found" will result in http 404, you cannot conclude that http 404 will imply "entity occurrence not found".
HTTP codes exist for a reason. Whoever consumes your API should be able to handle the response straight away, without having to result on the body contents.
In your case, 404(Not Found) looks quite suitable.
Alternatively, if you always return a 200, doesn't that beat the purpose of a response code altogether? If you are getting a response, you already know that your request got through to some extent.
TLDR;
Use 404 :)
I have recently worked on a Rest API with Spring Boot and the best practices found on the internet said this :
Parameters null or value not set : 400 / Bad request
Returned value not found (record or list empty) : 404 / Not found
Exception from server (database error, network error etc.) : 500 / Internal server error
Those links will help you : best practice error handling, ControllerAdvice, error message
A REST API is part of the integration domain, not the business domain. It's a skin that your domain model wears to disguise itself as a web site aka an HTTP compliant key value store.
Here, 404 is an appropriate choice because it mimics the response that would be returned by a key value store if you tried to get a key that wasn't currently stored.
I would follow the meaning of HTTP status codes.
Wiki says (https://en.wikipedia.org/wiki/List_of_HTTP_status_codes):
This class of status code is intended for situations in which the error seems to have been caused by the client
So to be clear: mydomain.com/customers/{id} is a valid URL an the server understands the request. The fact that customer with id=5 doesn't exists has nothing to do with a "false URL" or "not understandable request".
In my opinion this should return some 2xx status code with further information inside json (definitions made by your REST API)
I am working on a Ticket Reservation application. I am required to build a web-service which takes in request for cancellation, checks with a downstream system (via SOAP), whether it can be cancelled, and returns the appropriate response to the calling system after updating my tables.
I have to build a bunch of similar web-services for cancellation, rescheduling, et for which I'm planning to use RESTful web-services
This I'm planning to achieve using the POST method of the REST API, using JAX-RS. I could see that all the web-services I'm going to build suit the POST verb, and the other HTTP methods (GET, POST and DELETE) doesn't seem like they need to be used here. In that case what is the actual use case of these HTTP methods in REST? Am I right in using only POST?
Your REST resource is the ticket. Use GETs to read the ticket, PUT to modify the ticket state, and DELETE to do a logical delete (cancellation).
For any other operation, use the wildcard operation POST.
Have a look at this blog post Brief Introduction to REST, where the author goes through the core REST principles.
For the purpose of a cancellation, I would actually use the DELETE method. In the case of a successful cancellation, return a 200 with either response body confirming success or a response body containing the details of the reservation. Or a 204 if you don't want to return a body.
If it can't be canceled, you have your choice from the 400 series of errors (e.g. 404 if there is no such reservation, 403 if the request is forbidden, etc.) or the 500 series if there is a bug or malfunction.
You will certainly use the other HTTP verbs for all the other reservation actions--making a reservation, changing it, etc.
Consider your Ticket Reservations as your application resources.
Clients to your application would:
submit GETrequest to retrieve a representation (XML, JSON or anything else) one or many ticket reservations (given the URL they use, eg: /tickets to retrieve all of them - or all they are allowed to see, /tickets/1to retrieve a representation of the Ticket Reservation whose id is 1, tickets/?start=0&size=10 for paginated content, etc.)
submit POST requests on /ticketsto create a new reservation (and the response would provide the client with a location giving the location of the created reservation)
submit a PUT request to /tickets/1 (with a representation of the new reservation in the request body) to update the reservation identified by 1
submit a DELETE request to /tickets/1 to delete the reservation identified by 1
The main idea behind the use of such verbs is that the URLs should identify resources (and not actions), and the HTTP verb would be the action.
If you use everything with POST, you'll be more or less doing SOAP.
This article will give you more information on hat I tried to hihlight above: http://martinfowler.com/articles/richardsonMaturityModel.html
There's quite a lot to say about designing RESTful applications. You really should read one or more of these books: "Restful Web Services" - http://amzn.com/0596529260, "RESTful Web APIs" - http://amzn.com/B00F5BS966, "REST in Practice: Hypermedia and Systems Architecture" - http://amzn.com/B0046RERXY or "RESTful Web Services Cookbook" - http://amzn.com/B0043D2ESQ.
Get a cup of coffee and enjoy some reading :-)
Reading below link , I could note that "doGet() allows bookmarks".
http://www.developersbook.com/servlets/interview-questions/servlets-interview-questions-faqs.php : search "It allows bookmarks"
Can anyone tell how and what is the use of it ?
All the parameters of GET request are contained in the url so when you are requesting for a resource using GET request, it can be formed using request URL itself.
Consider an example www.somesite.com.somePage.jsp. This generates a GET request because we are asking for a resource somePage.jsp.
If you are asking for a resource, then it is the GET request.
GET requests are used to retrieve data.
any GET request calls the doGet() method of servlet
GET requests are idempotent, i.e. calling the same resource again and again do not cause any side effects to the resources.
Hence, a GET request can have bookmarks
EDIT :-
As suggested by Jerry Andrews, POST methods do not have the query data unlike GET requests to form the resource properly with the help of only url. Hence they are not bookmarked.
It means that If you bookmark the URL of the servlet that has doGet() implemented, you could always get the same page again when you re-visit. This is very common when you have searches, link for products, news, etc.
All,
I'm trying to find out, unambiguously, what method (GET or POST) Flash/AS2 uses with XML.sendAndLoad.
Here's what the help/docs (http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00002340.html) say about the function
Encodes the specified XML object into
an XML document, sends it to the
specified URL using the POST method,
downloads the server's response, and
loads it into the resultXMLobject
specified in the parameters.
However, I'm using this method to send XML data to a Java Servlet developed and maintained by another team of developers. And they're seeing log entries that look like this:
GET /portal/delegate/[someService]?svc=setPayCheckInfo&XMLStr=[an encoded version of the XML I send]
After a Google search to figure out why the POST shows up as a GET in their log, I found this Adobe technote (http://kb2.adobe.com/cps/159/tn_15908.html). Here's what it says:
When loadVariables or getURL actions are
used to send data to Java servlets it
can appear that the data is being sent
using a GET request, when the POST
method was specified in the Flash
movie.
This happens because Flash sends the
data in a GET/POST hybrid format. If
the data were being sent using a GET
request, the variables would appear in
a query string appended to the end of
the URL. Flash uses a GET server
request, but the Name/Value pairs
containing the variables are sent in a
second transmission using POST.
Although this causes the servlet to
trigger the doGet() method, the
variables are still available in the
server request.
I don't really understand that. What is a "GET/POST hybrid format"?
Why does the method Flash uses (POST or GET) depend on whether the data is sent to a Java servlet or elsewhere (e.g., a PHP page?)
Can anyone make sense of this? Many thanks in advance!
Cheers,
Matt
Have you try doing something like that :
var sendVar=new LoadVars();
var xml=new XML("<r>test</r>");
sendVar.xml=xml;
sendVar.svc="setPayCheckInfo";
var receiveXML=new XML();
function onLoad(success) {
if (success) {
trace("receive:"+receiveXML);
} else {
trace('error');
}
}
receiveXML.onLoad=onLoad;
sendVar.sendAndLoad("http://mywebserver", receiveXML, "POST");
The hybrid format is just a term Macromedia invented to paint over its misuse of HTTP.
HTTP is very vague on what you can do with GET and POST. But the convention is that no message body is used in GET. Adobe violates this convention by sending parameters in the message body.
Flash sends the same request regardless of the server. You have problem in Servlet because most implementation (like Tomcat) ignores message body for GET. PHP doesn't care the verb and it processes the message body for GET too.