How to ensure consistency while updating a document through REST API - rest

I am designing a REST API that will have two client updating it, possibly at the same time:
* Client A will GET a document, spend some X minutes processing and modifying it, then PUT it back.
* Client B might PUT a new document at any time.
The problem arises when Client B PUT's new document whilst Client A is processing old version of the document. In this case, Client A will eventually override the changes Client B made, by PUT'ing modified version of an old document. I would like Client A to drop the processing result instead.
To explain it better, here is an example of straightforward(problematic) workflow:
Client A GET <- Document version 1
Client B PUT -> Document version 2
Client A PUT -> Document version 1.1
Desired workflow:
Client A GET <- Document version 1
Client B PUT -> Document version 2
Client A PUT -> Error. Client A drops the results and restarts
Client A GET <- Document version 2
Client A PUT -> Document version 2.1
Obviously, this can be achieved with versioning the documents in some manner. My question is whether there exists some standard way to achieve it (I'm sure I'm not the only one with this kind of problem), or should I design my own solution.

You're looking for RFC 7232. Specifically, you want either the If-Unmodified-Since header or the If-Match header. They will make Client A's PUT request conditional on the resource being unchanged on the server.

Related

REST best practice for updating an item in an array of items

In my single page application that uses RESTful services, I want to know what the best practice is for updating one item in an array of items.
Prerequisites
1. Front-end makes a GET request to fetch a list of items
2. Front-end formats the list of items (i.e. converts dates from UTC to local time)
3. Front-end makes a PUT request to the back-end to update the name of an item
Possible solutions
Solution #1
4. Back-end responds with HTTP-200 and the single updated item
5. Front-end reformats the updated item
6. Front-end splices the list of items, finding and replacing the updated item
PRO
- One API request to update the item
CON
- Duplication of data on the front-end, no single source of truth (i.e. the list of items)
Solution #2
4. Back-end responds with HTTP-200 and the updated list of items
5. Front-end reformats the list of items
PRO
- One API request to update the item
CON
- Does not follow the single responsibility principle (i.e. the API for updating the item updates the single item, and returns all items)
Solution #3
4. Back-end responds with HTTP-200 and the single updated item
5. Front-end makes a GET request to fetch all of the items
6. Front-end reformats the list of items
PRO
- More flexible for future implementations, APIs follow the single responsibility principle
CON
- Two API requests to update the item
I want to know what the best practice is for updating one item in an array of items.
An important thing to understand about REST, or HTTP, is that we are designing messages to be consumed by general-purpose components. Which is to say, we are using the readily standardized forms to communicate the semantics.
An HTTP PUT has the semantics of upserting a document into a document store. For your example, where we GET a representation of a list resource, make local edits, and PUT the result, the payload of the PUT is a copy of the complete representation of the resource -- what we are asking is that the server make it's copy look like the client's copy.
Assuming that the server elects to apply the new representation to its copy of the resource, the payload of the response could be a status message ("It worked"), or a copy of the new representation of the resource, or even an empty document (204 No Content) with metadata that describing the new representation of the resource (and the implication that the server accepted the client's representation without modification).
The key idea behind PUT, however, is that the payload is a complete representation of the resource, not merely a description of a change made to it. If the document is very large (in particular, large in comparison to the HTTP headers), and the edit you are making is small, then you may prefer to send a patch-document describing the changes you made to the document, specifying the PATCH method in the request.
Of course, on the web, the most popular document format didn't include hypermedia support for PUT or PATCH, and the most popular clients were browsers, not document editors, so we had to design our change protocols around POST. So it's "fine" to do it that way too, you just need to think about how representations of form data are going to be applied to the resource.
Solution 2 does follow the single responsibility principle, you might be confused by the naming and 'responsibility', but if we consider the true definition of SRP: 'single reason for change' Solution 2 is completely fine and the preferred way if performance is not critical.
https://deviq.com/single-responsibility-principle/

REST: How to support create-Or-Update and partial-update ? (aka PUT vs PATCH)

We are designing WebAPI for our software for managing ecommerce product information. We want to provide (among many others) two operations:
Simple one: allow user to add/modify existing product information:
don't create new product if it not exists
don't delete any information from existing product which was not provided in this request
In my opinion HTTP PATCH method is proper way to handle this scenario (with json-patch or json-merge-ptach) with URL like this: /products/{ID}
Harder one: allow user to add/modify existing product or create one
create product if not exists in DB
don't delete any information from existing product which was not provided in this request (same behaviour as in first case)
I'm struggling with designing REST endpoint for this second use case. I have few options but none of them fits perfectly for me in the REST principles:
a) Add custom HTTP header to the endpoint designed for first case (patch) to allow a caller to control of "not found behaviour" eg. create-entity-when-not-exists: true/false - but in my opinion PATCH shouldn't be used for creating resources.
b) Design new endpoint using PUT with special header "preserve-not-provided-data" - this on the other hand violates for me PUT principles because PUT is create-or-replace not create-or-update method
c) Create PATCH for /products URL (without {ID} at the end) - in this case we are updating whole collection(resource) of products - so if product exists we can update it or create new one if not exists.
For now c) solution looks fine for me with one exception: If in the future we would like to support batch operations (for both use cases: 1 and 2) we would like to use /products URL and it will conflict with URL from solution c)
What do you think ? Do you have any other ideas ?
PUT and PATCH have differing message semantics, but the core context ("remote authoring") is the same. In both cases, the client request is "Please, server, make your representation of this resource match my local copy".
For example, I GET a JSON document from the server. I make local edits to it. Now I want to "save" my changes on the server. If the document is modest in size, I might just send the entire revised document over the network. If the document is very large, and my changes are modest, then I might instead send the patch instead.
If you imagine using HTTP to publish edits of HTML web pages to a server, then you've got the right frame of reference. There's not a lot of practical difference between "please patch the title of your copy of the document" and "here is a complete new copy of the document, with my edit to the title". The bytes on disk are going to be the same in either case.
Given that, it would be very odd if those two methods for publishing a new revision of the document were to have vastly different side effects.
Your third approach, based on modifying /products, is potentially fine for both your individual and batch. The server gets the new representation of /products (or the patch document describing the changes), decides whether to accept the changes, and if so computes what it needs to do to its own database to make things work.
Note:
A PUT request applied to the target resource can have side effects on other resources.
The HTTP specification is relatively strict about what the message means, but offers the server a lot of leeway in how it behaves in response.

Axon - How to retrieve the new entity version number in the CommandHandler?

I'm currently writing a distributed application with a microservice architecture.
For that I am applying the CQRS pattern and event sourcing with the help of the axon framework. Therefore the data is eventual consistent.
Both, the write and the read side, are accessible over HTTP; REST specifically.
The initial problem:
After updating/creating an entity, the user [1] should be able to see the results. Because the events are handled asynchronously, the client/UI doesn't know when the entity is really updated (or created). So when the client fetches the data after sending the update-request but before the event is processed, the unchanged data is returned. Therefore the user could think, that the application is broken and/or sends a new request.
Solution attempt:
While looking for a solution for the read-after-write problem I came accross this blog entry.
There is proposed to return the new entity version in the write response. The client can then request the data with the expected entity version (as Expect header). If the actual version is equal or greater than the expected version, the data is returned. Or else an empty response with a Retry-After Header is returned.
The problem:
When the client sends an UpdateFoo request to the write side, the application sends a corresponding UpdateFooCommand over the CommandGateway. The Command is processed by the entity aggregate which publishes the FooUpdatedEvent. The read side receives this event and updates its entity view which can be accessed over the REST interface of the read side.
This is controlled by the axon framework. The handlers are annotated with #CommandHandler and #EventSourcingHandler respectively.
Now: How can I access the new version number of the affected entity in the CommandHandler, so that this number can be returned in the update response?
Thanks in advance
[1] Not only users. There can als be non human clients.
you can use AggregateLifecycle.getVersion() from within your aggregate. You can choose to return that value as part of your command's results and pass that information when doing a query. If the query doesn't have that version number of the aggregate's information, yet, you can (wait and) retry.

In a RESTFul API, what's the correct http verb to a revert / rollback action?

Imagine a simple document management webservice strutured like this:
document/
GET -> retrieves all documents
POST -> creates a new document
document/[id]
GET -> retrieves the "latest" revision of document specified by ID
POST -> creates a new revision of the document
document/[id]/revision
GET -> retrieves all revisions of the document
POST -> Alias to POST->document/[id]
document/[id]/revision/[revisionID]
GET -> retrieves the specified revision of the document
Now, let's say I want to rollback a document to a previous arbitrary revision (for instance, from revision 5 to 3).
In a RESTful point of view, what ROUTE and what VERB should be used for this kind of operation? Should I create a new verb for rollback operations?
Keep in mind that in a rollback operation nothing is deleted. Internally, the server just recognises a different revision number as the latest.
Since you have the representations for each revision available, and the rollback operation should be idempotent, the most straightforward approach would be simply doing a PUT to document/[id] with the contents of GET document/[id]/revision/[revisionid], for the revisionid you want document/[id] to be set to.

How to avoid invalid concurrent modifications in EF 4

I have a 3-tier application:
Client application
Server application
Database server
The server uses Entity Framework 4 to read and write data to/from the database.
Imagine following situation:
Client application creates an instance of an entity with a RowVersion property. At this point in time, the property is equal to null.
Client application sends a request "Save this instance in the database" to the server.
Server saves the object in the database and automatically sets the value of the RowVersion property. But at the client side, that value is still equal to null.
Client application modifies the object it created in the first step, sends a request to the server and the server gets a concurrency exception when trying to save the new version of the object.
Are there any standard mechanisms for solving this type of problem?
I dont know how the system works inside (think communication between Client and Server goes using some API). As I see you trying to handle the situation when 2 clients modifying same entity and you need to notify the client if he is trying to save the version that is older that current.
So I will do next:
On step 3 server must return the version ID (first save of entity)
Next modification of entity by client will have a version id and you need to check if current version id is equal or older than you
have on server (think that rowversion is timestamp)
Server logic will handle this states and send to client response: saved a new version (if current version is equal and will send back
new version id) or false state if version is older (other client made
modification already).
This is it in simplified way.
[Update]
Looks like in this article you will find the implementation that is very close to your needs:
http://weblogs.asp.net/ricardoperes/archive/2012/05/28/yet-another-asp-net-mvc-crud-tutorial.aspx