My data access layer supports the upsert operations (Spring Data's CrudRepository.save()), when the id field is not set a new record is inserted and when the id field is set it is updated.
I am wondering how to justify the additional effort required to create two separate REST methods (both on the backend and the frontend side):
POST /users, for creating a new user (and generating the URI of the newly created resource)
PUT /users/{id}, for updating the existing users
over creating just one REST method:
POST /users
Are there any benefits of having two seperate methods other than being more RESTful?
It's more clearer to using different resources for different actions.
By REST ideology - PUT Idempotent method and POST not Idempotent. So each POST request should return new item in response, but PUT should return the same item in response.
I think it's a good when behavior is expected.
But if you write documentation for your api, you can using one resource for both actions (but I would choose the first option).
The data access layer supporting upsert does not mean that the REST API should support it, too. I would not overload POST /users with two meanings. Stick to two different resources.
Edit:
POST /users has the general meaning of 'add a new instance to the resource collection'. I see no way to extend this to '... or update existing instance if an ID is given'. /users is the collection resource, not a single resource you want to manipulate. Doing a POST to a collection resource should manipulate the collection, not a single existing resource.
Related
I have read several things about API's but there is something that is not clear to me on the subject of how to structure the resources. I will give you an easy but illustrative example. We imagine we have this relationship:
|Clients| (1:1) ------<>----- (0:M) |Orders| (1:1) ------<>------ (1:1) |Statuses|
A client can have zero or many orders and each order has a status.
The question comes when making resources, the resources that are clear are as follows:
GET /clients (get a list)
GET /clients/10 (get detail of one client)
POST /clients (create a client passing data by BODY)
(there could be more like the PUT but to simplify the example I simplify.)
The question is, to get the Orders from a Customer such as the resource?
GET /clientes/10/orders
Or in place:
GET /orders?id_cliente=10
The same to get the detail of an Order, what would it be like?
GET /clientes/10/orders/10
Or it would simply make sense to do this (which would also show the information of the State that you have):
GET /orders/10
Or when you want to delete an order:
DELETE /orders/10
or
DELETE /clientes/10/orders/10
And to create an Order, should the Customer always exist or could a Order and a Customer be created at the same time with the following resource? For example, a Customer not registered when making a purchase will place the Order and register at the same time)
POST /orders
Passing the Customer data in the BODY to it as the Order data would go. First the Customer would be created and then the Order.
If there is anyone who knows what all the valid resources of the sample relationship would look like, it would be good to share them. I don't want to get into paginate topics or other topics that are also important in an API. Only in the matter of resources.
To resolve you confusion, you can just ask yourself the following questions.
Does my resource have a unique resource id? - There should not be multiple resource elements pointing to a same resource.
Whether child resource can exist without the parent? - If it can exist, then it should not be considered as a child resource, but has to be concluded as individual resources.
In your case, according to the above, it is clear that the clients resource is a parent of orders resource. So the API endpoints must be,
/clients (GET) - get all clients
/clients/$client_id (GET) - get a client
/clients/$client_id/orders (GET) - get all orders of the particular client
/clients/$client_id/orders (POST) - create new order for the client
/clients/$client_id/orders/$order_id (PUT) - Modify the particular order for the client
/clients/$client_id/orders/$order_id (DELETE) - Delete the particular order for the client
And for your last question on creating a parent resource when a child resource create api called,
Refer my answer
Note : Sorting, filtering, limits and pagination can be supported using query parameters in your APIs.
Imagine, We have an Entity School and this entity has a one to many relationship with Student entity. In other words, there is a collection of Students attached to a given School
If we are to replace the entire Student collection via a single API call,
API_URL/school/:school_id/students
which is the best Rest method to go along with. I think PUT is only used on an Entity not on a Collection. Hence, available options would be to use either PATCH or POST
I think PUT is only used on an Entity not on a Collection
No - PUT is used on a resource, not on an entity or collection.
The PUT method requests that the state of the target resource be created or replaced with the state defined by the representation enclosed in the request message payload.
The changes that happen to the entities in your domain are a side effect of the manipulation of REST resources. See Jim Webber's talk REST: DDD in the Large.
If your message body is a replacement representation for the resource, then either POST or PUT is the appropriate method to use
If your message body is a patch document, then you should use POST or PATCH.
If you are concerned that POST would be overloaded, then create a new resource in your design to manage this part of your integration protocol.
Again, heed Jim Webber:
URIs do NOT map onto domain objects - that violates encapsulation. Work (ex: issuing commands to the domain model) is a side effect of managing resources. In other words, the resources are part of the anti-corruption layer. You should expect to have many many more resources in your integration domain than you do business objects in your business domain.
I'm facing same issue. My teammates hate none resource nouns in the path. So in order to pass the API design review and to distinct an operation on whole collection from one on a single resource, I go one level up to the school.
GET /schools/1234
{
"schoolMetadat": "xxxx",
"students": []
}
And PATCH on the students property. An update to a property is always replacement.
For updating the entire resource use PUT, for partial update use PATCH.
PATCH API_URL/school/:school_id {students: [...]}
PUT API_URL/school/:school_id/students [...]
PATCH API_URL/school/:school_id/students {add: [...], remove: [...]}
And don't confuse web services in the presentation layer with ORMs in the data access layer.
We have customers API that takes {customer-name, customer-mobile, customer-email} and creates customer in the database.
We also have order API that takes {productId, customer-name, customer-mobile, customer-email}.
The code for order API:
First creates customer based on {name,mobile,email} passed in the order API and return back customerId.
The {productId, customerId} further gets saved in the database in the order table.
Is this restful practice that one API is internally first creating some other resource?
Please note that its an over simplified example where API expects only one type of product in the order API.
It's fine for a single POST call to result in multiple resources being created. It's not generally the best idea but there are use cases where it makes sense - example cases might include (usual legal disclaimer... not limited to...)
the POST method is to the parent resource of all the created resources. So, a POST /accounts call might result in an /accounts/<accountId> resource being created but also an /accounts/<accountId>/tweets resource. In this instance, the /accounts/<accountId> parent is the 'actual' resource being created.
the POST method might create multiple resources representing multiple ways in which the resource may interact with other parts of the system. So, a POST /accounts response might create resources under /accounts/<accountId> and /users/<accountId> (because an account is-a user and user id are a super set of account ids, for arguments sake). However, the client really only gets told about the one under the '/accounts' path (via the Location header). The other created resource is basically a side-effect.
The key point, really, is that the POST method returns a single Location header - representing the 'primary' resource created - and that subsequent 'GET's on that URI are capable of locating any the other resources via links.
If you find yourself in a situation where creating multiple resources via a single POST request results in you having to return different values for the Location header, then something's wrong with your resource breakdown. It should be clear that a 'POST' will always create one particular type of resource, a URI to being returned in the header. Other resources might be created as side-effects.
I'm converting a SOAP based RPC style "web service" to a JSON based REST web service using ASP.NET Web API.
Methods such as AddXYZ / UpdateXYZ / RemoveXYZ map cleanly to the HTTP verbs for POST/PUT/DELETE. Are there any best practices/guidance for mapping typical RPC style operations such as "ExecuteXYZ" or "AssignXYZ" style methods to it's REST counterpart?
My take is that such operations would map to corresponding URL addressable resources such as "ExecuteXYZRequest" and "AssignXYZRequest"
http://myhost/myservice/ExecuteXYZRequest
http://myhost/myservice/AssignXYZRequest
A request to execute "ExecuteXYZ" would then translate to a POST operation.
Getting the submitted request would translate to a GET(typically would be used to get the status of the submitted request).
http://myhost/myservice/ExecuteXYZRequest/1 <--- 1 is the ID of the request
Cancelling the request(assuming it's cancellable) would translate to a DELETE
POST would not really map to anything.
Does the above sound like a reasonable REST implementation or am I totally off in my thinking here?
Thought/guidance much appreciated.
UPDATE
Here is the specific example I'm trying to model:
A many to many relationship between a Contact and an Event entity. What would be the best way to model the membership of a Contact to an Event as a REST resource such that a Contact can be added/ removed from an Event. In the RPC land This would be a method such as "AssignContactToEvent" which takes the IDs of both entities and set up the relationship between these two. How can this be modeled naturally in REST as a resource. I recall that there is a concept of links and "rel" but cannot find a concrete practical example illustrating how to model something like this using Web API
Question is whether it makes sense for the RPC methods to map to REST
resources as indicated in the post
In a nutshell; no, it doesn't make sense to map methods to resources in the way you describe :)
In order to successfully "do REST" we have to think a little differently, and abandon all thoughts of RPC and CRUD-operations; these are really rather limiting once you embrace being RESTful!
The key abstraction of information in REST is a resource. Any
information that can be named can be a resource: a document or image,
a temporal service (e.g. "today's weather in Los Angeles"), a
collection of other resources, a non-virtual object (e.g. a person),
and so on. In other words, any concept that might be the target of an
author's hypertext reference must fit within the definition of a
resource. A resource is a conceptual mapping to a set of entities, not
the entity that corresponds to the mapping at any particular point in
time.
http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm
A method or action/verb is then not a resource, so it has no place in a URI -- unless of course you're building an application that allows people to create their own methods, which would be rather unusual!
Taking your specific example for a contacts and events relationship, it's important to understand that your 'AssignContactToEvent' is an action that happens under the Web-API layer and cannot be modelled RESTfully; I hope this will become clear in the course of the following examples :)
First we need some good resources to model a list of all Contacts, and a list of all Events:
/contacts
/events
These resources model an individual Contact or Event identified by an ID-token:
/contacts/{contact_id}
/events/{event_id}
The users of your application want to know who is involved in a particular Event, so we need a resource that models a list of the Event's participants:
/events/{event_id}/participants
When we want to add a Contact to an Event, we could POST a minimal Contact-representation (containing just the Contact-ID) to the Event's participants-list:
POST /events/{event_id}/participants/ HTTP/1.1
Content-Type: application/json
{'id': {contact_id}}
To remove a Contact from an Event:
DELETE /events/{event_id}/participants/{contact_id} HTTP/1.1
Your application-users also want to see at-a-glance the Events a Contact is participating in, so you need another to resource to model this:
/contacts/{contact_id}/events
Similarly, you can now GET a list of Events for the Contact, and assign Events using POST:
POST /contacts/{contact_id}/events/ HTTP/1.1
Content-Type: application/json
{'id': {event_id}}
The important point to take onboard is that whenever you need to model something new, you create a resource. The details of how you store the properties and relationships of data-objects are abstracted away behind a Web-API. Indeed, the data-storage technology might change in future, say from relational to object-store, or you change your programming language or framework, but in all cases your URI's (and Web-API) remain the same. REST and HTTP are designed to endure well-beyond the technologies that run under-the-hood.
As a final example of creating new resources, consider a resource that models a list of Contact's who have an organiser-role:
/events/{event_id}/organisers
or this one that models the list of Events that a Contact is organising:
/contacts/{contact_id}/events-organised
If you have a authentication-system, then you might want to see the events you are attending:
/my-account/events
I hope this helps to clarify the purpose of a Web-API and following RESTful principles.
There are two approaches that I have seen so far.
One is to map the action to a verb if there are very few actions so there is no collision. So if action is not safe nor idempotent then POST, otherwise if not safe but idempotent then PUT:
POST http://myhost/myservice/XYZ
Other is to define the action as a logical resource:
POST http://myhost/myservice/XYZ/Assignment
Later is richer and I favour that.
Few Important Points
RPC Endpoint -> REST Entry Point
RPC read method -> REST GET on Resource
RPC create method -> REST POST operation
PRC delete method -> REST DELETE operation
RPC SOAP Message -> REST PayLoad
additonaly , think about Cache headers , Content-Type headers like #Consumes, #Produces
We have a model that looks like this
Login <- Email Addresses <- Person -> Teen
And a stored procedure which takes some properties from teen, some from person, and some from Login, and creates a new teen, returning a person entity.
Looking from a classic RPC perspective, this is easy...just expose a method InsertTeen and have it call the stored procedure.
I've been trying to wrap my head around the RESTful idea of having URLs as my resources (nouns), and the only actions being HTTP actions (verbs). Obviously, a URL like /api/InsertTeen is not RESTful at all.
But here I'm not dealing with any particular resource.
The only thing I can thing of here would be to expose a resource like insertTeenRequest.
Are there any other ideas of how to do this? Am I being too much of a "zealot"?
If you want to be really RESTful, you should use several requests to your API in this case. For example first you create Teen with POST to /api/teens/, then create Person with POST to /api/persons/ and so on.
Pretty new to REST myself, but my thinking is that here you would use a "POST" with the body of the request containing the data needed to create a 'Teen', in whatever format you are using, usually JSON or XML. Here, I'm not sure whether you treat Teens as Persons with additional properties, or a Teen is modeled as an entity itself:
<person login="abc" email="abc#foo.com">
<person-property-1>value1</person-property-1>
<person-property-2>value2</person-property-2>
<teen>
<teen-property-1>value3</teen-property-1>
<teen-property-2>value4</teen-property-2>
</teen>
</person>
or
<teen login="abc" email="abc#foo.com">
<person-property-1>value1</person-property-1>
<person-property-2>value2</person-property-2>
<teen-property-1>value3</teen-property-1>
<teen-property-2>value4</teen-property-2>
</teen>
Regarding the URI, I believe the segments should be nouns rather than verbs since the URI is supposed to address a resource, so /api/teens rather than /api/InsertTeen.
/api/teens with an HTTP GET would return a list of all Teens, and /api/teens with an HTTP POST would insert a new Teen. To round out the CRUD operations, /api/teens/{id} using HTTP GET would return a specific Teen, /api/teens/{id} with an HTTP PUT would update a Teen using the values passed in the request body, and /api/teens/{id} called with HTTP DELETE would delete the specified Teen.
Edit
Read over your question again, and I may have misunderstood. If you aren't treating 'teens' as a resource, but only 'people', then I would consider /api/people with an HTTP POST, and depending on the values passed in the body of the request, do whatever is appropriate to store that 'person'. So, if the request contained 'teen' values, call your stored procedure that creates a 'Teen' and returns a 'Person'.
HTH