Successfully reported this slideshow.

Introducing JSR 354 The Money & Currency API

2

Share

YouTube videos are no longer supported on SlideShare

View original on YouTube

@YourTwitterHandle#Devoxx #YourTag
Introducing JSR 354
The Money & Currency API
Wim van Haaren
Jeroen Burggraaf
www.trital...
@YourTwitterHandle#Devoxx #YourTag
About us
Wim van Haaren
Co-founder of Tritales
wim@tritales.nl
jdev.it/blog/
#Devoxx #M...
Upcoming SlideShare
JSR354 Utrecht JUG 20171027
JSR354 Utrecht JUG 20171027
Loading in …3
×
1 of 51
1 of 51

Introducing JSR 354 The Money & Currency API

2

Share

Download to read offline

Talk at Devoxx Belgium 2016 about JSR 354 The Money & Currenct API by Tritales' co-founders Wim van Haaren and Jeroen Burggraaf.

Monetary values are a key feature of many applications, yet the JDK provides little or no support. The existing java.util.Currency class is strictly a structure used for representing current ISO-4217 currencies, but not associated values or custom currencies. The JDK also provides no support for monetary arithmetic or currency conversion, nor for a standard value type to represent a monetary amount.

Enter JSR 354 – Money and Currency. Started in 2012 and finalized in 2015, the objective of this little known API is to provide a money and currency API for Java, targeted at all users of currencies and monetary amounts, both simple but also expandable. The API provides support for standard ISO-4217 and custom currencies, and a model for monetary amounts and rounding. It will have extension points for adding additional features like currency exchange, financial calculations and formulas.

This session will address the motivation behind the API, some of the use cases that it covers, describe the API, and demonstrate the usage through some examples using the reference implementation.

Talk at Devoxx Belgium 2016 about JSR 354 The Money & Currenct API by Tritales' co-founders Wim van Haaren and Jeroen Burggraaf.

Monetary values are a key feature of many applications, yet the JDK provides little or no support. The existing java.util.Currency class is strictly a structure used for representing current ISO-4217 currencies, but not associated values or custom currencies. The JDK also provides no support for monetary arithmetic or currency conversion, nor for a standard value type to represent a monetary amount.

Enter JSR 354 – Money and Currency. Started in 2012 and finalized in 2015, the objective of this little known API is to provide a money and currency API for Java, targeted at all users of currencies and monetary amounts, both simple but also expandable. The API provides support for standard ISO-4217 and custom currencies, and a model for monetary amounts and rounding. It will have extension points for adding additional features like currency exchange, financial calculations and formulas.

This session will address the motivation behind the API, some of the use cases that it covers, describe the API, and demonstrate the usage through some examples using the reference implementation.

More Related Content

Related Books

Free with a 14 day trial from Scribd

See all

Related Audiobooks

Free with a 14 day trial from Scribd

See all

