ppb
ppb

Reputation: 2613

Idempotency of REST API

I have an application with sping-data-jpa integration. In my repository class, I have a method:

@Transactional
@Modifying
@Query(value = "some insert query", nativeQuery = true)
void create(.....);

This method is inserting data into the database.

This method internally is called from POST REST API. Currently, if data is already present in DB then API returns an error response. Now Client of this API wants to perform the same operation with same data multiple time and want success response means I need to make this API as Idempotent. How I can make this API as Idempotent? Does method change from POST to PUT will work or need to add more changes along with Method change? What kind of changes?

Upvotes: 2

Views: 2824

Answers (3)

josepdecid
josepdecid

Reputation: 1847

By definition, POST is not an idempotent method, so there's no sense in returning a Success when the resource is already created.

What you could do is move your POST logic to a PUTmethod and implement something similar to the commonly known as "Create or Update". So being PUT idempotent, it seems the logical choice here for both your create and update.

Here is some additional information for idempotent methods:

Upvotes: 0

VoiceOfUnreason
VoiceOfUnreason

Reputation: 57214

Does method change from POST to PUT will work or need to add more changes along with Method change?

No, the important thing about "idempotent" is that the request handler does the right thing. Nothing magic happens by changing the method that you use.

The good news is that, technically, your implementation is already idempotent (at least from the description). There is a definition in RFC 7231 that you should review. The important element is that receiving two copies of the request leaves the resource in the same state as receiving one copy of the request.

So "all" you need to do is figure out how to know that the error is because the record is already in the database (and not for some other reason), and then replace the error you are currently sending with a response that looks like the success message.

As the other answers have noted, because POST doesn't promise idempotent semantics, generic components aren't going to know that messages can be retried, so will just fail if the original response is lost. It's only the custom client issuing the request that might know that the POST can successfully be retried.

(Compare this with GET -- your browser knows that GET requests are idempotent; the browser doesn't have to ask the human if the request is safe to retry, because the server is already promising to handle the request safely).

There is nothing wrong with using a POST method on an idempotent message exchange (although some other methods may be a better choice if the other semantics match).

Upvotes: 3

Makoto
Makoto

Reputation: 106390

A POST has no notion of idempotency.

Methods can also have the property of "idempotence" in that (aside
from error or expiration issues) the side-effects of N > 0 identical
requests is the same as for a single request. The methods GET, HEAD,
PUT and DELETE share this property. Also, the methods OPTIONS and
TRACE SHOULD NOT have side effects, and so are inherently idempotent.

So that basically means that you've got two different verbs - a POST for initial creation, and a PUT for updates. This would be a cleaner approach anyway given that future maintainers would know for certain that your POST methods weren't expected to maintain state and would basically be reserved for creation, and PUT methods would be reserved for updating and maintaining existing state.

Upvotes: -1

Related Questions