22. March 2017
timer-icon 10 min

Managing concurrency in a distributed RESTful environment with Spring Boot and Angular 2

Handling concurrent access is quite common in transactional data managing systems. As long as your application only creates and reads data records concurrency is not compelling. But as soon as you modify data – which e.g. happens when updating or deleting an existing record – you need to decide how to handle this.

The easiest approach is “the last change wins”. This implies you just ignore any change that might have taken place between reading and updating the record. However this leads to the so called “lost update problem” – which for must business scenarios is obviously not applicable.

Therefore we need a more advanced solution how to handle concurrent access. Hence there are two possible approaches:

  • Pessimistic concurrency control: The system locks the data record as long as a client works with it and prevents any modification by another client.
  • Optimistic concurrency control: Together with the data itself a versioning token is given to the client. When trying to modify the record the systems checks if this token is still valid, which means no change took place in the meantime. The change is only applied if no conflict is detected.

Typically distributed systems are stateless, thus the pessimistic solution does not really fit. One reason for this is that most distributed systems use REST or at least HTTP for communication – which itself is already stateless. Therefore the optimistic concurrency control is the preferred approach.

In this post I will describe how optimistic locking with RESTful communication is implemented. Spring Boot is used for the back end (micro-)service and as a client – or so to say service consumer – we’ll use an Angular 2 web front end.

Usage of HTTP Headers and Status Codes

Preliminary remark: For reasons of simplicity the following steps focus on how to handle updates (done with the HTTP verb PUT). Nevertheless the same principle may be adapted for deletions (done with DELETE) or other non-safe modifications (e.g. POST or PATCH).

As already mentioned for optimistic concurrency control we need a way to provide the clients with tokens containing versioning information of the data they receive.
Like most modern distributed systems we use the de facto standard for synchronous communication: The RESTful application paradigm. And generally speaking REST is done via HTTP. So it is worth to have a closer look if HTTP provides any mechanism that might be suitable to handle these tokens.

And – good news – HTTP1.1 comes with an appropriate header field called ETag:
“The ETag or entity tag is part of HTTP […]. ETags can also be used for optimistic concurrency control, as a way to help prevent simultaneous updates of a resource from overwriting each other.” (see Wikipedia)

Accordingly if a REST client GETs a resource the back end service sends the versioning information in the response header field ETag:

Getting the ETag HTTP response header

The ETag may contain a hash value of the resource’s content, a hash of the last modification timestamp or even just a revision number.

The service consumer must cache the received versioning information and when calling a PUT operation add it to the request header field If-Match.

Setting the If-Match HTTP request header

Basically the If-Match header makes the request conditional. In our case the back end service must check if the condition “resource was not modified” is fulfilled.

If the condition is satisfied, that means the update is possible, the HTTP status code 200 (OK) with the updated resource as payload is sent (or alternatively 204 (No Content)).
If however the update cannot be applied because the resource was modified in the meantime the service will return the status code 412 (Precondition Failed). Receiving that status the client has to decide how to handle the conflict – by reloading the resource and discarding or merging the changes.

Remark: The HTTP header fields ETag, If-Match and If-None-Match are also used for web cache validation, what will not be described in this blog post (further details).

Usage of the JPA Annotation @Version

So far we have seen how the versioning information is transmitted between service provider (our back end) and the service consumer (our client). But where do we get this information?

A common approach is to use a collision-resistant hash function of the resource’s content. This generates a value like shown in the screenshots above.

But if the data is persisted in a relational database using an ORM framework like Hibernate (or generally speaking the Java Persistence API (JPA)) we may retrieve the revision number in another way:
JPA provides the @Version annotation to mark a technical attribute for managing a dedicated revision number (see line 4-6):

Basically the entity’s version attribute and the associated database column are managed by JPA and are used to detect conflicting updates. Therefore JPA already takes care of incrementing the revision number with every update:

The version column managed by JPA

We will go into detail about this in the next chapter. For now let’s just capture that this revision number is exactly what we need as token to hand out to the client via the ETag header.