Introducing JSR 354 The Money & Currency API

  1. 1. @YourTwitterHandle#Devoxx #YourTag Introducing JSR 354 The Money & Currency API Wim van Haaren Jeroen Burggraaf www.tritales.nl #Devoxx #Money @tritales
  2. 2. @YourTwitterHandle#Devoxx #YourTag About us Wim van Haaren Co-founder of Tritales wim@tritales.nl jdev.it/blog/ #Devoxx #Money @tritales Jeroen Burggraaf Co-founder of Tritales jeroen@tritales.nl www.tritales.nl
  3. 3. @YourTwitterHandle#Devoxx #YourTag#Devoxx #Money @tritales Motivation
  4. 4. @YourTwitterHandle#Devoxx #YourTag Why a Money library? Martin Fowler: “A large proportion of the computers in this world manipulate money, so it’s always puzzled me that money isn’t actually a first class data type in any mainstream programming language. The lack of a type causes problems, the most obvious surrounding currencies. …” http://martinfowler.com/eaaCatalog/money.html #Devoxx #Money @tritales
  5. 5. @YourTwitterHandle#Devoxx #YourTag Eric Evans: “On project after project, software developers have to reinvent the wheel, creating objects for simple recurring concepts such as "money" and "currency”…” http://timeandmoney.sourceforge.net/ #Devoxx #Money @tritales
  6. 6. @YourTwitterHandle#Devoxx #YourTag Money • Numerical value • Currency #Devoxx #Money @tritales
  7. 7. @YourTwitterHandle#Devoxx #YourTag Primitive floating types #Devoxx #Money @tritales double value = 1.03 - .42; 0.6100000000000001
  8. 8. @YourTwitterHandle#Devoxx #YourTag Primitive Integer Types Convert to cents #Devoxx #Money @tritales public class Product { private String name; private long money; }
  9. 9. @YourTwitterHandle#Devoxx #YourTag#Devoxx #Money @tritales Product b1 = new Product(“Westmalle", 5_00); Product b2 = new Product(“Koninck", 4_00); 900 int sum = b1.getMoney() + b2.getMoney();
  10. 10. @YourTwitterHandle#Devoxx #YourTag BigDecimal #Devoxx #Money @tritales Product b1 = new Product(“Westmalle", BigDecimal.valueOf(5D)); Product b2 = new Product(“Koninck", BigDecimal.valueOf(4D)); 9.0 BigDecimal sum = b1.getMoney().add(b2.getMoney()); € or $ or …? Currency?
  11. 11. @YourTwitterHandle#Devoxx #YourTag Currency String #Devoxx #Money @tritales public class Product { private String name; private String currency; private BigDecimal money; } Type-safety? Validation?
  12. 12. @YourTwitterHandle#Devoxx #YourTag Currency Enum #Devoxx #Money @tritales public class Product { private String name; private Currency currency; private BigDecimal money; } enum Currency { EURO, POUND, DOLLAR; } i18n? ISO-4217?
  13. 13. @YourTwitterHandle#Devoxx #YourTag java.util.Currency • Simple • Supports ISO-4217 #Devoxx #Money @tritales public class Product { private String name; private Currency currency; private BigDecimal money; }
  14. 14. @YourTwitterHandle#Devoxx #YourTag#Devoxx #Money @tritales Product b1 = new Product(“Westmalle", Currency.getInstance("EUR"), BigDecimal.valueOf(5)); Product b2 = new Product(“Koninck", Currency.getInstance("USD"), BigDecimal.valueOf(4)); if (b1.getCurrency().equals(b2.getCurrency())) { // ... }
  15. 15. @YourTwitterHandle#Devoxx #YourTag Utility class #Devoxx #Money @tritales public static class ProductUtils { public static BigDecimal sum(Product a, Product b) { if(a.getCurrency().equals(b.getCurrency())) { return a.getValue().add(b.getValue()); } throw new IllegalArgumentException(); } } A lot of Utility classes Don’t forget to use them
  16. 16. @YourTwitterHandle#Devoxx #YourTag Money #Devoxx #Money @tritales public class Money { private final BigDecimal value; private final Currency currency; // behavior goes here ... }
  17. 17. @YourTwitterHandle#Devoxx #YourTag#Devoxx #Money @tritales public class Product { private String name; private Money money; } Currency euro = Currency.getInstance("EUR"); Product b1 = new Product(“Westmalle”, new Money(BigDecimal.valueOf(5), euro)); Product b2 = new Product(“Koninck", new Money(BigDecimal.valueOf(4), euro)); Money money = b1.getMoney().add(b2.getMoney());
  18. 18. @YourTwitterHandle#Devoxx #YourTag Motivation for Money • Monetary values are a key feature to many applications • No standard value type to represent a monetary amount • ISO-4217 ambiguous/confusing • Historical & virtual currencies missing • Conversions & arithmetic missing • Formatting missing #Devoxx #Money @tritales
  19. 19. @YourTwitterHandle#Devoxx #YourTag JSR 354 – Money and Currency API • Started 2012 – finalized 2015 • Targeted for JDK 9 • Standalone API: • Available for JDK 7/8 • Specification (http://javamoney.github.io/api.html) • RI “Moneta” (http://javamoney.github.io/ri.html) #Devoxx #Money @tritales
  20. 20. @YourTwitterHandle#Devoxx #YourTag#Devoxx #Money @tritales Core API
  21. 21. @YourTwitterHandle#Devoxx #YourTag CurrencyUnit CurrencyUnit currency = Monetary.getCurrency("EUR"); CurrencyUnit currency = Monetary.getCurrency( new Locale("nl", "NL")); #Devoxx #Money @tritales
  22. 22. @YourTwitterHandle#Devoxx #YourTag MonetaryAmount boolean isGreaterThan(MonetaryAmount amt) boolean isGreaterThanOrEqualTo(MonetaryAmount amt) boolean isLessThan(MonetaryAmount amt) boolean isLessThanOrEqualTo(MonetaryAmount amt) boolean isEqualTo(MonetaryAmount amt) boolean isNegative() boolean isNegativeOrZero() boolean isPositive() boolean isPositiveOrZero() boolean isZero() #Devoxx #Money @tritales MonetaryAmount add(MonetaryAmount amt) MonetaryAmount subtract(MonetaryAmount amt) MonetaryAmount multiply(Number multiplicand) MonetaryAmount divide(Number divisor) MonetaryAmount remainder(Number divisor) MonetaryAmount negate() CurrencyUnit getCurrency() MonetaryAmount with(MonetaryOperator operator) <R> R query(MonetaryQuery<R> query)
  23. 23. @YourTwitterHandle#Devoxx #YourTag Creating Money #Devoxx #Money @tritales MonetaryAmount money = MonetaryAmounts.getDefaultAmountFactory() .setCurrency("EUR") .setNumber(200.5) .create(); MonetaryAmount money = Money.of(200.5, "EUR");
  24. 24. @YourTwitterHandle#Devoxx #YourTag NumberValue #Devoxx #Money @tritales MonetaryAmount m1 = Money.of(10.21, "EUR”); NumberValue numberValue = m1.getNumber(); NumberValue extends java.lang.Number  convert to primitive types (long, double, etc.)
  25. 25. @YourTwitterHandle#Devoxx #YourTag#Devoxx #Money @tritales Operator & Query
  26. 26. @YourTwitterHandle#Devoxx #YourTag MonetaryOperator & MonetaryQuery Functional interfaces #Devoxx #Money @tritales public interface MonetaryOperator { MonetaryAmount apply(MonetaryAmount amount); } public interface MonetaryQuery<R>{ R queryFrom(MonetaryAmount amount); }
  27. 27. @YourTwitterHandle#Devoxx #YourTag#Devoxx #Money @tritales MonetaryAmount money = Money.of(10, “EUR”); MonetaryOperator doubleOperator = m -> m.multiply(2); doubleOperator.apply(money); // EUR 20.00000 money.with(doubleOperator); // EUR 20.00000 MonetaryOperator
  28. 28. @YourTwitterHandle#Devoxx #YourTag MonetaryQuery #Devoxx #Money @tritales MonetaryAmount money = Money.of(10, “EUR”); MonetaryQuery<String> currencyCodeQuery = m -> m.getCurrency().getCurrencyCode(); currencyCodeQuery.queryFrom(money); //EUR money.query(currencyCodeQuery); //EUR
  29. 29. @YourTwitterHandle#Devoxx #YourTag#Devoxx #Money @tritales Formatting
  30. 30. @YourTwitterHandle#Devoxx #YourTag MonetaryAmountFormat #Devoxx #Money @tritales public interface MonetaryAmountFormat extends MonetaryQuery<String> { AmountFormatContext getContext(); default String format(MonetaryAmount amount) {} void print(Appendable appendable, MonetaryAmount amount) throws IOException; MonetaryAmount parse(CharSequence text) throws MonetaryParseException; }
  31. 31. @YourTwitterHandle#Devoxx #YourTag format() #Devoxx #Money @tritales MonetaryAmount money = Money.of(12, “USD”); MonetaryAmountFormat format = MonetaryFormats.getAmountFormat(Locale.US); String s = format.format(money); // USD12.00
  32. 32. @YourTwitterHandle#Devoxx #YourTag Custom formats #Devoxx #Money @tritales CurrencyUnit currency = Monetary.getCurrency(new Locale("nl", "NL")); MonetaryAmountFormat patternFormat = MonetaryAmountDecimalFormatBuilder .of("¤ ###.###,00") .withCurrencyUnit(currency) .build(); MonetaryAmount money = Money.of(12000, currency); String format = patternFormat.format(money); // € 12.000,00
  33. 33. @YourTwitterHandle#Devoxx #YourTag#Devoxx #Money @tritales Conversion
  34. 34. @YourTwitterHandle#Devoxx #YourTag Conversion #Devoxx #Money @tritales MonetaryAmount money = Money.of(10,“USD”); MonetaryAmount money2 = Money.of(10,“EUR”); MonetaryAmount result = money.add(money2); javax.money.MonetaryException: Currency mismatch: USD/EU “Changing currency by applying exchange rate”
  35. 35. @YourTwitterHandle#Devoxx #YourTag ExchangeRateProvider #Devoxx #Money @tritales MonetaryAmount money = Money.of(10, "EUR"); ExchangeRateProvider provider = MonetaryConversions. getExchangeRateProvider(ExchangeRateType.ECB); CurrencyConversion currencyConversion = provider.getCurrencyConversion("USD"); MonetaryAmount result = currencyConversion.apply(money); // USD 11.49500
  36. 36. @YourTwitterHandle#Devoxx #YourTag Exchange rate on a specific date #Devoxx #Money @tritales MonetaryAmount money = Money.of(10,“EUR”); LocalDate localDate = Year.of(2016).atMonth(Month.MAY).atDay(10); ExchangeRateProvider provider = MonetaryConversions.getExchangeRateProvider(ExchangeRateType.IMF_HIST); ConversionQuery query = ConversionQueryBuilder.of().setTermCurrency(dollar).set(localDate).build(); CurrencyConversion currencyConversion = provider.getCurrencyConversion(query); MonetaryAmount result = currencyConversion.apply(money); // USD 11.37200
  37. 37. @YourTwitterHandle#Devoxx #YourTag#Devoxx #Money @tritales Streams
  38. 38. @YourTwitterHandle#Devoxx #YourTag Sorting #Devoxx #Money @tritales MonetaryAmount[] m = { Money.of(9,"EUR"), Money.of(10,"USD"), Money.of(11,"GBP"), Money.of(26,"GBP") }; Stream.of(m) .sorted(MonetaryFunctions.sortCurrencyUnit()) .collect(Collectors.toList()); // [EUR 9, GBP 11, GBP 26, USD 10] Stream.of(m) .sorted(MonetaryFunctions.sortNumber()) .collect(Collectors.toList()); // [EUR 9, USD 10, GBP 11, GBP 26] EUR 10 == USD 10
  39. 39. @YourTwitterHandle#Devoxx #YourTag Sorting using exchange rate #Devoxx #Money @tritales MonetaryAmount[] m = { Money.of(9,"EUR"),Money.of(10,"USD"),Money.of(7.8,"GBP") }; ExchangeRateProvider provider = MonetaryConversions. getExchangeRateProvider(ExchangeRateType.IMF); Stream.of(m) .sorted(MonetaryFunctions.sortValuable(provider)) .collect(Collectors.toList()); // [USD 10, GBP 7.8, EUR 9]
  40. 40. @YourTwitterHandle#Devoxx #YourTag Multiple Sorters #Devoxx #Money @tritales MonetaryAmount[] m = { Money.of(9, "EUR"), Money.of(10, "EUR"), Money.of(9, "GBP"), Money.of(26,"GBP") }; Stream.of(m).sorted( sortNumber().thenComparing(sortCurrencyUnit())) .collect(Collectors.toList()); // [EUR 9, GBP 9, EUR 10, GBP 26]
  41. 41. @YourTwitterHandle#Devoxx #YourTag Reduction Methods Predefined higher order functions in the RI Moneta, e.g.: • MonetaryFunctions.sum() • MonetaryFunctions.average() • MonetaryFunctions.min() • MonetaryFunctions.max() #Devoxx #Money @tritales
  42. 42. @YourTwitterHandle#Devoxx #YourTag sum() #Devoxx #Money @tritales MonetaryAmount[] money = { Money.of(10, "USD"), Money.of(10, "USD"), Money.of(10, "USD"), Money.of(9, "USD"), Money.of(8, "USD") }; Optional<MonetaryAmount> result = Stream.of(money) .reduce(MonetaryFunctions.sum()); // USD 47
  43. 43. @YourTwitterHandle#Devoxx #YourTag#Devoxx #Money @tritales MonetaryAmount[] money = { Money.of(10, "USD"), Money.of(12, "EUR"), Money.of(15, "USD")}; Optional<MonetaryAmount> result = Stream.of(money) .reduce(MonetaryFunctions.sum()); javax.money.MonetaryException: Currency mismatch: EUR/USD
  44. 44. @YourTwitterHandle#Devoxx #YourTag#Devoxx #Money @tritales ExchangeRateProvider provider = MonetaryConversions .getExchangeRateProvider(ExchangeRateType.IMF); Stream.of(m1,m2,m3) .reduce( MonetaryFunctions.sum( provider, Monetary.getCurrency("EUR"))); // € 34.60
  45. 45. @YourTwitterHandle#Devoxx #YourTag Predicate #Devoxx #Money @tritales “Higher order function that operates on a value and returns a boolean” Predicates can be used to filter: Collection<T> filteredCollection = Stream.of(collection).filter(predicate).collect(Collectors.toList()); Moneta provides predicates: Predicate<MonetaryAmount> isGreaterThan = MonetaryFunctions.isGreaterThan(money);
  46. 46. @YourTwitterHandle#Devoxx #YourTag#Devoxx #Money @tritales Predicates on currency MonetaryAmount[] m = {Money.of(10, dollar), Money.of(8, euro), Money.of(9, dollar)}; Stream.of(m).filter(MonetaryFunctions.isCurrency(dollar)) .collect(Collectors.toList()); // [USD 10, USD 9] Stream.of(m).anyMatch(MonetaryFunctions.isCurrency(dollar)); // true Stream.of(m).allMatch(MonetaryFunctions.isCurrency(dollar)); // false
  47. 47. @YourTwitterHandle#Devoxx #YourTag#Devoxx #Money @tritales Predicates on value MonetaryAmount[] m = {Money.of(10, dollar), Money.of(8, euro), Money.of(9, dollar)}; Stream.of(m).filter(MonetaryFunctions.isGreaterThan(Money.zero(dollar))) .collect(Collectors.toList()); // [USD 10, EUR 8, USD 9] Stream.of(m).anyMatch(MonetaryFunctions.isGreaterThan(Money.zero(dollar))); // true
  48. 48. @YourTwitterHandle#Devoxx #YourTag Summarizing Money #Devoxx #Money @tritales • Currently no proper money support in the JDK • JSR 354 fixes this in JDK 9 or as library in JDK 7/8: • MonetaryAmount class, encapsulates amount & currency • Operators & queries • Formatting • Exchange rate conversions • Sorting & reduction • Predicates
  49. 49. @YourTwitterHandle#Devoxx #YourTag References • https://www.gitbook.com/book/otaviojava/money-api/details • https://jcp.org/aboutJava/communityprocess/final/jsr354/index.html • http://javamoney.github.io/ • http://javamoney.github.io/api.html • http://javamoney.github.io/ri.html • http://javamoney.github.io/lib.html #Devoxx #Money @tritales
  50. 50. @YourTwitterHandle#Devoxx #YourTag#Devoxx #Money @tritales wim@tritales.nl jdev.it/blog/ jeroen@tritales.nl www.tritales.nl info@tritales.nl @tritales

