JavaMoney / jsr354-ri

JSR 354 - Moneta: Reference Implementation
Other
344 stars 101 forks source link

Disabling standard rate providers failed #170

Closed dominik42 closed 6 years ago

dominik42 commented 7 years ago

As mentioned at Stackoverflow an issues was filed as JAVAMONEY-131 regarding disabling of the standard rate provider like ECBCurrentRateProvider, ECBHistoric90RateProvider, IMFRateProvider etc. The JIRA page mentioned above isn't available any longer, at github I can't find any regarding issue and with version 1.1 this bug still exists. Here the content of my javamoney.properties

# Turn off loading of the default Moneta ExchangeRateProviders.
{1}load.ECBCurrentRateProvider.type=NEVER
{1}load.ECBHistoric90RateProvider.type=NEVER
{1}load.ECBHistoricRateProvider.type=NEVER
{1}load.IMFRateProvider.type=NEVER
{1}load.AbstractECBRateProvider=NEVER

But somehow the services are started

The exchange rate with resourceId ECBHistoric90RateProvider was started remotely
The exchange rate with resourceId IMFRateProvider was started remotely
The exchange rate with resourceId ECBCurrentRateProvider was started remotely
Loaded ECBCurrentRateProvider exchange rates for days:1
Loaded ECBHistoric90RateProvider exchange rates for days:63
Loaded ECBHistoricRateProvider exchange rates for days:4358

How can I disable all standard provider ?

dominik42 commented 7 years ago

any news here ?

atsticks commented 7 years ago

Not yet, will have a look at it asap. We should get out a maintenance release of the RI asap, so hopefully we can include this issues as well.

fprochazka commented 6 years ago

To understand the loading system, investigate DefaultLoaderService#registerData(org.javamoney.moneta.spi.LoadDataInformation)


I was able to achieve disabling them with this config

# Default conversion chain
{1}conversion.default-chain=IDENT,ECB

# Disable loading resources that are not used
{1}load.ECBHistoric90RateProvider.type=LAZY
{1}load.ECBHistoric90RateProvider.startRemote=false
{1}load.ECBHistoricRateProvider.type=LAZY
{1}load.ECBHistoricRateProvider.startRemote=false
{1}load.IMFRateProvider.type=LAZY
{1}load.IMFRateProvider.startRemote=false
{1}load.IMFHistoricRateProvider.type=LAZY
{1}load.IMFHistoricRateProvider.startRemote=false
dominik42 commented 6 years ago

Thanks for this hint. With it, I only see the following logs: 07:59:43.851 [] INFO vert.ECBAbstractRateProvider - Loaded ECBCurrentRateProvider exchange rates for days: 07:59:43.899 [] INFO vert.ECBAbstractRateProvider - Loaded ECBHistoric90RateProvider exchange rates for days:63 07:59:44.747 [] INFO vert.ECBAbstractRateProvider - Loaded ECBHistoricRateProvider exchange rates for days:4358

but no „… start remotely“ any more, fine ! But how can I disable the ‚loading‘ of those rate provider too ?

fprochazka commented 6 years ago

I don't think you can - not easily.

atsticks commented 6 years ago

Loading of the exchange rate providers is controlled by the service loader logic. The mentioned config AFAIK only is for controlling the loading logic, so loading cannot be switched of as of now.

atsticks commented 6 years ago

With 1.2 the rate providers come in their own jars, so just avoid loding them, e.g. using Mven excludes, should work fine.

wderose commented 5 years ago

@atsticks: Thank you for the suggestion to avoid loading unnecessary rate providers at build/assembly time using Maven/SBT.

The issue I face is even if I only use moneta-convert-imf or moneta-convert-ecb both jars contain historic rate providers that I would like to prevent from loading data into memory. My use case only calls for the current providers.

I've tried updating my javamoney.properties file as suggested in this thread but have not been able to prevent the historic providers from loading additional historic fx quotes.

Is there a way to specify the exact providers I'd like start/load in the 1.3 release?

# Default conversion chain
{1}conversion.default-chain=IDENT,IMF,ECB

# Disable loading resources that are not used
{1}load.ECBHistoric90RateProvider.type=LAZY
{1}load.ECBHistoric90RateProvider.startRemote=false

{1}load.ECBHistoricRateProvider.type=LAZY
{1}load.ECBHistoricRateProvider.startRemote=false

