Currency enhancements in JDK7

In the JDK, applications can use java.util.Currency class to deal with currencies. They can query what currency is used in a given country, or what localized symbol is used for that currency in a particular locale. To provide applications with those currency information, the JDK contains the currency data that is based on the ISO 4217 standard. From time to time, due to a variety of reasons, the ISO 4217 data are often updated by the maintenance agency. Keeping up with these updates in the JDK is critical for applications that deal with currencies, such as a banking application. Otherwise, those applications would result in a wrong financial transaction (cf. see my old entry regarding the Turkish pastry story here)

Now, one of the issues in the current JDK's currency support is that the currency data is embedded in "lib/rt.jar" as a class file. So every time the ISO 4217 maintenance agency releases a currency update, such as Slovenia switching to Euro currency, the rt.jar file needs to be updated. This makes it impossible for customers to replace just the currency data portion when needed, without upgrading the whole JDK. This issue is analogous to the TimeZone data being separated from the JDK class files, and they can be upgraded separately.

The purpose of this blog entry is to announce that this will no longer be an issue in the JDK7, as I have just checked-in the necessary changes for this issue (woohoo!), which will soon be public in the OpenJDK build. In the new structure, the currency data is separately placed in "<JAVA_HOME>/lib" directory as a binary file "", which can be replaced not in sync with the JDK update release schedule. One added feature to this is that you could even provide your own properties file to override the contents in the currency data file. If you create a properties file as "<JAVA_HOME>/lib/", which contains "key=value" pairs where the "key" is a ISO 3166 country code, and the "value" consists of three-letter currency code, three-digit numeric code, and the minor unit (separeted by a comma), it would override the currency data for that country designated by the "key". For example if it has "JP=JPZ,999,2", this would override the Japanese currency data.

Also, along with this Currency enhancement, I added a couple of new APIs. First one is to acquire all the available currencies in the JDK as follows:

public static Set<Currency> getAvailableCurrencies()

Next one is to return a numeric ISO 4217 code for a Currency instance:

public int getNumericCode()

The last one is to return the display name for a Currency instance. Instead of getSymbol() returning "$" for the US Dollar ("USD"), this API returns "US Dollar" in the "US" locale.

public String getDisplayName()
public String getDisplayName(Locale displayLocale)

The initial release of this API contains localized currency names for 10 locales, i.e., English, French, German, Italian, Japanese, Korean, Simplified Chinese, Spanish, Swedish, and Traditional Chinese.

I also added an SPI in java.util.spi.CurrencyNameProvider for the languages other than the above, so that one could provide localized display names in any language:

public getDisplayName(String currencyCode,
                      Locale displayLocale)

These are the changes that I have checked in, and I hope this is useful for developers. I would have liked to provide a working demo, but it's not possible to do it with a yet released build :-)


 This is definately good thing. Just I'm not sure
 why it is impossible to make better: take value
 from Windows regional settings if it is available. I understand that there are some other
 OSes except Windows, but for the end users it
 would be best variant to change time only once in
 the OS settings. (Also take into account that most part of users still have Windows) Since JVM
 is anyway OS specific why it can't include a
 module reading this information from OS? (For the
 OS-es which do not support this you could use the
 described in this article approach) Could you
 please comment on this?



Posted by Maxim on July 01, 2007 at 06:56 PM PDT #

"Also take into account that most part of users still have Windows" @Maxim: Most end users maybe run Windows, but on the server side where Java is strongest and most deployments occur I can assure you that Windows is not the dominant OS. It is true that if the JVM could pick up locale specific information from the OS that would make it one less place to update \*on that specific computer\* - on the other hand, there are JVMs from many vendors running on a multitude of platforms and OSes, and if you make it OS specific you get code duplication there instead and a rich source of deploy time bugs. Many Linux distros handle locale data differently, some only install a single locale for the current user, some use UTF-8 and some not, how is that going to work on a server with many international customers that needs to handle transaction records from all over the world? My two cents is that it is better to specify these things in the JVM so developers can be assured that it is there and platform agnostic. :) Anyway, great work Sato-san, thank you.

Posted by Lars Westergren on July 01, 2007 at 11:32 PM PDT #

Maxim and Lars,

Thank you for your valuable comments! I see points in both comments. Since the point that Maxim made is not only specific to the currency support but also applies to all the international preferences, such as date/number formatting, we have a separate request to reflect the underlying OS's i18n settings to the JVM (6337471: desktop/system locale preferences support) .

