You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ac...@apache.org on 2020/03/24 15:42:00 UTC

[camel-karaf] branch master updated (80d9b92 -> 76c9853)

This is an automated email from the ASF dual-hosted git repository.

acosentino pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/camel-karaf.git.


    from 80d9b92  CAMEL-14779: Move Main out of camel-spring due to osgi circular dependency issue
     new b4e74c1  Added camel-osgi-activator component
     new 76c9853  Camel-Osgi-Activator: Added metadata after regen

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 components/camel-osgi-activator/pom.xml            | 195 ++++++++++++++++++++
 .../src/assembly/test-bundles.xml                  |  48 +++++
 .../services/org/apache/camel/other.properties     |   7 +
 .../src/generated/resources/osgi-activator.json    |  13 ++
 .../src/main/docs/osgi-activator.adoc              |  73 ++++++++
 .../camel/osgi/activator/CamelRoutesActivator.java | 181 +++++++++++++++++++
 .../activator/CamelRoutesActivatorConstants.java}  |  56 +++---
 .../osgi/activator/CamelOsgiActivatorIT.java       | 198 +++++++++++++++++++++
 .../component/osgi/activator/PaxExamOptions.java   | 103 +++++++++++
 components/pom.xml                                 |   1 +
 10 files changed, 845 insertions(+), 30 deletions(-)
 create mode 100644 components/camel-osgi-activator/pom.xml
 create mode 100644 components/camel-osgi-activator/src/assembly/test-bundles.xml
 create mode 100644 components/camel-osgi-activator/src/generated/resources/META-INF/services/org/apache/camel/other.properties
 create mode 100644 components/camel-osgi-activator/src/generated/resources/osgi-activator.json
 create mode 100644 components/camel-osgi-activator/src/main/docs/osgi-activator.adoc
 create mode 100644 components/camel-osgi-activator/src/main/java/org/apache/camel/osgi/activator/CamelRoutesActivator.java
 copy components/{camel-test-blueprint/src/test/java/org/apache/camel/test/blueprint/builder/my/MyRouteBuilder.java => camel-osgi-activator/src/main/java/org/apache/camel/osgi/activator/CamelRoutesActivatorConstants.java} (75%)
 create mode 100644 components/camel-osgi-activator/src/test/java/org/apache/camel/component/osgi/activator/CamelOsgiActivatorIT.java
 create mode 100644 components/camel-osgi-activator/src/test/java/org/apache/camel/component/osgi/activator/PaxExamOptions.java


[camel-karaf] 02/02: Camel-Osgi-Activator: Added metadata after regen

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acosentino pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-karaf.git

commit 76c985367d7164bc2c437e84dd22487c706b95d2
Author: Andrea Cosentino <an...@gmail.com>
AuthorDate: Tue Mar 24 16:31:13 2020 +0100

    Camel-Osgi-Activator: Added metadata after regen
---
 .../resources/META-INF/services/org/apache/camel/other.properties       | 2 +-
 .../camel-osgi-activator/src/generated/resources/osgi-activator.json    | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/components/camel-osgi-activator/src/generated/resources/META-INF/services/org/apache/camel/other.properties b/components/camel-osgi-activator/src/generated/resources/META-INF/services/org/apache/camel/other.properties
index 989d3e7..9138f8a 100644
--- a/components/camel-osgi-activator/src/generated/resources/META-INF/services/org/apache/camel/other.properties
+++ b/components/camel-osgi-activator/src/generated/resources/META-INF/services/org/apache/camel/other.properties
@@ -1,6 +1,6 @@
 # Generated by camel build tools - do NOT edit this file!
 name=osgi-activator
-groupId=org.apache.camel
+groupId=org.apache.camel.karaf
 artifactId=camel-osgi-activator
 version=3.2.0-SNAPSHOT
 projectName=Camel :: OSGi Activator
