Repository: incubator-brooklyn
Updated Branches:
  refs/heads/master f52d9e052 -> 40de86652


HTTP connection pooling for BrooklynApi clients

- introduce factories to create clients
- PoolingBrooklynApiFactory uses PoolingHttpClientConnectionManager
- DefaultBrooklynApiFactory replaces the old BrooklynApi constructors
  using a new ApacheHttpClient4Executor for each client
- deprecate existing BrooklynApi constructors


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/971c217d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/971c217d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/971c217d

Branch: refs/heads/master
Commit: 971c217d220986aece361b312b0793e4239d3d26
Parents: 48e4fe3
Author: googlielmo <[email protected]>
Authored: Wed Nov 4 14:30:05 2015 +0100
Committer: Guglielmo Nigri <[email protected]>
Committed: Wed Nov 4 15:43:12 2015 +0100

----------------------------------------------------------------------
 .../brooklyn/rest/client/BrooklynApi.java       |  52 ++++++++-
 .../rest/client/BrooklynApiFactory.java         |  29 +++++
 .../rest/client/DefaultBrooklynApiFactory.java  |  50 +++++++++
 .../rest/client/PoolingBrooklynApiFactory.java  | 108 +++++++++++++++++++
 .../ApplicationResourceIntegrationTest.java     |   5 +-
 .../rest/client/BrooklynApiRestClientTest.java  |   5 +-
 6 files changed, 245 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/971c217d/usage/rest-client/src/main/java/org/apache/brooklyn/rest/client/BrooklynApi.java
----------------------------------------------------------------------
diff --git 
a/usage/rest-client/src/main/java/org/apache/brooklyn/rest/client/BrooklynApi.java
 
b/usage/rest-client/src/main/java/org/apache/brooklyn/rest/client/BrooklynApi.java
index fa3b7ee..184b659 100644
--- 
a/usage/rest-client/src/main/java/org/apache/brooklyn/rest/client/BrooklynApi.java
+++ 
b/usage/rest-client/src/main/java/org/apache/brooklyn/rest/client/BrooklynApi.java
@@ -33,7 +33,7 @@ import javax.ws.rs.core.Response;
 import org.apache.http.auth.AuthScope;
 import org.apache.http.auth.Credentials;
 import org.apache.http.auth.UsernamePasswordCredentials;
-import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.impl.client.*;
 import org.jboss.resteasy.client.ClientExecutor;
 import org.jboss.resteasy.client.ClientRequest;
 import org.jboss.resteasy.client.ClientResponse;
