What is the right way to use HttpClientConnectionManager with CloseableHttpClient in Apache? - java

Context
I have an instance of org.apache.hc.client5.http.impl.classic.CloseableHttpClient
and a singleton instance of org.apache.hc.client5.http.io.HttpClientConnectionManager to communicate with some remote API.
I have created a singleton pool of HTTP connections to create an instance of the HTTP client.
What is the right way to use HttpClientConnectionManager?
Should I really use try-with-resource (or old-style try-finally) to work with CloseableHttpClient?
If I close the HTTP client, a connection will be closed also from this pool. And then I can't use this pool to communicate with a remote API.
Of course, I've read the documentation https://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html
Maybe something I missed. Could anyone explain me?

You should also be using CloseableHttpClient as a singleton (on a per distinct service basis).
If you want to continue creating short lived instances of CloseableHttpClient with the same HttpClientConnectionManager please make sure to mark it as shared when creating CloseableHttpClient instances with HttpClientBuilder.

Related

Java - Is Spring's ReactorNettyWebSocketClient thread safe?

I'm wondering what best-practice usage is of Spring's WebSocketClient implementation, ReactorNettyWebSocketClient. I can't find details of this anywhere in the documentation.
Can I use this client as a singleton for all my web socket connections to different URLs? I have upwards of ten servers I need to connect to. Or should I instantiate a new instance per connection?
For example, is this acceptable usage?
#Bean
public WebSocketClient webSocketClient() {
return new ReactorNettyWebSocketClient();
}
Thanks in advance.
ReactorNettyWebSocketClient is stateless except HttpClient field.
HttpClient is 100% stateless, so it is safe to have singleton

How to set TLS parameters on a CXF conduit?

My application has two outgoing SOAP connections. For those, I want to implement TLS. Both are created using CXF.
The javax.xml.ws.Service.getPort() returns an individual bindingProvider (both connections use their own WSDL) but both use the same org.apache.cxf.bus.spring.SpringBus instance.
Before using the bindingProvider, I set the TLS client parameters on the Conduit:
Client client = ClientProxy.getClient(bindingProvider); // different
HTTPConduit httpConduit = (HTTPConduit) client.getConduit(); // same for both connections
TLSClientParameters tlsClientParameters = new TLSClientParameters();
tlsClientParameters.setTrustManagers(getTrustmanagers());
httpConduit.setTlsClientParameters(tlsClientParameters);
The issue is, the retrieved client is different for both connections, but the conduit is the same object. Thus, when I set the parameters for the second connection on the same object, I overwrite the priorly set settings.
The FAQ answer if CXF is threadsafe with "yes" and a number of exceptions. I think the second exception applies here. It says:
CXF answer: CXF proxies are thread safe for MANY use cases. The exceptions are:
[...]
Settings on the conduit - if you use code or configuration to directly manipulate the conduit (like to set TLS settings or similar), those are not thread safe. The conduit is per-instance and thus those settings would be shared. Also, if you use the FailoverFeature and LoadBalanceFeatures, the conduit is replaced on the fly. Thus, settings set on the conduit could get lost before being used on the setting thread.
[...]
For the conduit issues, you COULD install a new ConduitSelector that uses a thread local or similar. That's a bit complex though.
I'm not entirely sure if thread safety is my issue. I create the two connections each in their own component. Springs uses only one thread for initializing all the components, so both connections are initialized by the same thread. But afterwards, the connection is used threads from a pool. Overwriting the settings happens during intialization, so before sending actual SOAP messages using different threads.
When the Conduit is created in org.apache.cxf.endpoint.AbstractConduitSelector#getSelectedConduit, it is done using the SpringBus which is the same instance for both objects.
So, the FAQ tell me to use my own custom ConduitSelector.
I tried setting it before the initialization above:
Client client = ClientProxy.getClient(bindingProvider);
client.setConduitSelector(
new UpfrontConduitSelector(
new URLConnectionHTTPConduit(client.getBus(),
client.getEndpoint().getEndpointInfo())));
and I tried the same after the initialization. In both cases, after setting the conduit selector, when something uses the BindingProvider (which is a Proxy-object), it gets a NullPointerException although the object is not null.
My issue here is to either get the custom conduit selector running or to see that my issue can be solved completely differently or just to get some inspiration :)
Some guy on SO seems to have solved this here, but the answer to his question is not helping me.
I found a solution.
The issue indeed had nothing to do with multithreading, but with the way the SpringBus is wired into my objects and how the Conduit is created from it.
The solution was to give each service its own SpringBus.
So before I create each SOAP-service by calling its c'tor in javax.xml.ws.Service, I do
BusFactory bf = BusFactory.newInstance();
Bus b = bf.createBus();
BusFactory.setThreadDefaultBus(b);
which sets a new threadlocal default bus which is then used for the service created. Thus, my two services each have their own SpringBus and they both create their own Conduit.
This works because each service is a spring #Component and all spring components are created by the main thread. So there is only one thread and no way this code will not be executed sequentially.

