The problem with using AsyncHttpClient.close()
is that it shuts down the thread pool executor used by the provider, then there is no way to re-use the client without re-building it, because as per documentation, the executor instance cannot be reused once ts is shutdown. So, there is no way but re-build the client if you go that way (unless you implement your own ExecutorService that would have another shutdown logic, but it is a long way to go, IMHO).
However, from looking into the implementation of NettyAsyncHttpProvider
, I can see that it stores the reference to the given AsyncHttpClientConfig
instance and calls its getProxyServerSelector()
to get the proxy settings for every new NettyAsyncHttpProvider.execute(Request...)
invocation (i.e. for every request executed by AsyncHttpClient
).
Then, if we could make the getProxyServerSelector()
return the configurable instance of ProxyServerSelector
, that would do the thing.
Unfortunately, AsyncHttpClientConfig
is designed to be a read-only container, instantiated by AsyncHttpClientConfig.Builder
.
To overcome this limitation, we would have to hack it, using, say, "wrap/delegate" approach:
Create a new class, derived from AsyncHttpClientConfig
. The class should wrap the given separate AsyncHttpClientConfig
instance and implement the delegation of the AsyncHttpClientConfig
getters to that instance.
To be able to return the proxy selector we want at any given point of time, we make this setting mutable in a this wrapper class and expose the setter for it.
Example:
public class MyAsyncHttpClientConfig extends AsyncHttpClientConfig
{
private final AsyncHttpClientConfig config;
private ProxyServerSelector proxyServerSelector;
public MyAsyncHttpClientConfig(AsyncHttpClientConfig config)
{
this.config = config;
}
@Override
public int getMaxTotalConnections() { return config.maxTotalConnections; }
@Override
public int getMaxConnectionPerHost() { return config.maxConnectionPerHost; }
// delegate the others but getProxyServerSelector()
...
@Override
public ProxyServerSelector getProxyServerSelector()
{
return proxyServerSelector == null
? config.getProxyServerSelector()
: proxyServerSelector;
}
public void setProxyServerSelector(ProxyServerSelector proxyServerSelector)
{
this.proxyServerSelector = proxyServerSelector;
}
}
- Now, in your example, wrap your
AsyncHttpClient
config instance with our new wrapper and use it to configure the AsyncHttpClient
:
Example:
MyAsyncHttpClientConfig myConfig = new MyAsyncHttpClientConfig(config);
return new AsyncHttpClient(new NettyAsyncHttpProvider(myConfig), myConfig);
- Whenever you invoke
myConfig.setProxyServerSelector(newSelector)
, the new request executed by NettyAsyncHttpProvider
instance in your client will use the new proxy server settings.
A few hints/warnings:
This approach relies on the internal implementation of NettyAsyncHttpProvider
; therefore make your own judgement on maintainability, future Netty libraries versions upgrade strategy etc. You could always look at the Netty source code before upgrading to the new version. At the current point, I personally think it is unlikely to change too much to invalidate this implementation.
You could get ProxyServerSelector
for ProxyServer
by using com.ning.http.util.ProxyUtils.createProxyServerSelector(proxyServer)
- that's exactly what AsyncHttpClientConfig.Builder
does.
The given example has no synchronization logic for accessing proxyServerSelector
; you may want to add some as your application logic needs.
Maybe it is a good idea to submit a feature request for AsyncHttpClient
to be able to setup a "configuration factory" for the AsyncHttpProvider
so all these complications would vanish :-)