diff --git a/components/camel-osgi-activator/src/generated/resources/osgi-activator.json b/components/camel-osgi-activator/src/generated/resources/osgi-activator.json
index 26df4ea..178d847 100644
--- a/components/camel-osgi-activator/src/generated/resources/osgi-activator.json
+++ b/components/camel-osgi-activator/src/generated/resources/osgi-activator.json
@@ -6,7 +6,7 @@
     "description": "Camel OSGi Activator for running Camel routes from other bundles",
     "deprecated": false,
     "firstVersion": "3.1.0",
-    "groupId": "org.apache.camel",
+    "groupId": "org.apache.camel.karaf",
     "artifactId": "camel-osgi-activator",
     "version": "3.2.0-SNAPSHOT"
   }


[camel-karaf] 01/02: Added camel-osgi-activator component

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acosentino pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-karaf.git

commit b4e74c1b122d75d9555772bd6b2ef78be2187ff0
Author: Andrea Cosentino <an...@gmail.com>
AuthorDate: Tue Mar 24 16:25:17 2020 +0100

    Added camel-osgi-activator component
---
 components/camel-osgi-activator/pom.xml            | 195 ++++++++++++++++++++
 .../src/assembly/test-bundles.xml                  |  48 +++++
 .../services/org/apache/camel/other.properties     |   7 +
 .../src/generated/resources/osgi-activator.json    |  13 ++
 .../src/main/docs/osgi-activator.adoc              |  73 ++++++++
 .../camel/osgi/activator/CamelRoutesActivator.java | 181 +++++++++++++++++++
 .../activator/CamelRoutesActivatorConstants.java   |  26 +++
 .../osgi/activator/CamelOsgiActivatorIT.java       | 198 +++++++++++++++++++++
 .../component/osgi/activator/PaxExamOptions.java   | 103 +++++++++++
 components/pom.xml                                 |   1 +
 10 files changed, 845 insertions(+)

