I have a class (let's call it Money) that handles calculation of monetary values. It's a wrapper for BigDecimal and uses the correct decimal precision for money. It has worked pretty well for many years, but we have had an incident that had some major repercussions and need to determine the cause, and if the use of this class was the cause.
We read values from an Excel file using jExcelApi. We use this API because the files we are working with are Excel 2003 files. The value is read from this file using the getContents
method. The field in the Excel file is in the General
format and after reading it, the result instantiates a new instance of the money class using the following static method of the Money class:
public static Money valueOf(String s, int precision) {
try {
Number n = format.parse(s);
return new Money(new BigDecimal(n.doubleValue()), precision);
}
catch (ParseException e) {
throw new IllegalArgumentException("Cannot convert as money " + s);
}
}
precision
is 2 and format is an instance of DecimalFormat("#0.00###;-0.00###")
e.g.
Money amount = Money.valueOf(sheet.getCell(col, row).getContents());
So a value of 1500
(no decimals) was used in the sheet and used as input. What happened was that this value somehow got duplicated in the following way
15150000
creating a severely overstated amount. It's as if the same value was pushed in between the digits. So instead of only 1500, the value was 15 million.
I've have not been able to replicate this problem. The values are always calculated correctly. It's quite possible that the system was operating at peak at the time and that the swap space was being used, but I don't see how this would only affect one record of over 3500 records with the same amount.
Any ideas? Is it possible that the memory was not cleared?
Our technology stack:
Ubuntu 15.04 with 8GB RAM
Java 8
Tomcat 8.5
MySQL 5.7.15