Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
@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...
@YourTwitterHandle#Devoxx #YourTag#Devoxx #Money @tritales
Motivation
@YourTwitterHandle#Devoxx #YourTag
Why a Money library?
Martin Fowler:
“A large proportion of the computers in
this world ...
@YourTwitterHandle#Devoxx #YourTag
Eric Evans:
“On project after project, software developers have to
reinvent the wheel, ...
@YourTwitterHandle#Devoxx #YourTag
Money
• Numerical value
• Currency
#Devoxx #Money @tritales
@YourTwitterHandle#Devoxx #YourTag
Primitive floating types
#Devoxx #Money @tritales
double value = 1.03 - .42;
0.61000000...
@YourTwitterHandle#Devoxx #YourTag
Primitive Integer Types
Convert to cents
#Devoxx #Money @tritales
public class Product ...
@YourTwitterHandle#Devoxx #YourTag#Devoxx #Money @tritales
Product b1 = new Product(“Westmalle", 5_00);
Product b2 = new P...
@YourTwitterHandle#Devoxx #YourTag
BigDecimal
#Devoxx #Money @tritales
Product b1 = new Product(“Westmalle",
BigDecimal.va...
@YourTwitterHandle#Devoxx #YourTag
Currency String
#Devoxx #Money @tritales
public class Product {
private String name;
pr...
@YourTwitterHandle#Devoxx #YourTag
Currency Enum
#Devoxx #Money @tritales
public class Product {
private String name;
priv...
@YourTwitterHandle#Devoxx #YourTag
java.util.Currency
• Simple
• Supports ISO-4217
#Devoxx #Money @tritales
public class P...
@YourTwitterHandle#Devoxx #YourTag#Devoxx #Money @tritales
Product b1 = new Product(“Westmalle",
Currency.getInstance("EUR...
@YourTwitterHandle#Devoxx #YourTag
Utility class
#Devoxx #Money @tritales
public static class ProductUtils {
public static...
@YourTwitterHandle#Devoxx #YourTag
Money
#Devoxx #Money @tritales
public class Money {
private final BigDecimal value;
pri...
@YourTwitterHandle#Devoxx #YourTag#Devoxx #Money @tritales
public class Product {
private String name;
private Money money...
@YourTwitterHandle#Devoxx #YourTag
Motivation for Money
• Monetary values are a key feature to many applications
• No stan...
@YourTwitterHandle#Devoxx #YourTag
JSR 354 – Money and Currency API
• Started 2012 – finalized 2015
• Targeted for JDK 9
•...
@YourTwitterHandle#Devoxx #YourTag#Devoxx #Money @tritales
Core API
@YourTwitterHandle#Devoxx #YourTag
CurrencyUnit
CurrencyUnit currency =
Monetary.getCurrency("EUR");
CurrencyUnit currency...
@YourTwitterHandle#Devoxx #YourTag
MonetaryAmount
boolean isGreaterThan(MonetaryAmount amt)
boolean isGreaterThanOrEqualTo...
@YourTwitterHandle#Devoxx #YourTag
Creating Money
#Devoxx #Money @tritales
MonetaryAmount money =
MonetaryAmounts.getDefau...
@YourTwitterHandle#Devoxx #YourTag
NumberValue
#Devoxx #Money @tritales
MonetaryAmount m1 = Money.of(10.21, "EUR”);
Number...
@YourTwitterHandle#Devoxx #YourTag#Devoxx #Money @tritales
Operator &
Query
@YourTwitterHandle#Devoxx #YourTag
MonetaryOperator & MonetaryQuery
Functional interfaces
#Devoxx #Money @tritales
public ...
@YourTwitterHandle#Devoxx #YourTag#Devoxx #Money @tritales
MonetaryAmount money = Money.of(10, “EUR”);
MonetaryOperator do...
@YourTwitterHandle#Devoxx #YourTag
MonetaryQuery
#Devoxx #Money @tritales
MonetaryAmount money = Money.of(10, “EUR”);
Mone...
@YourTwitterHandle#Devoxx #YourTag#Devoxx #Money @tritales
Formatting
@YourTwitterHandle#Devoxx #YourTag
MonetaryAmountFormat
#Devoxx #Money @tritales
public interface MonetaryAmountFormat
ext...
@YourTwitterHandle#Devoxx #YourTag
format()
#Devoxx #Money @tritales
MonetaryAmount money = Money.of(12, “USD”);
MonetaryA...
@YourTwitterHandle#Devoxx #YourTag
Custom formats
#Devoxx #Money @tritales
CurrencyUnit currency =
Monetary.getCurrency(ne...
@YourTwitterHandle#Devoxx #YourTag#Devoxx #Money @tritales
Conversion
@YourTwitterHandle#Devoxx #YourTag
Conversion
#Devoxx #Money @tritales
MonetaryAmount money = Money.of(10,“USD”);
Monetary...
@YourTwitterHandle#Devoxx #YourTag
ExchangeRateProvider
#Devoxx #Money @tritales
MonetaryAmount money = Money.of(10, "EUR"...
@YourTwitterHandle#Devoxx #YourTag
Exchange rate on a specific date
#Devoxx #Money @tritales
MonetaryAmount money = Money....
@YourTwitterHandle#Devoxx #YourTag#Devoxx #Money @tritales
Streams
@YourTwitterHandle#Devoxx #YourTag
Sorting
#Devoxx #Money @tritales
MonetaryAmount[] m =
{ Money.of(9,"EUR"), Money.of(10,...
@YourTwitterHandle#Devoxx #YourTag
Sorting using exchange rate
#Devoxx #Money @tritales
MonetaryAmount[] m =
{ Money.of(9,...
@YourTwitterHandle#Devoxx #YourTag
Multiple Sorters
#Devoxx #Money @tritales
MonetaryAmount[] m =
{ Money.of(9, "EUR"), Mo...
@YourTwitterHandle#Devoxx #YourTag
Reduction Methods
Predefined higher order functions in the RI Moneta, e.g.:
• MonetaryF...
@YourTwitterHandle#Devoxx #YourTag
sum()
#Devoxx #Money @tritales
MonetaryAmount[] money = {
Money.of(10, "USD"),
Money.of...
@YourTwitterHandle#Devoxx #YourTag#Devoxx #Money @tritales
MonetaryAmount[] money = {
Money.of(10, "USD"),
Money.of(12, "E...
@YourTwitterHandle#Devoxx #YourTag#Devoxx #Money @tritales
ExchangeRateProvider provider =
MonetaryConversions
.getExchang...
@YourTwitterHandle#Devoxx #YourTag
Predicate
#Devoxx #Money @tritales
“Higher order function that operates on a value and ...
@YourTwitterHandle#Devoxx #YourTag#Devoxx #Money @tritales
Predicates on currency
MonetaryAmount[] m = {Money.of(10, dolla...
@YourTwitterHandle#Devoxx #YourTag#Devoxx #Money @tritales
Predicates on value
MonetaryAmount[] m = {Money.of(10, dollar),...
@YourTwitterHandle#Devoxx #YourTag
Summarizing Money
#Devoxx #Money @tritales
• Currently no proper money support in the J...
@YourTwitterHandle#Devoxx #YourTag
References
• https://www.gitbook.com/book/otaviojava/money-api/details
• https://jcp.or...
@YourTwitterHandle#Devoxx #YourTag#Devoxx #Money @tritales
wim@tritales.nl
jdev.it/blog/
jeroen@tritales.nl
www.tritales.n...
Upcoming SlideShare
Loading in …5
×

Introducing JSR 354 The Money & Currency API

217 views

Published on

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.

Published in: Technology
  • Be the first to comment

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

×