{1}load.IMFHistoricRateProvider.type=LAZY
{1}load.IMFHistoricRateProvider.startRemote=false
thweiss commented 4 years ago

I implemented my own ExchangeRateProvider and would like to use the other ones as a fallback in certain test environments of my application with poor data quality. It would be nice to control this by means of staging the javamoney.properties.

ayedo commented 4 years ago

The way this is currently solved is confusing to me: as a user I feel like I have no control over what is happening. Like @wderose I would like to have a single provider with no historic data that loads data once a day. I could not figure out how to do that?

We are using the currency conversions in user web requests, and don't know how do deal with the 20s pauses when JavaMoney downloads some files.

keilw commented 4 years ago

At least @thweiss mentioned, he created his own, and I know, corporate users like Zalando also do, so it should work now, I don't think they build their own Moneta, just extending it. Did you try the example @fprochazka gave? It worked for him as well, hence the ticket is closed. I don't believe it needs to be reopened, but if some of you are happy to contribute to a special example under https://github.com/JavaMoney/javamoney-examples, please feel free to create a ticket, and participate in the example.

There's a conversion example in https://github.com/JavaMoney/javamoney-examples/blob/master/console/javamoney-console-java10/src/main/java/org/javamoney/examples/console/java10/convert/ConversionExample.java (also a Java 8 equivalent) but they only pick between IMF and ECB, not disable one of them or add a new provider.

ayedo commented 4 years ago

Thank for your reply. I've tried the solution provided by @fprochazka but it does not work for me. I still get the following in my log:

Loaded ECBHistoricRateProvider exchange rates for days:5562

This is my config:


# Default conversion chain
{1}conversion.default-chain=IDENT,ECB

# Disable loading resources that are not used
{1}load.ECBHistoric90RateProvider.type=LAZY
{1}load.ECBHistoric90RateProvider.startRemote=false
{1}load.ECBHistoricRateProvider.type=LAZY
{1}load.ECBHistoricRateProvider.startRemote=false
{1}load.IMFRateProvider.type=LAZY
{1}load.IMFRateProvider.startRemote=false
{1}load.IMFHistoricRateProvider.type=LAZY
{1}load.IMFHistoricRateProvider.startRemote=false

what am I doing wrong?

keilw commented 4 years ago

I hope @fprochazka could tell you a little more e.g. where he placed the file (on the classpath I would assume) If he'd be too busy to respond, I may be able to look into it on Fri or over the weekend, because I have a few days with no client work during the day.

keilw commented 4 years ago

And feel free to create a ticket for the example because that could help others to understand how to use it.

ayedo commented 4 years ago

OK, thanks. No stress.

I can create a ticket, but I'm not sure for what. I don't think there is a bug, but I just can't figure out how to configure my use case.

Does anybody have the same use case as me?

I cannot have JavaMoney download resources while blocking one of our client request for 20 seconds. I want it to download what it needs on startup, and then regularly in an asynchronous fashion. I only need one provider for daily data.

keilw commented 4 years ago

Yes, e.g. @fprochazka or @dominik42, which is why I think it can't hurt to create a quick and easy example that shows how to do that. Companies like Zalando also did that earlier, so it should work but we had no time to fully document that case and it seems neither did Zalando, maybe they demonstrated it during a MeetUp, but I don't think it was documented in a publicly available space.

fprochazka commented 4 years ago

Well... I've completely changed the strategy for loading exchanges rates, because loading it per-process and holding in memory became a problem for us.

I was forced to introduce several hacks to disable the default loading completely, introduced an abstract database provider, that is then extended for each exchange rate type and also made our own loader, that is executed periodically, that uses the parsing logic from moneta, but once the exchange rates are parsed, it then saves them to database, where the database provider can pick it up.

I was planning on introducing a propper solution for disabling the exchange rate providers and sending a PR, but never got to it, sorry.

keilw commented 4 years ago

If you still can, we appreciate, does it require a change and custom-build of Moneta right now? I cannot outrule Zalando also does because they are a large company, but the goal (especially for a follow-up JSR) would be to just configure it.

fprochazka commented 4 years ago

I'd love to send a PR that would make this easier, but I can't promise I'll have time in the near future.

keilw commented 4 years ago

OK no worries, did it work with the mentioned file only or did you have to fork and patch parts of the RI?

ghost commented 4 years ago

