Author: davsclaus
Date: Sat Dec 15 11:34:58 2012
New Revision: 1422224

URL: http://svn.apache.org/viewvc?rev=1422224&view=rev
Log:
CAMEL-5687: Fixed jetty to not always create a http client, even if a producer 
is newer in use. Removed the danger of using shared http clients, which makes 
lifecycle of these harder. Instead made it easier to configure individual http 
client thread pool sizes per endpoint instead.

Modified:
    
camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java
    
camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyHttpEndpoint.java
    
camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyHttpProducer.java

Modified: 
camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java?rev=1422224&r1=1422223&r2=1422224&view=diff
==============================================================================
--- 
camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java
 (original)
+++ 
camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java
 Sat Dec 15 11:34:58 2012
@@ -59,7 +59,6 @@ import org.eclipse.jetty.servlet.FilterH
 import org.eclipse.jetty.servlet.ServletContextHandler;
 import org.eclipse.jetty.servlet.ServletHolder;
 import org.eclipse.jetty.servlets.MultiPartFilter;
-import org.eclipse.jetty.util.component.LifeCycle;
 import org.eclipse.jetty.util.thread.QueuedThreadPool;
 import org.eclipse.jetty.util.thread.ThreadPool;
 import org.slf4j.Logger;
@@ -88,8 +87,6 @@ public class JettyHttpComponent extends 
     protected Map<Integer, SelectChannelConnector> socketConnectors;
     protected Map<String, Object> sslSocketConnectorProperties;
     protected Map<String, Object> socketConnectorProperties;
-    protected HttpClient httpClient;
-    protected ThreadPool httpClientThreadPool;
     protected Integer httpClientMinThreads;
     protected Integer httpClientMaxThreads;
     protected Integer minThreads;
@@ -101,7 +98,6 @@ public class JettyHttpComponent extends 
     protected Long continuationTimeout;
     protected boolean useContinuation = true;
     protected SSLContextParameters sslContextParameters;