And what Lars mentioned in his comment is exactly the reason that Java has its own locale data in it. So I believe that it's up to the customer's use case whether it would honor Java's locale data or OS's one. Our current proposal on how to implement the said request is to provide users with some kind of switch (we don't know yet what it would be, a new Java Control Panel option, system property, or something else) that would allow users to select the locale data policy. However the default behavior would be to use Java's data, in order to keep the compatibility.

Posted by Naoto Sato on July 02, 2007 at 04:24 AM PDT #

I only wonder additionally if there will be some kind of CurrenyEditor available as well. Cause the Renderer (e.g. in Tables) work fine, but no Editor for Currency is provided so far which would allow to Edit the input the same way as it is displayed

Posted by LeO on July 03, 2007 at 07:25 AM PDT #

That would be nice. Although I have not tried, I think it can be implemented fairly easily, using InputVerifier and NumberFormat classes. The editor always shows the formatted text from a currency formatter NumberFormat.getCurrencyInstance(), and if the user edits it, always check the validity in InputVerifier.verify() with the currency formatter's "parse()" method. This way, a WYSIWYG currency editor can be implemented.

Posted by Naoto Sato on July 03, 2007 at 09:31 AM PDT #

Let's say it the other way: I have already tried the Numberformatter + MaskFormatter but failed finally due to the missing support of displaying the EUR-sign in the Formatter for the Editor. I guess the EUR-Sign has to be treated specially by the Formatter - who knows. After several hours I canceled the project out of frustration. 'fairly easily' would be trival, or not? But frankly said, searching on the Internet, nothing found which provides THAT functionallity. Yeah, some components with the currency-symbol outside (as Label)- but nothing inside.

Posted by LeO on July 03, 2007 at 09:48 PM PDT #

Sorry, for once more. I do NOT wanna flood this Blog. Nevertheless I think I missed to explain before, why I see this as an issue. The main issue arises from the usage within a JTable. Where everything should be in one cell => everything in the same Editor and this should correspond to the Renderer.
The problem with the EUR-sign I have described above. The other problem I see is as well in what is treated as fraction separator, i.e. '.' vs. ',' - E.g. 1.5 is the IntegerEditor, and if I take the appropriate local Renderer it is rendered to 1,5 € - so far so good. But IF I copy paste from this cell I get the value 1.5 (I guess the Integer-Editor is started and from there the value is provided as 1.5 and not in the way as it is formated in the renderer [so either '1,5 €' or more preferable as '1,5' which recognize the local settings]). And the problem is, to paste in an Excel-sheet where the fraction is separted with a , and therefore assumes it is NOT a Float-value, but a String, or date, or ...
So, why do I mention this?
1. There might be some hacks, workarounds possible - I tried hard, but figured out, this requires a LOOOT more effort I was willing to spend for a solution. e.g. write my own MaskEditor for Cells [with no idea, how to support the € in the Editor], write my own TransferHandler to deal with the currency and Locale-Settings, etc.
2. Your title is 'Currency enhancements in JDK7' and therefore I assumed this is as well for Tables with their Editors + Renderers (the Render work somehow the easy way). Loacle Editor is neither supported as there is neither a Currency Editor.
My 2c (or probaly 3c?? ;))

Posted by LeO on July 04, 2007 at 08:41 AM PDT #

Oh, please don't be sorry. I really appreciate comments like this, as that is part of the reason I am blogging about i18n features here.

Today, I spent some time to look at those NumberFormatter in javax.swing.text package. And found out that it indeed has some funny behavior, for example the one described in the bug 4678007. So I would think this is rather a bug in NumberFormatter class. If you could file a bug report, that would be great (and of course I take my comment 'fairly easily' back).

For your point #2, my original intention was to inform the enhancement related to java.util.Currency class and Swing's Editor/Renderer were not in the scope.

Posted by Naoto Sato on July 05, 2007 at 08:02 AM PDT #

This is great news! Really fantastic, well done! I do have one question. We use currencies like MXP, a currency which has been removed from ISO 4217 and hence from the Java list of currencies, for client historical performance calculations. Now you mention that you will be able to override currencies with a properties file. My question is, can you specify new ones too?

Posted by Kieron Wilkinson on July 09, 2007 at 11:52 PM PDT #

Sure. The reason we provided this override capability is to give users a chance to deal with the ISO 4217 changes by themselves, until the JDK releases its official updated currency data. Actually in the Japanese example, "JPZ" currency code is a made-up one, which is not in the ISO 4217 data.

Posted by Naoto Sato on July 10, 2007 at 04:11 AM PDT #

That is great! I didn't ask that question very well though, because for MXP, it has the same country code, its just the older version. Can you have mutiple currencies for the same country? Actually I suspect it is a bug, since most of the other out-dated currencies are still defined in Java. Perhaps I should file a bug report...

Posted by Kieron Wilkinson on July 11, 2007 at 12:30 AM PDT #

The Currency class only has the latest currency code for a country. The reason we have some old currency codes is that we could not remove them when they got replaced with new ones for compatibility reasons. So we keep all the obsolete currency codes since we introduced this Currency class. MXP was already obsolete when Currency class was introduced, that's why it's not in the currency data. I think this can be resolved if we provide the historical currency data information.

Posted by Naoto Sato on July 11, 2007 at 03:50 AM PDT #

Okay, thanks very much for the info!

Posted by Kieron Wilkinson on July 11, 2007 at 05:28 PM PDT #

You're probably aware of JSR-275 - Units and Measures for Java 7 and of the JScience project which is providing the reference implementation. (The latest version of the spec is here and the proposed API here.)

I'd like to encourage you to make the standard Java 7 currency support work seamlessly with the new Java 7 units and measures framework. As the JScience monetary package description illustrates, having money work like other measures simplifies common calculations, such as the price of gas (or cost per unit volume of any product), fuel economy, and any other calculation involving money and physical units. These all become very clear and simple when money works like other measures. As a bonus, handling exchange rates between currencies also becomes simple and much more general.

Is integration with the new units and measures framework in the plan or under consideration?

Posted by James Gates on July 17, 2007 at 11:32 PM PDT #

Thank you for the information. I wasn't aware of the JSR.

By briefly looking at it, it looks to me that the JSR provides the measurement framework, including the SI measurement system implementation from JScience. However if I understand it correctly, the monetary package implementation in JScience is not a part of the JSR.

I agree that it would be convenient to have a capability for monetary exchange, though. And if that monetary implementation of JScience would be to be incorporated into the JDK, definitely we need to seamlessly integrate them.

Posted by Naoto Sato on July 18, 2007 at 04:28 AM PDT #

Post a Comment:
Comments are closed for this entry.



« April 2014

No bookmarks in folder