From 8672609245fac6db5c66a8271faf9865dffaae57 Mon Sep 17 00:00:00 2001 From: Kiran Govindaiah Date: Wed, 14 Sep 2016 18:46:22 +0530 Subject: [PATCH] CAMEL-10317: Added support to use Http synchronous client with Olingo2 Component --- .../api/impl/AbstractFutureCallback.java | 8 +++ .../olingo2/api/impl/Olingo2AppImpl.java | 58 ++++++++++++++++--- .../component/olingo2/Olingo2Component.java | 17 ++++-- .../olingo2/Olingo2Configuration.java | 19 +++++- 4 files changed, 88 insertions(+), 14 deletions(-) diff --git a/components/camel-olingo2/camel-olingo2-api/src/main/java/org/apache/camel/component/olingo2/api/impl/AbstractFutureCallback.java b/components/camel-olingo2/camel-olingo2-api/src/main/java/org/apache/camel/component/olingo2/api/impl/AbstractFutureCallback.java index 0f90d649f8da8..1ad332e4d7469 100644 --- a/components/camel-olingo2/camel-olingo2-api/src/main/java/org/apache/camel/component/olingo2/api/impl/AbstractFutureCallback.java +++ b/components/camel-olingo2/camel-olingo2-api/src/main/java/org/apache/camel/component/olingo2/api/impl/AbstractFutureCallback.java @@ -16,6 +16,7 @@ */ package org.apache.camel.component.olingo2.api.impl; +import java.io.Closeable; import java.io.IOException; import java.util.regex.Pattern; @@ -85,6 +86,13 @@ public final void completed(HttpResponse result) { onCompleted(result); } catch (Exception e) { failed(e); + } finally { + if (result instanceof Closeable) { + try { + ((Closeable) result).close(); + } catch (final IOException ignore) { + } + } } } diff --git a/components/camel-olingo2/camel-olingo2-api/src/main/java/org/apache/camel/component/olingo2/api/impl/Olingo2AppImpl.java b/components/camel-olingo2/camel-olingo2-api/src/main/java/org/apache/camel/component/olingo2/api/impl/Olingo2AppImpl.java index 7f6a80ec901b0..c3caf01fed95b 100644 --- a/components/camel-olingo2/camel-olingo2-api/src/main/java/org/apache/camel/component/olingo2/api/impl/Olingo2AppImpl.java +++ b/components/camel-olingo2/camel-olingo2-api/src/main/java/org/apache/camel/component/olingo2/api/impl/Olingo2AppImpl.java @@ -17,6 +17,7 @@ package org.apache.camel.component.olingo2.api.impl; import java.io.ByteArrayInputStream; +import java.io.Closeable; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; @@ -46,6 +47,7 @@ import org.apache.http.HttpResponse; import org.apache.http.HttpVersion; import org.apache.http.StatusLine; +import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; import org.apache.http.client.methods.HttpGet; @@ -57,12 +59,14 @@ import org.apache.http.entity.ContentType; import org.apache.http.entity.InputStreamEntity; import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.nio.client.CloseableHttpAsyncClient; import org.apache.http.impl.nio.client.HttpAsyncClientBuilder; import org.apache.http.impl.nio.client.HttpAsyncClients; import org.apache.http.message.BasicHttpResponse; import org.apache.http.message.BasicStatusLine; -import org.apache.http.nio.client.util.HttpAsyncClientUtils; import org.apache.olingo.odata2.api.ODataServiceVersion; import org.apache.olingo.odata2.api.batch.BatchException; import org.apache.olingo.odata2.api.client.batch.BatchChangeSet; @@ -111,7 +115,10 @@ public final class Olingo2AppImpl implements Olingo2App { private static final String MULTIPART_MIME_TYPE = "multipart/"; private static final ContentType TEXT_PLAIN_WITH_CS_UTF_8 = ContentType.TEXT_PLAIN.withCharset(Consts.UTF_8); - private final CloseableHttpAsyncClient client; + /** + * Reference to CloseableHttpAsyncClient (default) or CloseableHttpClient + */ + private final Closeable client; private String serviceUri; private ContentType contentType; @@ -121,11 +128,12 @@ public final class Olingo2AppImpl implements Olingo2App { * Create Olingo2 Application with default HTTP configuration. */ public Olingo2AppImpl(String serviceUri) { - this(serviceUri, null); + // By default create HTTP Asynchronous client + this(serviceUri, (HttpAsyncClientBuilder) null); } /** - * Create Olingo2 Application with custom HTTP client builder. + * Create Olingo2 Application with custom HTTP Asynchronous client builder. * * @param serviceUri Service Application base URI. * @param builder custom HTTP client builder. @@ -133,12 +141,30 @@ public Olingo2AppImpl(String serviceUri) { public Olingo2AppImpl(String serviceUri, HttpAsyncClientBuilder builder) { setServiceUri(serviceUri); + CloseableHttpAsyncClient asyncClient; + if (builder == null) { + asyncClient = HttpAsyncClients.createDefault(); + } else { + asyncClient = builder.build(); + } + asyncClient.start(); + this.client = asyncClient; + this.contentType = ContentType.create("application/json", Consts.UTF_8); + } + + /** + * Create Olingo2 Application with custom HTTP Synchronous client builder. + * + * @param serviceUri Service Application base URI. + * @param builder Custom HTTP Synchronous client builder. + */ + public Olingo2AppImpl(String serviceUri, HttpClientBuilder builder) { + setServiceUri(serviceUri); if (builder == null) { - this.client = HttpAsyncClients.createDefault(); + this.client = HttpClients.createDefault(); } else { this.client = builder.build(); } - this.client.start(); this.contentType = ContentType.create("application/json", Consts.UTF_8); } @@ -178,7 +204,12 @@ public void setContentType(String contentType) { @Override public void close() { - HttpAsyncClientUtils.closeQuietly(client); + if (client != null) { + try { + client.close(); + } catch (final IOException ignore) { + } + } } @Override @@ -1003,7 +1034,18 @@ public void execute(HttpUriRequest httpUriRequest, ContentType contentType, } // execute request - client.execute(httpUriRequest, callback); + if (client instanceof CloseableHttpAsyncClient) { + ((CloseableHttpAsyncClient) client).execute(httpUriRequest, callback); + } else { + // invoke the callback methods explicitly after executing the + // request synchronously + try { + CloseableHttpResponse result = ((CloseableHttpClient) client).execute(httpUriRequest); + callback.completed(result); + } catch (IOException e) { + callback.failed(e); + } + } } } diff --git a/components/camel-olingo2/camel-olingo2-component/src/main/java/org/apache/camel/component/olingo2/Olingo2Component.java b/components/camel-olingo2/camel-olingo2-component/src/main/java/org/apache/camel/component/olingo2/Olingo2Component.java index 0a6a0e831ea56..ce950fd79edfc 100644 --- a/components/camel-olingo2/camel-olingo2-component/src/main/java/org/apache/camel/component/olingo2/Olingo2Component.java +++ b/components/camel-olingo2/camel-olingo2-component/src/main/java/org/apache/camel/component/olingo2/Olingo2Component.java @@ -30,6 +30,7 @@ import org.apache.camel.util.jsse.SSLContextParameters; import org.apache.http.HttpHost; import org.apache.http.client.config.RequestConfig; +import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.nio.client.HttpAsyncClientBuilder; /** @@ -124,9 +125,9 @@ public Olingo2AppWrapper createApiProxy(Olingo2Configuration endpointConfigurati private Olingo2AppWrapper createOlingo2App(Olingo2Configuration configuration) { - HttpAsyncClientBuilder clientBuilder = configuration.getHttpAsyncClientBuilder(); + Object clientBuilder = configuration.getHttpAsyncClientBuilder(); if (clientBuilder == null) { - clientBuilder = HttpAsyncClientBuilder.create(); + HttpAsyncClientBuilder asyncClientBuilder = HttpAsyncClientBuilder.create(); // apply simple configuration properties final RequestConfig.Builder requestConfigBuilder = RequestConfig.custom(); @@ -139,7 +140,7 @@ private Olingo2AppWrapper createOlingo2App(Olingo2Configuration configuration) { } // set default request config - clientBuilder.setDefaultRequestConfig(requestConfigBuilder.build()); + asyncClientBuilder.setDefaultRequestConfig(requestConfigBuilder.build()); SSLContextParameters sslContextParameters = configuration.getSslContextParameters(); if (sslContextParameters == null) { @@ -147,7 +148,7 @@ private Olingo2AppWrapper createOlingo2App(Olingo2Configuration configuration) { sslContextParameters = new SSLContextParameters(); } try { - clientBuilder.setSSLContext(sslContextParameters.createSSLContext(getCamelContext())); + asyncClientBuilder.setSSLContext(sslContextParameters.createSSLContext(getCamelContext())); } catch (GeneralSecurityException e) { throw ObjectHelper.wrapRuntimeCamelException(e); } catch (IOException e) { @@ -155,7 +156,13 @@ private Olingo2AppWrapper createOlingo2App(Olingo2Configuration configuration) { } } - apiProxy = new Olingo2AppWrapper(new Olingo2AppImpl(configuration.getServiceUri(), clientBuilder)); + Olingo2AppImpl olingo2App; + if (clientBuilder == null || clientBuilder instanceof HttpAsyncClientBuilder) { + olingo2App = new Olingo2AppImpl(configuration.getServiceUri(), (HttpAsyncClientBuilder) clientBuilder); + } else { + olingo2App = new Olingo2AppImpl(configuration.getServiceUri(), (HttpClientBuilder) clientBuilder); + } + apiProxy = new Olingo2AppWrapper(olingo2App); apiProxy.getOlingo2App().setContentType(configuration.getContentType()); apiProxy.getOlingo2App().setHttpHeaders(configuration.getHttpHeaders()); diff --git a/components/camel-olingo2/camel-olingo2-component/src/main/java/org/apache/camel/component/olingo2/Olingo2Configuration.java b/components/camel-olingo2/camel-olingo2-component/src/main/java/org/apache/camel/component/olingo2/Olingo2Configuration.java index e383941caea80..d2fa8700e5c2b 100644 --- a/components/camel-olingo2/camel-olingo2-component/src/main/java/org/apache/camel/component/olingo2/Olingo2Configuration.java +++ b/components/camel-olingo2/camel-olingo2-component/src/main/java/org/apache/camel/component/olingo2/Olingo2Configuration.java @@ -27,6 +27,7 @@ import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.http.HttpHost; import org.apache.http.entity.ContentType; +import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.nio.client.HttpAsyncClientBuilder; /** @@ -59,6 +60,8 @@ public class Olingo2Configuration { private SSLContextParameters sslContextParameters; @UriParam private HttpAsyncClientBuilder httpAsyncClientBuilder; + @UriParam + private HttpClientBuilder httpClientBuilder; public Olingo2ApiName getApiName() { return apiName; @@ -171,6 +174,18 @@ public void setHttpAsyncClientBuilder(HttpAsyncClientBuilder httpAsyncClientBuil this.httpAsyncClientBuilder = httpAsyncClientBuilder; } + public HttpClientBuilder getHttpClientBuilder() { + return httpClientBuilder; + } + + /** + * Custom HTTP client builder for more complex HTTP client configuration, overrides connectionTimeout, socketTimeout, proxy and sslContext. + * Note that a socketTimeout MUST be specified in the builder, otherwise OData requests could block indefinitely + */ + public void setHttpClientBuilder(HttpClientBuilder httpClientBuilder) { + this.httpClientBuilder = httpClientBuilder; + } + @Override public int hashCode() { return new HashCodeBuilder() @@ -182,6 +197,7 @@ public int hashCode() { .append(proxy) .append(sslContextParameters) .append(httpAsyncClientBuilder) + .append(httpClientBuilder) .hashCode(); } @@ -197,7 +213,8 @@ public boolean equals(Object obj) { && proxy == null ? other.proxy == null : proxy.equals(other.proxy) && sslContextParameters == null ? other.sslContextParameters == null : sslContextParameters.equals(other.sslContextParameters) && httpAsyncClientBuilder == null ? other.httpAsyncClientBuilder == null - : httpAsyncClientBuilder.equals(other.httpAsyncClientBuilder); + : httpAsyncClientBuilder.equals(other.httpAsyncClientBuilder) + && httpClientBuilder == null ? other.httpClientBuilder == null : httpClientBuilder.equals(other.httpClientBuilder); } return false; }