diff --git a/components/camel-osgi-activator/pom.xml b/components/camel-osgi-activator/pom.xml
new file mode 100644
index 0000000..393205a
--- /dev/null
+++ b/components/camel-osgi-activator/pom.xml
@@ -0,0 +1,195 @@
+<?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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.camel.karaf</groupId>
+        <artifactId>components</artifactId>
+        <version>3.2.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>camel-osgi-activator</artifactId>
+    <packaging>jar</packaging>
+
+    <name>Camel :: OSGi Activator</name>
+    <description>Camel OSGi Activator for running Camel routes from other bundles</description>
+
+    <properties>
+        <camel.osgi.activator>org.apache.camel.osgi.activator.CamelRoutesActivator</camel.osgi.activator>
+        <camel.osgi.dynamic>*</camel.osgi.dynamic>
+        <firstVersion>3.1.0</firstVersion>
+    </properties>
+
+    <dependencies>
+        <!-- osgi -->
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi.cmpn</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi.core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-core-osgi</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-core-languages</artifactId>
+        </dependency>
+        <!-- test -->
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-timer</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-log</artifactId>
+            <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>
+
+        <!-- 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>
+            <plugin>
+                <groupId>org.apache.servicemix.tooling</groupId>
+                <artifactId>depends-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>generate-depends-file</id>
+                        <goals>
+                            <goal>generate-depends-file</goal>
+                        </goals>
+                    </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/components/camel-osgi-activator/src/assembly/test-bundles.xml b/components/camel-osgi-activator/src/assembly/test-bundles.xml
new file mode 100644
index 0000000..a7798e9
--- /dev/null
+++ b/components/camel-osgi-activator/src/assembly/test-bundles.xml
@@ -0,0 +1,48 @@
+<?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.
+
+-->
+<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
+  <id>bundles</id>
+  <formats>
+    <format>dir</format>
+  </formats>
+  <includeBaseDirectory>false</includeBaseDirectory>
+  <dependencySets>
+    <dependencySet>
+      <outputDirectory/>
+      <outputFileNameMapping>${artifact.artifactId}.jar</outputFileNameMapping>
+      <includes>
+        <include>org.apache.camel:camel-api</include>
+        <include>org.apache.camel:camel-base</include>
+        <include>org.apache.camel:camel-core-engine</include>
+        <include>org.apache.camel:camel-core-osgi</include>
+        <include>org.apache.camel:camel-core-languages</include>
+        <include>org.apache.camel:camel-management-api</include>
+        <include>org.apache.camel:camel-osgi-activator</include>
+        <include>org.apache.camel:camel-support</include>
+        <include>org.apache.camel:camel-util</include>
+        <include>org.apache.camel:camel-timer</include>
+        <include>org.apache.camel:camel-log</include>
+      </includes>
+      <scope>test</scope>
+    </dependencySet>
+  </dependencySets>
+</assembly>
\ No newline at end of file
diff --git a/components/camel-osgi-activator/src/generated/resources/META-INF/services/org/apache/camel/other.properties b/components/camel-osgi-activator/src/generated/resources/META-INF/services/org/apache/camel/other.properties
new file mode 100644
index 0000000..989d3e7
--- /dev/null
+++ b/components/camel-osgi-activator/src/generated/resources/META-INF/services/org/apache/camel/other.properties
@@ -0,0 +1,7 @@
+# Generated by camel build tools - do NOT edit this file!
+name=osgi-activator
+groupId=org.apache.camel
+artifactId=camel-osgi-activator
+version=3.2.0-SNAPSHOT
+projectName=Camel :: OSGi Activator
+projectDescription=Camel OSGi Activator for running Camel routes from other bundles
diff --git a/components/camel-osgi-activator/src/generated/resources/osgi-activator.json b/components/camel-osgi-activator/src/generated/resources/osgi-activator.json
new file mode 100644
index 0000000..26df4ea
--- /dev/null
+++ b/components/camel-osgi-activator/src/generated/resources/osgi-activator.json
@@ -0,0 +1,13 @@
+{
+  "other": {
+    "kind": "other",
+    "name": "osgi-activator",
+    "title": "Osgi Activator",
+    "description": "Camel OSGi Activator for running Camel routes from other bundles",
+    "deprecated": false,
+    "firstVersion": "3.1.0",
+    "groupId": "org.apache.camel",
+    "artifactId": "camel-osgi-activator",
+    "version": "3.2.0-SNAPSHOT"
+  }
+}
diff --git a/components/camel-osgi-activator/src/main/docs/osgi-activator.adoc b/components/camel-osgi-activator/src/main/docs/osgi-activator.adoc
new file mode 100644
index 0000000..407e4b6
--- /dev/null
+++ b/components/camel-osgi-activator/src/main/docs/osgi-activator.adoc
@@ -0,0 +1,73 @@
+[[OsgiActivator]]
+= OSGi Camel Routes Activator
+
+*Since Camel 3.1*
+
+A small OSGi activator for starting an OSGi Apache Camel Project.
+
+The bundle starts a shared CamelContext and registers any RouteBuilder instances
+(discovered via the OSGi Service Registry), from any other bundles that gets installed.
+And when the bundles gets uninstalled then the routes are stopped and removed from the shared CamelContext.
+
+== Important
+
+This OSGi activator is a based prototype for quickly starting up an OSGi container with a single shared
+CamelContext and then being able to use OSGi dynamism to deploy and undeploy bundlers with Camel routes.
+
+Beware that this OSGi activator is a basic implementation and has limited support for dealing with errors
+when new routes are added which may clash with existing routes (route ids).
+
+Configuration of the CamelContext is also very limited.
+
+Therefore only use this for prototyping and experiments. This is NOT recommended for production usage.
+
+== Install bundle
+
+Register an Apache Camel RouteBuilder as an OSGi service.
+
+Using OSGi annotations:
+
+[source,java]
+----
+@Component(service = RouteBuilder.class)
+public class MyRouteBuilder extends RouteBuilder {
+    @Override
+    public void configure() throws Exception {
+        from("timer:test?fixedRate=true&period=1000")
+            .log("Hello");
+    }
+}
+----
+
+Or Manually:
+
+[source,java]
+----
+public void start(BundleContext context) throws Exception {
+  context.registerService(RouteBuilder.class, new MyRouteBuilder(), null);
+}
+----
+
+And it's automatically added or removed to the context from any bundle!
+
+[source,text]
+----
+Route: route1 started and consuming from: timer://test?fixedRate=true&period=1000
+----
+
+For routes that need to be started before the CamelContext the "camel.osgi.activator.pre-startup" service property may be added.  
+
+[source,java]
+----
+@Component(service = RouteBuilder.class, property = {CamelRoutesActivatorConstants.PRE_START_UP_PROP_NAME + "=true"})
+public class MyStartupRouteBuilder extends RouteBuilder {
+    @Override
+    public void configure() throws Exception {
+        getContext().setStreamCaching(true);
+
+        restConfiguration().component("netty-http").port(8080);
+    }
+}
+----
+
+If this RouteBuilder is added after other non pre startup RouteBuilders then CamelContext will automatically restart.  This allows pre start up RouteBuilder to run their configure methods before other RouteBuilders.
diff --git a/components/camel-osgi-activator/src/main/java/org/apache/camel/osgi/activator/CamelRoutesActivator.java b/components/camel-osgi-activator/src/main/java/org/apache/camel/osgi/activator/CamelRoutesActivator.java
new file mode 100644
index 0000000..2b2160a
--- /dev/null
+++ b/components/camel-osgi-activator/src/main/java/org/apache/camel/osgi/activator/CamelRoutesActivator.java
@@ -0,0 +1,181 @@
+/*
+ * 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.osgi.activator;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.core.osgi.OsgiDefaultCamelContext;
+import org.apache.camel.model.ModelCamelContext;
+import org.apache.camel.model.RouteDefinition;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class CamelRoutesActivator implements BundleActivator, ServiceTrackerCustomizer<RouteBuilder, RouteBuilder> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(CamelRoutesActivator.class);
+    private ServiceRegistration<CamelContext> camelContextRef;
+    private ModelCamelContext camelContext;
+    private BundleContext bundleContext;
+    private ServiceTracker<RouteBuilder, RouteBuilder> routeServiceTracker;
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public void start(BundleContext context) throws Exception {
+        this.bundleContext = context;
+        
+        this.camelContext = new OsgiDefaultCamelContext(this.bundleContext);
+        
+        camelContextRef = this.bundleContext.registerService(CamelContext.class, camelContext, null);
+        
+        camelContext.start();
+
+        this.routeServiceTracker = new ServiceTracker<RouteBuilder, RouteBuilder>(context, RouteBuilder.class, this);
+        
+        this.routeServiceTracker.open();
+
+        LOG.info("Camel OSGi Activator RouteBuilder ServiceTracker Tracker Open");
+    }
+
+    @Override
+    public RouteBuilder addingService(ServiceReference<RouteBuilder> reference) {
+        RouteBuilder builder = this.bundleContext.getService(reference);
+        if (isPreStartRouteBuilder(reference)) {
+            reloadTrackedServices(reference);
+        } else {
+            addRoute(builder);
+        }
+        return builder;
+    }
+    
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        this.routeServiceTracker.close();
+        stopAndClearCamelRoutes();
+        this.bundleContext.ungetService(camelContextRef.getReference());
+    }
+    
+    @Override
+    public void modifiedService(ServiceReference<RouteBuilder> reference, RouteBuilder service) {
+        removedService(reference, service);
+        addingService(reference);
+    }
+
+    @Override
+    public void removedService(ServiceReference<RouteBuilder> reference, RouteBuilder service) {
+        if (isPreStartRouteBuilder(reference)) {
+            reloadTrackedServices();
+        } else {
+            removeRoute(service);
+        }
+    }
+    
+    private boolean isPreStartRouteBuilder(ServiceReference<RouteBuilder> reference) {
+        
+        boolean result = false;
+        
+        Object preStartProperty = reference.getProperty(CamelRoutesActivatorConstants.PRE_START_UP_PROP_NAME);
+        
+        if (preStartProperty instanceof Boolean) {
+            result = (Boolean)preStartProperty;
+        } else if (preStartProperty instanceof String) {
+            result = Boolean.parseBoolean((String) preStartProperty);
+        }
+                
+        return result;
+    }
+    
+    private void loadAndRestartCamelContext(List<ServiceReference<RouteBuilder>> existingRouteBuildersReferences) {
+        if (existingRouteBuildersReferences != null) {
+            List<RouteBuilder> postStartUpRoutes = new ArrayList<>();
+            for (ServiceReference<RouteBuilder> currentRouteBuilderReference : existingRouteBuildersReferences) {
+                RouteBuilder builder = this.bundleContext.getService(currentRouteBuilderReference);
+                if (isPreStartRouteBuilder(currentRouteBuilderReference)) {
+                    addRoute(builder);
+                } else {
+                    postStartUpRoutes.add(builder);
+                }
+            }
+            camelContext.start();
+            postStartUpRoutes.forEach(this::addRoute);
+        }
+    }
+    
+    private void reloadTrackedServices(ServiceReference<RouteBuilder> reference) {
+        LOG.info("Reload Camel Context Routes Triggered");
+        try {
+            synchronized (camelContext) {
+                stopAndClearCamelRoutes();
+                List<ServiceReference<RouteBuilder>> routeServiceReferenceArrayList = new ArrayList<>();
+                if (reference != null) {
+                    routeServiceReferenceArrayList.add(reference);
+                }
+                ServiceReference<RouteBuilder>[] existingTrackedRoutes = this.routeServiceTracker.getServiceReferences();
+                if (existingTrackedRoutes != null) {
+                    routeServiceReferenceArrayList.addAll(Arrays.asList(existingTrackedRoutes));
+                }
+                loadAndRestartCamelContext(routeServiceReferenceArrayList);
+            }
+        } catch (Exception e) {
+            LOG.error("Error Reloading Camel Context Routes", e);
+        }
+    }
+    
+    private void reloadTrackedServices() {
+        reloadTrackedServices(null);
+    }
+
+    private void addRoute(RouteBuilder builder) {
+        try {
+            // need to synchronize here since adding routes is not synchronized
+            synchronized (camelContext) {
+                this.camelContext.addRoutes(builder);
+                LOG.debug("Camel Routes from RouteBuilder Class {} Added to Camel OSGi Activator Context", builder.getClass().getName());
+            }
+        } catch (Exception e) {
+            LOG.error("Error Adding Camel RouteBuilder", e);
+        }
+    }
+
+    private void stopAndClearCamelRoutes() throws Exception {
+        camelContext.stop();
+        camelContext.removeRouteDefinitions(new ArrayList<RouteDefinition>(this.camelContext.getRouteDefinitions()));
+    }
+
+    private void removeRoute(RouteBuilder service) {
+        List<RouteDefinition> routesToBeRemoved = service.getRouteCollection().getRoutes();
+        try {
+            synchronized (camelContext) {
+                camelContext.removeRouteDefinitions(routesToBeRemoved);
+                LOG.debug("Camel Routes from RouteBuilder Class {} Removed from Camel OSGi Activator Context",
+                        service.getClass().getName());
+            }
+        } catch (Exception e) {
+            LOG.error("Error Removing Camel Route Builder", e);
+        }
+    }
+
+}
diff --git a/components/camel-osgi-activator/src/main/java/org/apache/camel/osgi/activator/CamelRoutesActivatorConstants.java b/components/camel-osgi-activator/src/main/java/org/apache/camel/osgi/activator/CamelRoutesActivatorConstants.java
new file mode 100644
index 0000000..dc01581
--- /dev/null
+++ b/components/camel-osgi-activator/src/main/java/org/apache/camel/osgi/activator/CamelRoutesActivatorConstants.java
@@ -0,0 +1,26 @@
+/*
+ * 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.osgi.activator;
+
+public final class CamelRoutesActivatorConstants {
+
+    public static final String PRE_START_UP_PROP_NAME = "camel.osgi.activator.pre-startup";
+    
+    private CamelRoutesActivatorConstants() {
+        
+    }
+}
diff --git a/components/camel-osgi-activator/src/test/java/org/apache/camel/component/osgi/activator/CamelOsgiActivatorIT.java b/components/camel-osgi-activator/src/test/java/org/apache/camel/component/osgi/activator/CamelOsgiActivatorIT.java
new file mode 100644
index 0000000..d08df32
--- /dev/null
+++ b/components/camel-osgi-activator/src/test/java/org/apache/camel/component/osgi/activator/CamelOsgiActivatorIT.java
@@ -0,0 +1,198 @@
+/*
+ * 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.osgi.activator;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Date;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.inject.Inject;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.osgi.activator.CamelRoutesActivatorConstants;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
+import org.ops4j.pax.exam.spi.reactors.PerClass;
+import org.ops4j.pax.tinybundles.core.TinyBundles;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.ops4j.pax.exam.CoreOptions.junitBundles;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.CoreOptions.streamBundle;
+
+@RunWith(PaxExam.class)
+@ExamReactorStrategy(PerClass.class)
+public class CamelOsgiActivatorIT {
+    @Inject
+    private BundleContext bc;
+
+    @Configuration
+    public Option[] configuration() throws IOException, URISyntaxException, ClassNotFoundException {
+        return options(
+                PaxExamOptions.KARAF.option(),
+                PaxExamOptions.CAMEL_CORE_OSGI.option(),
+                streamBundle(
+                        TinyBundles.bundle()
+                            .read(
+                                Files.newInputStream(
+                                    Paths.get("target/test-bundles")
+                                        .resolve("camel-osgi-activator.jar")))
+                            .build()),
+                junitBundles());
+    }
+    
+    @Test
+    public void testBundleLoaded() throws Exception {
+        boolean hasOsgi = false;
+        boolean hasCamelCoreOsgiActivator = false;
+        for (Bundle b : bc.getBundles()) {
+            if ("org.apache.camel.camel-core-osgi".equals(b.getSymbolicName())) {
+                hasOsgi = true;
+                assertEquals("Camel Core OSGi not activated", Bundle.ACTIVE, b.getState());
+            }
+            
+            if ("org.apache.camel.camel-osgi-activator".equals(b.getSymbolicName())) {
+                hasCamelCoreOsgiActivator = true;
+                assertEquals("Camel OSGi Activator not activated", Bundle.ACTIVE, b.getState());
+            }
+        }
+        assertTrue("Camel Core OSGi bundle not found", hasOsgi);
+        assertTrue("Camel OSGi Activator bundle not found", hasCamelCoreOsgiActivator);
+    }
+
+    @Test
+    public void testRouteLoadAndRemoved() throws Exception {
+        CountDownLatch latch = new CountDownLatch(1);
+        ServiceRegistration<RouteBuilder> testServiceRegistration = bc.registerService(RouteBuilder.class,
+                new RouteBuilder() {
+
+                    @Override
+                    public void configure() throws Exception {
+                        from("timer:test?fixedRate=true&period=300").process(exchange -> {
+                            latch.countDown();
+                        });
+                    }
+                }, null);
+
+        latch.await(10, TimeUnit.SECONDS);
+
+        CamelContext camelContext = bc.getService(bc.getServiceReference(CamelContext.class));
+
+        assertEquals("There should be one route in the context.", 1, camelContext.getRoutes().size());
+
+        testServiceRegistration.unregister();
+
+        assertEquals("There should be no routes in the context.", 0, camelContext.getRoutes().size());
+
+    }
+    
+    @Test
+    public void testPreStartupLoadAndRemoved() throws Exception {
+        CountDownLatch preStartLatch = new CountDownLatch(1);
+        
+        CountDownLatch postStartLatch = new CountDownLatch(1);
+        
+        CamelContext camelContext = bc.getService(bc.getServiceReference(CamelContext.class));
+        
+        Date originalCamelStartTime = camelContext.getStartDate(); 
+        
+        ServiceRegistration<RouteBuilder> testRegularServiceRegistration = bc.registerService(RouteBuilder.class,
+                new RouteBuilder() {
+
+                    @Override
+                    public void configure() throws Exception {
+                        from("timer:test1?fixedRate=true&period=300")
+                            .description("PostStartRoute")
+                            .process(exchange -> {
+                                postStartLatch.countDown();
+                            });
+                    }
+                }, null);
+        
+        postStartLatch.await(10, TimeUnit.SECONDS);
+        
+        Date regularRouteAddCamelContextStartTime = camelContext.getStartDate();
+        
+        assertEquals("Camel Context Should NOT be restarted when removing regular RouteBuilder", originalCamelStartTime, regularRouteAddCamelContextStartTime);
+        
+        assertEquals("There should be one route in the context.", 1, camelContext.getRoutes().size());
+        
+        assertEquals("The PostStartRoute should be first.", "PostStartRoute", camelContext.getRoutes().get(0).getDescription());
+
+        
+        Dictionary<String, String> preStartUpProperties = new Hashtable<>();
+        preStartUpProperties.put(CamelRoutesActivatorConstants.PRE_START_UP_PROP_NAME, "true");
+        ServiceRegistration<RouteBuilder> testPreStartupServiceRegistration = bc.registerService(RouteBuilder.class, 
+                new RouteBuilder() {
+                    
+                    @Override
+                    public void configure() throws Exception {
+                        getContext().setStreamCaching(true);
+                        
+                        from("timer:test2?fixedRate=true&period=300")
+                            .description("PreStartRoute")
+                            .process(exchange -> {
+                                preStartLatch.countDown();
+                            });
+                        
+                    }
+                }, preStartUpProperties);
+
+        preStartLatch.await(10, TimeUnit.SECONDS);
+
+        Date preStartCamelContextStartTime = camelContext.getStartDate();
+        
+        assertTrue("Camel Context Should be restarted when adding startup RouteBuilder", preStartCamelContextStartTime.after(originalCamelStartTime));
+
+        assertEquals("There should be two route in the context.", 2, camelContext.getRoutes().size());
+        
+        assertEquals("The PreStartRoute should be first.", "PreStartRoute", camelContext.getRoutes().get(0).getDescription());
+
+        testPreStartupServiceRegistration.unregister();
+
+        Date preStartRemovedCamelContextStartTime = camelContext.getStartDate();
+        
+        assertEquals("There should be one routes in the context.", 1, camelContext.getRoutes().size());
+        
+        assertTrue("Camel Context Should be restarted when removing startup RouteBuilder", preStartRemovedCamelContextStartTime.after(preStartCamelContextStartTime));
+        
+        testRegularServiceRegistration.unregister();
+        
+        Date regularRouteRemovedCamelContextStartTime = camelContext.getStartDate();
+        
+        assertEquals("Camel Context Should NOT be restarted when removing regular RouteBuilder", preStartRemovedCamelContextStartTime, regularRouteRemovedCamelContextStartTime);
+
+        assertEquals("There should be no routes in the context.", 0, camelContext.getRoutes().size());
+
+    }
+
+}
diff --git a/components/camel-osgi-activator/src/test/java/org/apache/camel/component/osgi/activator/PaxExamOptions.java b/components/camel-osgi-activator/src/test/java/org/apache/camel/component/osgi/activator/PaxExamOptions.java
new file mode 100644
index 0000000..38f3a8e
--- /dev/null
+++ b/components/camel-osgi-activator/src/test/java/org/apache/camel/component/osgi/activator/PaxExamOptions.java
@@ -0,0 +1,103 @@
+/*
+ * 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.osgi.activator;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.karaf.container.internal.JavaVersionUtil;
+import org.ops4j.pax.exam.karaf.options.LogLevelOption;
+import org.ops4j.pax.exam.options.DefaultCompositeOption;
+import org.ops4j.pax.exam.options.extra.VMOption;
+import org.ops4j.pax.tinybundles.core.TinyBundles;
+
+import static org.ops4j.pax.exam.CoreOptions.maven;
+import static org.ops4j.pax.exam.CoreOptions.streamBundle;
+import static org.ops4j.pax.exam.CoreOptions.when;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.configureConsole;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.karafDistributionConfiguration;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.logLevel;
+
+public enum PaxExamOptions {
+    
+    KARAF(
+            karafDistributionConfiguration()
+                .frameworkUrl(
+                    maven()
+                        .groupId("org.apache.karaf")
+                        .artifactId("apache-karaf")
+                        .versionAsInProject()
+                        .type("zip"))
+                .name("Apache Karaf")
+                .useDeployFolder(false)
+                .unpackDirectory(new File("target/paxexam/unpack/")),
+            keepRuntimeFolder(),
+            // Don't bother with local console output as it just ends up cluttering the logs
+            configureConsole().ignoreLocalConsole(),
+            // Force the log level to INFO so we have more details during the test. It defaults to WARN.
+            logLevel(LogLevelOption.LogLevel.INFO),
+            when(JavaVersionUtil.getMajorVersion() >= 9)
+                .useOptions(
+                        new VMOption("-classpath"),
+                        new VMOption("lib/jdk9plus/*" + File.pathSeparator + "lib/boot/*")
+                        )
+        ),
+        CAMEL_CORE_OSGI(
+                createStreamBundleOption("camel-core-engine.jar"),
+                createStreamBundleOption("camel-core-languages.jar"),
+                createStreamBundleOption("camel-api.jar"),
+                createStreamBundleOption("camel-base.jar"),
+                createStreamBundleOption("camel-management-api.jar"),
+                createStreamBundleOption("camel-support.jar"),
+                createStreamBundleOption("camel-util.jar"),
+                createStreamBundleOption("camel-timer.jar"),
+                createStreamBundleOption("camel-log.jar"),
+                createStreamBundleOption("camel-core-osgi.jar")
+        );
+
+    private final Option[] options;
+
+    PaxExamOptions(Option... options) {
+        this.options = options;
+    }
+
+    public Option option() {
+        return new DefaultCompositeOption(options);
+    }
+    
+    public static Option createStreamBundleOption(String fileName) {
+        InputStream bundleInputStream = null;
+        try {
+            bundleInputStream = Files.newInputStream(
+                    Paths.get("target/test-bundles")
+                        .resolve(fileName));
+            
+        } catch (IOException e) {
+            throw new RuntimeException("Error resolving Bundle", e);
+        }
+        
+        return streamBundle(
+                    TinyBundles.bundle()
+                        .read(bundleInputStream)
+                        .build());
+    }
+}
diff --git a/components/pom.xml b/components/pom.xml
index 3ccab0a..901ad02 100644
--- a/components/pom.xml
+++ b/components/pom.xml
@@ -37,6 +37,7 @@
         <module>camel-cxf-blueprint</module>
         <module>camel-cxf-transport-blueprint</module>
         <module>camel-kura</module>
+        <module>camel-osgi-activator</module>
         <module>camel-paxlogging</module>
     </modules>