- 
          
- 
                Notifications
    You must be signed in to change notification settings 
- Fork 101
Description
Maybe I'm not understanding this, so please correct me if I'm mistaken, but there seems to be a huge overhead in creating monetary amounts in the real world.
Let's say a client is processing connections to a financial server in several threads. Each thread wants to simply create a MonetaryAmount instance using the default implementation. Naturally that would be Monetary.getDefaultAmountFactory(), but we don't know what the amount factory will be until runtime (which is why we're not hard-coding the implementation to use any particular amount factory). But there's a problem: javax.money.MonetaryAmountFactory specifically says it is not guaranteed to be thread-safe:
Implementation specification
Instances of this interface are not required to be thread-safe!
Since we are plugging in a serializer/deserializer to our serialization library (e.g. Jackson), we have no idea if these will be called from a single thread or not, so we are forced to call Monetary.getDefaultAmountFactory() each time, are we not?
Unfortunately javax.money.Monetary.getDefaultAmountFactory() has a huge overhead—it actually invokes all the Java SPI lookup infrastructure each time!!
    public static MonetaryAmountFactory<?> getDefaultAmountFactory() {
        return Optional.ofNullable(monetaryAmountsSingletonSpi())
                .orElseThrow(() -> new MonetaryException("No MonetaryAmountsSingletonSpi loaded."))
                .getDefaultAmountFactory();
    }
    private static MonetaryAmountsSingletonSpi monetaryAmountsSingletonSpi() {
        try {
            return Bootstrap.getService(MonetaryAmountsSingletonSpi.class);
        } catch (Exception e) {
            Logger.getLogger(Monetary.class.getName())
                    .log(Level.SEVERE, "Failed to load MonetaryAmountsSingletonSpi.", e);
            return null;
        }
    }So for each one of those thousands or millions of monetary amounts, the application is supposed to invoke the Java SPI infrastructure to look up the default amount MonetaryAmountFactory? I haven't ran any tests, but just on the face of it that sounds absurd. I need to keep the default MonetaryAmountFactory around somewhere, but as mentioned above, MonetaryAmountFactory isn't guaranteed to be thread safe.
Am I expected to resort to ThreadLocal or something similar in my deserializer so I can keep a separate amount factory around per thread?
Note that the JavaxMoneyModule for Jackson (which I believe came from Zalando) completely ignores the admonition about thread safety, and keeps a MonetaryAmountFactory around to be used by all deserialization, ignoring threads!
    private <T extends MonetaryAmount> JavaxMoneyModule(final AmountWriter<?> writer, final FieldNames names, final MonetaryAmountFormatFactory formatFactory, final MonetaryAmountFactory<T> amountFactory) {
        this.writer = writer;
        this.names = names;
        this.formatFactory = formatFactory;
        this.amountFactory = amountFactory;
    }
…
        //Use provided amountFactory to deserialize a MonetaryAmount
        deserializers.addDeserializer(MonetaryAmount.class, new MonetaryAmountDeserializer<>(amountFactory, names));It would thus seem the Zalander/Jackson Java money module is blatantly ignoring the thread-safety of the MonetaryAmountFactory (probably because, like me, the alternative seems unfathomable). But thread-safety isn't just something we can ignore.
How was this envisioned to be used in the real world?