Merge branch 'master' of github.com:apache/camel into CAMEL-14227
diff --git a/components/camel-elasticsearch-rest/src/main/docs/elasticsearch-rest-component.adoc b/components/camel-elasticsearch-rest/src/main/docs/elasticsearch-rest-component.adoc
index cc8f75b..6185d07 100644
--- a/components/camel-elasticsearch-rest/src/main/docs/elasticsearch-rest-component.adoc
+++ b/components/camel-elasticsearch-rest/src/main/docs/elasticsearch-rest-component.adoc
@@ -192,7 +192,7 @@
 |===
 
 == Configure the component and enable basic authentication
-To use the Elasticsearch component is has to be configured with a minimum configuration.
+To use the Elasticsearch component it has to be configured with a minimum configuration.
 
 [source,java]
 ----
diff --git a/components/camel-kafka/src/main/java/org/apache/camel/component/kafka/KafkaProducer.java b/components/camel-kafka/src/main/java/org/apache/camel/component/kafka/KafkaProducer.java
index 47ba7b0..c316774 100644
--- a/components/camel-kafka/src/main/java/org/apache/camel/component/kafka/KafkaProducer.java
+++ b/components/camel-kafka/src/main/java/org/apache/camel/component/kafka/KafkaProducer.java
@@ -33,6 +33,7 @@
 
 import org.apache.camel.AsyncCallback;
 import org.apache.camel.Exchange;
+import org.apache.camel.Message;
 import org.apache.camel.component.kafka.serde.KafkaHeaderSerializer;
 import org.apache.camel.spi.HeaderFilterStrategy;
 import org.apache.camel.support.DefaultAsyncProducer;
@@ -190,14 +191,24 @@
                 public ProducerRecord next() {
                     // must convert each entry of the iterator into the value according to the serializer
                     Object next = msgList.next();
+                    String innerTopic = msgTopic;
+
+                    if (next instanceof Exchange && ((Exchange) next).getIn().getHeader(KafkaConstants.OVERRIDE_TOPIC) != null) {
+                        innerTopic = (String) ((Exchange) next).getIn().removeHeader(KafkaConstants.OVERRIDE_TOPIC);
+                    }
+
+                    if (next instanceof Message && ((Message) next).getHeader(KafkaConstants.OVERRIDE_TOPIC) != null) {
+                        innerTopic = (String) ((Message) next).removeHeader(KafkaConstants.OVERRIDE_TOPIC);
+                    }
+
                     Object value = tryConvertToSerializedType(exchange, next, endpoint.getConfiguration().getSerializerClass());
 
                     if (hasPartitionKey && hasMessageKey) {
-                        return new ProducerRecord(msgTopic, partitionKey, null, key, value, propagatedHeaders);
+                        return new ProducerRecord(innerTopic, partitionKey, null, key, value, propagatedHeaders);
                     } else if (hasMessageKey) {
-                        return new ProducerRecord(msgTopic, null, null, key, value, propagatedHeaders);
+                        return new ProducerRecord(innerTopic, null, null, key, value, propagatedHeaders);
                     } else {
-                        return new ProducerRecord(msgTopic, null, null, null, value, propagatedHeaders);
+                        return new ProducerRecord(innerTopic, null, null, null, value, propagatedHeaders);
                     }
                 }
 
diff --git a/components/camel-kafka/src/test/java/org/apache/camel/component/kafka/KafkaProducerTest.java b/components/camel-kafka/src/test/java/org/apache/camel/component/kafka/KafkaProducerTest.java
index 93512fc..bda3ecc 100644
--- a/components/camel-kafka/src/test/java/org/apache/camel/component/kafka/KafkaProducerTest.java
+++ b/components/camel-kafka/src/test/java/org/apache/camel/component/kafka/KafkaProducerTest.java
@@ -16,12 +16,16 @@
  */
 package org.apache.camel.component.kafka;
 
+import java.util.Arrays;
 import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Properties;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
+import java.util.stream.Collectors;
 
+import org.apache.camel.AggregationStrategy;
 import org.apache.camel.AsyncCallback;
 import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
@@ -29,6 +33,9 @@
 import org.apache.camel.TypeConverter;
 import org.apache.camel.impl.DefaultCamelContext;
 import org.apache.camel.impl.engine.DefaultHeadersMapFactory;
+import org.apache.camel.processor.aggregate.GroupedExchangeAggregationStrategy;
+import org.apache.camel.processor.aggregate.GroupedMessageAggregationStrategy;
+import org.apache.camel.support.DefaultExchange;
 import org.apache.camel.support.DefaultMessage;
 import org.apache.kafka.clients.producer.Callback;
 import org.apache.kafka.clients.producer.ProducerConfig;
@@ -303,6 +310,56 @@
         assertRecordMetadataExists();
     }
 