The following sequence diagram sums up the described usage of the HTTP headers and status codes together with the entity’s version:

Implementing the service provider with Spring Boot

Well, enough theoretical explanations – let’s start implementing.
Our service providing back end is implemented with Spring Boot. More specifically we have a Spring MVC RestController that adds and extracts the required HTTP headers and does the update condition check.

Setting the ETag response header field

When looking for ETag support in Spring you’ll find the ShallowEtagHeaderFilter. This filter may easily be added as a configuration to your Spring Boot application:

The filter adds an ETag header to all GET responses containing a hash value of the resource’s content:

The shallow ETag value generated by the Spring filter

Looks quite convenient, doesn’t it? But unfortunately this is only a shallow implementation of the ETag mechanism. It is sufficient for web cache validation using the If-None-Match header.
But what we need is support of the If-Match header and this has not yet been implemented in Spring. So unluckily this filter won’t help and we have to implement the mechanism ourselves.

The good news, though, is as we wanted to use the entity’s version anyway setting the ETag header in the RestController method is pretty easy:

In line 3 the Spring Data Repository reads the Book entity for the requested identifier. The Book’s version attribute is then set to the ETag response header field (see line 9). We just add two double quotes to make the value compliant to the HTTP specification.

When performing a GET the response header field now contains the Book’s version:

Getting the entity's version as ETag value

Extracting the If-Match request header and checking the constraint

All right, we are now able to send the revision number within the ETag to the client. The client returns the value when trying to update the resource with a PUT operation.

Therefore we have to extract the transmitted value and see if our update constraint is fulfilled.
The steps that need to be realized are shown in the following activity diagram:

Activity diagram how to implement the optimistic locking

First of all we need to extract the value from the If-Match request header field. If the PUT request does not contain the header it is not valid, therefore the HTTP status code 400 (Bad Request) is returned.
In case the value is found it is compared to the latest version of the entity. If these values don’t match the status code 412 (Precondition Failed) is sent and processing is done.
As soon as the two values are the same the resource is updated.
Even after comparing the received version with the current version – that means after reading the stored record from the database and before updating it – there might be another transaction that changes the record in the very same moment. Therefore it is still possible that an OptimisticLockException occurs. In this case the HTTP status code 409 (Conflict) is returned.
Supposing that the update is executed correctly the status code 200 (OK) is sent to the client.

The code fragment below shows the realization of the Spring MVC RestController method:

In line 8 the If-Match value is extracted. If it is found it is matched against the Book’s current version – complemented with the ETag specific double quotes (line 12).
If the values differ the status code 412 is returned. If however the values are identical we try to save the updated Book entity (line 16-19).
The updated Book resource is added to the payload of the response and sent with the status code 200.
The OptimisticLockException that might be thrown by JPA/Hibernate is caught and mapped to the status code 409 (line 24-26).

Further consideration

Of course this example just shows the prototypical implementation. When adapting it for a real-life scenario I suggest the following optimizations:

  • Move the cross-functional aspect of adding and extracting the HTTP header fields to a base class or HandlerInterceptor
  • Add a service layer instead of calling the Spring Data Repository straight from the RestController
  • Shift the exception handling to an ErrorController
  • Return more specific error messages in the response’s payload

Finally two comments concerning our Spring Boot implementation:

  1. Instead of doing the comparison of the header field yourself it is worth having a look if Spring already provides a build-in mechanism.
    At first glance the method ServletWebRequest.checkNotModified(String etag) is exactly what we’re looking for. Then again – like mentioned above – Spring so far only manages the If-None-Match header and the If-Match header is not taken care of yet. Therefore this method is unfortunately not usable until now.
  2. When returning the status code 200 and the updated resource in the PUT response’s payload you have to provide the ETag of the updated resource as well (see line 22 in the code fragment above). Unluckily this is only possible if using at least Spring Boot version 1.4.3. For example with version 1.4.1 setting the ETag for PUT and POST operations is ignored, only GET is processed appropriate.

Implementing the service consumer with Angular 2

As stated previously the client must cache the versioning information received in the ETag response header and when calling a PUT operation return it using the request header field If-Match. In this last chapter I’ll show how this is done using an Angular 2 front end.

Handling the received ETag header value

For dealing with the received data we create a resource class – which behaves almost like a DTO. This BookResource would look like this:

Please note the technical attribute eTag which will be used for caching the received value (in line 7).

The API layer of the Angular 2 service consumer uses the Angular Http client to perform the REST operations. Therefore we create a class ApiService containing the method to GET a single Book from the back end service:

Line 7-9 shows the implementation of the method itself.
Parsing the response to JSON and mapping it to the BookResource is done in the helper method mapResponse (line 13-23). So far this approach corresponds to the Angular documentation. The specificity lies in line 21 where we extract the value from the ETag response header and add it to the JSON string so it is mapped to our BookResource.
Remark: Of course the error handling (line 15-17) has to be improved for a real-life application.

Calling this method can be done like this:

Returning the versioning information

So far we have read the ETag value and cached it in the BookResource. Now when calling the PUT operation we need to send it back. Therefore we add a put method to the ApiService:

In Line 3 you can see how the value – which is handed over as parameter – is added to the If-Match request header.

To call this method you have to provide the eTag parameter, which can easily be selected from the BookResource:

That’s it, we have extracted, cached and returned the versioning information.


In this blog post I showed how distributed optimistic locking using REST, Spring Boot and Angular 2 may be done.
Summarizing I would like to emphasize the importance of the HTTP header fields ETag and If-Match. Even if another back end or client framework is used this mechanism still provides a standardized way to transmit versioning tokens between service provider and consumer.

Subsequent one last remark concerning the distributed communication: I described how an Angular 2 client may handle the ETag information. But of course the same applies for any other client – even if the service consumer is another microservice. That means if you have synchronous RESTful communication between your microservices the described pattern might easily be adapted. However I doubt if synchronous communication between microservices is a good practice. I would rather suggest doing this in an asynchronous manner. But that discussion is out of scope of this blog post.

