TeamCity – Using Personal Builds to help improve cycle time

So you are working on a large project, many developers committing regularly to the same code base, you run all the unit tests, commit and you break the build. Now everyone on your team is angry (As they should be!). How could this have happened when you ran all of the tests? The reason is that you did not update before running tests locally and committing. The problem is that constantly updating and building can waste a lot of time. Even if you do update, run all tests, then commit, there is still a chance another developer made a commit during that cycle. The solution: Team City Personal Builds.

Personal Builds

The great people at JetBrains have a feature in TeamCity that allows you to use your build server build agents for “Personal Builds”. More great news is that TeamCity plugins that make use of this interesting TeamCity feature are available for IDEs such as IntelliJ and Visual Studio.

So now when you use your IDE tool with the TeamCity plugin you would use the “Remote Run” option to make your commit. TeamCity will then spin up a personal build, apply your code changes to a fresh checkout of the repository, build, and run all unit tests. If your “Personal Build” passes, your code changes will be committed. Now, here is the great part, if it fails, your code changes will NOT be committed, and you will be notified of the failure.

This feature of TeamCity allows developers to get out of the update, run all tests, and commit cycle and offload some of that work to their TeamCity server.

IntelliJ Plugin Setup

  • File->Settings->Plugins
  • Click on the “Available” tab
  • In the search box enter “TeamCity” (The option JetBrians TeamCity Plugin should show up in the list)
  • Right click on the plugin and select “Download and install”
  • You should see a TeamCity option on your IntelliJ toolbar
  • Enter your TeamCity credentials, setup your notifications

So now, when you commit use TeamCity – > Remote Run rather than using the Version Control menu. You will be notified if your commit is accepted or rejected.

Visual Studio Plugin Setup

To download the Plugin, login to your TeamCity server, go to the “My Settings & Tools” page. You will find a download link for the plugin in the “TeamCity Tools” panel on the righthand side of the page.

Hibernate – Cascade delete does not delete ALL related rows

Recently I had a problem where a cascade delete was not deleting all related rows. I am fairly new to HIbernate, so I thought I would post my solution in case anyone else runs into this problem.

To explain the problem, lets say I have a hibernate entity called “Customer” that has a one to many mapping to another hibernate entity called “Subscriptions”. In my test I saved a Customer with several Subscriptions then deleted the Customer and asserted that all related entries in the Subscriptions table were removed. The problem was that each time only ONE entry was removed, but never ALL related entries in the Subscription table.

The “Customer” entity was set up with a relationship to “Subscriptions” as follows:

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @Cascade({org.hibernate.annotations.CascadeType.DELETE_ORPHAN})
    @JoinColumn(name = "customerID", referencedColumnName = "id", nullable = false)
    private List subscriptions = new ArrayList();

The problem turned out to be that I needed to add a “Fetch” annotation:

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @Cascade({org.hibernate.annotations.CascadeType.DELETE_ORPHAN})
    @JoinColumn(name = "customerID", referencedColumnName = "id", nullable = false)
    @Fetch(value = FetchMode.SUBSELECT)
    private List subscriptions = new ArrayList();

This solved the problem. Now ALL related rows in the Subscriptions table sub select are removed on cascade delete of a Customer.

Java – REST APIs and Thread Safety

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 a developer introducing a local variable into a singleton class called CustomerInfo that is created when the application is started by our dependency injection framework which happens to be Spring. This class should never contain any state information. 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!