+    @Test
+    public void processSendsMessageWithListOfExchangesWithOverrideTopicHeaderOnEveryExchange() throws Exception {
+        endpoint.getConfiguration().setTopic("someTopic");
+        Mockito.when(exchange.getIn()).thenReturn(in);
+
+        // we set the initial topic
+        in.setHeader(KafkaConstants.OVERRIDE_TOPIC, "anotherTopic");
+        in.setHeader(KafkaConstants.KEY, "someKey");
+
+        // we add our exchanges in order to aggregate
+        final List<Exchange> nestedExchanges = createListOfExchangesWithTopics(Arrays.asList("overridenTopic1", "overridenTopic2", "overridenTopic3"));
+
+        // aggregate
+        final Exchange finalAggregatedExchange = aggregateExchanges(nestedExchanges, new GroupedExchangeAggregationStrategy());
+
+        in.setBody(finalAggregatedExchange.getIn().getBody());
+        in.setHeaders(finalAggregatedExchange.getIn().getHeaders());
+
+        producer.process(exchange);
+
+        // assert results
+        verifySendMessages(Arrays.asList("overridenTopic1", "overridenTopic2", "overridenTopic3"));
+        assertRecordMetadataExists(3);
+    }
+
+    @Test
+    public void processSendsMessageWithListOfMessagesWithOverrideTopicHeaderOnEveryExchange() throws Exception {
+        endpoint.getConfiguration().setTopic("someTopic");
+        Mockito.when(exchange.getIn()).thenReturn(in);
+
+        // we set the initial topic
+        in.setHeader(KafkaConstants.OVERRIDE_TOPIC, "anotherTopic");
+        in.setHeader(KafkaConstants.KEY, "someKey");
+
+        // we add our exchanges in order to aggregate
+        final List<Exchange> nestedExchanges = createListOfExchangesWithTopics(Arrays.asList("overridenTopic1", "overridenTopic2", "overridenTopic3"));
+
+        // aggregate
+        final Exchange finalAggregatedExchange = aggregateExchanges(nestedExchanges, new GroupedMessageAggregationStrategy());
+
+        in.setBody(finalAggregatedExchange.getIn().getBody());
+        in.setHeaders(finalAggregatedExchange.getIn().getHeaders());
+
+        producer.process(exchange);
+
+        // assert results
+        verifySendMessages(Arrays.asList("overridenTopic1", "overridenTopic2", "overridenTopic3"));
+        assertRecordMetadataExists(3);
+    }
+
     @SuppressWarnings({"unchecked", "rawtypes"})
     protected void verifySendMessage(Integer partitionKey, String topic, String messageKey) {
         ArgumentCaptor<ProducerRecord> captor = ArgumentCaptor.forClass(ProducerRecord.class);
@@ -327,10 +384,53 @@
         assertEquals(topic, captor.getValue().topic());
     }
 
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    protected void verifySendMessages(final List<String> expectedTopics) {
+        final ArgumentCaptor<ProducerRecord> captor = ArgumentCaptor.forClass(ProducerRecord.class);
+        Mockito.verify(producer.getKafkaProducer(), Mockito.atLeast(expectedTopics.size())).send(captor.capture());
+        final List<String> actualTopics = captor.getAllValues()
+                .stream()
+                .map(ProducerRecord::topic)
+                .collect(Collectors.toList());
+
+        assertEquals(expectedTopics, actualTopics);
+    }
+
     private void assertRecordMetadataExists() {
         List<RecordMetadata> recordMetaData1 = (List<RecordMetadata>) in.getHeader(KafkaConstants.KAFKA_RECORDMETA);
         assertTrue(recordMetaData1 != null);
         assertEquals("Expected one recordMetaData", recordMetaData1.size(), 1);
         assertTrue(recordMetaData1.get(0) != null);
     }
+
+    private void assertRecordMetadataExists(final int numMetadata) {
+        List<RecordMetadata> recordMetaData1 = (List<RecordMetadata>) in.getHeader(KafkaConstants.KAFKA_RECORDMETA);
+        assertTrue(recordMetaData1 != null);
+        assertEquals("Expected one recordMetaData", recordMetaData1.size(), numMetadata);
+        assertTrue(recordMetaData1.get(0) != null);
+    }
+
+    private Exchange aggregateExchanges(final List<Exchange> exchangesToAggregate, final AggregationStrategy strategy) {
+        Exchange exchangeHolder = new DefaultExchange(camelContext);
+
+        for (final Exchange innerExchange: exchangesToAggregate) {
+            exchangeHolder = strategy.aggregate(exchangeHolder, innerExchange);
+        }
+
+        strategy.onCompletion(exchangeHolder);
+
+        return exchangeHolder;
+    }
+
+    private List<Exchange> createListOfExchangesWithTopics(final List<String> topics) {
+        final List<Exchange> resultLists = new LinkedList<>();
+
+        topics.forEach(topic -> {
+            final Exchange innerExchange = new DefaultExchange(camelContext);
+            innerExchange.getIn().setHeader(KafkaConstants.OVERRIDE_TOPIC, topic);
+            resultLists.add(innerExchange);
+        });
+
+        return resultLists;
+    }
 }
diff --git a/components/camel-netty-http/src/main/docs/netty-http-component.adoc b/components/camel-netty-http/src/main/docs/netty-http-component.adoc
index 30a5ee5..1a8237f 100644
--- a/components/camel-netty-http/src/main/docs/netty-http-component.adoc
+++ b/components/camel-netty-http/src/main/docs/netty-http-component.adoc
@@ -280,7 +280,7 @@
 | *camel.component.netty-http.executor-service* | To use the given EventExecutorGroup. The option is a io.netty.util.concurrent.EventExecutorGroup type. |  | String
 | *camel.component.netty-http.header-filter-strategy* | To use a custom org.apache.camel.spi.HeaderFilterStrategy to filter headers. The option is a org.apache.camel.spi.HeaderFilterStrategy type. |  | String
 | *camel.component.netty-http.lazy-start-producer* | Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing. | false | Boolean
-| *camel.component.netty-http.maximum-pool-size* | The thread pool size for the EventExecutorGroup if its in use. The default value is 16. | 16 | Integer
+| *camel.component.netty-http.maximum-pool-size* | Sets a maximum thread pool size for the netty consumer ordered thread pool. The default size is 2 x cpu core 1. Setting this value to eg 10 will then use 10 threads unless 2 x cpu core 1 is a higher value, which then will override and be used. For example if there are 8 cores, then the consumer thread pool will be 17. This thread pool is used to route messages received from Netty by Camel. We use a separate thread pool to ensure ordering of messages and also in case some messages will block, then nettys worker threads (event loop) wont be affected. |  | Integer
 | *camel.component.netty-http.netty-http-binding* | To use a custom org.apache.camel.component.netty.http.NettyHttpBinding for binding to/from Netty and Camel Message API. The option is a org.apache.camel.component.netty.http.NettyHttpBinding type. |  | String
 | *camel.component.netty-http.security-configuration.authenticate* | Whether to enable authentication <p/> This is by default enabled. |  | Boolean
 | *camel.component.netty-http.security-configuration.constraint* | The supported restricted. <p/> Currently only Basic is supported. |  | String
diff --git a/components/camel-netty/src/main/docs/netty-component.adoc b/components/camel-netty/src/main/docs/netty-component.adoc
index 81ef113..92ad922 100644
--- a/components/camel-netty/src/main/docs/netty-component.adoc
+++ b/components/camel-netty/src/main/docs/netty-component.adoc
@@ -269,7 +269,7 @@
 | *camel.component.netty.enabled* | Whether to enable auto configuration of the netty component. This is enabled by default. |  | Boolean
 | *camel.component.netty.executor-service* | To use the given EventExecutorGroup. The option is a io.netty.util.concurrent.EventExecutorGroup type. |  | String
 | *camel.component.netty.lazy-start-producer* | Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing. | false | Boolean
-| *camel.component.netty.maximum-pool-size* | The thread pool size for the EventExecutorGroup if its in use. The default value is 16. | 16 | Integer
+| *camel.component.netty.maximum-pool-size* | Sets a maximum thread pool size for the netty consumer ordered thread pool. The default size is 2 x cpu core 1. Setting this value to eg 10 will then use 10 threads unless 2 x cpu core 1 is a higher value, which then will override and be used. For example if there are 8 cores, then the consumer thread pool will be 17. This thread pool is used to route messages received from Netty by Camel. We use a separate thread pool to ensure ordering of messages and also in case some messages will block, then nettys worker threads (event loop) wont be affected. |  | Integer
 | *camel.component.netty.ssl-context-parameters* | To configure security using SSLContextParameters. The option is a org.apache.camel.support.jsse.SSLContextParameters type. |  | String
 | *camel.component.netty.use-global-ssl-context-parameters* | Enable usage of global SSL context parameters. | false | Boolean
 | *camel.component.netty.configuration.client-pipeline-factory* | *Deprecated*  |  | ClientInitializerFactory
diff --git a/components/camel-rabbitmq/pom.xml b/components/camel-rabbitmq/pom.xml
index 2df2b6c..c70f19c 100644
--- a/components/camel-rabbitmq/pom.xml
+++ b/components/camel-rabbitmq/pom.xml
@@ -53,6 +53,11 @@
         <!-- testing -->
         <dependency>
             <groupId>org.apache.camel</groupId>