Comment article


  1. Florian

    Thank you for this article. I wonder how to manage this when using DTO between Spring and Angular.

    Especially when DTO is angular page oriented, and can aggregate multiple entities and mix their fields.

    • Schwörer Christian

      Hi Florian,
      thanks for your feedback.

      Concerning DTOs which aggregate multiple entities: Good question, I’m afraid there is no simple answer.
      The straightforward approach to just user your entity’s version just seems not applicable for this.

      Just a thought, not sure if this leads to anything:
      Perhaps you could add a timestamp to your DTO. And your entities contain an lastUpdatedOn field. And before saving you compare if your returned DTOs timestamp is not older than any of the lastUpdatedOn fields.
      But this is just a spontaneous idea, I didn’t think it through to the end.

      Best regards,

  2. Thorsten Witt

    Great article. But how would you handle concurrent POST-Request that create the same entity?

    • Schwörer Christian

      Hi Thorsten,
      thanks for your patience and sorry for the veeery delayed answer. Our wordpress instance was migrated and I wasn’t notified about your comment.

      I’m not sure if I understood your question correctly – wouldn’t two POSTs automatically lead to two separate entities?


  3. Ben

    Hi Christian! Although I´m a little late to the party: Thanks for the great article!

    I have a question regarding controller/service-structure: intuitively it seems to me, that the matching of the eTag should be done in the web-layer (the controller-class), since services should not have to concern themselves with headers. However, in order to match the eTag, one must handle the entity in question, which probably should not be done by a controller, but by a service.

    Do you have any recommendations regarding this?

    Thanks in advance 🙂

    • Schwörer Christian

      Hi Ben,
      excuse the very late reply. Our wordpress instance was migrated and I wasn’t notified about your comment. 🙁

      Concerning your question: it depends. 😉
      I can agree with you, the eTag handling should be in the controller, the actual logic in a service.
      So I would implement the check in the service but the handling – based on exceptions or return values – in the Controller.

      I hope that helps.

      Thanks again for your patience,
      Cheers Christian

  4. Stefan

    Let’s say i have a “votes” variable on server side, wit GET and PUT. How to display the same, correct “votes” variable, on multiple opened pages?

    Right now, I’m just doing a “.get()” each second. Any better ways?!


    • Schwörer Christian

      Hi Stefan,
      sorry for the very late reply. Our wordpress instance moved and unfortunately I wasn’t informed about your comment/question.

      Hmmm… I think your question is rather a general one, not really eTag-specific, isn’t it?
      Polling every second is a valid option I think. Perhaps Websockets to push the update might be another one, depends on your use case and tech stack.


  5. Christian Schwörer

    Great news! 🙂
    I’ll get back to you concerning the mentioned beer. 😉

  6. Marco

    It works!

  7. Christian Schwörer

    To be honest I never tried it with “plain” Spring Data Rest as we normally have RestControllers that encapsulated some business logic. But I would not be surprised if it works just by convention.

    I would really appreciate to hear if it worked for you.
    Best regards!

  8. Marco

    Yes, that’s my case. I’ve already added @Version in my abstract entity as you wrote above, and it actually is converted into an ETag.
    So, if the front-end (Angular, in my project) is able to send the If-Match, you say that everything is automaGically managed by Spring? Spring doc, in your link, seems to agree, while the Baeldung page of the second link is not so happy about write operations…
    So, Spring Data REST and its siblings manage the optimistic lock on PUT/PATCH operations on a single entity? Wow… If so, I might be the happiest developer on my floor! 🙂 And I owe you a beer.

    I’ll let you know if it works, on my machine. 🙂 Thanks!

  9. Christian Schwörer

    Hi Marco, thanks for your answer. 🙂

    By saying “My repositories are empty interfaces, I have no need for controllers” do you mean your repositories are exposed directly? E.g. with the optional @RepositoryRestResource?

    In this case using the ETag might even be easier as Spring Data support it more or less out of the box.
    See https://docs.spring.io/spring-data/rest/docs/current/reference/html/#conditional.etag or http://www.baeldung.com/etags-for-rest-with-spring#spring as a good starting point.

    Happy coding,

  10. Marco

    Very nice article on a topic I’m struggling on right now!
    What about Spring Boot and the fact that everything is took care by it? My repositories are empty interfaces, I have no need for controllers (except in a few special cases).
    So, how to manage this situation? Should I create all repositories and controllers from scratch for this purpose only?

  11. Christian Schwörer

    Hi Deniss,

    Many thanks for your feedback!

    Concerning your question regarding the exception handling:
    In the shown exemplary REST Controller the mapping of an exception to the corresponding HTTP status is done quite rudimentary.

    E.g. if the OptimisticLockingFailureException occurs it is mapped to the HTTP status 409 (Conflict) within the method (see line 25 in the example above). But if there are more than one method this needs to be repeated.

    Therefore Spring MVC provides the annotation @ExeptionHandler to do this on Controller level and not in every method (see https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc).

    This is already an improvement but it is still limited to one Controller. So if you have several Controllers you should go even further by using @ControllerAdvice as global mechanism (see https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/annotation/ControllerAdvice.html).

    A colleague of mine provides a good example if you need further inspiration: https://github.com/nt-ca-aqe/library-app/blob/master/library-service/src/main/kotlin/library/service/api/ErrorHandlers.kt

    If you have further questions please don’t hesitate to ask,
    Cheers Christian

  12. Deniss

    Thanks! Amazing article!
    Shift the exception handling to an ErrorController – can you please maybe elaborate more on this?

  13. Christian Schwörer

    You’re very welcome! 🙂

  14. Christian Schwörer

    Thank you!
    Good to know that the time spent for creating the diagrams was invested well. 🙂

  15. Vladimir

    Good post about versioning! Thank you for ETag

  16. wojt

    I wish there were more posts like this one. I especially appreciate the concise explanation and the effort you’ve put in preparing these elegant diagrams.