Need to create javax.ws.rs.client.Client for each webservcie call

Create a javax.ws.rs-ap.jar client and send the request to the server:
javax.ws.rs.client.Client client = ClientBuilder.newBuilder().build();
I have writtten the above code to call multiple api(get user by id, get all users and deleteUser).
My question is here.
I am creating a new Client for each api cal.
Just wanted to know i can create a single instance of Client and make multiple calls ?
Yes, a Client can be reused as long as it's lifecycle is managed properly. This means when a client instance is created, it should be closed properly as well using the close() method, once it's purpose is served. Refer to the Client API documentation.
Note that multiple client instances would be needed if each client has a different client configuration.

Relationship between HttpClient, HttpConnection and ClientConnectionManager

Lets consider one of the latest (4.2.x) releases of HttpComponents.
Please explain how generally an instance of HttpClient is related to instance of HttpConnection (such as ManagedClientConnectionImpl) and also ClientConnectionManager.
Who knows about who ?
I will refer to them below ommiting [Http] prefix. So, HttpClient -> Client
I understand that Client keeps reference to ClientConnectionManager.
Does that mean that Client also has reference to underlying Connection object ?
Does ConnectionManager knows about all Clients linked to it ?
How HttpGet, which is used by HttpClient to perform execute, knows about stream, exposed thru response's Entity ? (which it does, because we can close the stream by calling .abort() on HttpGet object.) Is HttpGet instance also linked to Connection object ?
I am confused and would appreciate detailed overview answering the questions above. To give examples, you could use any specific implementations, such as DefaultHttpClient, ManagedClientConnectionImpl, BasicClientConnectionManager, if it would make understanding easier.
HttpClient is a facade to the request execution pipeline. The exact composition of the execution pipeline depends on the configuration of the HttpClient instance. Think of it as a browser with multiple tabs.
One of more HttpClient instances can depend on one ClientConnectionManager sharing the underlying pool of persistent connections. ClientConnectionManager instances have no knowledge of HttpClient instances that depend upon them. They just lease connections to whatever entity requests them.
Each request is executed within a particular HttpContext. HttpContext instance is a collection of all stateful objects involved in execution of the actual HTTP exchange. HttpContext instances are not thread-safe and may not be shared by multiple worker threads.
When initiating an HTTP exchange HttpClient leases a ManagedClientConnection instance from the ClientConnectionManager it is associated with. It serializes and transmits the request message to the opposite endpoint, receives a response head, and binds the underlying connection to the response HttpEntity instance (when available) without reading the response content. This enables the consumer of HttpResponse instance stream the response content without intermediate in-memory buffering. This also makes it necessary for the consumer to ensure proper release of resources (in particular ManagedClientConnection) associated with the response.

concurrent request to jersey rest service

I am developing a very simple REST web service with Eclipse, Tomcat7 and Jersey implementation, with a connection to MySQL.
Looking to the jersey documentation i know that every request create a new object of the root resource class. But i dont know if every request is independet, for example if one request have to wait a long time, the server will accept more request normaly?
The problem is :
I have 2 main classes, 1 class implements Jersey with annotations(Proxy.java), and other class that connects to a BD(Notificator.java), there is only one instance of this class (Singleton) in order to use only 1 Connection object. The classes who implements Jersey use this class. So, if one of the request is blocked , i dont know if the others will run because they are using the same (Notificator.java) instance.
The relation is N instances of(Proxy.java) uses the only one (Notificator.java) witch have one Connection to a MySQL.
Jersey is developed on top of servlets. There is a new thread for each of the incoming request. Your code is creating a bottleneck for all the threads as there is a contention for single available connection object. If you have multiple requests then only one request will be using that connection and others have to wait. If the wait is not too long then there is no problem. But if wait is more than the HTTP REQUEST TIMEOUT then your other requests may end up as TIMED OUT.
I understand that you may be having single connection bottleneck due to some business requriement/ complication. So in all such cases where we cannot process all the requests simulataneously and there can be variety of reasons for it, then we should create our web services as Asynchronous. Asynchronous web services work on the model of SUBMIT REQUEST-> REQUEST ACCEPTED(will be processed asynchronously) and JOB URL returned for polling-> CLIENT POLLS till the JOB IS NOT COMPLETED.
Hope it helps!
Try database connection pooling, more on this here:
http://en.wikipedia.org/wiki/Connection_pool
How to establish a connection pool in JDBC?

Categories