Using conditional breakpoints to fix a bug

Mikey

June 18, 2019

In this blog, we will be going through an example of catching a corner case within an application using conditional breakpoints.

What is a conditional breakpoint?

Conditional breakpoints allow you to break inside the code when a specific expression that evaluates to true. Example conditions could be:

  • variable != null;
  • variable > X;
  • variable.equals("myName")
  • this.request.getParameter("foo").contains("bar")
  • this.runDays.contains("sat")

Why are conditional breakpoints useful?

Conditional breakpoints can be useful for many reasons, with two common reasons being to catch a hard to reproduce an issue and to limit firing a breakpoint to a specific user of the application.


If for example, you know you have a NullPointerException occurring in your application, setting a condition so the breakpoint only fires when a variable is equal to null will mean you do not collect breakpoint data with no value.


If you had a report from a customer that when they use the product they have an issue, but you are unable to reproduce this issue  locally. You would be able to set a breakpoint to check that the account, email or IP address for the user is equal to their account.


For this example, we will be using our Spring Boot shop application. This application has been developed specifically as a nerd.vision test app and contains several known bugs to show nerd.vision in action. We will be debugging a specific issue within the application where we have a corner case and wish to know exactly what causes this issue.‍

Example - corner case bug

This example looks at an occasional error that occurs when items are bought from a shopping cart. When an order is placed code within the application will trigger a function to restock the product if less than 10% of the initial product quantity remains.

The quantity to be restocked is based on the amount of the quantity remaining for the product. The idea behind this is to dynamically control the stock flow of products and ensure the stock levels are always appropriate. If a product sells more the quantity will increase over time, whereas if the product sells less the stock level will decrease over time.


Under normal circumstances, this functionality works:

  • If for example, we have 10 items of the product in stock and the user buys 9, the restock function will execute and order 11 new items (the original value the remainder of the current stock).
  • If we have 10 items of the product and a user buys all 10 the restock function will execute and order 20 new items (two times the original value).

There is however a case that the restocking process order an incorrect quantity of items, the number of items ordered will be less than the original quantity. To find this case we can set conditional breakpoints.

Configuring the conditional breakpoint

If we used a standard breakpoint, every time a user buys the items in the cart a breakpoint would fire in nerd.vision, but 99% of the time we would gain no value from the breakpoints as the code is functioning as expected.


To catch this error we will add a conditional breakpoint on line 111 of the CartServiceImpl class within our buy now function. In our breakpoint we will configure the email notification as we cannot guarantee the issue will occur when you are available and monitoring nerd.vision for fired breakpoints.

We know that the issue at hand is that for some reason the quantity of items restocked is less than the initial quantity of the product  before the customer hit buy now, which would leave a shortage of stock for this product. We only fire a breakpoint when this is the case, we will add a condition to our breakpoint that the initial quantity of products is greater than the quantity being restocked.

Debugging the issue

When our issue occurs, we will receive an email and can view our breakpoint in nerd.vsion.


Finding the bug

What we can see in the breakpoint is that the restock quantity is indeed less than the initial quantity, proving the issue exists, but we can also find the cause of the issue.

We can see that the in the cart, the user attempted to buy 11 items, where there were only 10 items in stock.

This caused the quantity of the product was set to -1 on line 102, which will mean that when the restock quantity is calculated it will be initial quantity (10) + -1 which is equal to 9.

Resolving the issue

From setting this breakpoint we can reproduce the issue and see that the issue occurs when a user attempts to buy more items in the cart than the shop has in stock.

Fixing this issue could be done in multiple ways, the ideal solution is to limit the maximum number of items the user can add in the cart and add a check into the buy now function that an attempt to buy more items than the shop has in stock is stopped and handled.


Technical Support Engineer and Developer advocate for nerd.vision and other software projects. Background in object-oriented software development and data analysis. Personal hobbies include simulation gaming and watch collecting.