playframework / playframework

The Community Maintained High Velocity Web Framework For Java and Scala.
http://www.playframework.com
Apache License 2.0
12.55k stars 4.1k forks source link

Conflict ahc-xxx.properties for play built-in asyncHttpClient and others #7545

Open zhengcan opened 7 years ago

zhengcan commented 7 years ago

Are you looking for help?

No

Play Version (2.5.x / etc)

2.6.0

API (Scala / Java / Neither / Both)

Neither

Operating System (Ubuntu 15.10 / MacOS 10.10 / Windows 10)

MacOS 10.12

JDK (Oracle 1.8.0_72, OpenJDK 1.8.x, Azul Zing)

Oracle 1.8.0

Library Dependencies

My app use javaWs and a thirdparty library, which depends asyncHttpClient.

Expected Behavior

The application runs well.

Actual Behavior

AsyncHttpClient cannot be created. We can receive exception stacktrack like below:

2 errors
    at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:470)
    at com.google.inject.internal.InternalInjectorCreator.initializeStatically(InternalInjectorCreator.java:155)
    at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:107)
    at com.google.inject.Guice.createInjector(Guice.java:99)
    at com.google.inject.Guice.createInjector(Guice.java:84)
    at play.api.inject.guice.GuiceBuilder.injector(GuiceInjectorBuilder.scala:181)
    at play.api.inject.guice.GuiceApplicationBuilder.build(GuiceApplicationBuilder.scala:137)
    at play.api.inject.guice.GuiceApplicationLoader.load(GuiceApplicationLoader.scala:21)
    at play.core.server.DevServerStart$$anon$1.$anonfun$get$6(DevServerStart.scala:171)
    at play.utils.Threads$.withContextClassLoader(Threads.scala:21)
Caused by: java.lang.NumberFormatException: null
    at java.lang.Integer.parseInt(Integer.java:542)
    at java.lang.Integer.parseInt(Integer.java:615)
    at org.asynchttpclient.config.AsyncHttpClientConfigHelper$Config.getInt(AsyncHttpClientConfigHelper.java:85)
    at org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultMaxRedirects(AsyncHttpClientConfigDefaults.java:59)
    at org.asynchttpclient.DefaultAsyncHttpClientConfig$Builder.<init>(DefaultAsyncHttpClientConfig.java:582)
    at system.GuiceModule.configure(GuiceModule.java:87)
    at com.google.inject.AbstractModule.configure(AbstractModule.java:62)
    at com.google.inject.spi.Elements$RecordingBinder.install(Elements.java:340)
    at com.google.inject.spi.Elements.getElements(Elements.java:110)
    at com.google.inject.util.Modules$OverrideModule.configure(Modules.java:177)

Reproducible Test Case

Add an offical asyncHttpClient as a dependency, and create a new DefaultAsyncHttpClient in any where.

zhengcan commented 7 years ago

The AsyncHttpClientConfigHelper will read default config from ahc-default.properties and ahc.properties from resource bundle. In offical jar, the content of these properties is prefixed with org.asynchttpclient, such as:

org.asynchttpclient.threadPoolName=AsyncHttpClient
org.asynchttpclient.maxConnections=-1
org.asynchttpclient.maxConnectionsPerHost=-1

In shaded-asynchttpclient-1.0.0.jar, the content of the ahc-default.properties is like this:

play.shaded.ahc.org.asynchttpclient.threadPoolName=AsyncHttpClient
play.shaded.ahc.org.asynchttpclient.maxConnections=-1
play.shaded.ahc.org.asynchttpclient.maxConnectionsPerHost=-1

So, we've got two ahc-default.properties with different content, but they are sharing the same name. The AsyncHttpClient may read any version of this file, and report exception as expected.

zhengcan commented 7 years ago

I wish the shaded version could rename the embedded ahc-default.properties to another one, and don't affect the offical AHC at all :)

wsargent commented 7 years ago

I can't rename the shaded version, because the code itself looks for that string.

wsargent commented 7 years ago

It's not ideal to use two instances of AsyncHttpClient, because they will use two different Netty thread pools, and so there'll be unneeded overhead.

wsargent commented 7 years ago

See https://github.com/playframework/play-ws/pull/149

richdougherty commented 7 years ago

Is it possible to use something like this to concatenate the two properties files together?

https://github.com/sbt/sbt-assembly#merge-strategy

zhengcan commented 7 years ago

I'm using a thirdparty library to execute RPC invocation, which is based on AHC. Previously, it shared the same AHC jar with Play Framework. But in 2.6, it won't any more.

If we merge two properties files in shaded AHC jar, it'll be ok to use offical version of AHC. But I'm not sure whether the shaded AHC will run well. Because the ClassLoader may use ANY one of two ahc-default.properties in two different jars. As workaround, I put a new and merged ahc.properties in /conf folder to fix this problem.