-    protected boolean isExplicitHttpClient;
 
     class ConnectorRef {
         Server server;
@@ -150,44 +146,24 @@ public class JettyHttpComponent extends 
         Boolean useContinuation = getAndRemoveParameter(parameters, 
"useContinuation", Boolean.class);
         String httpMethodRestrict = getAndRemoveParameter(parameters, 
"httpMethodRestrict", String.class);
         SSLContextParameters sslContextParameters = 
resolveAndRemoveReferenceParameter(parameters, "sslContextParametersRef", 
SSLContextParameters.class);
-        
-        
+        SSLContextParameters ssl = sslContextParameters != null ? 
sslContextParameters : this.sslContextParameters;
+
         // configure http client if we have url configuration for it
         // http client is only used for jetty http producer (hence not very 
commonly used)
         HttpClient client = null;
         if (IntrospectionSupport.hasProperties(parameters, "httpClient.") || 
sslContextParameters != null) {
-            client = getNewHttpClient();
-            
+            client = createHttpClient(httpClientMinThreads, 
httpClientMaxThreads, ssl);
+
             if (IntrospectionSupport.hasProperties(parameters, "httpClient.")) 
{
-                if (isExplicitHttpClient) {
-                    LOG.warn("The user explicitly set an HttpClient instance 
on the component, "
-                             + "but this endpoint provides HttpClient 
configuration.  Are you sure that "
-                             + "this is what was intended?  Applying endpoint 
configuration to a new HttpClient instance "
-                             + "to avoid altering existing HttpClient 
instances.");
-                }
-            
                 // set additional parameters on http client
                 IntrospectionSupport.setProperties(client, parameters, 
"httpClient.");
                 // validate that we could resolve all httpClient. parameters 
as this component is lenient
                 validateParameters(uri, parameters, "httpClient.");
             }
             
-            // Note that the component level instance is already configured in 
getNewHttpClient.
-            // We replace it here for endpoint level config.
-            if (sslContextParameters != null) {
-                if (isExplicitHttpClient) {
-                    LOG.warn("The user explicitly set an HttpClient instance 
on the component, "
-                             + "but this endpoint provides 
SSLContextParameters configuration.  Are you sure that "
-                             + "this is what was intended?  Applying endpoint 
configuration to a new HttpClient instance "
-                             + "to avoid altering existing HttpClient 
instances.");
-                }
-                
-                ((CamelHttpClient) 
client).setSSLContext(sslContextParameters.createSSLContext());
+            if (ssl != null) {
+                ((CamelHttpClient) 
client).setSSLContext(ssl.createSSLContext());
             }
-        } else {
-            // Either we use the default one created by the component or we 
are using
-            // one explicitly set by the end user, either way, we just use it 
as is.
-            client = getHttpClient();
         }
         // keep the configure parameters for the http client
         for (String key : parameters.keySet()) {
@@ -247,12 +223,10 @@ public class JettyHttpComponent extends 
         }
         
         endpoint.setEnableMultipartFilter(enableMultipartFilter);
-        
         if (multipartFilter != null) {
             endpoint.setMultipartFilter(multipartFilter);
             endpoint.setEnableMultipartFilter(true);
         }
-        
         if (filters != null) {
             endpoint.setFilters(filters);
         }
@@ -263,15 +237,12 @@ public class JettyHttpComponent extends 
         if (useContinuation != null) {
             endpoint.setUseContinuation(useContinuation);
         }
-
         if (httpMethodRestrict != null) {
             endpoint.setHttpMethodRestrict(httpMethodRestrict);
         }
-        
-        if (sslContextParameters == null) {
-            sslContextParameters = this.sslContextParameters;
+        if (ssl != null) {
+            endpoint.setSslContextParameters(ssl);
         }
-        endpoint.setSslContextParameters(sslContextParameters);
 
         setProperties(endpoint, parameters);
         return endpoint;
@@ -648,14 +619,15 @@ public class JettyHttpComponent extends 
         this.socketConnectors = socketConnectors;
     }
 
-    public synchronized HttpClient getHttpClient() throws Exception {
-        if (httpClient == null) {
-            httpClient = this.getNewHttpClient();
-        }
-        return httpClient;
-    }
-    
-    public CamelHttpClient getNewHttpClient() throws Exception {
+    /**
+     * Creates a new {@link HttpClient} and configures its proxy/thread pool 
and SSL based on this
+     * component settings.
+     *
+     * @param minThreads optional minimum number of threads in client thread 
pool
+     * @param maxThreads optional maximum number of threads in client thread 
pool
+     * @param ssl        option SSL parameters
+     */
+    public static CamelHttpClient createHttpClient(Integer minThreads, Integer 
maxThreads, SSLContextParameters ssl) throws Exception {
         CamelHttpClient httpClient = new CamelHttpClient();
         httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
 
@@ -668,15 +640,18 @@ public class JettyHttpComponent extends 
             httpClient.setProxy(new Address(host, port));
         }
 
-        // use QueueThreadPool as the default bounded is deprecated (see 
SMXCOMP-157)
-        if (getHttpClientThreadPool() == null) {
-            QueuedThreadPool qtp = new QueuedThreadPool();
-            if (httpClientMinThreads != null) {
-                qtp.setMinThreads(httpClientMinThreads.intValue());
-            }
-            if (httpClientMaxThreads != null) {
-                qtp.setMaxThreads(httpClientMaxThreads.intValue());
+        // must have both min and max
+        if (minThreads != null || maxThreads != null) {
+
+            // must have both options
+            if (minThreads == null || maxThreads == null) {
+                throw new IllegalArgumentException("Both min and max thread 
pool sizes must be provided.");
             }
+
+            // use QueueThreadPool as the default bounded is deprecated (see 
SMXCOMP-157)
+            QueuedThreadPool qtp = new QueuedThreadPool();
+            qtp.setMinThreads(minThreads.intValue());
+            qtp.setMaxThreads(maxThreads.intValue());
             // let the thread names indicate they are from the client
             qtp.setName("CamelJettyClient(" + 
ObjectHelper.getIdentityHashCode(httpClient) + ")");
             try {
@@ -684,32 +659,22 @@ public class JettyHttpComponent extends 
             } catch (Exception e) {
                 throw new RuntimeCamelException("Error starting 
JettyHttpClient thread pool: " + qtp, e);
             }
-            setHttpClientThreadPool(qtp);
+            httpClient.setThreadPool(qtp);
         }
-        httpClient.setThreadPool(getHttpClientThreadPool());
-        
-        if (this.sslContextParameters != null) {
-            
httpClient.setSSLContext(this.sslContextParameters.createSSLContext());
-        }
-        
-        return httpClient;
-    }
 
-    public void setHttpClient(HttpClient httpClient) {
-        if (httpClient != null) {
-            this.isExplicitHttpClient = true;
-        } else {
-            this.isExplicitHttpClient = false;
+        if (ssl != null) {
+            httpClient.setSSLContext(ssl.createSSLContext());
         }
-        this.httpClient = httpClient;
-    }
-
-    public ThreadPool getHttpClientThreadPool() {
-        return httpClientThreadPool;
-    }
 
-    public void setHttpClientThreadPool(ThreadPool httpClientThreadPool) {
-        this.httpClientThreadPool = httpClientThreadPool;
+        if (LOG.isDebugEnabled()) {
+            if (minThreads != null) {
+                LOG.debug("Created HttpClient with thread pool {}-{} -> {}", 
new Object[]{minThreads, maxThreads, httpClient});
+            } else {
+                LOG.debug("Created HttpClient with default thread pool size -> 
{}", httpClient);
+            }
+        }
+        
+        return httpClient;
     }
 
     public Integer getHttpClientMinThreads() {
@@ -953,14 +918,6 @@ public class JettyHttpComponent extends 
     @Override
     protected void doStart() throws Exception {
         super.doStart();
-        if (httpClientThreadPool != null && httpClientThreadPool instanceof 
LifeCycle) {
-            LifeCycle lc = (LifeCycle) httpClientThreadPool;
-            lc.start();
-        }
-        if (httpClient != null && !httpClient.isStarted()) {
-            httpClient.start();
-        }
-        
         startMbContainer();
     }
 
@@ -984,15 +941,9 @@ public class JettyHttpComponent extends 
                 }
             }
         }
-        if (httpClient != null) {
-            httpClient.stop();
-        }
-        if (httpClientThreadPool != null && httpClientThreadPool instanceof 
LifeCycle) {
-            LifeCycle lc = (LifeCycle) httpClientThreadPool;
-            lc.stop();
-        }
         if (mbContainer != null) {
             mbContainer.stop();
+            mbContainer = null;
         }
     }
 }

Modified: 
camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyHttpEndpoint.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyHttpEndpoint.java?rev=1422224&r1=1422223&r2=1422224&view=diff
==============================================================================
--- 
camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyHttpEndpoint.java
 (original)
+++ 
camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyHttpEndpoint.java
 Sat Dec 15 11:34:58 2012
@@ -19,7 +19,6 @@ package org.apache.camel.component.jetty
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.List;
-
 import javax.servlet.Filter;
 
 import org.apache.camel.Consumer;
@@ -40,6 +39,8 @@ public class JettyHttpEndpoint extends H
     private boolean sessionSupport;
     private List<Handler> handlers;
     private HttpClient client;
+    private Integer httpClientMinThreads;
+    private Integer httpClientMaxThreads;
     private JettyHttpBinding jettyBinding;
     private boolean enableJmx;
     private boolean enableMultipartFilter;
@@ -60,7 +61,17 @@ public class JettyHttpEndpoint extends H
 
     @Override
     public Producer createProducer() throws Exception {
-        JettyHttpProducer answer = new JettyHttpProducer(this, getClient());
+        JettyHttpProducer answer = new JettyHttpProducer(this);
+        if (client != null) {
+            // use shared client
+            answer.setSharedClient(client);
+        } else {
+            // create a new client
+            // thread pool min/max from endpoint take precedence over from 
component
+            Integer min = httpClientMinThreads != null ? httpClientMinThreads 
: getComponent().getHttpClientMinThreads();
+            Integer max = httpClientMaxThreads != null ? httpClientMaxThreads 
: getComponent().getHttpClientMaxThreads();
+            answer.setClient(JettyHttpComponent.createHttpClient(min, max, 
sslContextParameters));
+        }
         answer.setBinding(getJettyBinding());
         if (isSynchronous()) {
             return new SynchronousDelegateProducer(answer);
@@ -91,12 +102,16 @@ public class JettyHttpEndpoint extends H
     }
 
     public HttpClient getClient() throws Exception {
-        if (client == null) {
-            return getComponent().getHttpClient();
-        }
         return client;
     }
 
+    /**
+     * Sets a shared {@link HttpClient} to use for all producers
+     * created by this endpoint. By default each producer will
+     * use a new http client, and not share.
+     * <p/>
+     * This options should only be used in special circumstances.
+     */
     public void setClient(HttpClient client) {
         this.client = client;
     }
@@ -170,4 +185,20 @@ public class JettyHttpEndpoint extends H
     public void setSslContextParameters(SSLContextParameters 
sslContextParameters) {
         this.sslContextParameters = sslContextParameters;
     }
+
+    @Override
+    protected void doStart() throws Exception {
+        if (client != null) {
+            client.start();
+        }
+        super.doStart();
+    }
+
+    @Override
+    protected void doStop() throws Exception {
+        super.doStop();
+        if (client != null) {
+            client.stop();
+        }
+    }
 }

Modified: 
camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyHttpProducer.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyHttpProducer.java?rev=1422224&r1=1422223&r2=1422224&view=diff
==============================================================================
--- 
camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyHttpProducer.java
 (original)
+++ 
camel/trunk/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyHttpProducer.java
 Sat Dec 15 11:34:58 2012
@@ -52,13 +52,31 @@ import org.slf4j.LoggerFactory;
  */
 public class JettyHttpProducer extends DefaultProducer implements 
AsyncProcessor {
     private static final transient Logger LOG = 
LoggerFactory.getLogger(JettyHttpProducer.class);
-    private final HttpClient client;
+    private HttpClient client;
+    private boolean sharedClient;
     private JettyHttpBinding binding;
 
+    /**
+     * Creates this producer.
+     * <p/>
+     * A client must be set before use, eg either {@link 
#setClient(org.eclipse.jetty.client.HttpClient)}
+     * or {@link #setSharedClient(org.eclipse.jetty.client.HttpClient)}.
+     *
+     * @param endpoint  the endpoint
+     */
+    public JettyHttpProducer(Endpoint endpoint) {
+        super(endpoint);
+    }
+
+    /**
+     * Creates this producer
+     *
+     * @param endpoint  the endpoint
+     * @param client    the non-shared client to use
+     */
     public JettyHttpProducer(Endpoint endpoint, HttpClient client) {
         super(endpoint);
-        this.client = client;
-        ObjectHelper.notNull(client, "HttpClient", this);
+        setClient(client);
     }
 
     @Override
@@ -240,15 +258,43 @@ public class JettyHttpProducer extends D
         this.binding = binding;
     }
 
+    public HttpClient getClient() {
+        return client;
+    }
+
+    public void setClient(HttpClient client) {
+        this.client = client;
+        this.sharedClient = false;
+    }
+
+    public HttpClient getSharedClient() {
+        if (sharedClient) {
+            return client;
+        } else {
+            return null;
+        }
+    }
+
+    public void setSharedClient(HttpClient sharedClient) {
+        this.client = sharedClient;
+        this.sharedClient = true;
+    }
+
     @Override
     protected void doStart() throws Exception {
-        client.start();
+        // only start non-shared client
+        if (!sharedClient && client != null) {
+            client.start();
+        }
         super.doStart();
     }
 
     @Override
     protected void doStop() throws Exception {
         super.doStop();
-        client.stop();
+        // only stop non-shared client
+        if (!sharedClient && client != null) {
+            client.stop();
+        }
     }
 }


Reply via email to