My Adventures in Coding

July 5, 2009

Java – REST APIs and Thread Safety

Filed under: Java,REST — Brian @ 7:26 pm
Tags:

In my current job, a few months ago we ran into some strange issues on production. Customers were complaining that sometimes they would receive incorrect data when accessing our REST APIs. We were never able to reproduce the issue and the strange results customers were receiving seemed entirely random. Until one day while a member of our team was accessing a REST API at the same time as a customer. As a result the customer received the employee’s information! After this discovery we found that when accessing a REST call in our system concurrently with different parameters we were consistently able to reproduce the problem the customer was complaining about. Yep, we had classes that were not thread safe and needed to be fixed!

The Bug

In our case the thread safety issue was related to the use of local variables inside a class declared as a singleton in our Spring configuration. The issue was a race condition between when the lookup parameter (e.g., customerId) was set and when it was used to lookup a requested value (e.g., email). Take a look at this example class:

public class CustomerInfo {
    int customerId;

    public void setCustomerId(int customerId) {
        this.customerId = customerId;
    }

    public String getEmail() {
        return customerRepository.getEmail(customerId);
    }
}

Let’s say we have two customers placing an order:
Customer 1: has an email address of jsmith@nowhere.com
Customer 2: has an email address of jdoe@nowhere.com

Now we have two callers accessing our REST API at the same time so two threads are using our CustomerInfo class:

  • Thread A: setCustomerId(1) – customerId=1
  • Thread B: setCustomerId(2) – customerId=2
  • Thread A: getEmail() – customerId=2 so email jdoe@nowhere.com is returned
  • Thread B: getEmail() – customerId=2 so email jdoe@nowhere.com is returned

The Fix

So even though the code calling the getEmail() method was calling it immediately after setting the customerId with the setCustomerId() method, if two threads were running at the same time the chances of the customerId being updated by one thread and affecting the results of another were very likely. There was no reason why we needed to set a customerId value in the class, this was just extra code that was not needed. So removing unnecessary code and fixing our thread safety issue ended up being connected:

public class CustomerInfo{
    public String getEmail(int customerId) {
        return customerRepository.getEmail(customerId);
    }
}

The way we were able to find and track down this concurrency bug was by writing a concurrency test first.

A Simple Concurrency Test

A concurrency test for a REST call does not have to be anything complicated. Just take a REST call you want to test and write a test following this basic outline:

  • One REST call to test
  • A list of valid parameters to use with that REST call and an expected value for each parameter.
  • This expected value is used to check that the request was successful (e.g., parameter CustomerID=2938 returns Email=johnsmith@gmail.com).
  • Pool of threads, each calling the REST call for each of the parameters in the list.
  • Verify every REST call in each thread returns the expected value.

Now run the test and if any of the REST calls return data that does not match the expected value, you know you have some code that is not thread safe. Now that you have this failing test in place you can proceed with finding and fixing your thread safety issues!

Advertisements

2 Comments »

  1. .i was assuming one customer copy per thread and it should be thread local …why it didnot happen in firstcase?

    Comment by speed — December 16, 2014 @ 12:14 pm | Reply

  2. Is your cusomterinfo object sigleton?

    Comment by speed — December 16, 2014 @ 12:14 pm | Reply


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: