Closed guofengzh closed 6 years ago
Hard to say, do you try this from a "strange" country like Russia, Turkey, etc. where there have been several restrictions or hacker attacks in recent weeks that may cause the IMF to ban certain countries or IP ranges?
This example is run on my home desktop in Beijing, China. But I use javamoney 1.2.1 in a project run on AWS in Korea. It has the same issue. Loading the data from ECB works well. I understand that IMFProvider works but has limited access in some countries. Thanks for your support.
This is thrown on a more regular basis. And mostly affects the "Last Five Days" like http://www.imf.org/external/np/fin/data/rms_five.aspx While other endpoints including Current Month have no problems.
Right now RMS_FIVE is the default, it is worth looking at alternative strategies, e.g. use historic/current month as a fallback.
It's quite bizarre because in the browser "Last Five Days" work again, but unit tests still fail for javamoney-examples
. Maybe batch access or some attributes/user agent, etc. are not accepted any more?
I can confirm that this problem is not IP or country specific. I tried it from several countries (Latvia, Germany, Switzerland, Unites States) with the same result starting with the first request:
Caused by: java.io.IOException: Request has been rejected by IMF server.
at org.javamoney.moneta.convert.imf.IMFRateReadingHandler.read(IMFRateReadingHandler.java:66)
at org.javamoney.moneta.convert.imf.IMFAbstractRateProvider.newDataLoaded(IMFAbstractRateProvider.java:114)
... 34 more
This is my demo application: https://github.com/McPringle/jsr-354-demo/blob/master/src/main/java/ch/fihlon/jsr354/demo/CurrencyConversionDemo.java
moneyApiVersion = 1.0.3 monetaVersion = 1.2.1
It seems to affect that 5 day query more than others. Not sure, what to do about it, but with a possible slight performance penalty we could try to access other endpoints/data sets that usually return a whole month.
Hello,
I had the same problem and I managed to solve it as follows:
In the file "LoadableResource.java" ("org.javamoney.moneta.internal.loader"), you must specify the "User-Agent" in the case of an http(s) request.
To do this, in the protected method "load", I added the following code after line 325:
if (conn instanceof HttpURLConnection) {
conn.setRequestProperty("User-Agent", "Chrome/51.0.2704.103");
}
Hoping that it can help you.
Thanks, would you be able to propose a PR with that?
Yes, I'll do that tomorrow.
After merging the PR it still gets rejected:
java.lang.IllegalArgumentException: Failed to load new data: org.javamoney.moneta.convert.imf.IMFRateProvider{ context: ProviderContext (
{User-Agent=Chrome/51.0.2704.103, rateTypes=[DEFERRED], providerDescription=International Monetary Fond, days=1, provider=IMF})}
at org.javamoney.moneta.internal.loader.DefaultLoaderListener.trigger(DefaultLoaderListener.java:85)
at org.javamoney.moneta.internal.loader.LoadDataLoaderService.execute(LoadDataLoaderService.java:41)
at org.javamoney.moneta.internal.loader.DefaultLoaderServiceFacade.loadData(DefaultLoaderServiceFacade.java:43)
at org.javamoney.moneta.internal.loader.DefaultLoaderService.loadData(DefaultLoaderService.java:264)
at org.javamoney.moneta.convert.imf.IMFRateProvider.<init>(IMFRateProvider.java:62)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:488)
at java.base/java.util.ServiceLoader$ProviderImpl.newInstance(ServiceLoader.java:777)
at java.base/java.util.ServiceLoader$ProviderImpl.get(ServiceLoader.java:721)
at java.base/java.util.ServiceLoader$3.next(ServiceLoader.java:1389)
at org.javamoney.moneta.internal.PriorityAwareServiceProvider.loadServices(PriorityAwareServiceProvider.java:98)
at org.javamoney.moneta.internal.PriorityAwareServiceProvider.getServices(PriorityAwareServiceProvider.java:65)
at javax.money.spi.Bootstrap.getServices(Bootstrap.java:102)
at org.javamoney.moneta.convert.internal.DefaultMonetaryConversionsSingletonSpi.reload(DefaultMonetaryConversionsSingletonSpi.java:64)
at org.javamoney.moneta.convert.internal.DefaultMonetaryConversionsSingletonSpi.<init>(DefaultMonetaryConversionsSingletonSpi.java:56)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:488)
at java.base/java.util.ServiceLoader$ProviderImpl.newInstance(ServiceLoader.java:777)
at java.base/java.util.ServiceLoader$ProviderImpl.get(ServiceLoader.java:721)
at java.base/java.util.ServiceLoader$3.next(ServiceLoader.java:1389)
at org.javamoney.moneta.internal.PriorityAwareServiceProvider.loadServices(PriorityAwareServiceProvider.java:98)
at org.javamoney.moneta.internal.PriorityAwareServiceProvider.getServices(PriorityAwareServiceProvider.java:65)
at javax.money.spi.Bootstrap.getService(Bootstrap.java:113)
at javax.money.convert.MonetaryConversions.getMonetaryConversionsSpi(MonetaryConversions.java:59)
at javax.money.convert.MonetaryConversions.getExchangeRateProvider(MonetaryConversions.java:169)
at javax.money.convert.MonetaryConversions.getExchangeRateProvider(MonetaryConversions.java:197)
at org.javamoney.moneta.convert.imf.IMFHistoricRateProviderTest.setup(IMFHistoricRateProviderTest.java:61)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:100)
at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:515)
at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:216)
at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:143)
at org.testng.TestRunner.beforeRun(TestRunner.java:624)
at org.testng.TestRunner.run(TestRunner.java:592)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:366)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:361)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:319)
at org.testng.SuiteRunner.run(SuiteRunner.java:268)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1264)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1189)
at org.testng.TestNG.runSuites(TestNG.java:1104)
at org.testng.TestNG.run(TestNG.java:1076)
at org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:69)
at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.executeMulti(TestNGDirectoryTestSuite.java:181)
at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.execute(TestNGDirectoryTestSuite.java:99)
at org.apache.maven.surefire.testng.TestNGProvider.invoke(TestNGProvider.java:113)
at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:200)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:153)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103)
Caused by: java.lang.IllegalArgumentException: Failed to load IMF data provided.
at org.javamoney.moneta.convert.imf.IMFAbstractRateProvider.newDataLoaded(IMFAbstractRateProvider.java:123)
at org.javamoney.moneta.convert.imf.IMFRateProvider.newDataLoaded(IMFRateProvider.java:39)
at org.javamoney.moneta.internal.loader.DefaultLoaderListener.trigger(DefaultLoaderListener.java:83)
... 57 more
Caused by: java.io.IOException: Request has been rejected by IMF server.
at org.javamoney.moneta.convert.imf.IMFRateReadingHandler.read(IMFRateReadingHandler.java:66)
at org.javamoney.moneta.convert.imf.IMFAbstractRateProvider.newDataLoaded(IMFAbstractRateProvider.java:114)
... 59 more
One can see, the UA is applied, but it has no effect on the test run.
I tried @c-delanneau code and it works very well. But I use the following and it works as well too in our desktop and the product server on AWS in Korea:
if (conn instanceof HttpURLConnection) {
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.63 Safari/537.36");
}
This sounds a little broader than just Chrome. Thanks @guofengzh. We may give it a try. Still strange, that wherever Travis-CI (the company itself is in Berlin) has its build servers it does not seem to have an effect, but if a production server on AWS in Korea works that is a good sign. Ideally it should for most countries or AWS regions. I could imagine that making it configurable somehow instead of hard-coding it was also helpful.
This was fixed with https://github.com/JavaMoney/jsr354-ri/pull/203
Is it possible that something like this is happening in other environments? We have a couple spring boot apps that are struggling to find the default "5 day" resource. This URL seems to work fine in a browser though.
Apr 26 18:03:08 2021-04-26 18:03:08.057 INFO 30680 --- [nio-8010-exec-2] o.j.m.internal.loader.LoadableResource : Failed to load resource input for IMFHistoricRateProvider from https://www.imf.org/external/np/fin/data/rms_five.aspx?tsvflag=Y
Apr 26 18:03:08 java[30680]: javax.net.ssl.SSLException: Received fatal alert: internal_error
This is the first time in almost 3 years anybody mentions anything here, so it doesn't seem to frequent. Of course the IMF could tighten security to try avoid attacks like DDNS or similar. We saw in project Agorava that some APIs like Facebook, Twitter and others work fine from a browser or mobile but once you try to access the same within a Spring or Java EE/Jakarta EE like environment, it would reject those requests with some weird "possible attack" message.
Beside this was closed and resolved back then.
Tipp: Check the user agent, your spring boot app uses. Try to make it look like a browser and don't use your application name. That solved a lot of problems in my apps where server-side protection kicked in on "suspicious" activity (like a "suspicious" user agent).
Thanks a lot, if you had time because at least occasionally Spring Boot or other web app users may face similar issues, you're welcome to contribute to a quick tip or similar either in a Wiki (https://github.com/JavaMoney/javamoney-examples/wiki among others, there is no Wiki here, and I'm not sure, if it is the best place but if you prefer this repo just say) or similar place? I also sent you an invitation @McPringle to join the organization as "Associate" if that's not enough to edit a Wiki we could also tweak the team, Contributor is normally for contributing JCP members, if you're already a JCP member, you'd be more than welcome to join that team even without listing on jcp.org.
I run ConversionExample.java in javamoney-examples, JDK 1.8, moneta 1.2.1, I got the following WARNING about IMFProvider:
Failed to read/load resource (checking fallback): IMFRateProvider java.lang.IllegalArgumentException: Failed to load new data: org.javamoney.moneta.convert.imf.IMFRateProvider{ context: ProviderContext ( {User-Agent=Chrome/51.0.2704.103, rateTypes=[DEFERRED], providerDescription=International Monetary Fond, days=1, provider=IMF})} at org.javamoney.moneta.internal.loader.DefaultLoaderListener.trigger(DefaultLoaderListener.java:85) at org.javamoney.moneta.internal.loader.LoadDataLoaderService.execute(LoadDataLoaderService.java:41) at org.javamoney.moneta.internal.loader.DefaultLoaderServiceFacade.loadData(DefaultLoaderServiceFacade.java:43) at org.javamoney.moneta.internal.loader.DefaultLoaderService.loadData(DefaultLoaderService.java:264) at org.javamoney.moneta.convert.imf.IMFRateProvider.<init>(IMFRateProvider.java:62) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at java.lang.Class.newInstance(Class.java:442) at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:380) at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:404) at java.util.ServiceLoader$1.next(ServiceLoader.java:480) at org.javamoney.moneta.internal.PriorityAwareServiceProvider.loadServices(PriorityAwareServiceProvider.java:98) at org.javamoney.moneta.internal.PriorityAwareServiceProvider.getServices(PriorityAwareServiceProvider.java:65) at javax.money.spi.Bootstrap.getServices(Bootstrap.java:102) at org.javamoney.moneta.convert.internal.DefaultMonetaryConversionsSingletonSpi.reload(DefaultMonetaryConversionsSingletonSpi.java:64) at org.javamoney.moneta.convert.internal.DefaultMonetaryConversionsSingletonSpi.<init>(DefaultMonetaryConversionsSingletonSpi.java:56) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at java.lang.Class.newInstance(Class.java:442) at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:380) at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:404) at java.util.ServiceLoader$1.next(ServiceLoader.java:480) at org.javamoney.moneta.internal.PriorityAwareServiceProvider.loadServices(PriorityAwareServiceProvider.java:98) at org.javamoney.moneta.internal.PriorityAwareServiceProvider.getServices(PriorityAwareServiceProvider.java:65) at javax.money.spi.Bootstrap.getService(Bootstrap.java:113) at javax.money.convert.MonetaryConversions.getMonetaryConversionsSpi(MonetaryConversions.java:59) at javax.money.convert.MonetaryConversions.getConversion(MonetaryConversions.java:89) at javax.money.convert.MonetaryConversions.getConversion(MonetaryConversions.java:105) at org.javamoney.examples.console.simple.conversion.ConversionExample.main(ConversionExample.java:40) Caused by: java.lang.IllegalArgumentException: Failed to load IMF data provided. at org.javamoney.moneta.convert.imf.IMFAbstractRateProvider.newDataLoaded(IMFAbstractRateProvider.java:123) at org.javamoney.moneta.convert.imf.IMFRateProvider.newDataLoaded(IMFRateProvider.java:39) at org.javamoney.moneta.internal.loader.DefaultLoaderListener.trigger(DefaultLoaderListener.java:83) ... 32 more Caused by: java.io.IOException: Request has been rejected by IMF server. at org.javamoney.moneta.convert.imf.IMFRateReadingHandler.read(IMFRateReadingHandler.java:66) at org.javamoney.moneta.convert.imf.IMFAbstractRateProvider.newDataLoaded(IMFAbstractRateProvider.java:114) ... 34 more
and
Failed to read/load resource (checking fallback): IMFHistoricRateProvider java.lang.IllegalArgumentException: Failed to load new data: org.javamoney.moneta.convert.imf.IMFHistoricRateProvider{ context: ProviderContext ( {User-Agent=Chrome/51.0.2704.103, rateTypes=[HISTORIC], providerDescription=Historic International Monetary Fond, days=0, provider=IMF-HIST})} at org.javamoney.moneta.internal.loader.DefaultLoaderListener.trigger(DefaultLoaderListener.java:85) at org.javamoney.moneta.internal.loader.LoadDataLoaderService.execute(LoadDataLoaderService.java:41) at org.javamoney.moneta.internal.loader.DefaultLoaderServiceFacade.loadData(DefaultLoaderServiceFacade.java:43) at org.javamoney.moneta.internal.loader.DefaultLoaderService.loadData(DefaultLoaderService.java:264) at org.javamoney.moneta.convert.imf.IMFHistoricRateProvider.<init>(IMFHistoricRateProvider.java:66) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at java.lang.Class.newInstance(Class.java:442) at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:380) at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:404) at java.util.ServiceLoader$1.next(ServiceLoader.java:480) at org.javamoney.moneta.internal.PriorityAwareServiceProvider.loadServices(PriorityAwareServiceProvider.java:98) at org.javamoney.moneta.internal.PriorityAwareServiceProvider.getServices(PriorityAwareServiceProvider.java:65) at javax.money.spi.Bootstrap.getServices(Bootstrap.java:102) at org.javamoney.moneta.convert.internal.DefaultMonetaryConversionsSingletonSpi.reload(DefaultMonetaryConversionsSingletonSpi.java:64) at org.javamoney.moneta.convert.internal.DefaultMonetaryConversionsSingletonSpi.<init>(DefaultMonetaryConversionsSingletonSpi.java:56) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at java.lang.Class.newInstance(Class.java:442) at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:380) at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:404) at java.util.ServiceLoader$1.next(ServiceLoader.java:480) at org.javamoney.moneta.internal.PriorityAwareServiceProvider.loadServices(PriorityAwareServiceProvider.java:98) at org.javamoney.moneta.internal.PriorityAwareServiceProvider.getServices(PriorityAwareServiceProvider.java:65) at javax.money.spi.Bootstrap.getService(Bootstrap.java:113) at javax.money.convert.MonetaryConversions.getMonetaryConversionsSpi(MonetaryConversions.java:59) at javax.money.convert.MonetaryConversions.getConversion(MonetaryConversions.java:89) at javax.money.convert.MonetaryConversions.getConversion(MonetaryConversions.java:105) at org.javamoney.examples.console.simple.conversion.ConversionExample.main(ConversionExample.java:40) Caused by: java.lang.IllegalArgumentException: Failed to load IMF data provided. at org.javamoney.moneta.convert.imf.IMFAbstractRateProvider.newDataLoaded(IMFAbstractRateProvider.java:123) at org.javamoney.moneta.convert.imf.IMFHistoricRateProvider.newDataLoaded(IMFHistoricRateProvider.java:47) at org.javamoney.moneta.internal.loader.DefaultLoaderListener.trigger(DefaultLoaderListener.java:83) ... 32 more Caused by: java.io.IOException: Request has been rejected by IMF server. at org.javamoney.moneta.convert.imf.IMFRateReadingHandler.read(IMFRateReadingHandler.java:66) at org.javamoney.moneta.convert.imf.IMFAbstractRateProvider.newDataLoaded(IMFAbstractRateProvider.java:114) ... 34 more
How to deal with this issue?