Category Image HttpsURLConnection and HttpClient


I recently implemented java's built-in HttpsURLConnection class to process credit card transactions using a POST request over SSL. I also spun off new threads to do the processing (connect, send request, read response) since waiting for the connection and waiting for the response could get time-consuming. I expected that HttpsURLConnection would open multiple parallel HTTP connections to the service provider's host, but it did not. Then I discovered the HttpClient library from the Apache Jakarta Commons project and this nailed the problem.......

I would guess that Sun is complying with standards and if you look at RFC 2626 Section 8.1.4 you will see that the standard calls for no more that 2 persistent connections should be maintained by a client to a host. The reason for this is to avoid network congestion.

However if the client IS a server itself with multiple users accessing it, then the 2*N proxy guideline in the last paragraph of this RFC would allow us to use lots of connections without feeling guilty since our web application server is really acting as an intermediary or proxy between our users and the credit card service provider.

So with HttpsURLConnection the result was that threads had to wait until other threads were done with the connection to the cc service provider host.

Implementing HttpClient was more convenient, in my honest opinion, than HttpsURLConnection and using multi-threaded connection manager instantiation of HttpClient allowed multiple threads to simultaneously POST requests and get responses. There still is an underlying delay in establishing and adding multiple initial HTTP connections but once it gets going, sequentially spawned threads automatically gain advantage from the established connections and request-response times stay super-fast across all threads.

To process secure POST requests against a host using a multi-threaded enabled HttpClient instance you only need to use these classes from the HttpClient library
HttpClient
HttpConnectionManagerParams
MultiThreadedHttpConnectionManager
PostMethod

If you have a class that processes CC transactions, you can establish a shared http client something like this:

// The HttpClient used for processing transactions
private static HttpClient httpClient;
private static HttpConnectionManagerParams params = new HttpConnectionManagerParams();
private static HttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();

// This runs when the class is initialized
static {
// Configure params for the Connection Manager
params.setDefaultMaxConnectionsPerHost( 20 );
params.setMaxTotalConnections( 30 );

// This next line may not be necessary since we specified default 2 lines ago, but here it is anyway
params.setMaxConnectionsPerHost( HostConfiguration.ANY_HOST_CONFIGURATION, 20 );

// Set up the connection manager
connectionManager.setParams( params );

// Finally set up the static multithreaded HttpClient
httpClient = new HttpClient( connectionManager );
}

To execute a POST method using this httpClient you can use something like this

try {
// Create the POST request
method = new PostMethod( transactionURL );

// Create the POST request body form values
// This methid just uses the method's addParameter method
// to add a series of key/value pairs to the body of the POST HTTP request
AddParametersToPostMethod( (PostMethod)method );

int statusCode = httpClient.executeMethod( method );

String result = method.getResponseBodyAsString();

// Do something with the result here
..........

} catch (Throwable t) {
// Handle errors here. In reality put a number of catch blocks for each type of error expected
} finally {
// Release the connection - IMPORTANT for HttpClient to re-use the connection
method.releaseConnection();
}


I don't want to muddy up this article by going into the threaded processing aspect of it. I'll do that in another article when I get time.

Posted: Wednesday - May 18, 2005 at 10:01 AM        


Published by