e-Commerce consultant, specializing in agile project delivery, security and identity management, cloud-based analytics and social media integration. Akber's experience is over two decades of solution delivery, from the AS/400 to J2EE and enterprise architecture. Akber has posted 2 posts at DZone. You can read more from them at their website. View Full User Profile

Fluency and Control with HttpClient

12.11.2012
| 5039 views |
  • submit to reddit

The new HttpClient provides a fluent interface that is quite intuitive.  However, any non-trivial implementation soon starts to miss the flexibility of configuring the connection manager.  As a pre-configured HttpClient can be passed into the fluent Executor each time, it is overhead to configure it each time. 

Here is a sample of a simple fluent Request from the tutorial:

String page = Request.Get("http://somehost/")
     .connectTimeout(1000)
     .socketTimeout(1000)
     .execute().returnContent().asString();

To maintain client-side state (cookies, authentication) between requests, the fluent Executor helps by keeping a cookie store and setting up other types of authentication:

Executor executor = Executor.newInstance()
    .authPreemptive(new HttpHost("myproxy", 8080));
executor.execute(Request.Post("http://somehost/some-form))
    .addHeader("X-Custom-header", "stuff")
    .execute().saveContent(new File("result.dump"));
executor.execute(Request.Get("http://somehost/"))
    .returnContent().asString();

Executor provides a HttpClient constructor but should we be setting one up each time we want to use an Executor 'conversation'.  Extending it in the singleton pattern provided an instance that was configured just once:

Executor executor = Executor.newInstance(OurHttpClient.getInstance());
page = executor.execute(Request . . . . . 
doc = Jsoup.parse(page);
doLogout(excutor);  //passing around the Executor to different methods
executor.clearCookies(); // in case it needs to be cleared

And relevant snippets from the singleton OurHttpClient

private static OurHttpClient instance;
private static PoolingClientConnectionManager cm;

private OurHttpClient(ClientConnectionManager connMgr) { // singleton
    super(connMgr)
}

private static void initialize() { // set up SSL and regular ports with any quirks
    SchemeRegistry . . . . 
    cm = new PoolingClientConnectionManager(schemeRegistry);
    cm.setDefaultMaxPerRoute(MAX_CONNS_ROUTE);
    cm.setMaxTotal(MAX_CONNS_TOTAL);
}


// The public getInstance method
public static OurHttpClient getInstance() {
    if (instance == null) {
        initialize(); // will create the Connection Manager
    }
    instance = new OurHttpClient(cm);  
     // an example of some other customization 
    instance.setRedirectStrategy(new LaxRedirectStrategy());
     // an example of other features being set up
    if (PROXY_HOST != null !"".equals(PROXY_HOST)) {

    }
    return instance;
}

Published at DZone with permission of its author, Akber Choudhry.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)