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.
Related
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.
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.
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.
I am using jersey client to send POST requests to a third party webservice. Since creating jersey clients is expensive, I am doing this inside the constructor of a service client class which is Spring managed. My thinking is that when my server starts up, Spring will create my service client bean, which in turn will cause the constructor to be invoked and so my jersey client will be created once. As long as the server is up, this jersey client will be responsible for sending out the requests and no further client initializations are required. However, I will be creating a new webresource for each call as creating jersey webresources is much cheaper.
package com.mypackage;
//Bunch of imports
class MyWebserviceClient {
//jersey client member variable
private Client jClient;
public MyWebserviceClient(){
//Create jersey client
jClient = Client.create();
//Other stuff
}
public void sendRequest(){
WebResource wr = jClient.resource(someUrl);
//Use the webresource to make webservice call
}
}
MyWebserviceClient is spring managed as such in the Spring config xml:
<bean id="myClient" class="com.mypackage,MyWebserviceClient"></bean>
The bean myClient will then be injected into the appropriate place where the service call needs to be made.
My questions
1) If my application is dealing with thousands of requests per hour is it efficient enough to handle all the requests with just one jersey client.
2) Do I need some kind of jersey client pool so that a large number of requests are taken care of more efficiently. If so, is there a way to do it?
3) I would like to know in general how multiple requests coming in from the end users are handled on the server side. Each request is a separate thread of execution on the server and all of them have access to the same jersey client object. If the jersey client object is busy with one such request, are the other requests from different end users going to wait till a response is received for the ongoing request?
4) Any better alternative to the one I am using.
Your thinking is right on track.
1 - Yes, and it is recommended to reuse a client instance:
from https://jersey.java.net/documentation/1.18/client-api.html#d4e623:
Client instances are expensive resources. It is recommended a configured instance is reused for the creation of Web resources. The creation of Web resources, the building of requests and receiving of responses are guaranteed to be thread safe. Thus a Client instance and WebResource instances may be shared between multiple threads.
2 - No need, the client itself can handle the requests. In the case of asynchronous requests, it internally uses a thread pool that is configurable.
3 - The Jersey client is thread safe, so threads will not block each other
4 - You can also consider providing the client as a dependency to MyWebserviceClient, and possibly reuse the same client between multiple classes
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?