Rest – Avoiding Double POST

restspring-mvc

We are implementing a RESTful webservice that will allow client applications to POST documents to it and it will store the document returning a unique identifier in the response. The clients will mostly be Spring MVC applications, but do not have to be.

The two client applications that we are currently working on have various JSPs which contains HTML forms that will contain file elements and other attributes. So a user will submit a form via POST to a Spring Controller in the client application. The Controller will read the bytes from the file and then POST them to the RESTful service, receive the unique identifier back, and store the unique identifier along with the other information from the form in the database.

As each client can have multiple JSPs with widely varying attributes in the forms, we don't see a way to just POST directly to the RESTful web service.

Is there a clean way to avoid the double POST?

I could see the possibility of having a reusable pop-up window that takes care of POSTing the document to the RESTful web service and then holding the unique document id either in the session or a hidden field on the parent form. I can see two downsides to this: 1) the user may not like having the extra step of going to the pop-up and 2) the document could be orphaned if the user does not submit the parent page.

EDIT / CLARIFICATION: the issue is not that a POST is being sent twice to the same resource, but rather avoiding have both a POST from JSP to Controller within the client application and then a second POST of the same data from the client application to the REST resource.

Best Answer

We faced the same issue and, as others suggested in comments, we made our POSTs idempotent. You can return a different code (in the 200 family) if the file was already there, just to inform the client (or you can just answer "200"). In our experience, this also plays nicely with "not-so-connected" devices (smartphones); if you need to retry a submission, you just retry it, without worrying of duplicates. You can make (and store) a UID that is based on the document content (a MD5 or SHA hash) and maybe even use it as your primary document ID.

We also considered making the client code more complicated, adding a GET to check if a particular document was already inserted:

  • GET (is this document present?)
  • POST (insert document)
  • ...

but this make the client heavier (especially if you compute the hash twice). It does not really waste bandwidth (in our case, being on a cell network, it was an important issue); most of the time, you just POST once and receive a OK answer (document was not there).

AND it will not solve your issue anyway; if you POST the document from another page just after the GET? Still, you can combine the two approaches, if you see that the double POST happens many times in your web application.

Related Topic