+            <artifactId>camel-endpointdsl</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
             <artifactId>camel-test-spring</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/components/camel-rabbitmq/src/main/java/org/apache/camel/component/rabbitmq/RabbitMQComponent.java b/components/camel-rabbitmq/src/main/java/org/apache/camel/component/rabbitmq/RabbitMQComponent.java
index 3172b24..e0d4b37 100644
--- a/components/camel-rabbitmq/src/main/java/org/apache/camel/component/rabbitmq/RabbitMQComponent.java
+++ b/components/camel-rabbitmq/src/main/java/org/apache/camel/component/rabbitmq/RabbitMQComponent.java
@@ -254,7 +254,12 @@
             localArgs.putAll(getArgs());
         }
         localArgs.putAll(PropertiesHelper.extractProperties(params, ARG_PREFIX));
-        endpoint.setArgs(localArgs);
+        Map<String, Object> existing = endpoint.getArgs();
+        if (existing != null) {
+            existing.putAll(localArgs);
+        } else {
+            endpoint.setArgs(localArgs);
+        }
 
         // Change null headers processing for message converter
         endpoint.getMessageConverter().setAllowNullHeaders(endpoint.isAllowNullHeaders());
diff --git a/components/camel-rabbitmq/src/test/java/org/apache/camel/component/rabbitmq/RabbitMQEndpointDSLTest.java b/components/camel-rabbitmq/src/test/java/org/apache/camel/component/rabbitmq/RabbitMQEndpointDSLTest.java
new file mode 100644
index 0000000..920d57e
--- /dev/null
+++ b/components/camel-rabbitmq/src/test/java/org/apache/camel/component/rabbitmq/RabbitMQEndpointDSLTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.rabbitmq;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.camel.Endpoint;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.endpoint.EndpointRouteBuilder;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+
+public class RabbitMQEndpointDSLTest extends CamelTestSupport {
+
+    @Test
+    public void testRabbitMQEndpointDsl() throws Exception {
+        Endpoint e = context.getEndpoints().stream().filter(RabbitMQEndpoint.class::isInstance).findFirst().get();
+        assertNotNull(e);
+
+        RabbitMQEndpoint re = (RabbitMQEndpoint) e;
+        assertNotNull(re.getArgs());
+
+        Map map = re.getArgs();
+        assertEquals(1, map.size());
+        assertEquals("queue.x-max-priority", map.keySet().iterator().next());
+        assertEquals("10", map.values().iterator().next());
+    }
+
+    @Override
+    protected RoutesBuilder createRouteBuilder() throws Exception {
+        return new EndpointRouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from(direct("start"))
+                    .to(rabbitmq("foo").advanced().args(Collections.singletonMap("queue.x-max-priority", "10")));
+            }
+        };
+    }
+}
diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelSpringBootApplicationController.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelSpringBootApplicationController.java
index eb18109..dc56eac 100644
--- a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelSpringBootApplicationController.java
+++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelSpringBootApplicationController.java
@@ -52,6 +52,11 @@
             }
 
             @Override