@@ -76,27 +76,63 @@ public class BrooklynApi {
     private final ClientExecutor clientExecutor;
     private static final Logger LOG = 
LoggerFactory.getLogger(BrooklynApi.class);
 
+    /**
+     * @deprecated since 0.9.0. Use {@link 
BrooklynApiFactory#getBrooklynApi(java.net.URL, String, String)} instead
+     * @see org.apache.brooklyn.rest.client.DefaultBrooklynApiFactory
+     * @see org.apache.brooklyn.rest.client.PoolingBrooklynApiFactory
+     */
+    @Deprecated
     public BrooklynApi(URL endpoint) {
         this(checkNotNull(endpoint, "endpoint").toString());
     }
 
+    /**
+     * @deprecated since 0.9.0. Use {@link 
BrooklynApiFactory#getBrooklynApi(java.net.URL, String, String)} instead
+     * @see org.apache.brooklyn.rest.client.DefaultBrooklynApiFactory
+     * @see org.apache.brooklyn.rest.client.PoolingBrooklynApiFactory
+     */
+    @Deprecated
     public BrooklynApi(String endpoint) {
         // username/password cannot be null, but credentials can
         this(endpoint, null);
     }
 
+    /**
+     * @deprecated since 0.9.0. Use {@link 
BrooklynApiFactory#getBrooklynApi(java.net.URL, String, String)} instead
+     * @see org.apache.brooklyn.rest.client.DefaultBrooklynApiFactory
+     * @see org.apache.brooklyn.rest.client.PoolingBrooklynApiFactory
+     */
+    @Deprecated
     public BrooklynApi(URL endpoint, String username, String password) {
         this(endpoint.toString(), new UsernamePasswordCredentials(username, 
password));
     }
 
+    /**
+     * @deprecated since 0.9.0. Use {@link 
BrooklynApiFactory#getBrooklynApi(java.net.URL, String, String)} instead
+     * @see org.apache.brooklyn.rest.client.DefaultBrooklynApiFactory
+     * @see org.apache.brooklyn.rest.client.PoolingBrooklynApiFactory
+     */
+    @Deprecated
     public BrooklynApi(String endpoint, String username, String password) {
         this(endpoint, new UsernamePasswordCredentials(username, password));
     }
 
+    /**
+     * @deprecated since 0.9.0. Use {@link 
BrooklynApiFactory#getBrooklynApi(java.net.URL, String, String)} instead
+     * @see org.apache.brooklyn.rest.client.DefaultBrooklynApiFactory
+     * @see org.apache.brooklyn.rest.client.PoolingBrooklynApiFactory
+     */
+    @Deprecated
     public BrooklynApi(URL endpoint, @Nullable Credentials credentials) {
         this(endpoint.toString(), credentials);
     }
 
+    /**
+     * @deprecated since 0.9.0. Use {@link 
BrooklynApiFactory#getBrooklynApi(java.net.URL, String, String)} instead
+     * @see org.apache.brooklyn.rest.client.DefaultBrooklynApiFactory
+     * @see org.apache.brooklyn.rest.client.PoolingBrooklynApiFactory
+     */
+    @Deprecated
     public BrooklynApi(String endpoint, @Nullable Credentials credentials) {
         try {
             new URL(checkNotNull(endpoint, "endpoint"));
@@ -114,11 +150,23 @@ public class BrooklynApi {
         }
     }
 
+    /**
+     * @deprecated since 0.9.0. Use {@link 
BrooklynApiFactory#getBrooklynApi(java.net.URL, String, String)} instead
+     * @see org.apache.brooklyn.rest.client.DefaultBrooklynApiFactory
+     * @see org.apache.brooklyn.rest.client.PoolingBrooklynApiFactory
+     */
+    @Deprecated
     public BrooklynApi(URL endpoint, ClientExecutor clientExecutor) {
         this.target = checkNotNull(endpoint, "endpoint").toString();
         this.clientExecutor = checkNotNull(clientExecutor, "clientExecutor");
     }
 
+    // to be used by factories
+    BrooklynApi(ClientExecutor clientExecutor, URL endpoint) {
+        this.target = checkNotNull(endpoint, "endpoint").toString();
+        this.clientExecutor = checkNotNull(clientExecutor, "clientExecutor");
+    }
+
     @SuppressWarnings("unchecked")
     private <T> T proxy(Class<T> clazz) {
         final T result0 = ProxyFactory.create(clazz, target, clientExecutor);
@@ -252,7 +300,7 @@ public class BrooklynApi {
     }
 
     /**
-     * @deprecated Use {@link #getEntity(Response, GenericType)} instead.
+     * @deprecated since 0.9.0. Use {@link #getEntity(Response, GenericType)} 
instead.
      */
     @Deprecated
     public static <T> T getEntityGeneric(Response response, GenericType<T> 
type) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/971c217d/usage/rest-client/src/main/java/org/apache/brooklyn/rest/client/BrooklynApiFactory.java
----------------------------------------------------------------------
diff --git 
a/usage/rest-client/src/main/java/org/apache/brooklyn/rest/client/BrooklynApiFactory.java
 
b/usage/rest-client/src/main/java/org/apache/brooklyn/rest/client/BrooklynApiFactory.java
new file mode 100644
index 0000000..b32c227
--- /dev/null
+++ 
b/usage/rest-client/src/main/java/org/apache/brooklyn/rest/client/BrooklynApiFactory.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.rest.client;
+
+import java.net.URL;
+
+/**
+ * Creates {@link BrooklynApi} instances.
+ */
+public interface BrooklynApiFactory {
+
+    BrooklynApi getBrooklynApi(URL endpoint, String username, String password);
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/971c217d/usage/rest-client/src/main/java/org/apache/brooklyn/rest/client/DefaultBrooklynApiFactory.java
----------------------------------------------------------------------
diff --git 
a/usage/rest-client/src/main/java/org/apache/brooklyn/rest/client/DefaultBrooklynApiFactory.java
 
b/usage/rest-client/src/main/java/org/apache/brooklyn/rest/client/DefaultBrooklynApiFactory.java
new file mode 100644
index 0000000..48e0eeb
--- /dev/null
+++ 
b/usage/rest-client/src/main/java/org/apache/brooklyn/rest/client/DefaultBrooklynApiFactory.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.rest.client;
+
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.jboss.resteasy.client.ClientExecutor;
+import org.jboss.resteasy.client.ClientRequest;
+import org.jboss.resteasy.client.core.executors.ApacheHttpClient4Executor;
+
+import java.net.URL;
+
+/**
+ * BrooklynApi factory.
+ * <p/>
+ * This Factory creates BrooklynApi instances that use an {@link 
ApacheHttpClient4Executor}
+ */
+public class DefaultBrooklynApiFactory implements BrooklynApiFactory {
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public BrooklynApi getBrooklynApi(URL endpoint, String username, String 
password) {
+        ClientExecutor clientExecutor;
+        if (username != null) {
+            DefaultHttpClient httpClient = new DefaultHttpClient();
+            httpClient.getCredentialsProvider().setCredentials(AuthScope.ANY, 
new UsernamePasswordCredentials(username, password));
+            clientExecutor = new ApacheHttpClient4Executor(httpClient);
+        } else {
+            clientExecutor = ClientRequest.getDefaultExecutor();
+        }
+        return new BrooklynApi(clientExecutor, endpoint);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/971c217d/usage/rest-client/src/main/java/org/apache/brooklyn/rest/client/PoolingBrooklynApiFactory.java
----------------------------------------------------------------------
diff --git 
a/usage/rest-client/src/main/java/org/apache/brooklyn/rest/client/PoolingBrooklynApiFactory.java
 
b/usage/rest-client/src/main/java/org/apache/brooklyn/rest/client/PoolingBrooklynApiFactory.java
new file mode 100644
index 0000000..f58f4f5
--- /dev/null
+++ 
b/usage/rest-client/src/main/java/org/apache/brooklyn/rest/client/PoolingBrooklynApiFactory.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.rest.client;
+
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.Credentials;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.jboss.resteasy.client.ClientExecutor;
+import org.jboss.resteasy.client.core.executors.ApacheHttpClient4Executor;
+
+import java.net.URL;
+
+/**
+ * BrooklynApi factory.
+ * <p/>
+ * This Factory uses a {@link PoolingHttpClientConnectionManager} to reuse 
HTTP connections.
+ */
+public class PoolingBrooklynApiFactory implements BrooklynApiFactory {
+
+    private Supplier<PoolingHttpClientConnectionManager> 
connectionManagerSupplier = Suppliers.memoize(new 
Supplier<PoolingHttpClientConnectionManager>() {
+        @Override
+        public PoolingHttpClientConnectionManager get() {
+            PoolingHttpClientConnectionManager connManager = new 
PoolingHttpClientConnectionManager();
+            connManager.setMaxTotal(maxPoolSize);
+            connManager.setDefaultMaxPerRoute(maxPoolSize);
+            return connManager;
+        }
+    });
+
+    private Supplier<RequestConfig> reqConfSupplier = Suppliers.memoize(new 
Supplier<RequestConfig>() {
+        @Override
+        public RequestConfig get() {
+
+            return RequestConfig.custom()
+                    .setConnectTimeout(timeOutInMillis)
+                    .setConnectionRequestTimeout(timeOutInMillis)
+                    .build();
+        }
+    });
+
+    protected final int maxPoolSize;
+    protected final int timeOutInMillis;
+
+    @SuppressWarnings("deprecation")
+    private ClientExecutor getPoolingClientExecutor(Credentials credentials) {
+        CredentialsProvider provider = new BasicCredentialsProvider();
+        provider.setCredentials(AuthScope.ANY, credentials);
+
+        CloseableHttpClient httpClient = HttpClients.custom()
+                .setDefaultCredentialsProvider(provider)
+                .setDefaultRequestConfig(reqConfSupplier.get())
+                .setConnectionManager(connectionManagerSupplier.get())
+                .build();
+
+        return new ApacheHttpClient4Executor(httpClient);
+    }
+
+    /**
+     * Creates a new PoolingBrooklynApiFactory with a max pool size of 20
+     * connections, and a connection timeout of 5000 milliseconds
+     */
+    public PoolingBrooklynApiFactory() {
+        this(20, 5000);
+    }
+
+    /**
+     * Creates a new PoolingBrooklynApiFactory
+     * @param maxPoolSize the maximum size of the pool
+     * @param timeOutInMillis connection timeout in milliseconds
+     */
+    public PoolingBrooklynApiFactory(int maxPoolSize, int timeOutInMillis) {
+        this.maxPoolSize = maxPoolSize;
+        this.timeOutInMillis = timeOutInMillis;
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public BrooklynApi getBrooklynApi(URL endpoint, String username, String 
password) {
+        UsernamePasswordCredentials credentials =
+                (username != null) ? new UsernamePasswordCredentials(username, 
password)
+                        : null;
+        return new BrooklynApi(getPoolingClientExecutor(credentials), 
endpoint);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/971c217d/usage/rest-client/src/test/java/org/apache/brooklyn/rest/client/ApplicationResourceIntegrationTest.java
----------------------------------------------------------------------
diff --git 
a/usage/rest-client/src/test/java/org/apache/brooklyn/rest/client/ApplicationResourceIntegrationTest.java
 
b/usage/rest-client/src/test/java/org/apache/brooklyn/rest/client/ApplicationResourceIntegrationTest.java
index 61facc7..7015113 100644
--- 
a/usage/rest-client/src/test/java/org/apache/brooklyn/rest/client/ApplicationResourceIntegrationTest.java
+++ 
b/usage/rest-client/src/test/java/org/apache/brooklyn/rest/client/ApplicationResourceIntegrationTest.java
@@ -22,6 +22,7 @@ import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.fail;
 
+import java.net.URL;
 import java.util.Collection;
 
 import javax.ws.rs.core.Response;
@@ -88,7 +89,9 @@ public class ApplicationResourceIntegrationTest {
                 .managementContext(getManagementContext())
                 .start();
 
-        api = new BrooklynApi("http://localhost:"; + 
server.getConnectors()[0].getPort() + "/");
+        DefaultBrooklynApiFactory defaultBrooklynApiFactory = new 
DefaultBrooklynApiFactory();
+
+        api = defaultBrooklynApiFactory.getBrooklynApi(new 
URL("http://localhost:"; + server.getConnectors()[0].getPort() + "/"), null, 
null);
     }
 
     @AfterClass(alwaysRun = true)

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/971c217d/usage/rest-client/src/test/java/org/apache/brooklyn/rest/client/BrooklynApiRestClientTest.java
----------------------------------------------------------------------
diff --git 
a/usage/rest-client/src/test/java/org/apache/brooklyn/rest/client/BrooklynApiRestClientTest.java
 
b/usage/rest-client/src/test/java/org/apache/brooklyn/rest/client/BrooklynApiRestClientTest.java
index 62c95b6..abc3bfe 100644
--- 
a/usage/rest-client/src/test/java/org/apache/brooklyn/rest/client/BrooklynApiRestClientTest.java
+++ 
b/usage/rest-client/src/test/java/org/apache/brooklyn/rest/client/BrooklynApiRestClientTest.java
@@ -18,6 +18,7 @@
  */
 package org.apache.brooklyn.rest.client;
 
+import java.net.URL;
 import java.util.List;
 import java.util.Map;
 
@@ -70,7 +71,9 @@ public class BrooklynApiRestClientTest {
                 .securityProvider(TestSecurityProvider.class)
                 .start();
 
-        api = new BrooklynApi("http://localhost:"; + 
server.getConnectors()[0].getPort() + "/",
+        DefaultBrooklynApiFactory defaultBrooklynApiFactory = new 
DefaultBrooklynApiFactory();
+
+        api = defaultBrooklynApiFactory.getBrooklynApi(new 
URL("http://localhost:"; + server.getConnectors()[0].getPort() + "/"),
                 TestSecurityProvider.USER, TestSecurityProvider.PASSWORD);
     }
 

Reply via email to