CAMEL-10392: HTTP session handling in Camel routes

Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/e607dc3f
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/e607dc3f
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/e607dc3f

Branch: refs/heads/master
Commit: e607dc3f116a4983306fa517300e1f3123945f79
Parents: 2c7c11a
Author: Stephan Siano <stephan.si...@sap.com>
Authored: Fri Oct 14 11:32:06 2016 +0200
Committer: Stephan Siano <stephan.si...@sap.com>
Committed: Thu Oct 20 08:48:36 2016 +0200

----------------------------------------------------------------------
 .../main/java/org/apache/camel/Exchange.java    |   1 +
 components/camel-ahc/pom.xml                    |   4 +
 .../camel-ahc/src/main/docs/ahc-component.adoc  |   3 +-
 .../apache/camel/component/ahc/AhcEndpoint.java |  14 ++
 .../camel/component/ahc/DefaultAhcBinding.java  |  38 ++++-
 .../component/ahc/AhcProducerSessionTest.java   | 111 +++++++++++++++
 components/camel-cxf/pom.xml                    |   4 +
 .../camel-cxf/src/main/docs/cxf-component.adoc  |   3 +-
 .../src/main/docs/cxfrs-component.adoc          |   3 +-
 .../camel/component/cxf/CxfClientCallback.java  |  32 ++++-
 .../apache/camel/component/cxf/CxfEndpoint.java |  33 +++++
 .../apache/camel/component/cxf/CxfProducer.java |  39 ++++-
 .../component/cxf/jaxrs/CxfRsEndpoint.java      |  12 ++
 .../component/cxf/jaxrs/CxfRsProducer.java      |  47 +++++-
 .../component/cxf/CxfProducerSessionTest.java   | 142 +++++++++++++++++++
 .../apache/camel/component/cxf/EchoService.java |  24 ++++
 .../component/cxf/EchoServiceSessionImpl.java   |  43 ++++++
 .../cxf/jaxrs/CxfRsProducerSessionTest.java     | 116 +++++++++++++++
 .../cxf/jaxrs/testbean/EchoService.java         |  41 ++++++
 .../cxf/jaxrs/CxfRsSpringProducerSession.xml    |  90 ++++++++++++
 .../camel/http/common/HttpCommonEndpoint.java   |  14 ++
 .../http/common/cookie/BaseCookieHandler.java   |  53 +++++++
 .../camel/http/common/cookie/CookieHandler.java |  67 +++++++++
 .../common/cookie/ExchangeCookieHandler.java    |  43 ++++++
 .../common/cookie/InstanceCookieHandler.java    |  39 +++++
 .../src/main/docs/http-component.adoc           |   3 +-
 .../camel/component/http/HttpProducer.java      |  38 ++++-
 .../component/http/HttpProducerSessionTest.java | 117 +++++++++++++++
 .../http/handler/SessionReflectionHandler.java  |  47 ++++++
 components/camel-http4/pom.xml                  |   6 +
 .../src/main/docs/http4-component.adoc          |   5 +-
 .../camel/component/http4/HttpEndpoint.java     |   9 ++
 .../camel/component/http4/HttpProducer.java     |  30 +++-
 .../http4/HttpProducerSessionTest.java          | 117 +++++++++++++++
 .../http4/handler/SessionReflectionHandler.java |  47 ++++++
 .../component/jetty/JettyHttpEndpoint.java      |  14 ++
 .../component/jetty/JettyHttpProducer.java      |  12 +-
 .../src/main/docs/jetty-component.adoc          |   3 +-
 .../JettyHttpProducerSessionTest.java           | 120 ++++++++++++++++
 components/camel-netty4-http/pom.xml            |  11 +-
 .../src/main/docs/netty4-http-component.adoc    |   3 +-
 .../netty4/http/NettyHttpEndpoint.java          |  14 ++
 .../netty4/http/NettyHttpProducer.java          |  13 +-
 .../http/handlers/HttpClientChannelHandler.java |  16 ++-
 .../http/NettyHttpProducerSessionTest.java      | 111 +++++++++++++++
 components/camel-restlet/pom.xml                |   4 +
 .../src/main/docs/restlet-component.adoc        |   3 +-
 .../component/restlet/RestletEndpoint.java      |  14 ++
 .../component/restlet/RestletProducer.java      |  50 +++++++
 .../restlet/RestletProducerSessionTest.java     | 107 ++++++++++++++
 components/camel-undertow/pom.xml               |   4 +
 .../src/main/docs/undertow-component.adoc       |   3 +-
 .../component/undertow/UndertowEndpoint.java    |  14 ++
 .../component/undertow/UndertowProducer.java    |  32 +++++
 .../UndertowHttpProducerSessionTest.java        | 120 ++++++++++++++++
 55 files changed, 2074 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/e607dc3f/camel-core/src/main/java/org/apache/camel/Exchange.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/Exchange.java 
b/camel-core/src/main/java/org/apache/camel/Exchange.java
index 0a00d18..b23da1a 100644
--- a/camel-core/src/main/java/org/apache/camel/Exchange.java
+++ b/camel-core/src/main/java/org/apache/camel/Exchange.java
@@ -100,6 +100,7 @@ public interface Exchange {
     String CONTENT_ENCODING      = "Content-Encoding";
     String CONTENT_LENGTH        = "Content-Length";
     String CONTENT_TYPE          = "Content-Type";
+    String COOKIE_HANDLER        = "CamelCookieHandler";
     String CORRELATION_ID        = "CamelCorrelationId";
 
     String DATASET_INDEX             = "CamelDataSetIndex";

http://git-wip-us.apache.org/repos/asf/camel/blob/e607dc3f/components/camel-ahc/pom.xml
----------------------------------------------------------------------
diff --git a/components/camel-ahc/pom.xml b/components/camel-ahc/pom.xml
index 7c423c9..c1d98da 100644
--- a/components/camel-ahc/pom.xml
+++ b/components/camel-ahc/pom.xml
@@ -41,6 +41,10 @@
       <artifactId>camel-core</artifactId>
     </dependency>
     <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-http-common</artifactId>
+    </dependency>
+    <dependency>
       <groupId>org.asynchttpclient</groupId>
       <artifactId>async-http-client</artifactId>
       <version>${ahc-version}</version>

http://git-wip-us.apache.org/repos/asf/camel/blob/e607dc3f/components/camel-ahc/src/main/docs/ahc-component.adoc
----------------------------------------------------------------------
diff --git a/components/camel-ahc/src/main/docs/ahc-component.adoc 
b/components/camel-ahc/src/main/docs/ahc-component.adoc
index f897c48..e058b88 100644
--- a/components/camel-ahc/src/main/docs/ahc-component.adoc
+++ b/components/camel-ahc/src/main/docs/ahc-component.adoc
@@ -50,7 +50,7 @@ AhcEndpoint Options
 
 
 // endpoint options: START
-The AHC component supports 12 endpoint options which are listed below:
+The AHC component supports 13 endpoint options which are listed below:
 
 {% raw %}
 [width="100%",cols="2,1,1m,1m,5",options="header"]
@@ -61,6 +61,7 @@ The AHC component supports 12 endpoint options which are 
listed below:
 | bridgeEndpoint | producer | false | boolean | If the option is true then the 
Exchange.HTTP_URI header is ignored and use the endpoint's URI for request. You 
may also set the throwExceptionOnFailure to be false to let the AhcProducer 
send all the fault response back.
 | bufferSize | producer | 4096 | int | The initial in-memory buffer size used 
when transferring data between Camel and AHC Client.
 | connectionClose | producer | false | boolean | Define if the Connection 
Close header has to be added to HTTP Request. This parameter is false by default
+| cookieHandler | producer |  | CookieHandler | Configure a cookie handler to 
maintain a HTTP session
 | headerFilterStrategy | producer |  | HeaderFilterStrategy | To use a custom 
HeaderFilterStrategy to filter header to and from Camel message.
 | throwExceptionOnFailure | producer | true | boolean | Option to disable 
throwing the AhcOperationFailedException in case of failed responses from the 
remote server. This allows you to get all responses regardless of the HTTP 
status code.
 | transferException | producer | false | boolean | If enabled and an Exchange 
failed processing on the consumer side and if the caused Exception was send 
back serialized in the response as a application/x-java-serialized-object 
content type (for example using Jetty or Servlet Camel components). On the 
producer side the exception will be deserialized and thrown as is instead of 
the AhcOperationFailedException. The caused exception is required to be 
serialized. This is by default turned off. If you enable this then be aware 
that Java will deserialize the incoming data from the request to Java and that 
can be a potential security risk.

http://git-wip-us.apache.org/repos/asf/camel/blob/e607dc3f/components/camel-ahc/src/main/java/org/apache/camel/component/ahc/AhcEndpoint.java
----------------------------------------------------------------------
diff --git 
a/components/camel-ahc/src/main/java/org/apache/camel/component/ahc/AhcEndpoint.java
 
b/components/camel-ahc/src/main/java/org/apache/camel/component/ahc/AhcEndpoint.java
index 0afc438..e56a7c5 100644
--- 
a/components/camel-ahc/src/main/java/org/apache/camel/component/ahc/AhcEndpoint.java
+++ 
b/components/camel-ahc/src/main/java/org/apache/camel/component/ahc/AhcEndpoint.java
@@ -27,6 +27,7 @@ import org.apache.camel.AsyncEndpoint;
 import org.apache.camel.Consumer;
 import org.apache.camel.Processor;
 import org.apache.camel.Producer;
+import org.apache.camel.http.common.cookie.CookieHandler;
 import org.apache.camel.impl.DefaultEndpoint;
 import org.apache.camel.spi.HeaderFilterStrategy;
 import org.apache.camel.spi.HeaderFilterStrategyAware;
@@ -70,6 +71,8 @@ public class AhcEndpoint extends DefaultEndpoint implements 
AsyncEndpoint, Heade
     private Map<String, Object> clientConfigOptions;
     @UriParam(label = "producer", defaultValue = "false")
     private boolean connectionClose;
+    @UriParam(label = "producer")
+    private CookieHandler cookieHandler;
 
     public AhcEndpoint(String endpointUri, AhcComponent component, URI 
httpUri) {
         super(endpointUri, component);
@@ -248,6 +251,17 @@ public class AhcEndpoint extends DefaultEndpoint 
implements AsyncEndpoint, Heade
         this.connectionClose = connectionClose;
     }
 
+    public CookieHandler getCookieHandler() {
+        return cookieHandler;
+    }
+
+    /**
+     * Configure a cookie handler to maintain a HTTP session
+     */
+    public void setCookieHandler(CookieHandler cookieHandler) {
+        this.cookieHandler = cookieHandler;
+    }
+
     @Override
     protected void doStart() throws Exception {
         super.doStart();

http://git-wip-us.apache.org/repos/asf/camel/blob/e607dc3f/components/camel-ahc/src/main/java/org/apache/camel/component/ahc/DefaultAhcBinding.java
----------------------------------------------------------------------
diff --git 
a/components/camel-ahc/src/main/java/org/apache/camel/component/ahc/DefaultAhcBinding.java
 
b/components/camel-ahc/src/main/java/org/apache/camel/component/ahc/DefaultAhcBinding.java
index c1346b2..dae132b 100644
--- 
a/components/camel-ahc/src/main/java/org/apache/camel/component/ahc/DefaultAhcBinding.java
+++ 
b/components/camel-ahc/src/main/java/org/apache/camel/component/ahc/DefaultAhcBinding.java
@@ -25,6 +25,8 @@ import java.io.Serializable;
 import java.io.UnsupportedEncodingException;
 import java.net.URI;
 import java.nio.charset.Charset;
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -65,10 +67,11 @@ public class DefaultAhcBinding implements AhcBinding {
         }
 
         RequestBuilder builder = new RequestBuilder();
+        URI uri;
         try {
             // creating the url to use takes 2-steps
             String url = AhcHelper.createURL(exchange, endpoint);
-            URI uri = AhcHelper.createURI(exchange, url, endpoint);
+            uri = AhcHelper.createURI(exchange, url, endpoint);
             // get the url from the uri
             url = uri.toASCIIString();
 
@@ -82,6 +85,7 @@ public class DefaultAhcBinding implements AhcBinding {
         builder.setMethod(method);
 
         populateHeaders(builder, endpoint, exchange);
+        populateCookieHeaders(builder, endpoint, exchange, uri);
         populateBody(builder, endpoint, exchange);
 
         return builder.build();
@@ -118,6 +122,25 @@ public class DefaultAhcBinding implements AhcBinding {
         }
     }
 
+    private void populateCookieHeaders(RequestBuilder builder, AhcEndpoint 
endpoint, Exchange exchange, URI uri) throws CamelExchangeException {
+        if (endpoint.getCookieHandler() != null) {
+            try {
+                Map<String, List<String>> cookieHeaders = 
endpoint.getCookieHandler().loadCookies(exchange, uri);
+                for (Map.Entry<String, List<String>> entry : 
cookieHeaders.entrySet()) {
+                    String key = entry.getKey();
+                    if (entry.getValue().size() > 0) {
+                        // use the default toString of a ArrayList to create 
in the form [xxx, yyy]
+                        // if multi valued, for a single value, then just 
output the value as is
+                        String s =  entry.getValue().size() > 1 ? 
entry.getValue().toString() : entry.getValue().get(0);
+                        builder.addHeader(key, s);
+                    }
+                }
+            } catch (IOException e) {
+                throw new CamelExchangeException("Error loading cookies", 
exchange, e);
+            }
+        }
+    }
+
     protected void populateBody(RequestBuilder builder, AhcEndpoint endpoint, 
Exchange exchange) throws CamelExchangeException {
         Message in = exchange.getIn();
         if (in.getBody() == null) {
@@ -211,11 +234,24 @@ public class DefaultAhcBinding implements AhcBinding {
     @Override
     public void onHeadersReceived(AhcEndpoint endpoint, Exchange exchange, 
HttpResponseHeaders headers) throws Exception {
         List<Entry<String, String>> l = headers.getHeaders().entries();
+        Map<String, List<String>> m = new HashMap<String, List<String>>();
         for (Entry<String, String> entry : headers.getHeaders().entries()) {
             String key = entry.getKey();
             String value = entry.getValue();
+            m.put(key, Collections.singletonList(value));
             exchange.getOut().getHeaders().put(key, value);
         }
+        // handle cookies
+        if (endpoint.getCookieHandler() != null) {
+            try {
+                // creating the url to use takes 2-steps
+                String url = AhcHelper.createURL(exchange, endpoint);
+                URI uri = AhcHelper.createURI(exchange, url, endpoint);
+                endpoint.getCookieHandler().storeCookies(exchange, uri, m);
+            } catch (Exception e) {
+                throw new CamelExchangeException("Error storing cookies", 
exchange, e);
+            }
+        }
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/camel/blob/e607dc3f/components/camel-ahc/src/test/java/org/apache/camel/component/ahc/AhcProducerSessionTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-ahc/src/test/java/org/apache/camel/component/ahc/AhcProducerSessionTest.java
 
b/components/camel-ahc/src/test/java/org/apache/camel/component/ahc/AhcProducerSessionTest.java
new file mode 100644
index 0000000..ca9bebe
--- /dev/null
+++ 
b/components/camel-ahc/src/test/java/org/apache/camel/component/ahc/AhcProducerSessionTest.java
@@ -0,0 +1,111 @@
+/**
+ * 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.camel.component.ahc;
+
+import javax.servlet.http.HttpSession;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.http.common.HttpMessage;
+import org.apache.camel.http.common.cookie.ExchangeCookieHandler;
+import org.apache.camel.http.common.cookie.InstanceCookieHandler;
+import org.apache.camel.impl.JndiRegistry;
+import org.junit.Test;
+
+public class AhcProducerSessionTest extends BaseAhcTest {
+
+    @Test
+    public void testProducerNoSession() throws Exception {
+        getMockEndpoint("mock:result").expectedBodiesReceived("New New World", 
"New New World");
+        template.sendBody("direct:start", "World");
+        template.sendBody("direct:start", "World");
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void testProducerInstanceSession() throws Exception {
+        getMockEndpoint("mock:result").expectedBodiesReceived("Old New World", 
"Old Old World");
+        template.sendBody("direct:instance", "World");
+        template.sendBody("direct:instance", "World");
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void testProducerExchangeSession() throws Exception {
+        getMockEndpoint("mock:result").expectedBodiesReceived("Old New World", 
"Old New World");
+        template.sendBody("direct:exchange", "World");
+        template.sendBody("direct:exchange", "World");
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected JndiRegistry createRegistry() throws Exception {
+        JndiRegistry jndiRegistry = super.createRegistry();
+        jndiRegistry.bind("instanceCookieHandler", new 
InstanceCookieHandler());
+        jndiRegistry.bind("exchangeCookieHandler", new 
ExchangeCookieHandler());
+        return jndiRegistry;
+    }
+
+    private String getTestServerEndpointSessionUrl() {
+        // session handling will not work for localhost
+        return getProtocol() + "://127.0.0.1:" + getPort() + "/session";
+    }
+
+    private String getTestServerEndpointSessionUri() {
+        return "jetty:" + getTestServerEndpointSessionUrl() + 
"?sessionSupport=true";
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start")
+                    .to("ahc:" + getTestServerEndpointSessionUrl())
+                    .to("ahc:" + getTestServerEndpointSessionUrl())
+                    .to("mock:result");
+
+                from("direct:instance")
+                    .to("ahc:" + getTestServerEndpointSessionUrl() + 
"?cookieHandler=#instanceCookieHandler")
+                    .to("ahc:" + getTestServerEndpointSessionUrl() + 
"?cookieHandler=#instanceCookieHandler")
+                    .to("mock:result");
+
+                from("direct:exchange")
+                    .to("ahc:" + getTestServerEndpointSessionUrl() + 
"?cookieHandler=#exchangeCookieHandler")
+                    .to("ahc:" + getTestServerEndpointSessionUrl() + 
"?cookieHandler=#exchangeCookieHandler")
+                    .to("mock:result");
+
+                from(getTestServerEndpointSessionUri())
+                    .process(new Processor() {
+                        @Override
+                        public void process(Exchange exchange) throws 
Exception {
+                            HttpMessage message = 
exchange.getIn(HttpMessage.class);
+                            HttpSession session = 
message.getRequest().getSession();
+                            String body = message.getBody(String.class);
+                            if ("bar".equals(session.getAttribute("foo"))) {
+                                message.setBody("Old " + body);
+                            } else {
+                                session.setAttribute("foo", "bar");
+                                message.setBody("New " + body);
+                            }
+                        }
+                    });
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/e607dc3f/components/camel-cxf/pom.xml
----------------------------------------------------------------------
diff --git a/components/camel-cxf/pom.xml b/components/camel-cxf/pom.xml
index be08f29..5cd9cc4 100644
--- a/components/camel-cxf/pom.xml
+++ b/components/camel-cxf/pom.xml
@@ -96,6 +96,10 @@
       <groupId>org.apache.camel</groupId>
       <artifactId>camel-cxf-transport</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-http-common</artifactId>
+    </dependency>
 
     <dependency>
       <groupId>org.apache.cxf</groupId>

http://git-wip-us.apache.org/repos/asf/camel/blob/e607dc3f/components/camel-cxf/src/main/docs/cxf-component.adoc
----------------------------------------------------------------------
diff --git a/components/camel-cxf/src/main/docs/cxf-component.adoc 
b/components/camel-cxf/src/main/docs/cxf-component.adoc
index 4184b90..a7d42d9 100644
--- a/components/camel-cxf/src/main/docs/cxf-component.adoc
+++ b/components/camel-cxf/src/main/docs/cxf-component.adoc
@@ -143,7 +143,7 @@ The CXF component supports 2 options which are listed below.
 
 
 // endpoint options: START
-The CXF component supports 35 endpoint options which are listed below:
+The CXF component supports 36 endpoint options which are listed below:
 
 {% raw %}
 [width="100%",cols="2,1,1m,1m,5",options="header"]
@@ -156,6 +156,7 @@ The CXF component supports 35 endpoint options which are 
listed below:
 | bridgeErrorHandler | consumer | false | boolean | Allows for bridging the 
consumer to the Camel routing Error Handler which mean any exceptions occurred 
while the consumer is trying to pickup incoming messages or the likes will now 
be processed as a message and handled by the routing Error Handler. By default 
the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with 
exceptions that will be logged at WARN/ERROR level and ignored.
 | exceptionHandler | consumer (advanced) |  | ExceptionHandler | To let the 
consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler 
is enabled then this options is not in use. By default the consumer will deal 
with exceptions that will be logged at WARN/ERROR level and ignored.
 | exchangePattern | consumer (advanced) |  | ExchangePattern | Sets the 
exchange pattern when the consumer creates an exchange.
+| cookieHandler | producer |  | CookieHandler | Configure a cookie handler to 
maintain a HTTP session
 | defaultOperationName | producer |  | String | This option will set the 
default operationName that will be used by the CxfProducer which invokes the 
remote service.
 | defaultOperationNamespace | producer |  | String | This option will set the 
default operationNamespace that will be used by the CxfProducer which invokes 
the remote service.
 | hostnameVerifier | producer |  | HostnameVerifier | The hostname verifier to 
be used. Use the notation to reference a HostnameVerifier from the registry.

http://git-wip-us.apache.org/repos/asf/camel/blob/e607dc3f/components/camel-cxf/src/main/docs/cxfrs-component.adoc
----------------------------------------------------------------------
diff --git a/components/camel-cxf/src/main/docs/cxfrs-component.adoc 
b/components/camel-cxf/src/main/docs/cxfrs-component.adoc
index b1b7ee8..3836666 100644
--- a/components/camel-cxf/src/main/docs/cxfrs-component.adoc
+++ b/components/camel-cxf/src/main/docs/cxfrs-component.adoc
@@ -81,7 +81,7 @@ The CXF-RS component supports 1 options which are listed 
below.
 
 
 // endpoint options: START
-The CXF-RS component supports 30 endpoint options which are listed below:
+The CXF-RS component supports 31 endpoint options which are listed below:
 
 {% raw %}
 [width="100%",cols="2,1,1m,1m,5",options="header"]
@@ -102,6 +102,7 @@ The CXF-RS component supports 30 endpoint options which are 
listed below:
 | publishedEndpointUrl | consumer |  | String | This option can override the 
endpointUrl that published from the WADL which can be accessed with resource 
address url plus _wadl
 | exceptionHandler | consumer (advanced) |  | ExceptionHandler | To let the 
consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler 
is enabled then this options is not in use. By default the consumer will deal 
with exceptions that will be logged at WARN/ERROR level and ignored.
 | exchangePattern | consumer (advanced) |  | ExchangePattern | Sets the 
exchange pattern when the consumer creates an exchange.
+| cookieHandler | producer |  | CookieHandler | Configure a cookie handler to 
maintain a HTTP session
 | hostnameVerifier | producer |  | HostnameVerifier | The hostname verifier to 
be used. Use the notation to reference a HostnameVerifier from the registry.
 | sslContextParameters | producer |  | SSLContextParameters | The Camel SSL 
setting reference. Use the notation to reference the SSL Context.
 | throwExceptionOnFailure | producer | true | boolean | This option tells the 
CxfRsProducer to inspect return codes and will generate an Exception if the 
return code is larger than 207.

http://git-wip-us.apache.org/repos/asf/camel/blob/e607dc3f/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfClientCallback.java
----------------------------------------------------------------------
diff --git 
a/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfClientCallback.java
 
b/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfClientCallback.java
index bcef9cf..b2810c5 100644
--- 
a/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfClientCallback.java
+++ 
b/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfClientCallback.java
@@ -16,12 +16,16 @@
  */
 package org.apache.camel.component.cxf;
 
+import java.io.IOException;
+import java.util.List;
 import java.util.Map;
 
 import org.apache.camel.AsyncCallback;
 import org.apache.camel.Exchange;
 import org.apache.cxf.endpoint.ClientCallback;
 import org.apache.cxf.endpoint.ConduitSelector;
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.message.Message;
 import org.apache.cxf.service.model.BindingOperationInfo;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -33,31 +37,40 @@ public class CxfClientCallback extends ClientCallback {
     private final Exchange camelExchange;
     private final org.apache.cxf.message.Exchange cxfExchange;
     private final BindingOperationInfo boi;
-    private final CxfBinding binding;
+    private final CxfEndpoint endpoint;
     
     
     public CxfClientCallback(AsyncCallback callback, 
                              Exchange camelExchange,
                              org.apache.cxf.message.Exchange cxfExchange,
                              BindingOperationInfo boi,
-                             CxfBinding binding) {
+                             CxfEndpoint endpoint) {
         this.camelAsyncCallback = callback;
         this.camelExchange = camelExchange;
         this.cxfExchange = cxfExchange;
         this.boi = boi;
-        this.binding = binding;       
+        this.endpoint = endpoint;
     }
     
     public void handleResponse(Map<String, Object> ctx, Object[] res) {
         try {
             super.handleResponse(ctx, res);            
         } finally {
+            // add cookies to the cookie store
+            if (endpoint.getCookieHandler() != null) {
+                try {
+                    Map<String, List<String>> cxfHeaders = 
CastUtils.cast((Map<?, 
?>)cxfExchange.getInMessage().get(Message.PROTOCOL_HEADERS));
+                    endpoint.getCookieHandler().storeCookies(camelExchange, 
endpoint.getRequestUri(camelExchange), cxfHeaders);
+                } catch (IOException e) {
+                    LOG.error("Cannot store cookies", e);
+                }
+            }
             // bind the CXF response to Camel exchange and
             // call camel callback
             // for one way messages callback is already called in 
             // process method of org.apache.camel.component.cxf.CxfProducer
             if (!boi.getOperationInfo().isOneWay()) {
-                binding.populateExchangeFromCxfResponse(camelExchange, 
cxfExchange, ctx);
+                
endpoint.getCxfBinding().populateExchangeFromCxfResponse(camelExchange, 
cxfExchange, ctx);
                 camelAsyncCallback.done(false);
             }
             if (LOG.isDebugEnabled()) {
@@ -84,12 +97,21 @@ public class CxfClientCallback extends ClientCallback {
                 camelExchange.setException(ex);
             }
         } finally {
+            // add cookies to the cookie store
+            if (endpoint.getCookieHandler() != null) {
+                try {
+                    Map<String, List<String>> cxfHeaders = 
CastUtils.cast((Map<?, 
?>)cxfExchange.getInMessage().get(Message.PROTOCOL_HEADERS));
+                    endpoint.getCookieHandler().storeCookies(camelExchange, 
endpoint.getRequestUri(camelExchange), cxfHeaders);
+                } catch (IOException e) {
+                    LOG.error("Cannot store cookies", e);
+                }
+            }
             // copy the context information and 
             // call camel callback
             // for one way messages callback is already called in 
             // process method of org.apache.camel.component.cxf.CxfProducer
             if (!boi.getOperationInfo().isOneWay()) {
-                binding.populateExchangeFromCxfResponse(camelExchange, 
cxfExchange, ctx);
+                
endpoint.getCxfBinding().populateExchangeFromCxfResponse(camelExchange, 
cxfExchange, ctx);
                 camelAsyncCallback.done(false);
             }
             if (LOG.isDebugEnabled()) {

http://git-wip-us.apache.org/repos/asf/camel/blob/e607dc3f/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfEndpoint.java
----------------------------------------------------------------------
diff --git 
a/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfEndpoint.java
 
b/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfEndpoint.java
index 11edd4e..2311560 100644
--- 
a/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfEndpoint.java
+++ 
b/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfEndpoint.java
@@ -18,6 +18,8 @@ package org.apache.camel.component.cxf;
 
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
+import java.net.URI;
+import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -49,6 +51,7 @@ import org.apache.camel.AsyncEndpoint;
 import org.apache.camel.CamelContext;
 import org.apache.camel.CamelException;
 import org.apache.camel.Consumer;
+import org.apache.camel.Exchange;
 import org.apache.camel.ExchangePattern;
 import org.apache.camel.Processor;
 import org.apache.camel.Producer;
@@ -59,6 +62,7 @@ import 
org.apache.camel.component.cxf.common.message.CxfConstants;
 import org.apache.camel.component.cxf.feature.CXFMessageDataFormatFeature;
 import org.apache.camel.component.cxf.feature.PayLoadDataFormatFeature;
 import org.apache.camel.component.cxf.feature.RAWDataFormatFeature;
+import org.apache.camel.http.common.cookie.CookieHandler;
 import org.apache.camel.impl.DefaultEndpoint;
 import org.apache.camel.impl.SynchronousDelegateProducer;
 import org.apache.camel.spi.HeaderFilterStrategy;
@@ -201,6 +205,8 @@ public class CxfEndpoint extends DefaultEndpoint implements 
AsyncEndpoint, Heade
     private String password;
     @UriParam(label = "advanced", prefix = "properties.", multiValue = true)
     private Map<String, Object> properties;
+    @UriParam(label = "producer")
+    private CookieHandler cookieHandler;
 
     public CxfEndpoint() {
         setExchangePattern(ExchangePattern.InOut);
@@ -1066,6 +1072,17 @@ public class CxfEndpoint extends DefaultEndpoint 
implements AsyncEndpoint, Heade
         }
     }
 
+    public CookieHandler getCookieHandler() {
+        return cookieHandler;
+    }
+
+    /**
+     * Configure a cookie handler to maintain a HTTP session
+     */
+    public void setCookieHandler(CookieHandler cookieHandler) {
+        this.cookieHandler = cookieHandler;
+    }
+
     @Override
     protected void doStart() throws Exception {
         if (headerFilterStrategy == null) {
@@ -1437,4 +1454,20 @@ public class CxfEndpoint extends DefaultEndpoint 
implements AsyncEndpoint, Heade
     public void setHostnameVerifier(HostnameVerifier hostnameVerifier) {
         this.hostnameVerifier = hostnameVerifier;
     }
+
+    /**
+     * get the request uri for a given exchange.
+     */
+    URI getRequestUri(Exchange camelExchange) {
+        String uriString = 
camelExchange.getIn().getHeader(Exchange.DESTINATION_OVERRIDE_URL, 
String.class);
+        if (uriString == null) {
+            uriString = getAddress();
+        }
+        try {
+            return new URI(uriString);
+        } catch (URISyntaxException e) {
+            LOG.error("cannot determine request URI", e);
+            return null;
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/e607dc3f/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfProducer.java
----------------------------------------------------------------------
diff --git 
a/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfProducer.java
 
b/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfProducer.java
index c92abff..91b9ddb 100644
--- 
a/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfProducer.java
+++ 
b/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/CxfProducer.java
@@ -16,12 +16,14 @@
  */
 package org.apache.camel.component.cxf;
 
+import java.io.IOException;
 import java.io.InputStream;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.TreeMap;
 
 import javax.xml.namespace.QName;
 import javax.xml.ws.Holder;
@@ -38,6 +40,7 @@ import org.apache.camel.util.ServiceHelper;
 import org.apache.cxf.Bus;
 import org.apache.cxf.binding.soap.model.SoapHeaderInfo;
 import org.apache.cxf.endpoint.Client;
+import org.apache.cxf.helpers.CastUtils;
 import org.apache.cxf.jaxws.context.WrappedMessageContext;
 import org.apache.cxf.message.ExchangeImpl;
 import org.apache.cxf.message.Message;
@@ -125,8 +128,7 @@ public class CxfProducer extends DefaultProducer implements 
AsyncProcessor {
             invocationContext.put(Client.RESPONSE_CONTEXT, responseContext);
             invocationContext.put(Client.REQUEST_CONTEXT, 
prepareRequest(camelExchange, cxfExchange));
             
-            CxfClientCallback cxfClientCallback = new 
CxfClientCallback(callback, camelExchange, cxfExchange, boi, 
-                                                                        
endpoint.getCxfBinding());
+            CxfClientCallback cxfClientCallback = new 
CxfClientCallback(callback, camelExchange, cxfExchange, boi, endpoint);
             // send the CXF async request
             client.invoke(cxfClientCallback, boi, getParams(endpoint, 
camelExchange), 
                           invocationContext, cxfExchange);
@@ -171,6 +173,15 @@ public class CxfProducer extends DefaultProducer 
implements AsyncProcessor {
         } catch (Exception exception) {
             camelExchange.setException(exception);
         } finally {
+            // add cookies to the cookie store
+            if (endpoint.getCookieHandler() != null) {
+                try {
+                    Map<String, List<String>> cxfHeaders = 
CastUtils.cast((Map<?, 
?>)cxfExchange.getInMessage().get(Message.PROTOCOL_HEADERS));
+                    endpoint.getCookieHandler().storeCookies(camelExchange, 
endpoint.getRequestUri(camelExchange), cxfHeaders);
+                } catch (IOException e) {
+                    LOG.error("Cannot store cookies", e);
+                }
+            }
             // bind the CXF response to Camel exchange
             if (!boi.getOperationInfo().isOneWay()) {
                 
endpoint.getCxfBinding().populateExchangeFromCxfResponse(camelExchange, 
cxfExchange,
@@ -208,7 +219,27 @@ public class CxfProducer extends DefaultProducer 
implements AsyncProcessor {
         // bind the request CXF exchange
         endpoint.getCxfBinding().populateCxfRequestFromExchange(cxfExchange, 
camelExchange, 
                 requestContext);
-        
+
+        // add appropriate cookies from the cookie store to the protocol 
headers
+        if (endpoint.getCookieHandler() != null) {
+            try {
+                Map<String, List<String>> transportHeaders = 
CastUtils.cast((Map<?, ?>)requestContext.get(Message.PROTOCOL_HEADERS));
+                boolean added;
+                if (transportHeaders == null) {
+                    transportHeaders = new TreeMap<String, 
List<String>>(String.CASE_INSENSITIVE_ORDER);
+                    added = true;
+                } else {
+                    added = false;
+                }
+                
transportHeaders.putAll(endpoint.getCookieHandler().loadCookies(camelExchange, 
endpoint.getRequestUri(camelExchange)));
+                if (added && transportHeaders.size() > 0) {
+                    requestContext.put(Message.PROTOCOL_HEADERS, 
transportHeaders);
+                }
+            } catch (IOException e) {
+                LOG.warn("Cannot load cookies", e);
+            }
+        }
+
         // Remove protocol headers from scopes.  Otherwise, response headers 
can be
         // overwritten by request headers when SOAPHandlerInterceptor tries to 
create
         // a wrapped message context by the copyScoped() method.
@@ -216,7 +247,7 @@ public class CxfProducer extends DefaultProducer implements 
AsyncProcessor {
         
         return requestContext.getWrappedMap();
     }
-    
+
     private BindingOperationInfo prepareBindingOperation(Exchange 
camelExchange, org.apache.cxf.message.Exchange cxfExchange) {
         // get binding operation info
         BindingOperationInfo boi = getBindingOperationInfo(camelExchange);

http://git-wip-us.apache.org/repos/asf/camel/blob/e607dc3f/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsEndpoint.java
----------------------------------------------------------------------
diff --git 
a/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsEndpoint.java
 
b/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsEndpoint.java
index 097c442..3435d20 100644
--- 
a/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsEndpoint.java
+++ 
b/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsEndpoint.java
@@ -32,6 +32,7 @@ import org.apache.camel.Processor;
 import org.apache.camel.Producer;
 import org.apache.camel.Service;
 import org.apache.camel.component.cxf.NullFaultListener;
+import org.apache.camel.http.common.cookie.CookieHandler;
 import org.apache.camel.impl.DefaultEndpoint;
 import org.apache.camel.spi.HeaderFilterStrategy;
 import org.apache.camel.spi.HeaderFilterStrategyAware;
@@ -126,6 +127,8 @@ public class CxfRsEndpoint extends DefaultEndpoint 
implements HeaderFilterStrate
     private boolean propagateContexts;
     @UriParam(label = "advanced")
     private CxfRsEndpointConfigurer cxfRsEndpointConfigurer;
+    @UriParam(label = "producer")
+    private CookieHandler cookieHandler;
 
     public CxfRsEndpoint() {
     }
@@ -799,5 +802,14 @@ public class CxfRsEndpoint extends DefaultEndpoint 
implements HeaderFilterStrate
         this.cxfRsEndpointConfigurer = configurer;
     }
 
+    public CookieHandler getCookieHandler() {
+        return cookieHandler;
+    }
 
+    /**
+     * Configure a cookie handler to maintain a HTTP session
+     */
+    public void setCookieHandler(CookieHandler cookieHandler) {
+        this.cookieHandler = cookieHandler;
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/e607dc3f/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducer.java
----------------------------------------------------------------------
diff --git 
a/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducer.java
 
b/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducer.java
index afe20b4b..8ff54c3 100644
--- 
a/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducer.java
+++ 
b/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducer.java
@@ -16,10 +16,13 @@
  */
 package org.apache.camel.component.cxf.jaxrs;
 
+import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.lang.reflect.Method;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
+import java.net.CookieStore;
+import java.net.HttpCookie;
 import java.net.URLDecoder;
 import java.util.Collection;
 import java.util.HashMap;
@@ -27,6 +30,7 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
+import javax.ws.rs.core.NewCookie;
 import javax.ws.rs.core.Response;
 
 import org.apache.camel.CamelExchangeException;
@@ -35,6 +39,7 @@ import org.apache.camel.Message;
 import org.apache.camel.component.cxf.CxfEndpointUtils;
 import org.apache.camel.component.cxf.CxfOperationException;
 import org.apache.camel.component.cxf.common.message.CxfConstants;
+import org.apache.camel.http.common.cookie.CookieHandler;
 import org.apache.camel.impl.DefaultProducer;
 import org.apache.camel.util.IOHelper;
 import org.apache.camel.util.LRUSoftCache;
@@ -204,7 +209,11 @@ public class CxfRsProducer extends DefaultProducer {
         setupClientMatrix(client, exchange); 
 
         setupClientQueryAndHeaders(client, exchange);
-        
+
+        // handle cookies
+        CookieHandler cookieHandler = 
((CxfRsEndpoint)getEndpoint()).getCookieHandler();
+        loadCookies(exchange, client, cookieHandler);
+
         // invoke the client
         Object response = null;
         if (responseClass == null || Response.class.equals(responseClass)) {
@@ -224,6 +233,8 @@ public class CxfRsProducer extends DefaultProducer {
             }
         }
         int statesCode = client.getResponse().getStatus();
+        // handle cookies
+        saveCookies(exchange, client, cookieHandler);
         //Throw exception on a response > 207
         //http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
         if (throwException) {
@@ -249,6 +260,33 @@ public class CxfRsProducer extends DefaultProducer {
         }
     }
 
+    private void saveCookies(Exchange exchange, Client client, CookieHandler 
cookieHandler) {
+        if (cookieHandler != null) {
+            CookieStore cookieStore = cookieHandler.getCookieStore(exchange);
+            for (NewCookie newCookie: 
client.getResponse().getCookies().values()) {
+                HttpCookie cookie = new HttpCookie(newCookie.getName(), 
newCookie.getValue());
+                cookie.setComment(newCookie.getComment());
+                cookie.setDomain(newCookie.getDomain());
+                cookie.setHttpOnly(newCookie.isHttpOnly());
+                cookie.setMaxAge(newCookie.getMaxAge());
+                cookie.setPath(newCookie.getPath());
+                cookie.setSecure(newCookie.isSecure());
+                cookie.setVersion(newCookie.getVersion());
+                cookieStore.add(client.getCurrentURI(), cookie);
+            }
+        }
+    }
+
+    private void loadCookies(Exchange exchange, Client client, CookieHandler 
cookieHandler) throws IOException {
+        if (cookieHandler != null) {
+            for (Map.Entry<String, List<String>> cookie : 
cookieHandler.loadCookies(exchange, client.getCurrentURI()).entrySet()) {
+                if (cookie.getValue().size() > 0) {
+                    client.header(cookie.getKey(), cookie.getValue());
+                }
+            }
+        }
+    }
+
     protected void invokeProxyClient(Exchange exchange) throws Exception {
         Message inMessage = exchange.getIn();
         Object[] varValues = 
inMessage.getHeader(CxfConstants.CAMEL_CXF_RS_VAR_VALUES, Object[].class);
@@ -280,10 +318,17 @@ public class CxfRsProducer extends DefaultProducer {
         }
         // get the method
         Method method = findRightMethod(sfb.getResourceClasses(), methodName, 
getParameterTypes(parameters));
+
+        // handle cookies
+        CookieHandler cookieHandler = 
((CxfRsEndpoint)getEndpoint()).getCookieHandler();
+        loadCookies(exchange, target, cookieHandler);
+
         // Will send out the message to
         // Need to deal with the sub resource class
         Object response = method.invoke(target, parameters);
         int statesCode = target.getResponse().getStatus();
+        // handle cookies
+        saveCookies(exchange, target, cookieHandler);
         if (throwException) {
             if (response instanceof Response) {
                 Integer respCode = ((Response) response).getStatus();

http://git-wip-us.apache.org/repos/asf/camel/blob/e607dc3f/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/CxfProducerSessionTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/CxfProducerSessionTest.java
 
b/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/CxfProducerSessionTest.java
new file mode 100644
index 0000000..86ecd2f
--- /dev/null
+++ 
b/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/CxfProducerSessionTest.java
@@ -0,0 +1,142 @@
+/**
+ * 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.camel.component.cxf;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.http.common.cookie.ExchangeCookieHandler;
+import org.apache.camel.http.common.cookie.InstanceCookieHandler;
+import org.apache.camel.impl.JndiRegistry;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
+import org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean;
+import org.apache.cxf.transport.http_jetty.JettyHTTPServerEngineFactory;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class CxfProducerSessionTest extends CamelTestSupport {
+    private static final int PORT = CXFTestSupport.getPort1();
+    private static final String SIMPLE_SERVER_ADDRESS = "http://127.0.0.1:"; + 
PORT + "/CxfProducerSessionTest/test";
+    private static final String REQUEST_MESSAGE_EXPRESSION = "<ns1:echo 
xmlns:ns1=\"http://cxf.component.camel.apache.org/\";><arg0>${in.body}</arg0></ns1:echo>";
+    private static final Map<String, String> NAMESPACES = 
Collections.singletonMap("ns1", "http://cxf.component.camel.apache.org/";);
+    private static final String PARAMETER_XPATH = 
"/ns1:echoResponse/return/text()";
+
+    private String url = "cxf://" + SIMPLE_SERVER_ADDRESS + 
"?serviceClass=org.apache.camel.component.cxf.EchoService&dataFormat=PAYLOAD&synchronous=true";
+
+    @Override
+    public boolean isCreateCamelContextPerClass() {
+        return true;
+    }
+
+    @BeforeClass
+    public static void startServer() throws Exception {
+        // start a simple front service
+        JaxWsServiceFactoryBean svrFBean = new JaxWsServiceFactoryBean();
+        svrFBean.setServiceClass(EchoService.class);
+        JaxWsServerFactoryBean svrBean = new JaxWsServerFactoryBean(svrFBean);
+        svrBean.setAddress(SIMPLE_SERVER_ADDRESS);
+        svrBean.setServiceClass(EchoService.class);
+        svrBean.setServiceBean(new EchoServiceSessionImpl());
+        // make the Jetty server support sessions
+        Bus bus = BusFactory.newInstance().createBus();
+        JettyHTTPServerEngineFactory jettyFactory = 
bus.getExtension(JettyHTTPServerEngineFactory.class);
+        jettyFactory.createJettyHTTPServerEngine(PORT, 
"http").setSessionSupport(true);
+        svrBean.setBus(bus);
+        svrBean.create();
+    }
+
+    @AfterClass
+    public static void destroyServer() {
+        // If we don't destroy this the session support will spill over to 
other
+        // tests and they will fail
+        JettyHTTPServerEngineFactory.destroyForPort(PORT);
+    }
+
+    @Test
+    public void testNoSession() throws Exception {
+        getMockEndpoint("mock:result").expectedMessageCount(2);
+        String response = template.requestBody("direct:start", "World", 
String.class);
+        assertEquals("New New World", response);
+        response = template.requestBody("direct:start", "World", String.class);
+        assertEquals("New New World", response);
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void testExchangeSession() throws Exception {
+        getMockEndpoint("mock:result").expectedMessageCount(2);
+        String response = template.requestBody("direct:exchange", "World", 
String.class);
+        assertEquals("Old New World", response);
+        response = template.requestBody("direct:exchange", "World", 
String.class);
+        assertEquals("Old New World", response);
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void testInstanceSession() throws Exception {
+        getMockEndpoint("mock:result").expectedMessageCount(2);
+        String response = template.requestBody("direct:instance", "World", 
String.class);
+        assertEquals("Old New World", response);
+        response = template.requestBody("direct:instance", "World", 
String.class);
+        assertEquals("Old Old World", response);
+        assertMockEndpointsSatisfied();
+    }
+
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            public void configure() {
+                from("direct:start")
+                    .setBody().simple(REQUEST_MESSAGE_EXPRESSION)
+                    .to(url)
+                    .setBody().xpath(PARAMETER_XPATH, String.class, NAMESPACES)
+                    .setBody().simple(REQUEST_MESSAGE_EXPRESSION)
+                    .to(url)
+                    .setBody().xpath(PARAMETER_XPATH, String.class, NAMESPACES)
+                    .to("mock:result");
+                from("direct:instance")
+                    .setBody().simple(REQUEST_MESSAGE_EXPRESSION)
+                    .to(url + "&cookieHandler=#instanceCookieHandler")
+                    .setBody().xpath(PARAMETER_XPATH, String.class, NAMESPACES)
+                    .setBody().simple(REQUEST_MESSAGE_EXPRESSION)
+                    .to(url + "&cookieHandler=#instanceCookieHandler")
+                    .setBody().xpath(PARAMETER_XPATH, String.class, NAMESPACES)
+                    .to("mock:result");
+                from("direct:exchange")
+                    .setBody().simple(REQUEST_MESSAGE_EXPRESSION)
+                    .to(url + "&cookieHandler=#exchangeCookieHandler")
+                    .setBody().xpath(PARAMETER_XPATH, String.class, NAMESPACES)
+                    .setBody().simple(REQUEST_MESSAGE_EXPRESSION)
+                    .to(url + "&cookieHandler=#exchangeCookieHandler")
+                    .setBody().xpath(PARAMETER_XPATH, String.class, NAMESPACES)
+                    .to("mock:result");
+            }
+        };
+    }
+
+    @Override
+    protected JndiRegistry createRegistry() throws Exception {
+        JndiRegistry jndiRegistry = super.createRegistry();
+        jndiRegistry.bind("instanceCookieHandler", new 
InstanceCookieHandler());
+        jndiRegistry.bind("exchangeCookieHandler", new 
ExchangeCookieHandler());
+        return jndiRegistry;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/e607dc3f/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/EchoService.java
----------------------------------------------------------------------
diff --git 
a/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/EchoService.java
 
b/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/EchoService.java
new file mode 100644
index 0000000..11c4196
--- /dev/null
+++ 
b/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/EchoService.java
@@ -0,0 +1,24 @@
+/**
+ * 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.camel.component.cxf;
+
+import javax.jws.WebService;
+
+@WebService
+public interface EchoService {
+    String echo(String text) throws Exception;    
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/e607dc3f/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/EchoServiceSessionImpl.java
----------------------------------------------------------------------
diff --git 
a/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/EchoServiceSessionImpl.java
 
b/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/EchoServiceSessionImpl.java
new file mode 100644
index 0000000..c72355c
--- /dev/null
+++ 
b/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/EchoServiceSessionImpl.java
@@ -0,0 +1,43 @@
+/**
+ * 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.camel.component.cxf;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpSession;
+import javax.xml.ws.WebServiceContext;
+import javax.xml.ws.WebServiceException;
+import javax.xml.ws.handler.MessageContext;
+
+public class EchoServiceSessionImpl implements EchoService {
+
+    @Resource
+    private WebServiceContext context;
+
+    public String echo(String text) {
+        // Find the HttpSession
+        MessageContext mc = context.getMessageContext();
+        HttpSession session = 
((javax.servlet.http.HttpServletRequest)mc.get(MessageContext.SERVLET_REQUEST)).getSession();
+        if (session == null) {
+            throw new WebServiceException("No HTTP Session found");
+        }
+        if (session.getAttribute("foo") == null) {
+            session.setAttribute("foo", "bar");
+            return "New " + text;
+        }
+        return "Old " + text;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/e607dc3f/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducerSessionTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducerSessionTest.java
 
b/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducerSessionTest.java
new file mode 100644
index 0000000..30efb7b
--- /dev/null
+++ 
b/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducerSessionTest.java
@@ -0,0 +1,116 @@
+/**
+ * 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.camel.component.cxf.jaxrs;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.Message;
+import org.apache.camel.Processor;
+import org.apache.camel.component.cxf.CXFTestSupport;
+import org.apache.camel.component.cxf.common.message.CxfConstants;
+import org.apache.camel.test.spring.CamelSpringTestSupport;
+import org.junit.Test;
+import org.springframework.context.support.AbstractXmlApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+public class CxfRsProducerSessionTest extends CamelSpringTestSupport {
+    private static int port1 = CXFTestSupport.getPort1();
+    private static int port2 = 
CXFTestSupport.getPort("CxfRsProducerSessionTest.jetty");
+
+    @Override
+    public boolean isCreateCamelContextPerClass() {
+        return true;
+    }
+
+    public int getPort1() {
+        return port1;
+    }
+
+    public int getPort2() {
+        return port2;
+    }
+
+    @Override
+    protected AbstractXmlApplicationContext createApplicationContext() {
+        return new 
ClassPathXmlApplicationContext("org/apache/camel/component/cxf/jaxrs/CxfRsSpringProducerSession.xml");
+    }
+
+    protected void setupDestinationURL(Message inMessage) {
+        // do nothing here
+    }
+
+    @Test
+    public void testNoSessionProxy() {
+        String response = sendMessage("direct://proxy", "World", 
Boolean.FALSE).getOut().getBody(String.class);
+        assertEquals("New New World", response);
+        response = sendMessage("direct://proxy", "World", 
Boolean.FALSE).getOut().getBody(String.class);
+        assertEquals("New New World", response);
+    }
+
+    @Test
+    public void testExchangeSessionProxy() {
+        String response = sendMessage("direct://proxyexchange", "World", 
Boolean.FALSE).getOut().getBody(String.class);
+        assertEquals("Old New World", response);
+        response = sendMessage("direct://proxyexchange", "World", 
Boolean.FALSE).getOut().getBody(String.class);
+        assertEquals("Old New World", response);
+    }
+
+    @Test
+    public void testInstanceSession() {
+        String response = sendMessage("direct://proxyinstance", "World", 
Boolean.FALSE).getOut().getBody(String.class);
+        assertEquals("Old New World", response);
+        response = sendMessage("direct://proxyinstance", "World", 
Boolean.FALSE).getOut().getBody(String.class);
+        assertEquals("Old Old World", response);
+        // we do the instance tests for proxy and http in one test because 
order
+        // matters here
+        response = sendMessage("direct://httpinstance", "World", 
Boolean.TRUE).getOut().getBody(String.class);
+        assertEquals("Old Old World", response);
+    }
+
+    @Test
+    public void testNoSessionHttp() {
+        String response = sendMessage("direct://http", "World", 
Boolean.TRUE).getOut().getBody(String.class);
+        assertEquals("New New World", response);
+        response = sendMessage("direct://http", "World", 
Boolean.TRUE).getOut().getBody(String.class);
+        assertEquals("New New World", response);
+    }
+
+    @Test
+    public void testExchangeSessionHttp() {
+        String response = sendMessage("direct://httpexchange", "World", 
Boolean.TRUE).getOut().getBody(String.class);
+        assertEquals("Old New World", response);
+        response = sendMessage("direct://httpexchange", "World", 
Boolean.TRUE).getOut().getBody(String.class);
+        assertEquals("Old New World", response);
+    }
+
+    private Exchange sendMessage(String endpoint, String body, Boolean 
httpApi) {
+        Exchange exchange = template.send(endpoint, new Processor() {
+            public void process(Exchange exchange) throws Exception {
+                exchange.setPattern(ExchangePattern.InOut);
+                Message inMessage = exchange.getIn();
+                inMessage.setHeader(CxfConstants.OPERATION_NAME, "echo");
+                inMessage.setHeader(Exchange.HTTP_METHOD, "POST");
+                inMessage.setHeader(Exchange.HTTP_PATH, "/echoservice/echo");
+                inMessage.setHeader(CxfConstants.CAMEL_CXF_RS_USING_HTTP_API, 
httpApi);
+                inMessage.setHeader(CxfConstants.CAMEL_CXF_RS_RESPONSE_CLASS, 
String.class);
+                inMessage.setHeader(Exchange.ACCEPT_CONTENT_TYPE, 
"application/json");
+                inMessage.setBody(body);
+            }
+        });
+        return exchange;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/e607dc3f/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/testbean/EchoService.java
----------------------------------------------------------------------
diff --git 
a/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/testbean/EchoService.java
 
b/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/testbean/EchoService.java
new file mode 100644
index 0000000..36bf2ac
--- /dev/null
+++ 
b/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/testbean/EchoService.java
@@ -0,0 +1,41 @@
+/**
+ * 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.camel.component.cxf.jaxrs.testbean;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Cookie;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.NewCookie;
+import javax.ws.rs.core.Response;
+
+@Path("/echoservice/")
+public class EchoService {
+    @Context 
+    private HttpHeaders headers;
+    
+    @POST
+    @Path("/echo/")
+    public Response echo(String string) {
+        Cookie fooCookie = headers.getCookies().get("foo");
+        if (fooCookie != null && "bar".equals(fooCookie.getValue())) {
+            return Response.ok("Old " + string).build();
+        }
+        return Response.ok("New " + string).cookie(new NewCookie("foo", "bar", 
"/", null, 1, null, -1, false)).build();
+    }  
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/e607dc3f/components/camel-cxf/src/test/resources/org/apache/camel/component/cxf/jaxrs/CxfRsSpringProducerSession.xml
----------------------------------------------------------------------
diff --git 
a/components/camel-cxf/src/test/resources/org/apache/camel/component/cxf/jaxrs/CxfRsSpringProducerSession.xml
 
b/components/camel-cxf/src/test/resources/org/apache/camel/component/cxf/jaxrs/CxfRsSpringProducerSession.xml
new file mode 100644
index 0000000..7837077
--- /dev/null
+++ 
b/components/camel-cxf/src/test/resources/org/apache/camel/component/cxf/jaxrs/CxfRsSpringProducerSession.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans";
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+       xmlns:cxf="http://camel.apache.org/schema/cxf";
+       xmlns:jaxrs="http://cxf.apache.org/jaxrs";
+       xmlns:util="http://www.springframework.org/schema/util";
+       xsi:schemaLocation="
+       http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd
+       http://www.springframework.org/schema/util 
http://www.springframework.org/schema/util/spring-util.xsd
+       http://camel.apache.org/schema/cxf 
http://camel.apache.org/schema/cxf/camel-cxf.xsd
+       http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
+       http://camel.apache.org/schema/spring 
http://camel.apache.org/schema/spring/camel-spring.xsd
+    ">
+  <bean 
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
+
+  <jaxrs:server id="restService"
+                       
address="http://127.0.0.1:${CXFTestSupport.port1}/CxfRsProducerSessionTest/"; 
+                       staticSubresourceResolution="true">
+    <jaxrs:serviceBeans>
+      <ref bean="echoService"/>
+    </jaxrs:serviceBeans>       
+  </jaxrs:server>
+  
+  <bean id="echoService" 
class="org.apache.camel.component.cxf.jaxrs.testbean.EchoService" />
+
+  <cxf:rsClient id="rsClientProxy" 
address="http://127.0.0.1:${CXFTestSupport.port1}/CxfRsProducerSessionTest/";
+    serviceClass="org.apache.camel.component.cxf.jaxrs.testbean.EchoService"
+    loggingFeatureEnabled="true" />
+   
+  <cxf:rsClient id="rsClientHttp" 
address="http://127.0.0.1:${CXFTestSupport.port1}/CxfRsProducerSessionTest/"/>
+
+  <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring";>
+    <endpoint id="fromEndpoint" 
uri="jetty://http://127.0.0.1:${CxfRsProducerSessionTest.jetty}/CxfRsProducerSessionTest/echoservice"/>
+    <route>
+       <from uri="direct://proxy"/>
+       <to uri="cxfrs://bean://rsClientProxy"/>
+       <convertBodyTo type="java.lang.String"/>
+       <to uri="cxfrs://bean://rsClientProxy"/>
+    </route>
+    <route>
+       <from uri="direct://proxyinstance"/>
+       <to 
uri="cxfrs://bean://rsClientProxy?cookieHandler=#instanceCookieHandler"/>
+       <convertBodyTo type="java.lang.String"/>
+       <to 
uri="cxfrs://bean://rsClientProxy?cookieHandler=#instanceCookieHandler"/>
+    </route>
+    <route>
+       <from uri="direct://proxyexchange"/>
+       <to 
uri="cxfrs://bean://rsClientProxy?cookieHandler=#exchangeCookieHandler"/>
+       <convertBodyTo type="java.lang.String"/>
+       <to 
uri="cxfrs://bean://rsClientProxy?cookieHandler=#exchangeCookieHandler"/>
+    </route>
+    <route>
+       <from uri="direct://http"/>
+       <to uri="cxfrs://bean://rsClientHttp"/>
+       <convertBodyTo type="java.lang.String"/>
+       <to uri="cxfrs://bean://rsClientHttp"/>
+    </route>
+    <route>
+       <from uri="direct://httpinstance"/>
+       <to 
uri="cxfrs://bean://rsClientHttp?cookieHandler=#instanceCookieHandler"/>
+       <convertBodyTo type="java.lang.String"/>
+       <to 
uri="cxfrs://bean://rsClientHttp?cookieHandler=#instanceCookieHandler"/>
+    </route>
+    <route>
+       <from uri="direct://httpexchange"/>
+       <to 
uri="cxfrs://bean://rsClientHttp?cookieHandler=#exchangeCookieHandler"/>
+       <convertBodyTo type="java.lang.String"/>
+       <to 
uri="cxfrs://bean://rsClientHttp?cookieHandler=#exchangeCookieHandler"/>
+    </route>
+  </camelContext>
+
+  <bean id="instanceCookieHandler" 
class="org.apache.camel.http.common.cookie.InstanceCookieHandler"/>
+  <bean id="exchangeCookieHandler" 
class="org.apache.camel.http.common.cookie.ExchangeCookieHandler"/>  
+</beans>

http://git-wip-us.apache.org/repos/asf/camel/blob/e607dc3f/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpCommonEndpoint.java
----------------------------------------------------------------------
diff --git 
a/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpCommonEndpoint.java
 
b/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpCommonEndpoint.java
index cb6e7ec..8890cca 100644
--- 
a/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpCommonEndpoint.java
+++ 
b/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpCommonEndpoint.java
@@ -19,6 +19,7 @@ package org.apache.camel.http.common;
 import java.net.URI;
 import java.net.URISyntaxException;
 
+import org.apache.camel.http.common.cookie.CookieHandler;
 import org.apache.camel.impl.DefaultEndpoint;
 import org.apache.camel.spi.HeaderFilterStrategy;
 import org.apache.camel.spi.HeaderFilterStrategyAware;
@@ -129,6 +130,8 @@ public abstract class HttpCommonEndpoint extends 
DefaultEndpoint implements Head
     @UriParam(label = "consumer", defaultValue = "false",
             description = "Configure the consumer to work in async mode")
     private boolean async;
+    @UriParam(label = "producer", description = "Configure a cookie handler to 
maintain a HTTP session")
+    private CookieHandler cookieHandler;
 
     public HttpCommonEndpoint() {
     }
@@ -539,4 +542,15 @@ public abstract class HttpCommonEndpoint extends 
DefaultEndpoint implements Head
     public void setAsync(boolean async) {
         this.async = async;
     }
+
+    public CookieHandler getCookieHandler() {
+        return cookieHandler;
+    }
+
+    /**
+     * Configure a cookie handler to maintain a HTTP session
+     */
+    public void setCookieHandler(CookieHandler cookieHandler) {
+        this.cookieHandler = cookieHandler;
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/e607dc3f/components/camel-http-common/src/main/java/org/apache/camel/http/common/cookie/BaseCookieHandler.java
----------------------------------------------------------------------
diff --git 
a/components/camel-http-common/src/main/java/org/apache/camel/http/common/cookie/BaseCookieHandler.java
 
b/components/camel-http-common/src/main/java/org/apache/camel/http/common/cookie/BaseCookieHandler.java
new file mode 100644
index 0000000..5040272
--- /dev/null
+++ 
b/components/camel-http-common/src/main/java/org/apache/camel/http/common/cookie/BaseCookieHandler.java
@@ -0,0 +1,53 @@
+/**
+ * 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.camel.http.common.cookie;
+
+import java.io.IOException;
+import java.net.CookieManager;
+import java.net.CookieStore;
+import java.net.URI;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.camel.Exchange;
+
+/**
+ * A basic implementation of a CamelCookie handler based on the JDK
+ * CookieManager.
+ */
+public abstract class BaseCookieHandler implements CookieHandler {
+
+    @Override
+    public void storeCookies(Exchange exchange, URI uri, Map<String, 
List<String>> headerMap) throws IOException {
+        getCookieManager(exchange).put(uri, headerMap);
+    }
+
+    @Override
+    public Map<String, List<String>> loadCookies(Exchange exchange, URI uri) 
throws IOException {
+        // the map is not used, so we do not need to fetch the headers from the
+        // exchange
+        return getCookieManager(exchange).get(uri, Collections.emptyMap());
+    }
+
+    @Override
+    public CookieStore getCookieStore(Exchange exchange) {
+        return getCookieManager(exchange).getCookieStore();
+    }
+
+    protected abstract CookieManager getCookieManager(Exchange exchange);
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/e607dc3f/components/camel-http-common/src/main/java/org/apache/camel/http/common/cookie/CookieHandler.java
----------------------------------------------------------------------
diff --git 
a/components/camel-http-common/src/main/java/org/apache/camel/http/common/cookie/CookieHandler.java
 
b/components/camel-http-common/src/main/java/org/apache/camel/http/common/cookie/CookieHandler.java
new file mode 100644
index 0000000..1f8829d
--- /dev/null
+++ 
b/components/camel-http-common/src/main/java/org/apache/camel/http/common/cookie/CookieHandler.java
@@ -0,0 +1,67 @@
+/**
+ * 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.camel.http.common.cookie;
+
+import java.io.IOException;
+import java.net.CookieStore;
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.camel.Exchange;
+
+/**
+ * The interface for cookie handling will allow components to handle cookies 
for
+ * HTTP requests.
+ * <p>
+ * Note: The usual cookie policies apply, so cookies will only be handled for
+ * fully qualified host names in the URI (not local host names like "myhost" or
+ * "localhost").
+ */
+public interface CookieHandler {
+
+    /**
+     * Store cookies for a HTTP response in the cookie handler
+     * 
+     * @param exchange the exchange
+     * @param uri the URI of the called HTTP service
+     * @param headerMap a map containing the HTTP headers returned by the 
server
+     * @throws IOException if the cookies cannot be stored
+     */
+    void storeCookies(Exchange exchange, URI uri, Map<String, List<String>> 
headerMap) throws IOException;
+
+    /**
+     * Create cookie headers from the stored cookies appropriate for a given
+     * URI.
+     * 
+     * @param exchange the exchange
+     * @param uri the URI of the called HTTP service
+     * @return a map containing the cookie headers that can be set to the HTTP
+     *         request. Only cookies that are supposed to be sent to the URI in
+     *         question are considered.
+     * @throws IOException if the cookies cannot be loaded
+     */
+    Map<String, List<String>> loadCookies(Exchange exchange, URI uri) throws 
IOException;
+
+    /**
+     * Get the CookieStore. This method can be used if the is using a 
CookieHandler by itself.
+     *
+     * @param exchange the exchange
+     * @return the CookieStore
+     */
+    CookieStore getCookieStore(Exchange exchange);
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/e607dc3f/components/camel-http-common/src/main/java/org/apache/camel/http/common/cookie/ExchangeCookieHandler.java
----------------------------------------------------------------------
diff --git 
a/components/camel-http-common/src/main/java/org/apache/camel/http/common/cookie/ExchangeCookieHandler.java
 
b/components/camel-http-common/src/main/java/org/apache/camel/http/common/cookie/ExchangeCookieHandler.java
new file mode 100644
index 0000000..a661ead
--- /dev/null
+++ 
b/components/camel-http-common/src/main/java/org/apache/camel/http/common/cookie/ExchangeCookieHandler.java
@@ -0,0 +1,43 @@
+/**
+ * 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.camel.http.common.cookie;
+
+import java.net.CookieManager;
+
+import org.apache.camel.Exchange;
+
+/**
+ * This implementation of the
+ * {@link org.apache.camel.http.common.cookie.CookieHandler} interface keeps 
the
+ * cookies with the {@link org.apache.camel.Exchange}. As this implementation
+ * does not keep any state you can share it between different endpoints without
+ * limitation.
+ */
+public class ExchangeCookieHandler extends BaseCookieHandler {
+
+    @Override
+    protected CookieManager getCookieManager(Exchange exchange) {
+        Object handlerObj = exchange.getProperty(Exchange.COOKIE_HANDLER);
+        if (handlerObj instanceof java.net.CookieManager) {
+            return (CookieManager)handlerObj;
+        } else {
+            CookieManager handler = new CookieManager();
+            exchange.setProperty(Exchange.COOKIE_HANDLER, handler);
+            return handler;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/e607dc3f/components/camel-http-common/src/main/java/org/apache/camel/http/common/cookie/InstanceCookieHandler.java
----------------------------------------------------------------------
diff --git 
a/components/camel-http-common/src/main/java/org/apache/camel/http/common/cookie/InstanceCookieHandler.java
 
b/components/camel-http-common/src/main/java/org/apache/camel/http/common/cookie/InstanceCookieHandler.java
new file mode 100644
index 0000000..30795be
--- /dev/null
+++ 
b/components/camel-http-common/src/main/java/org/apache/camel/http/common/cookie/InstanceCookieHandler.java
@@ -0,0 +1,39 @@
+/**
+ * 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.camel.http.common.cookie;
+
+import java.net.CookieManager;
+
+import org.apache.camel.Exchange;
+
+/**
+ * This implementation of the
+ * {@link org.apache.camel.http.common.cookie.CookieHandler} interface keeps 
the
+ * cookies with the instance of this object. If it is shared between endpoints
+ * the sessions will be shared as long as they are sent to the same domain.
+ */
+public class InstanceCookieHandler extends BaseCookieHandler {
+    private CookieManager cookieHandler;
+
+    @Override
+    protected CookieManager getCookieManager(Exchange exchange) {
+        if (cookieHandler == null) {
+            cookieHandler = new CookieManager();
+        }
+        return cookieHandler;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/e607dc3f/components/camel-http/src/main/docs/http-component.adoc
----------------------------------------------------------------------
diff --git a/components/camel-http/src/main/docs/http-component.adoc 
b/components/camel-http/src/main/docs/http-component.adoc
index 5a204d7..fe0e6a1 100644
--- a/components/camel-http/src/main/docs/http-component.adoc
+++ b/components/camel-http/src/main/docs/http-component.adoc
@@ -147,7 +147,7 @@ The HTTP component supports 6 options which are listed 
below.
 
 
 // endpoint options: START
-The HTTP component supports 25 endpoint options which are listed below:
+The HTTP component supports 26 endpoint options which are listed below:
 
 {% raw %}
 [width="100%",cols="2,1,1m,1m,5",options="header"]
@@ -159,6 +159,7 @@ The HTTP component supports 25 endpoint options which are 
listed below:
 | bridgeEndpoint | producer | false | boolean | If the option is true 
HttpProducer will ignore the Exchange.HTTP_URI header and use the endpoint's 
URI for request. You may also set the option throwExceptionOnFailure to be 
false to let the HttpProducer send all the fault response back.
 | chunked | producer | true | boolean | If this option is false the Servlet 
will disable the HTTP streaming and set the content-length header on the 
response
 | connectionClose | producer | false | boolean | Specifies whether a 
Connection Close header must be added to HTTP Request. By default 
connectionClose is false.
+| cookieHandler | producer |  | CookieHandler | Configure a cookie handler to 
maintain a HTTP session
 | copyHeaders | producer | true | boolean | If this option is true then IN 
exchange headers will be copied to OUT exchange headers according to copy 
strategy. Setting this to false allows to only include the headers from the 
HTTP response (not propagating IN headers).
 | headerFilterStrategy | producer |  | HeaderFilterStrategy | To use a custom 
HeaderFilterStrategy to filter header to and from Camel message.
 | httpBinding | producer |  | HttpBinding | To use a custom HttpBinding to 
control the mapping between Camel message and HttpClient.

Reply via email to