+            protected void initCamelContext() throws Exception {
+                // spring boot has already initialized camel context so we should not do it again
+            }
+
+            @Override
             protected void doStop() throws Exception {
                 LOG.debug("Controller is shutting down CamelContext");
                 try {
diff --git a/core/camel-core-osgi-activator/pom.xml b/core/camel-core-osgi-activator/pom.xml
index 166905a..4b12500 100644
--- a/core/camel-core-osgi-activator/pom.xml
+++ b/core/camel-core-osgi-activator/pom.xml
@@ -57,73 +57,6 @@
       <artifactId>camel-core-osgi</artifactId>
       <scope>provided</scope>
     </dependency>
-    <!-- test -->
-
-    <!-- PAX Exam -->
-    <dependency>
-      <groupId>org.ops4j.pax.exam</groupId>
-      <artifactId>pax-exam</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.ops4j.pax.exam</groupId>
-      <artifactId>pax-exam-spi</artifactId>
-      <version>${pax-exam-version}</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.ops4j.pax.exam</groupId>
-      <artifactId>pax-exam-junit4</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.ops4j.pax.exam</groupId>
-      <artifactId>pax-exam-container-karaf</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.ops4j.pax.url</groupId>
-      <artifactId>pax-url-aether</artifactId>
-      <version>2.4.5</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.ops4j.pax.tinybundles</groupId>
-      <artifactId>tinybundles</artifactId>
-      <version>2.1.1</version>
-      <scope>test</scope>
-    </dependency>
-
-    <!-- Karaf & Command Shell -->
-    <dependency>
-      <groupId>org.apache.karaf</groupId>
-      <artifactId>apache-karaf</artifactId>
-      <version>${karaf4-version}</version>
-      <type>zip</type>
-      <scope>test</scope>
-      <exclusions>
-        <exclusion>
-          <groupId>org.apache.karaf.features</groupId>
-          <artifactId>framework</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-
-    <!-- Karaf Features -->
-    <dependency>
-      <groupId>org.apache.camel.karaf</groupId>
-      <artifactId>apache-camel</artifactId>
-      <version>${project.version}</version>
-      <classifier>features</classifier>
-      <type>xml</type>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>javax.inject</groupId>
-      <artifactId>javax.inject</artifactId>
-      <version>1</version>
-      <scope>test</scope>
-    </dependency>
   </dependencies>
   <build>
     <plugins>
@@ -139,44 +72,6 @@
           </execution>
         </executions>
       </plugin>
-      <plugin>
-        <artifactId>maven-assembly-plugin</artifactId>
-        <executions>
-          <execution>
-            <phase>pre-integration-test</phase>
-            <goals>
-              <goal>single</goal>
-            </goals>
-            <configuration>
-                <descriptors>
-                    <descriptor>src/assembly/test-bundles.xml</descriptor>
-                </descriptors>
-              <finalName>test</finalName>
-              <attach>false</attach>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-      <!-- Execute in the integration-test phase so that the packaged JAR 
-        can be used -->
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-surefire-plugin</artifactId>
-        <executions>
-          <execution>
-            <phase>integration-test</phase>
-            <goals>
-              <goal>test</goal>
-            </goals>
-            <configuration>
-              <includes>
-                <include>**/*IT.java</include>
-              </includes>
-              <forkedProcessTimeoutInSeconds>300</forkedProcessTimeoutInSeconds>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
     </plugins>
   </build>
 </project>
diff --git a/docs/components/modules/ROOT/pages/elasticsearch-rest-component.adoc b/docs/components/modules/ROOT/pages/elasticsearch-rest-component.adoc
index b7f7f80..196785d 100644
--- a/docs/components/modules/ROOT/pages/elasticsearch-rest-component.adoc
+++ b/docs/components/modules/ROOT/pages/elasticsearch-rest-component.adoc
@@ -193,7 +193,7 @@
 |===
 
 == Configure the component and enable basic authentication
-To use the Elasticsearch component is has to be configured with a minimum configuration.
+To use the Elasticsearch component it has to be configured with a minimum configuration.
 
 [source,java]
 ----
diff --git a/docs/components/modules/ROOT/pages/netty-component.adoc b/docs/components/modules/ROOT/pages/netty-component.adoc
index f2f2dc7..d543eca 100644
--- a/docs/components/modules/ROOT/pages/netty-component.adoc
+++ b/docs/components/modules/ROOT/pages/netty-component.adoc
@@ -62,9 +62,9 @@
 [width="100%",cols="2,5,^1,2",options="header"]
 |===
 | Name | Description | Default | Type
-| *maximumPoolSize* (advanced) | The thread pool size for the EventExecutorGroup if its in use. The default value is 16. | 16 | int
+| *maximumPoolSize* (consumer) | Sets a maximum thread pool size for the netty consumer ordered thread pool. The default size is 2 x cpu core 1. Setting this value to eg 10 will then use 10 threads unless 2 x cpu core 1 is a higher value, which then will override and be used. For example if there are 8 cores, then the consumer thread pool will be 17. This thread pool is used to route messages received from Netty by Camel. We use a separate thread pool to ensure ordering of messages and also in case some messages will block, then nettys worker threads (event loop) wont be affected. |  | int
 | *configuration* (advanced) | To use the NettyConfiguration as configuration when creating endpoints. |  | NettyConfiguration
-| *executorService* (advanced) | To use the given EventExecutorGroup. |  | EventExecutorGroup
+| *executorService* (consumer) | To use the given EventExecutorGroup. |  | EventExecutorGroup
 | *useGlobalSslContext Parameters* (security) | Enable usage of global SSL context parameters. | false | boolean
 | *sslContextParameters* (security) | To configure security using SSLContextParameters |  | SSLContextParameters
 | *basicPropertyBinding* (advanced) | Whether the component should use basic property binding (Camel 2.x) or the newer property binding with additional capabilities | false | boolean
@@ -270,7 +270,7 @@
 | *camel.component.netty.enabled* | Whether to enable auto configuration of the netty component. This is enabled by default. |  | Boolean
 | *camel.component.netty.executor-service* | To use the given EventExecutorGroup. The option is a io.netty.util.concurrent.EventExecutorGroup type. |  | String
 | *camel.component.netty.lazy-start-producer* | Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing. | false | Boolean
-| *camel.component.netty.maximum-pool-size* | The thread pool size for the EventExecutorGroup if its in use. The default value is 16. | 16 | Integer
+| *camel.component.netty.maximum-pool-size* | Sets a maximum thread pool size for the netty consumer ordered thread pool. The default size is 2 x cpu core 1. Setting this value to eg 10 will then use 10 threads unless 2 x cpu core 1 is a higher value, which then will override and be used. For example if there are 8 cores, then the consumer thread pool will be 17. This thread pool is used to route messages received from Netty by Camel. We use a separate thread pool to ensure ordering of messages and also in case some messages will block, then nettys worker threads (event loop) wont be affected. |  | Integer
 | *camel.component.netty.ssl-context-parameters* | To configure security using SSLContextParameters. The option is a org.apache.camel.support.jsse.SSLContextParameters type. |  | String
 | *camel.component.netty.use-global-ssl-context-parameters* | Enable usage of global SSL context parameters. | false | Boolean
 | *camel.component.netty.configuration.client-pipeline-factory* | *Deprecated*  |  | ClientInitializerFactory
diff --git a/docs/components/modules/ROOT/pages/netty-http-component.adoc b/docs/components/modules/ROOT/pages/netty-http-component.adoc
index f528fe6..6531bdc 100644
--- a/docs/components/modules/ROOT/pages/netty-http-component.adoc
+++ b/docs/components/modules/ROOT/pages/netty-http-component.adoc
@@ -105,8 +105,8 @@
 | *headerFilterStrategy* (advanced) | To use a custom org.apache.camel.spi.HeaderFilterStrategy to filter headers. |  | HeaderFilterStrategy
 | *securityConfiguration* (security) | Refers to a org.apache.camel.component.netty.http.NettyHttpSecurityConfiguration for configuring secure web resources. |  | NettyHttpSecurityConfiguration
 | *useGlobalSslContext Parameters* (security) | Enable usage of global SSL context parameters. | false | boolean
-| *maximumPoolSize* (advanced) | The thread pool size for the EventExecutorGroup if its in use. The default value is 16. | 16 | int
-| *executorService* (advanced) | To use the given EventExecutorGroup. |  | EventExecutorGroup
+| *maximumPoolSize* (consumer) | Sets a maximum thread pool size for the netty consumer ordered thread pool. The default size is 2 x cpu core 1. Setting this value to eg 10 will then use 10 threads unless 2 x cpu core 1 is a higher value, which then will override and be used. For example if there are 8 cores, then the consumer thread pool will be 17. This thread pool is used to route messages received from Netty by Camel. We use a separate thread pool to ensure ordering of messages and also in case some messages will block, then nettys worker threads (event loop) wont be affected. |  | int
+| *executorService* (consumer) | To use the given EventExecutorGroup. |  | EventExecutorGroup
 | *sslContextParameters* (security) | To configure security using SSLContextParameters |  | SSLContextParameters
 | *basicPropertyBinding* (advanced) | Whether the component should use basic property binding (Camel 2.x) or the newer property binding with additional capabilities | false | boolean
 | *lazyStartProducer* (producer) | Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing. | false | boolean
@@ -281,7 +281,7 @@
 | *camel.component.netty-http.executor-service* | To use the given EventExecutorGroup. The option is a io.netty.util.concurrent.EventExecutorGroup type. |  | String
 | *camel.component.netty-http.header-filter-strategy* | To use a custom org.apache.camel.spi.HeaderFilterStrategy to filter headers. The option is a org.apache.camel.spi.HeaderFilterStrategy type. |  | String
 | *camel.component.netty-http.lazy-start-producer* | Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing. | false | Boolean
-| *camel.component.netty-http.maximum-pool-size* | The thread pool size for the EventExecutorGroup if its in use. The default value is 16. | 16 | Integer
+| *camel.component.netty-http.maximum-pool-size* | Sets a maximum thread pool size for the netty consumer ordered thread pool. The default size is 2 x cpu core 1. Setting this value to eg 10 will then use 10 threads unless 2 x cpu core 1 is a higher value, which then will override and be used. For example if there are 8 cores, then the consumer thread pool will be 17. This thread pool is used to route messages received from Netty by Camel. We use a separate thread pool to ensure ordering of messages and also in case some messages will block, then nettys worker threads (event loop) wont be affected. |  | Integer
 | *camel.component.netty-http.netty-http-binding* | To use a custom org.apache.camel.component.netty.http.NettyHttpBinding for binding to/from Netty and Camel Message API. The option is a org.apache.camel.component.netty.http.NettyHttpBinding type. |  | String
 | *camel.component.netty-http.security-configuration.authenticate* | Whether to enable authentication <p/> This is by default enabled. |  | Boolean
 | *camel.component.netty-http.security-configuration.constraint* | The supported restricted. <p/> Currently only Basic is supported. |  | String
diff --git a/docs/user-manual/modules/ROOT/pages/faq.adoc b/docs/user-manual/modules/ROOT/pages/faq.adoc
index 7cbc56c..b56735c 100644
--- a/docs/user-manual/modules/ROOT/pages/faq.adoc
+++ b/docs/user-manual/modules/ROOT/pages/faq.adoc
@@ -97,6 +97,7 @@
 * xref:faq/how-should-i-package-applications-using-camel-and-activemq.adoc[How should I package applications using Camel and ActiveMQ?]
 * xref:faq/how-to-avoid-importing-bunch-of-cxf-packages-when-start-up-the-camel-cxf-endpoint-from-osgi-platform-.adoc[How to avoid importing bunch of cxf packages when start up the camel-cxf endpoint from OSGi platform?]
 * xref:faq/how-to-avoid-sending-some-or-all-message-headers.adoc[How to avoid sending some or all message headers?]
+* xref:faq/how-to-create-executable-jar-camel-main.adoc[How to create executable JAR for camel-main project?]
 * xref:faq/how-to-define-a-static-camel-converter-method-in-scala.adoc[How to define a static Camel converter method in Scala?]
 * xref:faq/how-to-remove-the-http-protocol-headers-in-the-camel-message.adoc[How to remove the http protocol headers in the camel message?]
 * xref:faq/how-to-send-the-same-message-to-multiple-endpoints.adoc[How to send the same message to multiple endpoints?]
diff --git a/docs/user-manual/modules/ROOT/pages/faq/how-to-create-executable-jar-camel-main.adoc b/docs/user-manual/modules/ROOT/pages/faq/how-to-create-executable-jar-camel-main.adoc
new file mode 100644
index 0000000..87294a3
--- /dev/null
+++ b/docs/user-manual/modules/ROOT/pages/faq/how-to-create-executable-jar-camel-main.adoc
@@ -0,0 +1,36 @@
+[[HowtocreateexecutableJARcamelmain-HowtocreateexecutableJARcamelmain]]
+= How to create executable JAR for camel-main project
+
+You need to use `maven-shade-plugin` to create executable JAR.
+Be aware that uber jar is not fully tested feature and it is Your responsibility to ensure all services are fully functional.
+You might need some modifications, depending on Your project structure.
+See xref:faq/how-do-i-use-a-big-uber-jar.adoc[How do I use a big (uber) JAR?] for more details.
+
+[source]
+----
+<plugin>
+    <groupId>org.apache.maven.plugins</groupId>
+    <artifactId>maven-shade-plugin</artifactId>
+    <version>3.2.1</version>
+    <executions>
+        <execution>
+            <phase>package</phase>
+            <goals>
+                <goal>shade</goal>
+            </goals>
+            <configuration>
+                <shadedArtifactAttached>true</shadedArtifactAttached>
+                <shadedClassifierName>executable-jar</shadedClassifierName>
+                <transformers>
+                    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+                        <mainClass>my.package.MainClass</mainClass>
+                    </transformer>
+                    <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                        <resource>META-INF/services/org/apache/camel/TypeConverterLoader</resource>
+                    </transformer>
+                </transformers>
+            </configuration>
+        </execution>
+    </executions>
+</plugin>
+----
diff --git a/parent/pom.xml b/parent/pom.xml
index ccc0c28..4608be7 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -536,7 +536,7 @@
         <rdf4j-rio-version>2.4.4</rdf4j-rio-version>
         <rdf4j-model-version>2.4.4</rdf4j-model-version>
         <reactive-streams-version>1.0.3</reactive-streams-version>
-        <reactor-version>3.2.12.RELEASE</reactor-version>
+        <reactor-version>3.2.13.RELEASE</reactor-version>
         <reflections-bundle-version>0.9.11_1</reflections-bundle-version>
         <regexp-bundle-version>1.4_1</regexp-bundle-version>
         <rescu-version>2.0.2</rescu-version>
@@ -551,7 +551,7 @@
         <robotframework-version>3.1.1</robotframework-version>
         <rome-version>1.12.2</rome-version>
         <rxjava-version>1.3.8</rxjava-version>
-        <rxjava2-version>2.2.13</rxjava2-version>
+        <rxjava2-version>2.2.15</rxjava2-version>
         <saxon-bundle-version>9.9.1-5_1</saxon-bundle-version>
         <saxon-version>9.9.1-5</saxon-version>
         <scala-version>2.11.7</scala-version>
diff --git a/platforms/karaf/features/src/main/resources/features.xml b/platforms/karaf/features/src/main/resources/features.xml
index c4eebec..6ca6982 100644
--- a/platforms/karaf/features/src/main/resources/features.xml
+++ b/platforms/karaf/features/src/main/resources/features.xml
@@ -58,7 +58,6 @@
     <bundle>mvn:org.apache.camel/camel-core-engine/${project.version}</bundle>
     <bundle>mvn:org.apache.camel/camel-core/${project.version}</bundle>
     <bundle>mvn:org.apache.camel/camel-core-osgi/${project.version}</bundle>
-    <bundle>mvn:org.apache.camel/camel-core-osgi-activator/${project.version}</bundle>
     <bundle>mvn:org.apache.camel/camel-cloud/${project.version}</bundle>
     <bundle>mvn:org.apache.camel/camel-jaxp/${project.version}</bundle>
     <bundle>mvn:org.apache.camel/camel-main/${project.version}</bundle>
diff --git a/tests/camel-itest-karaf/pom.xml b/tests/camel-itest-karaf/pom.xml
index 883a552..a3b67ba 100644
--- a/tests/camel-itest-karaf/pom.xml
+++ b/tests/camel-itest-karaf/pom.xml
@@ -84,6 +84,19 @@
             </exclusions>
         </dependency>
         <dependency>
+            <groupId>org.apache.karaf</groupId>
+            <artifactId>apache-karaf</artifactId>
+            <version>${karaf4-version}</version>
+            <type>zip</type>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.apache.karaf.features</groupId>
+                    <artifactId>framework</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
             <groupId>org.apache.felix</groupId>
             <artifactId>org.apache.felix.configadmin</artifactId>
             <scope>test</scope>
@@ -125,6 +138,12 @@
             <type>pom</type>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>javax.inject</groupId>
+            <artifactId>javax.inject</artifactId>
+            <version>1</version>
+            <scope>test</scope>
+        </dependency>
 
         <!-- test and logging -->
         <dependency>
@@ -133,6 +152,41 @@
             <scope>test</scope>
         </dependency>
 
+        <!-- PAX Exam -->
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-spi</artifactId>
+            <version>${pax-exam-version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-junit4</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-container-karaf</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.url</groupId>
+            <artifactId>pax-url-aether</artifactId>
+            <version>2.4.5</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.tinybundles</groupId>
+            <artifactId>tinybundles</artifactId>
+            <version>2.1.1</version>
+            <scope>test</scope>
+        </dependency>
+
         <!-- logging -->
         <dependency>
             <groupId>log4j</groupId>
@@ -197,6 +251,46 @@
                 </configuration>
             </plugin>
 
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <phase>pre-integration-test</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <configuration>
+                            <descriptors>
+                                <descriptor>src/assembly/test-bundles.xml</descriptor>
+                            </descriptors>
+                            <finalName>test</finalName>
+                            <attach>false</attach>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <!-- Execute in the integration-test phase so that the packaged JAR 
+            can be used -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <phase>integration-test</phase>
+                        <goals>
+                            <goal>test</goal>
+                        </goals>
+                        <configuration>
+                            <includes>
+                                <include>**/*IT.java</include>
+                            </includes>
+                            <forkedProcessTimeoutInSeconds>300</forkedProcessTimeoutInSeconds>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
         </plugins>
     </build>
 
diff --git a/core/camel-core-osgi-activator/src/test/java/org/apache/camel/core/osgi/main/it/BundleIT.java b/tests/camel-itest-karaf/src/test/java/org/apache/camel/itest/karaf/main/BundleIT.java
similarity index 98%
rename from core/camel-core-osgi-activator/src/test/java/org/apache/camel/core/osgi/main/it/BundleIT.java
rename to tests/camel-itest-karaf/src/test/java/org/apache/camel/itest/karaf/main/BundleIT.java
index 2cbd6bb..429df96 100644
--- a/core/camel-core-osgi-activator/src/test/java/org/apache/camel/core/osgi/main/it/BundleIT.java
+++ b/tests/camel-itest-karaf/src/test/java/org/apache/camel/itest/karaf/main/BundleIT.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.core.osgi.main.it;
+package org.apache.camel.itest.karaf.main;
 
 import java.io.IOException;
 import java.net.URISyntaxException;
diff --git a/core/camel-core-osgi-activator/src/test/java/org/apache/camel/core/osgi/main/it/PaxExamOptions.java b/tests/camel-itest-karaf/src/test/java/org/apache/camel/itest/karaf/main/PaxExamOptions.java
similarity index 97%
rename from core/camel-core-osgi-activator/src/test/java/org/apache/camel/core/osgi/main/it/PaxExamOptions.java
rename to tests/camel-itest-karaf/src/test/java/org/apache/camel/itest/karaf/main/PaxExamOptions.java
index 15284c4..07b43f4 100644
--- a/core/camel-core-osgi-activator/src/test/java/org/apache/camel/core/osgi/main/it/PaxExamOptions.java
+++ b/tests/camel-itest-karaf/src/test/java/org/apache/camel/itest/karaf/main/PaxExamOptions.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.core.osgi.main.it;
+package org.apache.camel.itest.karaf.main;
 
 import java.io.File;