https://kotlinlang.org logo
#compose
Title
# compose
s

Stylianos Gakis

12/22/2021, 8:01 AM
Got a problem using
MonetaryAmount
from
org.javamoney:moneta
in compose @Preview functions. It seems like the
JDKCurrencyProvider
isn’t yet created for the previews, therefore it fails fetching the currency. Anyone had the same issue before that can provide some workaround? It would also be nice to be able to run a debugger on my code for the preview in order to see what fails exactly potentially? This is probably too hard though, considering I do not understand under which special rules the previews run exactly.
c

Carl Benson

12/22/2021, 8:49 AM
how you handle monetary amounts sounds like business logic and something that should live in a viewmodel or something else disconnected from UI code
s

Stylianos Gakis

12/22/2021, 8:53 AM
That is what I have been thinking too. However in this case, I am simply passing a MonetaryAmount down to my composable in order to be rendered on the screen, nothing more. And this certainly does feel like a UI concern, as I am then using a formatting function that requires the current locale, and an int regarding how many decimals that specific UI component wants to show:
Copy code
fun MonetaryAmount.format(locale: java.util.Locale, minimumDecimals: Int = 0): String {
    return NumberFormat.getCurrencyInstance(locale).also {
        it.currency = Currency.getInstance(currency.currencyCode)
        it.minimumFractionDigits = minimumDecimals
    }.format(this.number.numberValueExact(BigDecimal::class.java))
}
And it seems like I eventually got it working doing this:
Copy code
Money.of(
    someInt,
    CurrencyUnitBuilder.of("SEK", "default").build()
)
Which works fine for the previews as it just prints out the currency code itself no matter what it is without doing any lookups, perfect for dummy data anyway.
c

Carl Benson

12/22/2021, 9:08 AM
great. totally unrelated question, but how do you like the Moneta library? I've been thinking about looking into it as well
s

Stylianos Gakis

12/22/2021, 9:25 AM
I’ll be honest and just say that I wasn’t there when it was introduced to the codebase. All the interaction I’ve had with it has pretty much been this function that I showed before, plus mapping a GraphQL fragment that we get from backend here, which works perfect since this is the only way we ever receive money from the backend. Afaik it’s just been working great for this use case, since we also are not doing any client-side calculations really aside from a + or a - here and there to show on the UI. No other opinions to share unfortunately, sorry 😊
t

tad

12/22/2021, 9:23 PM
ICU's
CurrencyAmount
works fine, btw
You shouldn't need Moneta unless you're doing conversions on the client, which would be somewhat strange
s

Stylianos Gakis

12/23/2021, 8:54 AM
CurrencyAmount seems to be API24 or over though? Plus we are as I said doing some small calculations on client side, mostly to add things together (to show sum of prices etc) can CurrencyAmount do that? At first glance it seems like a downgrade plus it forces API 24, why would I go with it? Is there some backporting for previous API levels at least?
t

tad

12/24/2021, 1:44 AM
CurrencyAmount is just a BigDecimal value and a Currency. It's trivial to create your own, and adding values in the same currency is also trivial (unless you use non-standard fractional values with bankers' rounding, which isn't all that bad). If you already have a Currency you shouldn't be hitting JDKCurrencyProvider, which Moneta appears to be doing?
s

Stylianos Gakis

12/24/2021, 8:50 AM
Two things • I still have concerns over the API 24 requirement • I am not touching something that already works perfectly fine especially when it deals with money 😅 I don't even know what "banker's rounding" is but guess what, I don't want to know either if Moneta handles it for me. I don't see how "Creating my own" is worth it over what, a small app size increase from including the library? Am I missing out on anything else? You seem to be quite persistent on not using Moneta, please do share if you think there are more good reasons
t

tad

12/26/2021, 7:49 PM
I'm just trying to help solve your problem. The main cause of this is Moneta's insistence on holding a
MonetaryContext
in its "immutable and thread-safe"
MonetaryAmount
type, which introduces a dependency on
JDKCurrencyProvider
, which needs the rest of the Moneta runtime initialized. In my opinion, having worked on Android banking apps for 10 years now, this is not a good recipe for limited-runtime use cases such as testing and UI previews, and client software in most cases can get away with a plain
Currency
+
BigDecimal
data type. I'm not saying to get rid of it, but I am suggesting to limit use of Moneta to your data layer and use a regular Kotlin data class in your UI layer, because your UI should not have to care about a working
MonetaContext
and it definitely should not be doing calculations anyway.
And as an aside, having evaluated Moneta and JSR-354 for banking applications in the past, it has almost no benefits for client-side applications and introduces a ton of complexity that usually leads to bugs. The main problem being that it is tying into the JVM's localization data just to create a
MonetaryAmount
, because that data type carries around all of the parameters needed to format and apply mathematical operations. This definitely causes issues on Android because that data is provided by the OEM, isn't updated regularly, is often incomplete, and you definitely aren't testing in all locales in which your app will be used. And most of this is useless because your backend won't (or shouldn't) trust any client-side calculations, and you end up using
NumberFormat
anyway for formatting amounts.
It's great for dealing with money in server applications though, where you generally want a tool to perform accurate money math and conversions.
s

Stylianos Gakis

12/26/2021, 10:32 PM
I’m just trying to help solve your problem
I’ll just note that my original problem was not being able to use Compose previews with it but I mentioned higher up how I found a simple solution that fits my needs. But with that said, thanks for your advice, I do appreciate it!
59 Views