1

We have a custom implementation of Spring's CommonsHttpInvokerRequestExecutor. Now, we wish to upgrade from httpclient 3.1 to httpclient 4.3.3, so I need to implement HttpComponentsHttpInvokerRequestExecutor instead.

However, the API is so different that I have been stuck on two points for a while now (I am new to httpclient, both 3 and 4, but I make my way using the API docs).

Does somebody have a clue on how to change this:

public CustomCommonsHttpInvokerRequestExecutor() {
    super();
    // No retry.
    getHttpClient().getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler(0, false));
}

@Override
protected void executePostMethod(final HttpInvokerClientConfiguration config, final HttpClient httpClient, final PostMethod postMethod) throws IOException {
    HttpState state = ((CustomHttpInvokerClientConfiguration) config).getState();
    if (state.getCredentials(AuthScope.ANY) != null) {
        postMethod.setDoAuthentication(true);
        httpClient.getParams().setAuthenticationPreemptive(true);
        httpClient.getState().setCredentials(AuthScope.ANY, state.getCredentials(AuthScope.ANY));
    } else {
        httpClient.getParams().setAuthenticationPreemptive(false);
    }
    httpClient.executeMethod(null, postMethod, state);
}

to this:

public CustomHttpComponentsHttpInvokerRequestExecutor() {
    super();
    // FIXME default: no retry
    // HttpClient client = getHttpClient();
}

@Override
protected HttpResponse executeHttpPost(final HttpInvokerClientConfiguration config, final HttpClient httpClient,
        final HttpPost httpPost) throws IOException {
    // FIXME Implement
    // get credentials with AuthScope.ANY
    // if (not null) {
    // preemptive authentication
    // } else {
    // HTTP authentication preemptive is not supported by default
    // The else should not be needed
    // }

    return super.executeHttpPost(config, httpClient, httpPost);
}
  • Concerning the 'no retry' problematic, most examples I have seen just assume the implementation of HttpClient and do a savage cast, which I would try to avoid.
  • Concerning the 'preemptive authentication' topic, since it is not supported natively anymore, I have searched and found examples on how to set it as always active, but no case such as in my own case.

Any help or lead greatly appreciated.

Chop
  • 4,267
  • 5
  • 26
  • 58
  • https://hc.apache.org/httpcomponents-client-4.3.x/examples.html check the examples closely for analog to your old 3.1 methods. Look at all the 'authentication' samples and look at "httpclient config" . – Robert Rowntree Dec 08 '14 at 14:52
  • Did that already, but I could not find an analog. The major problem is that I am not writing my own class, I am extending Spring's provided invokers. – Chop Dec 08 '14 at 18:32
  • interfaces in 4.3.5 are very DIFF from 3.1. If i were u i would pore over the new samples for methods that smell anything like your old spring signatures in the 3.1 version. – Robert Rowntree Dec 08 '14 at 18:48

1 Answers1

0

So, after discussing the problem from a more global point of view (How to update the settings of an HttpClient in httpclient 4.3+?), here is what I came up with (not totally finished, but the missing interceptor should not be that hard to implement, thanks to Preemptive Basic authentication with Apache HttpClient 4).

/* Copied from HttpComponentsHttpInvokerRequestExecutor */
private static final int DEFAULT_MAX_TOTAL_CONNECTIONS = 100;
private static final int DEFAULT_MAX_CONNECTIONS_PER_ROUTE = 5;
private static final int DEFAULT_READ_TIMEOUT_MILLISECONDS = (60 * 1000);

public CustomHttpComponentsHttpInvokerRequestExecutor() {
    super(makeDefaultHttpClient());
    setReadTimeout(DEFAULT_READ_TIMEOUT_MILLISECONDS);
}

private static HttpClient makeDefaultHttpClient() {
    // New non-deprecated ConnectionManager with same settings as super()
    PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
    connectionManager.setMaxTotal(DEFAULT_MAX_TOTAL_CONNECTIONS);
    connectionManager.setDefaultMaxPerRoute(DEFAULT_MAX_CONNECTIONS_PER_ROUTE);

    // HttpClient with ConnectionManager and no retry
    /*
     * TODO Add a request interceptor that will authenticate 
     * if credentials with AuthScope.ANY are provided.
     */
    HttpClient httpClient = HttpClientBuilder.create().setConnectionManager(connectionManager)
            .setRetryHandler(new DefaultHttpRequestRetryHandler(0, false)).build();
    return httpClient;
}

@Override
protected HttpPost createHttpPost(final HttpInvokerClientConfiguration config) throws IOException {
    HttpPost httpPost = super.createHttpPost(config);

    // Set the timeout for this request if it exists.
    Integer timeout = ((CustomHttpInvokerClientConfiguration) config).getReadTimeout();
    if (timeout != null) {
        RequestConfig rConfig = RequestConfig.copy(httpPost.getConfig()).setSocketTimeout(timeout).build();
        httpPost.setConfig(rConfig);
    }

    return httpPost;
}

As always, I will be interested in any feedback you might have.

Community
  • 1
  • 1
Chop
  • 4,267
  • 5
  • 26
  • 58