Working with money in Java: a quick introduction to JodaMoney library
Hi there! Today we would talk about money. Well, not exactly about how to get more money (although, a good topic), but how to work with money in Java. When we deal with money in Java we usually refer to BigDecimals, also there is a very useful library from the famous Joda project – Joda-Money that simplifies money operations. In this article we would highlight how to install this library in your project, create Money instances, do calculations and what is a difference between Money and BigMoney. Let start!
Joda-Money is a part of famous Joda project (mostly famous for JodaTime library) provides us classes to store amounts of money and do calculations. I need to mention, that it depends on Java 8+. You can install from Maven Central
Joda-Money does have a compile-time dependency on Joda-Convert, but this is not required at runtime thanks to the magic of annotations.
First we should create Money. Not literally of course (what’s a pity!), but as Java objects. Java-Money offers us several ways to accomplish this task using static APIs. We can divide them into 3 groups:
- From string: you can parse String that has a format
[3-symbols Currency code] [amount], for example “EUR 10.00” into Money object with
Money.parse(String s)method. By far, this method is the easiest one. It throws java.lang.IllegalArgumentException in case of bad formatted input.
- Create zero value: you can create a zero value of specified currency with
Money.zero(CurrencyUnit unit). You need to pass CurrencyUnit as an argument. Out of the box there are 7 currencies – EUR, USD, GBP, CHF etc. Although, you can add your owns.
- Passing both amount and currency: this group unifies overloaded methods
of(...). Amount can be of type BigDecimal or double value. When necessary, you can also specifiy rounding mode.
- Finally, we create Money objects as results of operations. Keep in mind, Money class is immutable.
Let do some practice first:
BigDecimal amount = new BigDecimal("10.00"); Money euros = Money.of(CurrencyUnit.EUR, amount); System.out.println(euros); // output: EUR 10.00 Money zero = Money.zero(CurrencyUnit.GBP); System.out.println(zero); // output: GBP 0.00 Money eurosString = Money.parse("EUR 10.00"); System.out.println(euros.isEqual(eurosString)); // output: true
Note, in the last case we use
isEqual method. It checks that monetary value are equal. Keep in mind, scale is ignored, so ‘EUR 10.00’ and ‘EUR 10’ are equal values. That is fun, but until now it is useless. JodaMoney provides us a decent amount of possible operations. But before we jump to operations, let briefly look on the important concept of major and minor parts.
Majors and minors
In JavaDocs you would meet many methods that have *Major or *Minor in their names. What does it mean? Suppose we have some amount of money, for example 100 euros. We can represent this money as Money object via parsing:
Money 100euros = Money.parse("EUR 100.00");
In this notation, there are two parts divided by point: major (100) and minor (00). When we operate with major/minor parts we pass some long values that affect either major or minor part. Take a look on following examples:
Money euros = Money.parse("EUR 100.00"); Money major = euros.plusMajor(50L); System.out.println(major); // output: EUR 150.00 Money minor = euros.plusMinor(50L); System.out.println(minor); // output: EUR 100.50
First thing first, Money is immutable, so all calculations create new instances. There are several groups of methods we can use:
We can perform operations with monetary value as whole, also with major or minor parts only. Take a look on code snippets below:
/*Addition*/ Money euros10 = Money.parse("EUR 10.00"); Money euros15 = Money.parse("EUR 15.00"); Money addition = euros10.plus(euros15); System.out.println(addition); // output: EUR 25.00 Money dollars16 = Money.of(CurrencyUnit.USD, 16.00); Money dollars14 = Money.of(CurrencyUnit.USD, new BigDecimal("14.00")); Money subtraction = dollars16.minus(dollars14); System.out.println(subtraction); // output: USD 2.00 Money pouns15 = Money.of(CurrencyUnit.GBP, 15.00); Money multiplication = pounds15.multipliedBy(2L); System.out.println(multiplication); // output: GBP 30.00 Money francs30 = Money.parse("CHF 30.00"); Money division = francs30.dividedBy(2.0d, RoundingMode.HALF_EVEN); System.out.println(division); // output: CHF 15.00
So here we checked basic operations that we can use with JodaMoney. Note, that methods are overloaded, so there are different possible ways to perform. For example, if we talk about division we can do following:
- divide by long value
- divide by double value and specify Rounding mode (what we did)
- divide by BigDecimal and specify Rounding mode
By the way, what happens if we would operate with different currencies at once:
Money francs10 = Money.parse("CHF 10.00"); Money euros10 = Money.parse("EUR 10.00"); Money result = francs10.plus(euros10); // CurrencyMismatchException thrown
In such cases
CurrencyMismatchException (which is a sub-class of IllegalArgumentException) is thrown.
Money vs. BigMoney
Finally, I want to distinct these two classes: Money and BigMoney. When to use which? Let check documentation:
- Money – an amount of money with the standard decimal places defined by the currency.
- BigMoney – an amount of money with unrestricted decimal place precision.
What is a difference? It is all about decimal places. Let suppose we use Euros. Euro has two decimal places (e.g. 100.00). So all Money instances that represent Euros work with 2 decimal places. Some currencies, like JPY (Japanese Yen) do not have decimal at all. So, decimal places depend on CurrencyUnit we’ve specified. BigMoney instances may have a scale that is positive or zero. Negative scales are normalized to zero.
Joda-Money library is very useful when you deal with money in your application. Though it is limited to basic operations and storage and does not have monetary logic (you should do it yourself), so you can use to implement all necessary logic of your application. This library is very tiny, easy to learn and has a very good documentation. In this post we highlighted how to install this library, create Money objects, do calculations and what is a difference between Money and BigMoney classes. If you have any questions about it – don’t hesitate to drop me a message or leave a comment below. Meanwhile, follow me in twitter for my latest posts announcments. Have a nice day!
Do you want to learn more about Vert.x framework and Java microservices? Take a look on the complete list of my Vertx tutorials and case studies.