I have the same problem as @ayedo. I overrided javamoney.properties in my SpringBoot application and locally it looks nice. But, when I run it on server, javamoney/properties which is in resources folder is ignoring. I am using version 1.4.2 of javamoney. Any ideas? ;)

keilw commented 4 years ago

Could you tell us a little more about the server, is it a JavaEE/Jakarta EE server or Spring Framework running in a container? I cannot say 100% sure, but there were a few issues Anatole got us into 1.4.x trying to do a "Tamaya Light" around properties, I assume it could be related to different class or module paths in an Enterprise container, but that is why we would like to know which containers are affected?

ghost commented 4 years ago

It is simple SpringBoot (2.2.5) application with Tomcat inside. ;) Should I simply decrease version to 1.3.x?

keilw commented 4 years ago

As a test or comparison why not. We are preparing 1.4.3 before eventually in the next year there could even be a new JavaMoney spec, but that'll take a little time. Thanks for the observations. I will not reopen it because I think there is a similar case reported by JBoss a while ago. They never came back to us if it was resolved, but potentially some issues with classloading in Tomcat and Wildfly/JBoss could have the same reason.

brassier commented 3 years ago

Is there any more insight on this issue? We also have a Spring Boot app (embedded tomcat) and overriding with the javamoney.properties seems to have no effect for us, similar to what's noted above.

keilw commented 3 years ago

No not that we know of, there are PRs like https://github.com/JavaMoney/jsr354-ri/pull/347 but they are about different things. The issue was closed and so far @fprochazka did not get a chance to raise a PR for this one.

brassier commented 3 years ago

Thanks @keilw. I actually confirmed that my spring boot javamoney.properties changes ARE getting picked up. I was being thrown off because the providers continue to be loaded even when disabling them in properties, as noted above.

What is the suggested way to adjust the rate providers that are leveraged if we want current but no historic providers? The javamoney.properties don't seem to actually turn anything off. If we want to stop using the historic providers, is there a way to do that either programmatically in app startup, or with properties updates?

brassier commented 3 years ago

In case this helps others, I'm using version 1.3 and was seemingly able to stop providers from loading using the NEVER type (as opposed to the LAZY type suggested above. My configuration is below:

{1}load.ECBHistoric90RateProvider.type=NEVER
{1}load.ECBHistoric90RateProvider.startRemote=false
{1}load.ECBHistoricRateProvider.type=NEVER
{1}load.ECBHistoricRateProvider.startRemote=false
{1}load.IMFHistoricRateProvider.type=NEVER
{1}load.IMFHistoricRateProvider.startRemote=false

Additionally, I wanted to load rates at startup AND with the default schedule. I was able to throw something like below into my app startup which fetches rates. Lastly, someone above noted waiting for 20 seconds for rates. Below will help that by pushing it to startup. The root cause of that might be due to this.

            Collection<LoaderService> loaders = Bootstrap.getServices(LoaderService.class);
            for (LoaderService loader : loaders) {
                Set<String> resources = loader.getResourceIds();
                for (String resource : resources) {
                    UpdatePolicy policy = loader.getUpdatePolicy(resource);
                    if (policy != UpdatePolicy.NEVER) {
                        logger.info("Loading Resource: " + resource);
                        loader.loadData(resource);
                    }
                }
            }
basarito commented 1 year ago

Is there any update on this?

My use case is that I want to disable loading of providers in some tests because it significantly slows down our pipelines.. at the moment it seems impossible to do, but looking at the source code it should be simple enough to do with an additional property in javamoney.properties?

In org.javamoney.moneta.spi.loader.LoaderConfigurator#load method we can just check for a property like load.ECBHistoricRateProvider.enabled=true and skip loading if false?

Like it was mentioned in comments above, setting load.ECBHistoricRateProvider.type=NEVER does nothing because it refers to updating, not loading.

keilw commented 1 year ago

The only way you can fully disable IMF or ECB is by patching Moneta and disabling the modules you don't like in moneta/pom.xml and moneta-convert/pom.xml. This is done temporarily in the 1.4.3 snapshot, to separate ECB problems (like #374) from those with IMF (like #353) but in theory if you're willing to build your own Moneta, you could also use that to disable one or both default provicers. At the moment I'm afraid, there is no other method. We may revisit that with a 1.5 release or a whole new Money JSR assuming that finds enough support in the JCP.