Editor's Notes

  • Good afternoon everybody and welcome to our talk about JSR 354 – The Money and Currency API.
  • First of all, who are we? Well, my name is Wim van Haaren…
    … and my name is Jeroen Burggraaf. We are the founders of Tritales, a company in the Netherlands. Together we have over 35 years of software development experience in both backend as well as frontend development. Lets start with our talk about the money and currency API.
  • Let’s quickly get to the reason why we are standing here.
    Why do we want to talk about a JSR about Money and Currency?
  • Well, a lot of applications have to deal with money.
    So why do the mainstream programming languages not provide data types for it? Especially since this has caused of lots of problems…
  • Furthermore, we as programmers keep on reinventing the wheel over and over again…
    To show some of the problems we could run into, we are going to start by having a look at how in the past we would typically go about dealing with money.
  • I guess you all know, that money is made up of two parts:
    it has a numerical value
    and it has a currency.
    But since the JDK doesn't provide a standard representation of money, how could we as
    developers represent it?
  • As a beginning developer our first attempt would probably to use a double. <KLIK>
    But then the output would not be quite what we expected. <KLIK>
    So, are floating points broken in Java? No, it's not, but this is how IEEE-754 standard works.
  • Let’s use integer types as our next attempt.
    If we are using a long, we will first have to convert the value of our money to cents.
    However, this solution does have some problems with readability and flexibility.
    Let’s say for example that we’ve got a Product class with a name and a value attribute.
  • And suppose we have two products defined somewhere in our system. <KLIK>
    And somewhere our colleague is going to sum up the two values. <KLIK>
    As you can imagine, it is very easy to go wrong with this design where we could easily forget the fact that we have to convert euros into cents.
  • Lets rewrite the last example using BigDecimal.
    BigDecimal makes our lives easier because it sounds more natural to say that a product is worth 9 euros rather than 900 cents. <KLIK>
    Now our co-worker won’t be confused about the value. So this is exactly what we want.
    However, there is a very important factor missing in our design. <KLIK>
    Because most of the time, the number 9 has no real meaning without a currency.
  • If our program deals with a single currency then we are totally fine and we don’t need to model currencies. However, this is not the case most of the time. So let's add a field of type String to hold the currency. Well, this is clearly not a good design because it's not type-safe. The String is not validated and could be anything that is not a valid currency.
  • We can make the currency type-safe by introducing an enum. Now we have a fixed set of currencies so we cannot use an incorrect currency. The enum, however, is still very limited and lacks various aspects like internationalization and standardization like ISO-4217. ISO 4217 is an international standard that represents currencies as 3-character codes.
  • A more advanced approach is to use the java.util.Currency class which is available in the JDK. It is type-safe and support the ISO currency standard. So we improve our product design by using it.
  • A Currency can be instantiated by providing an ISO currency code. So now we have a suitable amount and currency type.
  • However, to make it useful we need operations like addition, subtraction etc. and we need to take into account that the currencies of our two products might be different so it is essential to do some validation before operating on the amount values. We will end up with a lot of utility classes and it is important not to forget to use them.
  • Adding an abstraction for representing money becomes more and more obvious after we try all these tricks. Martin Fowler wrote an article describing an abstraction for representing money that solves the issues we have seen. This Money class should be the only type that is responsible for dealing with money and encapsulates the amount and currency and provides utility operations.
  • So let’s use this Money class and add it to the product. <<click>> Next we instantiate our products by providing a Money instances… <<click>> and now we can apply operations on the money instances. This raises the question why such a Money class is still not available in the JDK yet.
  • Let’s summarize the motivation to add a Money class. Monetary amounts are a key feature of many applications and there is no standard type yet. There are some quirks with ISO 4217. It contains some ambiguous currency codes like the central African franc which has two variants used in different areas. Furthermore, historical currencies are missing. Virtual currencies like Bitcoin are not supported. Conversion and arithmetic is missing. Formatting is not provided.
  • So we have seen problems and missing functionality in the JDK. This lead to the development of JSR 354, the money and currency API which started in 2012 and was finished in 2015. The new JSR is targeted for JDK 9. A standalone API will be available which can be used in JDK 7 and 8 in combination with the ‘Moneta’ reference implementation. Wim will now talk about the details of this new API.
  • So let’s have a closer look at the JSR 354 Specification.
    As we’ve seen Money is represented by a value and by its currency.
  • Currencies are represented by the CurrencyUnit interface. And implementations of this interface are required to be immutable and thread-safe
    A CurrencyUnit can be constructed in a multitude of ways. The easiest two ways are using the Currency code, which is a three character string. Or by passing in the Locale.
  • Amounts are represented by the MonetaryAmount interface.
    Again, implementations are required to be immutable and thread-safe
     
    There are alotof methods defined by the interface. But bascially there are four groups.
    1) boolean operators like isGreatherThan() or isPositive().
    2) arithmetic operator methods like add() and divide().
    3) a method to get the Currency for this amount.
    4) finally there is the query() method about which Jeroen will tell you more in a minute.
  • Amounts are generated using a MontaryAmountFactory. The simplest case, you would use the default factory.
    <klik>
    But using the RI Moneta, creating money is even simpler. Just call one of the static methods and provide it with a value and a currency
  • To retrieve the numerical value of a money amount, all you have to do is call the method getNumber() which will return a NumberValue object.
    NumberValue extends java.lang.Number and as a result it can easily be converted to primitive numerical types (e.g. int , long , float , double , short , byte ).
  • Let’s talk about monetary operators and queries.
  • The JSR provides two functional interfaces: MonetaryOperator and MonetaryQuery.
    MonetaryOperator takes a monetary amount, operates on it and produces a new monetary amount.
    MonetaryQuery provides queries for example for retrieving the fractional parts (cents). Both MonetaryOperator and MonetaryQuery can be instantiated using a lamba expression.
  • The Monetary operator accepts a monetary amount and returns a new monetary amount. In this example we create an amount of 10 euro’s which we want to multiply by 2. We create a monetary operator to do this. There are two ways to apply it, either use the ‘apply’ method of the operator with the amount as argument or use the ‘with’ method of the amount with the operator as argument.
  • Similar to MonetaryOperator, MonetaryQuery is a functional interface. It accepts a monetary amount and returns a generic type. You can perform queries on a monetary amount such as getting the currency code or the number of fraction digits. Again there are two ways to apply it.
  • One of the goals of the JSR was to make formatting simple and flexible, and to overcome problems with the current Java formatting options, especially the lack of thread safety.
  • To do so, the MonetaryAmountFormat was introduced. There are several methods defined by the interface but for now we’ll take a quick look at format().
  • Converting a MonetaryAmount to a textual representation is very easy.
    Just get your hands on a formatter from the MonetaryFormats singelton, and then call the format() method on it…
    For more control over the formatting you can also use QueryBuilders….
  • If the standard formats don’t suit you, you can always use custom formats. Here we see one possible example using a DecimalFormatQueryBuilder.
  • Conversion is the process of changing the currency of a monetary amount by applying an exchange rate. The exchange rate is the ratio between one currency and the other. The process of conversion is important when dealing with different international countries and currencies. As an example, let’s try to add two amounts with different currencies. What happens? <<click>> A MonetaryException is raised since the currencies don’t match.
    So before we can add these amounts, we have to make sure both amounts have the same currency by applying an exchange rate.
  • In order to apply an exchange rate we use an exchange rate provider. In this example we create such a provider and then apply it to the euro amount to convert it to a US dollar amount. After this we can add the two amounts without an exception. The exchange rate in this example is retrieved from the European Central Bank. It is also possible to retrieve the exchange rates from the International Monetary Fund and to get the currency on historic dates.
  • As an example we use the date of May 10th 2016 and try to get the exchange rate to convert to a US dollar amount. Fortunately this day is on a Tuesday and an exchange rate is available, otherwise an exception would have been thrown.
  • JSR354 was developed under Java 8, and so it uses Java 8 functionality alot.
    The RI Moneta provides some higher order functions in the MonetaryFunctions class that help you when working with Streams. Let’s have a look at some examples…
  • There are several functions available for sorting. Here, we see an example to sort alphabetically, and another to sort by the value.
    These sorting functions will not factor in exchange rates. In other words, ten Euros will be considered equal to ten US Dollars.
  • To sort based on the exchange rate, an ExchangeRateProvider must be provided.
  • TODO OUTPUT


    It is also possible to combine multiple sorters.
    The Comparator.thenComparing() method can be used to chain multiple sorting comparators. Essentially, the secondary comparator will be applied when two values are equal according to the first comparator.
  • Reduce, also known as fold , is a higher order function that, when applied on a stream, results in a value or none. For example, sum, average, min, and max.
    As an example we’ll take a look at sum(). The average(), min() and max() methods work similarly.

  • Sum is a reduction method. Given a stream of MonetaryAmount, it returns the sum of its elements.
  • If we want to sum up amounts with different currencies, an exception will be thrown to signal that a currency mismatch has occured.
  • To avoid that, an ExchangeRateProvider must be provided.
    And now we can sum up amounts with different currencies.
  • Let’s talk about predicates. As you will remember, a predicate is a higher order function that takes a value and results in a Boolean. It can be used for filtering a collection. The moneta reference implementation provides several predicates on a monetary amount value or currency.
  • Here we show some example of currency predicates. We create an array of two US dollar amounts and one euro amount. We use an isCurrency predicate to get all US dollar amounts. Next a predicate to determine if there is at least one US dollar amount in the collection and a predicate to determine if all amounts in the collection are US dollar amounts.
  • Next we show a couple of predicates that act on the monetary amount value. Again we create an array of monetary amounts and filter on amounts greater than zero. We also use a matcher to verify that there is at least one amount greater than zero.
  • We’ve reached the end of our presentation about the money and currency API. We will summarize what we have discussed. We saw that there is currently no proper support for monetary amounts in the JDK. JSR 354 fixes this in JDK 9. For JDK 8 and before a standalone API is provided that can be used in combination with the moneta reference implementation.
    The JSR provides a monetary amount class, monetary operators and queries, formatters, conversions, sorting, reduction, predicates, grouping and filtering.
  • Of course these 15 minutes are too short to cover the complete JSR. The following references provide more information about the money and currency API. Soon after the conference we will make the presentation available on slideshare. Visit our website for the link.
  • Thanks for attending our presentation. If you have any questions please come over to discuss them.
  • ×