Download - JSR 354 LJC-Hackday
Go for the Money
JSR 354 Hackday
London Java Community 2014
June 2014
Go for the money –JSR 354 Hackday
http://java.net/projects/javamoney
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Bio
Anatole Tresch
Consultant, Coach
Credit Suisse
Technical Coordinator & Architect
Specification Lead JSR 354
Regular Conference Speaker
Driving Java EE Config
Twitter/Google+: @atsticks
Java Config Discussion https://groups.google.com/forum/#!forum/java-config
Java Config Blog: http://javaeeconfig.blogspot.ch
Zurich Java Community (Google Community)
Zurich Hackergarten
2
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Agenda
3
Introduction
Possible Topics
Easy:
API Challenge: Moneymachine
Medium:
Adding functonalities to the RI, e.g. Special Roundings
BitCoin and other currencies
Test Financial Formulas in JavaMoney
Hard Improve FastMoney
Measure CPU and Memory Consumption
Write a Complex Integration Sample
Setup
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Introduction
javax.money
4
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Currencies
API
5
Allow currencies with arbitrary other currency codes
Register additional Currency Units using an flexible SPI Fluent API using a Builder (RI only)
(Historic Validity of currencies related to regions/countries and
vice versa (not part of JSR, but javamoney OSS project))
public interface CurrencyUnit{
public String getCurrencyCode();
public int getNumericCode();
public int getDefaultFractionDigits();
}
public final class MonetaryCurrencies{
public CurrencyUnit getCurrency(String currencyCode);
public CurrencyUnit getCurrency(Locale locale);
public boolean isCurrencyAvailable(String currencyCode);
public boolean isCurrencyAvailable(String locale);
}
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Currencies (continued)
API Samples
CurrencyUnit currency1 = MonetaryCurrencies.getCurrency("USD");
CurrencyUnit currency2 = MonetaryCurrencies.getCurrency(
Locale.GERMANY);
CurrencyUnit bitcoin = new BuildableCurrencyUnit.Builder("BTC")
.setNumericCode(123456)
.setDefaultFractionDigits(8)
.create();
6
Access a CurrencyUnit
Build a CurrencyUnit (RI only)
Register a CurrencyUnit
CurrencyUnit bitcoin = ….create(true);
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Monetary Amounts
General Aspects
7
Amount = Currency + Numeric Value
+ Capabilities
Arithmetic Functions, Comparison
Fluent API
Functional design for extendible functionality
(MonetaryOperator, MonetaryQuery)
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Monetary Amounts (continued)
Key Decisions
8
Support Several Numeric Representations (instead of one
single fixed value type)
Define Implementation Recommendations
• Rounding should to be modelled as separate concern (a MonetaryOperator)
• Ensure Interoperability by the MonetaryAmount
interface
• Precision/scale capabilities should be inherited to its
operational results.
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Monetary Amounts (continued)
The API public interface MonetaryAmount{
public CurrencyUnit getCurrency();
public NumberValue getNumber();
public MonetaryContext getMonetaryContext();
public MonetaryAmount with(MonetaryOperator operator);
public <R> R query(MonetaryQuery<R> query);
public MonetaryAmountFactory<? extends MonetaryAmount> getFactory();
…
public boolean isLessThanOrEqualTo(MonetaryAmount amt);
public boolean isLessThan(MonetaryAmount amt);
public boolean isEqualTo(MonetaryAmount amt);
public int signum();
…
public MonetaryAmount add(MonetaryAmount amount);
public MonetaryAmount subtract(MonetaryAmount amount);
public MonetaryAmount divide(long number);
public MonetaryAmount multiply(Number number);
public MonetaryAmount remainder(double number);
…
public MonetaryAmount stripTrailingZeros();
}
9
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Monetary Context
Modeling Amount Capabilities
10
Describes the capabilities of a MonetaryAmount.
Accessible from each MonetaryAmount instance.
Allows querying a feasible implementation type from
MonetaryAmounts.
Contains
common aspects
Max precision, max scale, implementation type
Arbitrary attributes
E.g. RoundingMode, MathContext, …
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Monetary Context (continued)
The API
public final class MonetaryContext extends AbstractContext
implements Serializable {
public int getPrecision();
public int getMaxScale();
public Class<? extends MonetaryAmount> getAmountType();
public static final class Builder{…}
}
public abstract class AbstractContext implements Serializable{
…
public <T> T getNamedAttribute(Class<T> type, Object key,
T defaultValue);
public <T> T getNamedAttribute(Class<T> type, Object key);
public <T> T getAttribute(Class<T> type, T defaultValue);
public <T> T getAttribute(Class<T> type);
public Set<Class<?>> getAttributeTypes();
}
11
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Creating Monetary Amounts
Monetary Amount Factory
12
Creates new instances of MonetaryAmount.
Declares
The concrete MonetaryAmount implementation type
returned.
The min/max MonetaryContext supported.
Can be configured with a target
CurrencyUnit
A numeric value
MonetaryContext.
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Creating Monetary Amounts (continued)
Monetary Amount Factory
public interface MonetaryAmountFactory<T extends MonetaryAmount> {
Class<? extends MonetaryAmount> getAmountType();
MonetaryAmountFactory<T> setCurrency(String currencyCode);
MonetaryAmountFactory<T> setCurrency(CurrencyUnit currency);
MonetaryAmountFactory<T> setNumber(double number);
MonetaryAmountFactory<T> setNumber(long number);
MonetaryAmountFactory<T> setNumber(Number number);
MonetaryAmountFactory<T> setContext(MonetaryContext monetaryContext);
MonetaryAmountFactory<T> setAmount(MonetaryAmount amount);
MonetaryContext getDefaultMonetaryContext();
MonetaryContext getMaximalMonetaryContext();
T create();
}
13
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Creating Monetary Amounts
Usage Samples
// Using the default type
MonetaryAmount amount1 = MonetaryAmounts.getAmountFactory()
.setCurrency("USD“)
.setNumber(1234566.15)
.create();
// Using an explicit type
Money amount2 = MonetaryAmounts.getAmountFactory(Money.class)
.setCurrency("USD“)
.setNumber(1234566.15)
.create();
// Query a matching implementation type
MonetaryContext monCtx = new MonetaryContext.Builder()
.setAmountFlavor(
AmountFlavor.PERFORMANT)
.create();
Class<? extends MonetaryAmount> type = MonetaryAmounts.queryAmontType(
monCtx);
MonetaryAmountFactory<?> fact = MonetaryAmounts.queryAmountFactory(
monCtx);
14
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Extension Points
MonetaryOperator
Takes an amount and procudes some other amount.
• With different value
• With different currency
• Or both // @FunctionalInterface
public interface MonetaryOperator {
public MonetaryAmount apply(MonetaryAmount amount);
}
• Operators then can be applied on every MonetaryAmount:
public interface MonetaryAmount{
…
public MonetaryAmount with (MonetaryOperator operator);
…
}
15
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Extension Points (continued)
MonetaryOperator: Use Cases
Extend the algorithmic capabilities
• Percentages
• Permil
• Different Minor Units
• Different Major Units
• Rounding
• Currency Conversion
• Financial Calculations
• …
16
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Extension Points (continued)
MonetaryOperator Example: Rounding and Percentage
17
// round an amount
MonetaryOperator rounding =
MoneyRoundings.getRounding(
MonetaryCurrencies.getCurrency(“USD”));
Money amount = Money.of(“USD”, 12.345567);
Money rounded = amount.with(rounding); // USD 12.35
// MonetaryFunctions, e.g. calculate 3% of it
Money threePercent = rounded.with(
MonetaryFunctions.getPercent(3));
// USD 0.3705
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Extension Points (continued)
MonetaryQuery
A MonetaryQuery takes an amount and procuces an arbitrary
result:
// @FunctionalInterface
public interface MonetaryQuery<T> {
public T queryFrom(MonetaryAmount amount);
}
Queries then can be applied on every MonetaryAmount:
public interface MonetaryAmount {
…
public <T> T query (MonetaryQuary<T> query);
…
}
18
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Currency Conversion
javax.money.convert.*
19
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Currency Conversion
ExchangeRate
A ExchangeRate models a conversion between two currencies:
• Base CurrencyUnit
• Terminating/target CurrencyUnit
• Provider
• Conversion Factor, where M(term) = M(base) * f
• Additional attributes (ConversionContext)
• Rate chain (composite rates)
Rates may be direct or derived (composite rates)
20
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Currency Conversion
ExchangeRateProvider
// access default provider (chain)
ExchangeRateProvider prov =
MonetaryConversions.getExchangeRateProvider();
// access a provider explicitly
prov = MonetaryConversions.getExchangeRateProvider("IMF");
// access explicit provider chain
prov = MonetaryConversions.getExchangeRateProvider("ECB", "IMF");
// access Exchange rates
ExchangeRate rate = provider.getExchangeRate("EUR", "CHF");
// Passing additional parameters
ExchangeRate rate = provider.getExchangeRate("EUR", "CHF",
ConversionContext.of(
System.currentTimeMillis() + 2000L) );
21 Go for the money - JSR 354 - http://java.net/projects/javamoney
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Currency Conversion (continued)
Performing Conversion
Accessing a CurrencyConversion (always targeted to a terminating CurrencyUnit):
// access from a ExchangeRateProvider
ExchangeRateProvider prov = …;
CurrencyConversion conv = prov.getCurrencyConversion("INR");
// access it directly (using default rate chain)
conv = MonetaryConversions.getConversion("INR");
// access it, using explicit provider chain
conv = MonetaryConversions.getConversion("INR", "ECB", "IMF");
Performing conversion:
MonetaryAmount chfAmount = MonetaryAmounts.of("CHF",10.50);
MonetaryAmount inrAmount = chfAmount.with(conv); // around EUR 8.75
22
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Formatting and Parsing
javax.money.format.*
23
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Formatting and Parsing
MonetaryAmountFormat
Similar to java.text.DecimalFormat accessible by Locale
Configured by AmountFormatContext
Supports also custom formats (configured an accessed using
AmountFormatContext)
Building AmountFormatContext using a fluent API
Thread safe!
24 Go for the money - JSR 354 - http://java.net/projects/javamoney
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Formatting and Parsing (continued)
MonetaryAmountFormat: Usage Example
// Access a provided format
MonetaryAmountFormat format = MonetaryFormats.getAmountFormat(
new Locale(“”, “in”));
System.out.println(format.format(
Money.of("INR", 39101112.123456))));
-> INR 3,91,01,112.10
// Access a custom format
MonetaryAmountFormat format = MonetaryFormats.getAmountFormat(
AmountFormatContext.of(“myCustomFormat”));
25 Go for the money - JSR 354 - http://java.net/projects/javamoney
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
JavaMoney OSS Project
org.javamoney.*
26
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
JavaMoney OSS Project
Extended Currency Services
Currency namespaces (e.g. ISO, VIRTUAL, …)
Currency namespace mapping
Validity Services (Historization API)
• access of historic currency data related to regions
Region Services
Region Forest
• Unicode CLDR region tree
• ISO 2-, 3-letter countries
• Custom Trees
Extendible token-based Formatting API
Financial Calculations & Formulas
27
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Links
Current Spec (work in progress, comments allowed): https://docs.google.com/document/d/1FfihURoCYrbkDcSf1W
XM6fHoU3d3tKooMnZLCpmpyV8/edit GitHub Project (JSR and JavaMoney):
https://github.com/JavaMoney/javamoney Umbrella Page: http://javamoney.org JSR 354: http://jcp.org
Java.net Project: http://java.net/projects/javamoney JUG Chennai Adoption (TrakStok):
https://github.com/jugchennaiadoptjava/TrakStok
Twitter: @jsr354 Cash Rounding: http://en.wikipedia.org/wiki/Swedish_rounding
28
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
HackDay - Possible Topics
29
Easy
- Money Machine Medium
- Extending RI - RI User Guide - JavaMoney Lib
- TCK
Hard
- L & P - Create Sample App - Implement a RI
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Adoption Areas JSR 354 – The Easy Way
API Challenge: MoneyMachine
30
Objective: Test the API for usability, make proposals to
improve
How:
Checkout/update the MoneyMachine project from https://github.com/atsticks/moneymachine.git
Implement the classes in the src/main/java to
make the tests green (skeletons are already there) The challenge will guide you throughout the whole JSR
Overall 40+ test cases of different complexity (easy to medium), you may also select only a subset ;-)
Add improvement proposals to the JSRs JIRA on
java.net Blog your (hopefully positive) experience, twitter, …
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Adoption Areas JSR 354 – The Easy Way
API Challenge: MoneyMachine Example
31
/**
* This class has to be implemented and helps us giving feedback on the JSR's API. This
* part of the
* project deals with basic aspects such as getting currencies and amounts.
* Created by Anatole on 07.03.14.
*/
public class Basics{
/**
* Get a CurrencyUnit using a currency code.
*
* @param currencyCode the currency code
* @return the corresponding CurrencyUnit instance.
*/
public CurrencyUnit getProvidedCurrency(String currencyCode){
throw new UnsupportedOperationException();
}
/**
* Get a CurrencyUnit using a Locale, modeling a country.
*
* @param locale The country locale.
* @return the corresponding CurrencyUnit instance.
*/
public CurrencyUnit getProvidedCurrency(Locale locale){
throw new UnsupportedOperationException();
}
...
}
Describes
the task to
be done
(incl. Some
hints)
Replace this
with
according
code
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Adoption Areas JSR 354 – The Easy Way
API Challenge: MoneyMachine Testing
32
To check your
implementation is correct,
simply execute the test suite
Correct ;-)
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Adoption Areas JSR 354 - Medium
Extending the Reference Implementation
33
Objective: Extend the RI
How:
Discuss your ideas with me to see where your idea fits
best Additional Roundings
Additional Currencies
Additional Exchange Rate Providers Additional Formats
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Adoption Areas JSR 354 - Medium
Documenting the Reference Implementation
34
Objective: Document the RI (user guide)
How:
Take a Topic
Write documentation (asciidoc)
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Adoption Areas JSR 354 – Medium Level
Helping on JavaMoney Library
35
Objective: Help on JavaMoney
How:
Financial calculations in calc need tests
Factor out Dataservice Layer All Modules require check on JavaDocs, Tests
Enhance APIs with Java 8 features (e.g. 310 types)
Write/enhance user guide (asciidoc) New functionalities, ideas?
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Adoption Areas JSR 354 – Medium Level
Help on the TCK
36
Objective: Help finalizing the TCK
How:
Write TCK tests (only a few missing)
Check Test Failure Messages Check Test Semantics
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Adoption Areas JSR 354 – Medium Level
Helping on the TCK (continued)
37
/**
* Test successful conversion for possible currency pairs.<br/>
* Hint: you may only check for rate factory, when using a hardcoded
* ExchangeRateProvider, such a provider
* must be also implemented and registered as an SPI.
*/
@Test @SpecAssertion(id = "432-A1", section="4.3.2")
public void testConversion(){
Assert.fail();
}
Describes the test
very briefly
References the according
section in the spec
Add your test code here.
Hint 1: if you are unsure first write a story line
Hint 2: some aspects may require to implement multiple
tests, just ensure the annotations are on all tests
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Adoption Areas JSR 354 – The Hard Way
Analyze and Improve Performance
38
Objective: Improve Performance
How:
Measure Performance and Memory Consumption Define corresponding improvement ideas Implement improvements Known aspects:
FastMoney implementation could be faster, especially for division
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Adoption Areas JSR 354 – The Hard Way
Write an Overall Example Application
39
Objective: Implement a Deployable Example Application
How:
Define Application Storyline Define Screens etc. Implement everything needed Deploy on CloudBees ?
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Adoption Areas JSR 354 – The Hard Way
Write an Implementation
40
Objective: Ensure Specification / API Quality
How:
Implement whole or parts of the specification Check the implementation against the TCK
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Setup
41
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Setup
42
• Install VirtualBox, if not yet done, download from https://www.virtualbox.org
• Download the prepared image and start it • Login with debian/debian • Open the IDE of your choice (Eclipse, IntelliJ and
Netbeans are preinstalled and setup) • Update the projects/repositories
• For Contributors:
• Ensure you have a GitHub user account • Create your own Branch of the corresponding repositories
• Switch your local repositories on your VM, on which you want to commit, to your branched repos
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Q & A
43
Go for the money - JSR 354 - http://java.net/projects/javamoney March 2014
Go for it!
44