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 09:18:49 UTC

[camel-karaf] branch master updated (9c542ad -> b6380d0)

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 9c542ad  Upgrade to Wrapper 0.5.6 and Maven 3.6.3
     new 8d239df  Added camel-kura to components
     new b6380d0  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:
 .../camel-kura}/pom.xml                            |  96 ++++---
 .../services/org/apache/camel/other.properties     |   7 +
 .../camel-kura/src/generated/resources/kura.json   |  14 +
 components/camel-kura/src/main/docs/kura.adoc      | 298 +++++++++++++++++++++
 .../apache/camel/component/kura/KuraRouter.java    | 149 +++++++++++
 .../camel/component/kura/KuraRouterTest.java       | 144 ++++++++++
 .../src/test/resources/log4j2.properties           |  14 +-
 .../camel-kura/src/test/resources/route.xml        |  16 +-
 .../services/org/apache/camel/component.properties |   2 +-
 .../camel/component/paxlogging/paxlogging.json     |   2 +-
 components/pom.xml                                 |  15 ++
 core/pom.xml                                       |  27 +-
 12 files changed, 715 insertions(+), 69 deletions(-)
 copy {core/camel-core-osgi => components/camel-kura}/pom.xml (56%)
 create mode 100644 components/camel-kura/src/generated/resources/META-INF/services/org/apache/camel/other.properties
 create mode 100644 components/camel-kura/src/generated/resources/kura.json
 create mode 100644 components/camel-kura/src/main/docs/kura.adoc
 create mode 100644 components/camel-kura/src/main/java/org/apache/camel/component/kura/KuraRouter.java
 create mode 100644 components/camel-kura/src/test/java/org/apache/camel/component/kura/KuraRouterTest.java
 copy {core/camel-core-osgi => components/camel-kura}/src/test/resources/log4j2.properties (76%)
 copy core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/impl/package.html => components/camel-kura/src/test/resources/route.xml (80%)


[camel-karaf] 02/02: 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 b6380d0188433d3d2f2700dd6162dd2de8c0545a
Author: Andrea Cosentino <an...@gmail.com>
AuthorDate: Tue Mar 24 09:59:05 2020 +0100

    Regen
---
 .../services/org/apache/camel/other.properties     |  2 +-
 .../camel-kura/src/generated/resources/kura.json   |  2 +-
 .../services/org/apache/camel/component.properties |  2 +-
 .../camel/component/paxlogging/paxlogging.json     |  2 +-
 components/pom.xml                                 | 14 +++++++++++
 core/pom.xml                                       | 27 +++++++++++-----------
 6 files changed, 32 insertions(+), 17 deletions(-)

diff --git a/components/camel-kura/src/generated/resources/META-INF/services/org/apache/camel/other.properties b/components/camel-kura/src/generated/resources/META-INF/services/org/apache/camel/other.properties
index 343cb4c..840e6a5 100644
--- a/components/camel-kura/src/generated/resources/META-INF/services/org/apache/camel/other.properties
+++ b/components/camel-kura/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=kura
-groupId=org.apache.camel
+groupId=org.apache.camel.karaf
 artifactId=camel-kura
 version=3.2.0-SNAPSHOT
 projectName=Camel :: Kura
diff --git a/components/camel-kura/src/generated/resources/kura.json b/components/camel-kura/src/generated/resources/kura.json
index 1d8e69d..a38c454 100644
--- a/components/camel-kura/src/generated/resources/kura.json
+++ b/components/camel-kura/src/generated/resources/kura.json
@@ -7,7 +7,7 @@
     "deprecated": false,
     "firstVersion": "2.15.0",
     "label": "iot,osgi",
-    "groupId": "org.apache.camel",
+    "groupId": "org.apache.camel.karaf",
     "artifactId": "camel-kura",
     "version": "3.2.0-SNAPSHOT"
   }
diff --git a/components/camel-paxlogging/src/generated/resources/META-INF/services/org/apache/camel/component.properties b/components/camel-paxlogging/src/generated/resources/META-INF/services/org/apache/camel/component.properties
index 86311c8..710d8f4 100644
--- a/components/camel-paxlogging/src/generated/resources/META-INF/services/org/apache/camel/component.properties
+++ b/components/camel-paxlogging/src/generated/resources/META-INF/services/org/apache/camel/component.properties
@@ -1,6 +1,6 @@
 # Generated by camel build tools - do NOT edit this file!
 components=paxlogging
-groupId=org.apache.camel
+groupId=org.apache.camel.karaf
 artifactId=camel-paxlogging
 version=3.2.0-SNAPSHOT
 projectName=Camel :: Pax Logging
diff --git a/components/camel-paxlogging/src/generated/resources/org/apache/camel/component/paxlogging/paxlogging.json b/components/camel-paxlogging/src/generated/resources/org/apache/camel/component/paxlogging/paxlogging.json
index 7f61f17..56e76a0 100644
--- a/components/camel-paxlogging/src/generated/resources/org/apache/camel/component/paxlogging/paxlogging.json
+++ b/components/camel-paxlogging/src/generated/resources/org/apache/camel/component/paxlogging/paxlogging.json
@@ -14,7 +14,7 @@
     "lenientProperties": false,
     "javaType": "org.apache.camel.component.paxlogging.PaxLoggingComponent",
     "firstVersion": "2.6.0",
-    "groupId": "org.apache.camel",
+    "groupId": "org.apache.camel.karaf",
     "artifactId": "camel-paxlogging",
     "version": "3.2.0-SNAPSHOT"
   },
diff --git a/components/pom.xml b/components/pom.xml
index 19a1315..9fe8905 100644
--- a/components/pom.xml
+++ b/components/pom.xml
@@ -108,6 +108,20 @@
                         </archive>
                     </configuration>
                 </plugin>
+      <plugin>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>camel-package-maven-plugin</artifactId>
+        <version>${camel-version}</version>
+        <executions>
+          <execution>
+            <id>generate</id>
+            <goals>
+              <goal>generate-component</goal>
+            </goals>
+            <phase>process-classes</phase>
+          </execution>
+        </executions>
+      </plugin>
         </plugins>
     </build>
 
diff --git a/core/pom.xml b/core/pom.xml
index fcc891b..029b870 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -40,19 +40,20 @@
 
     <build>
         <plugins>
-            <!--<plugin>
-                <groupId>org.apache.camel</groupId>
-                <artifactId>camel-package-maven-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>generate</id>
-                        <goals>
-                            <goal>generate</goal>
-                        </goals>
-                        <phase>process-classes</phase>
-                    </execution>
-                </executions>
-            </plugin>-->
+      <plugin>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>camel-package-maven-plugin</artifactId>
+        <version>${camel-version}</version>
+        <executions>
+          <execution>
+            <id>generate</id>
+            <goals>
+              <goal>generate-component</goal>
+            </goals>
+            <phase>process-classes</phase>
+          </execution>
+        </executions>
+      </plugin>
             <plugin>
                 <artifactId>maven-compiler-plugin</artifactId>
                 <executions>


[camel-karaf] 01/02: Added camel-kura to components

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 8d239dffb36a8ef3498e89f4dc812bb47ebbb91f
Author: Andrea Cosentino <an...@gmail.com>
AuthorDate: Tue Mar 24 08:34:21 2020 +0100

    Added camel-kura to components
---
 components/camel-kura/pom.xml                      | 125 +++++++++
 .../services/org/apache/camel/other.properties     |   7 +
 .../camel-kura/src/generated/resources/kura.json   |  14 +
 components/camel-kura/src/main/docs/kura.adoc      | 298 +++++++++++++++++++++
 .../apache/camel/component/kura/KuraRouter.java    | 149 +++++++++++
 .../camel/component/kura/KuraRouterTest.java       | 144 ++++++++++
 .../src/test/resources/log4j2.properties           |  30 +++
 components/camel-kura/src/test/resources/route.xml |  25 ++
 components/pom.xml                                 |   1 +
 9 files changed, 793 insertions(+)

diff --git a/components/camel-kura/pom.xml b/components/camel-kura/pom.xml
new file mode 100644
index 0000000..8b1f4af
--- /dev/null
+++ b/components/camel-kura/pom.xml
@@ -0,0 +1,125 @@
+<?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-kura</artifactId>
+    <packaging>jar</packaging>
+    <name>Camel :: Kura</name>
+    <description>Using Camel with Eclipse Kura (OSGi)</description>
+
+    <properties>
+        <firstVersion>2.15.0</firstVersion>
+        <label>iot,osgi</label>
+
+    </properties>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-support</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-core-osgi</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.framework</artifactId>
+            <version>${felix-framework-version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.configadmin</artifactId>
+            <version>${felix-configadmin-version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.scr</artifactId>
+            <version>${felix-scr-version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.scr.annotations</artifactId>
+            <version>${felix-scr-annotations-version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-api</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-slf4j-impl</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-xml-jaxb</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-mock</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-direct</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/components/camel-kura/src/generated/resources/META-INF/services/org/apache/camel/other.properties b/components/camel-kura/src/generated/resources/META-INF/services/org/apache/camel/other.properties
new file mode 100644
index 0000000..343cb4c
--- /dev/null
+++ b/components/camel-kura/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=kura
+groupId=org.apache.camel
+artifactId=camel-kura
+version=3.2.0-SNAPSHOT
+projectName=Camel :: Kura
+projectDescription=Using Camel with Eclipse Kura (OSGi)
diff --git a/components/camel-kura/src/generated/resources/kura.json b/components/camel-kura/src/generated/resources/kura.json
new file mode 100644
index 0000000..1d8e69d
--- /dev/null
+++ b/components/camel-kura/src/generated/resources/kura.json
@@ -0,0 +1,14 @@
+{
+  "other": {
+    "kind": "other",
+    "name": "kura",
+    "title": "Kura",
+    "description": "Using Camel with Eclipse Kura (OSGi)",
+    "deprecated": false,
+    "firstVersion": "2.15.0",
+    "label": "iot,osgi",
+    "groupId": "org.apache.camel",
+    "artifactId": "camel-kura",
+    "version": "3.2.0-SNAPSHOT"
+  }
+}
diff --git a/components/camel-kura/src/main/docs/kura.adoc b/components/camel-kura/src/main/docs/kura.adoc
new file mode 100644
index 0000000..43945d5
--- /dev/null
+++ b/components/camel-kura/src/main/docs/kura.adoc
@@ -0,0 +1,298 @@
+[[Kura-EclipseKuracomponent]]
+= Eclipse Kura component
+
+*Since Camel 2.15*
+
+This documentation page covers the integration options of Camel with the
+https://eclipse.org/kura/[Eclipse Kura] M2M gateway. The common reason
+to deploy Camel routes into the Eclipse Kura is to provide enterprise
+integration patterns and Camel components to the messaging M2M gateway.
+For example you might want to install Kura on Raspberry PI, then read
+temperature from the sensor attached to that Raspberry PI using Kura
+services and finally forward the current temperature value to your data
+center service using Camel EIP and components.
+
+[[Kura-KuraRouteractivator]]
+== KuraRouter activator
+
+Bundles deployed to the Eclipse Kura are usually
+http://eclipse.github.io/kura/doc/hello-example.html#create-java-class[developed
+as bundle activators]. So the easiest way to deploy Apache Camel routes
+into the Kura is to create an OSGi bundle containing the class extending
+`org.apache.camel.kura.KuraRouter` class:
+
+[source,java]
+-------------------------------------------------------
+public class MyKuraRouter extends KuraRouter {
+
+  @Override
+  public void configure() throws Exception {
+    from("timer:trigger").
+      to("netty-http:http://app.mydatacenter.com/api");
+  }
+
+}
+-------------------------------------------------------
+
+Keep in mind that `KuraRouter` implements
+the `org.osgi.framework.BundleActivator` interface, so you need to
+register its `start` and `stop` lifecycle methods
+while http://eclipse.github.io/kura/doc/hello-example.html#create-component-class[creating
+Kura bundle component class].
+
+Kura router starts its own OSGi-aware `CamelContext`. It means that for
+every class extending `KuraRouter`, there will be a dedicated
+`CamelContext` instance. Ideally we recommend to deploy one `KuraRouter`
+per OSGi bundle.
+
+[[Kura-DeployingKuraRouter]]
+=== Deploying KuraRouter
+
+Bundle containing your Kura router class should import the following
+packages in the OSGi manifest:
+
+[source,xml]
+--------------------------------------------------------------------------------------------------------------------
+Import-Package: org.osgi.framework;version="1.3.0",
+  org.slf4j;version="1.6.4",
+  org.apache.camel,org.apache.camel.impl,org.apache.camel.core.osgi,org.apache.camel.builder,org.apache.camel.model,
+  org.apache.camel.component.kura
+--------------------------------------------------------------------------------------------------------------------
+
+Keep in mind that you don't have to import every Camel component bundle
+you plan to use in your routes, as Camel components are resolved as the
+services on the runtime level.
+
+Before you deploy your router bundle, be sure that you have deployed
+(and started) the following Camel core bundles (using Kura GoGo
+shell)...
+
+[source,xml]
+-----------------------------------------------------------------------------------------------------------
+install file:///home/user/.m2/repository/org/apache/camel/camel-core/2.15.0/camel-core-2.15.0.jar
+start <camel-core-bundle-id>
+install file:///home/user/.m2/repository/org/apache/camel/camel-core-osgi/2.15.0/camel-core-osgi-2.15.0.jar
+start <camel-core-osgi-bundle-id>
+install file:///home/user/.m2/repository/org/apache/camel/camel-kura/2.15.0/camel-kura-2.15.0.jar 
+start <camel-kura-bundle-id>
+-----------------------------------------------------------------------------------------------------------
+
+...and all the components you plan to use in your routes:
+
+[source,xml]
+-----------------------------------------------------------------------------------------------------
+install file:///home/user/.m2/repository/org/apache/camel/camel-stream/2.15.0/camel-stream-2.15.0.jar
+start <camel-stream-bundle-id>
+-----------------------------------------------------------------------------------------------------
+
+Then finally deploy your router bundle:
+
+[source,xml]
+----------------------------------------------------------------------------------
+install file:///home/user/.m2/repository/com/example/myrouter/1.0/myrouter-1.0.jar
+start <your-bundle-id>
+----------------------------------------------------------------------------------
+
+[[Kura-KuraRouterutilities]]
+=== KuraRouter utilities 
+
+ Kura router base class provides many useful utilities. This section
+explores each of them.
+
+[[Kura-SLF4Jlogger]]
+==== SLF4J logger
+
+Kura uses SLF4J facade for logging purposes. Protected member `log`
+returns SLF4J logger instance associated with the given Kura router.
+
+[source,java]
+----------------------------------------------
+public class MyKuraRouter extends KuraRouter {
+
+    @Override
+    public void configure() throws Exception {
+        log.info("Configuring Camel routes!");
+        ...
+    }
+
+}
+----------------------------------------------
+
+[[Kura-BundleContext]]
+==== BundleContext
+
+Protected member `bundleContext` returns bundle context associated with
+the given Kura router.
+
+[source,java]
+---------------------------------------------------------------------------------------------------------------
+public class MyKuraRouter extends KuraRouter {
+
+    @Override
+    public void configure() throws Exception {
+        ServiceReference<MyService> serviceRef = bundleContext.getServiceReference(LogService.class.getName());
+        MyService myService = bundleContext.getService(serviceRef);
+        ...
+    }
+
+}
+---------------------------------------------------------------------------------------------------------------
+
+[[Kura-CamelContext]]
+==== CamelContext
+
+Protected member `camelContext` is the `CamelContext` associated with
+the given Kura router.
+
+[source,java]
+----------------------------------------------
+public class MyKuraRouter extends KuraRouter {
+
+    @Override
+    public void configure() throws Exception {
+        camelContext.getStatus();
+        ...
+    }
+
+}
+----------------------------------------------
+
+[[Kura-ProducerTemplate]]
+==== ProducerTemplate
+
+Protected member `producerTemplate` is the `ProducerTemplate` instance
+associated with the given Camel context.
+
+[source,java]
+-----------------------------------------------------------
+public class MyKuraRouter extends KuraRouter {
+
+    @Override
+    public void configure() throws Exception {
+        producerTemplate.sendBody("jms:temperature", 22.0);
+        ...
+    }
+
+}
+-----------------------------------------------------------
+
+[[Kura-ConsumerTemplate]]
+==== ConsumerTemplate
+
+Protected member `consumerTemplate` is the `ConsumerTemplate` instance
+associated with the given Camel context.
+
+[source,java]
+--------------------------------------------------------------------------------------------------
+public class MyKuraRouter extends KuraRouter {
+
+    @Override
+    public void configure() throws Exception {
+        double currentTemperature = producerTemplate.receiveBody("jms:temperature", Double.class);
+        ...
+    }
+
+}
+--------------------------------------------------------------------------------------------------
+
+[[Kura-OSGiserviceresolver]]
+==== OSGi service resolver
+
+OSGi service resolver (`service(Class<T> serviceType)`) can be used to
+easily retrieve service by type from the OSGi bundle context.
+
+[source,java]
+-------------------------------------------------------
+public class MyKuraRouter extends KuraRouter {
+
+    @Override
+    public void configure() throws Exception {
+        MyService myService = service(MyService.class);
+        ...
+    }
+
+}
+-------------------------------------------------------
+
+If service is not found, a `null` value is returned. If you want your
+application to fail if the service is not available, use
+`requiredService(Class)` method instead. The `requiredService` throws
+`IllegalStateException` if a service cannot be found.
+
+[source,java]
+---------------------------------------------------------------
+public class MyKuraRouter extends KuraRouter {
+
+    @Override
+    public void configure() throws Exception {
+        MyService myService = requiredService(MyService.class);
+        ...
+    }
+
+}
+---------------------------------------------------------------
+
+[[Kura-KuraRouteractivatorcallbacks]]
+=== KuraRouter activator callbacks
+
+Kura router comes with the lifecycle callbacks that can be used to
+customize the way the Camel router works. For example to configure the
+`CamelContext` instance associated with the router just before the
+former is started, override `beforeStart` method of the `KuraRouter`
+class:
+
+[source,java]
+--------------------------------------------------------------------------
+public class MyKuraRouter extends KuraRouter {
+ 
+  ...
+
+  protected void beforeStart(CamelContext camelContext) {
+    OsgiDefaultCamelContext osgiContext = (OsgiCamelContext) camelContext;
+    osgiContext.setName("NameOfTheRouter");
+  }
+
+}
+--------------------------------------------------------------------------
+
+[[Kura-LoadingXMLroutesfromConfigurationAdmin]]
+=== Loading XML routes from ConfigurationAdmin
+
+Sometimes it is desired to read the XML definition of the routes from
+the server configuration. This a common scenario for IoT gateways where
+over-the-air redeployment cost may be significant. To address this
+requirement each `KuraRouter` looks for the
+`kura.camel.BUNDLE-SYMBOLIC-NAME.route` property from the `kura.camel`
+PID using the OSGi ConfigurationAdmin. This approach allows you to
+define Camel XML routes file per deployed `KuraRouter`. In order to
+update a route, just edit an appropriate configuration property and
+restart a bundle associated with it. The content of
+the `kura.camel.BUNDLE-SYMBOLIC-NAME.route` property is expected to be
+Camel XML route file, for example:
+
+[source,java]
+------------------------------------------------------
+<routes xmlns="http://camel.apache.org/schema/spring">
+    <route id="loaded">
+        <from uri="direct:bar"/>
+        <to uri="mock:bar"/>
+    </route>
+</routes>
+------------------------------------------------------
+
+ 
+
+[[Kura-DeployingKurarouterasadeclarativeOSGiservice]]
+=== Deploying Kura router as a declarative OSGi service
+
+If you would like to deploy your Kura router as a declarative OSGi
+service, you can use `activate` and `deactivate` methods provided by
+`KuraRouter`.
+
+[source,java]
+----------------------------------------------------------------------------------------------------------------------------------------------
+<scr:component name="org.eclipse.kura.example.camel.MyKuraRouter" activate="activate" deactivate="deactivate" enabled="true" immediate="true">
+  <implementation class="org.eclipse.kura.example.camel.MyKuraRouter"/>
+</scr:component>
+----------------------------------------------------------------------------------------------------------------------------------------------
+
diff --git a/components/camel-kura/src/main/java/org/apache/camel/component/kura/KuraRouter.java b/components/camel-kura/src/main/java/org/apache/camel/component/kura/KuraRouter.java
new file mode 100644
index 0000000..6f48073
--- /dev/null
+++ b/components/camel-kura/src/main/java/org/apache/camel/component/kura/KuraRouter.java
@@ -0,0 +1,149 @@
+/*
+ * 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.kura;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ConsumerTemplate;
+import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.core.osgi.OsgiDefaultCamelContext;
+import org.apache.camel.model.Model;
+import org.apache.camel.model.RoutesDefinition;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class KuraRouter extends RouteBuilder implements BundleActivator {
+
+    // Member collaborators
+
+    protected final Logger log = LoggerFactory.getLogger(getClass());
+
+    protected BundleContext bundleContext;
+
+    protected CamelContext camelContext;
+
+    protected ProducerTemplate producerTemplate;
+
+    protected ConsumerTemplate consumerTemplate;
+
+    // Lifecycle
+
+    @Override
+    public void start(BundleContext bundleContext) throws Exception {
+        try {
+            this.bundleContext = bundleContext;
+            log.debug("Initializing bundle {}.", bundleContext.getBundle().getBundleId());
+            camelContext = createCamelContext();
+
+            camelContext.addRoutes(this);
+            ConfigurationAdmin configurationAdmin = requiredService(ConfigurationAdmin.class);
+            Configuration camelKuraConfig = configurationAdmin.getConfiguration(camelXmlRoutesPid());
+            if (camelKuraConfig != null && camelKuraConfig.getProperties() != null) {
+                Object routePropertyValue = camelKuraConfig.getProperties().get(camelXmlRoutesProperty());
+                if (routePropertyValue != null) {
+                    InputStream routesXml = new ByteArrayInputStream(routePropertyValue.toString().getBytes());
+                    ExtendedCamelContext ecc = camelContext.adapt(ExtendedCamelContext.class);
+                    RoutesDefinition routes = (RoutesDefinition) ecc.getXMLRoutesDefinitionLoader().loadRoutesDefinition(ecc, routesXml);
+                    camelContext.getExtension(Model.class).addRouteDefinitions(routes.getRoutes());
+                }
+            }
+
+            beforeStart(camelContext);
+            log.debug("About to start Camel Kura router: {}", getClass().getName());
+            camelContext.start();
+            producerTemplate = camelContext.createProducerTemplate();
+            consumerTemplate = camelContext.createConsumerTemplate();
+            log.debug("Bundle {} started.", bundleContext.getBundle().getBundleId());
+        } catch (Throwable e) {
+            String errorMessage = "Problem when starting Kura module " + getClass().getName() + ":";
+            log.warn(errorMessage, e);
+
+            // Print error to the Kura console.
+            System.err.println(errorMessage);
+            e.printStackTrace();
+
+            throw e;
+        }
+    }
+
+    @Override
+    public void stop(BundleContext bundleContext) throws Exception {
+        log.debug("Stopping bundle {}.", bundleContext.getBundle().getBundleId());
+        camelContext.stop();
+        log.debug("Bundle {} stopped.", bundleContext.getBundle().getBundleId());
+    }
+
+    protected void activate(ComponentContext componentContext, Map<String, Object> properties) throws Exception {
+        start(componentContext.getBundleContext());
+    }
+
+    protected void deactivate(ComponentContext componentContext) throws Exception {
+        stop(componentContext.getBundleContext());
+    }
+
+    // Callbacks
+
+    @Override
+    public void configure() throws Exception {
+        log.debug("No programmatic routes configuration found.");
+    }
+
+    protected CamelContext createCamelContext() {
+        return new OsgiDefaultCamelContext(bundleContext);
+    }
+
+    protected void beforeStart(CamelContext camelContext) {
+        log.debug("Empty KuraRouter CamelContext before start configuration - skipping.");
+    }
+
+    // API Helpers
+
+    protected <T> T service(Class<T> serviceType) {
+        ServiceReference reference = bundleContext.getServiceReference(serviceType.getName());
+        return reference == null ? null : (T) bundleContext.getService(reference);
+    }
+
+    protected <T> T requiredService(Class<T> serviceType) {
+        ServiceReference reference = bundleContext.getServiceReference(serviceType.getName());
+        if (reference == null) {
+            throw new IllegalStateException("Cannot find service: " + serviceType.getName());
+        }
+        return (T) bundleContext.getService(reference);
+    }
+
+    // Private helpers
+
+    protected String camelXmlRoutesPid() {
+        return "kura.camel";
+    }
+
+    protected String camelXmlRoutesProperty() {
+        return "kura.camel." + bundleContext.getBundle().getSymbolicName() + ".route";
+    }
+
+}
diff --git a/components/camel-kura/src/test/java/org/apache/camel/component/kura/KuraRouterTest.java b/components/camel-kura/src/test/java/org/apache/camel/component/kura/KuraRouterTest.java
new file mode 100644
index 0000000..7cb653b
--- /dev/null
+++ b/components/camel-kura/src/test/java/org/apache/camel/component/kura/KuraRouterTest.java
@@ -0,0 +1,144 @@
+/*
+ * 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.kura;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ServiceStatus;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.model.Model;
+import org.apache.commons.io.IOUtils;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+import static org.mockito.Mockito.mock;
+
+public class KuraRouterTest extends Assert {
+
+    TestKuraRouter router = new TestKuraRouter();
+
+    BundleContext bundleContext = mock(BundleContext.class, RETURNS_DEEP_STUBS);
+
+    ConfigurationAdmin configurationAdmin = mock(ConfigurationAdmin.class);
+
+    Configuration configuration = mock(Configuration.class);
+
+    @Before
+    public void before() throws Exception {
+        given(bundleContext.getBundle().getVersion().toString()).willReturn("version");
+        given(bundleContext.getBundle().getSymbolicName()).willReturn("symbolic_name");
+        given(bundleContext.getService(any(ServiceReference.class))).willReturn(configurationAdmin);
+
+        router.start(bundleContext);
+    }
+
+    @After
+    public void after() throws Exception {
+        router.stop(bundleContext);
+    }
+
+    @Test
+    public void shouldCloseCamelContext() throws Exception {
+        // When
+        router.stop(bundleContext);
+
+        // Then
+        Assert.assertEquals(ServiceStatus.Stopped, router.camelContext.getStatus());
+    }
+
+    @Test
+    public void shouldStartCamelContext() throws Exception {
+        // Given
+        String message = "foo";
+        MockEndpoint mockEndpoint = router.camelContext.getEndpoint("mock:test", MockEndpoint.class);
+        mockEndpoint.expectedBodiesReceived(message);
+
+        // When
+        router.producerTemplate.sendBody("direct:start", message);
+
+        // Then
+        mockEndpoint.assertIsSatisfied();
+    }
+
+    @Test
+    public void shouldCreateConsumerTemplate() throws Exception {
+        assertNotNull(router.consumerTemplate);
+    }
+
+    @Test
+    public void shouldReturnNoService() {
+        given(bundleContext.getServiceReference(any(String.class))).willReturn(null);
+        assertNull(router.service(ConfigurationAdmin.class));
+    }
+
+    @Test
+    public void shouldReturnService() {
+        assertNotNull(router.service(ConfigurationAdmin.class));
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void shouldValidateLackOfService() {
+        given(bundleContext.getServiceReference(any(String.class))).willReturn(null);
+        router.requiredService(ConfigurationAdmin.class);
+    }
+
+    @Test
+    public void shouldLoadXmlRoutes() throws Exception {
+        // Given
+        given(configurationAdmin.getConfiguration(anyString())).willReturn(configuration);
+        Dictionary<String, Object> properties = new Hashtable<>();
+        String routeDefinition = IOUtils.toString(getClass().getResource("/route.xml"), StandardCharsets.UTF_8);
+        properties.put("kura.camel.symbolic_name.route", routeDefinition);
+        given(configuration.getProperties()).willReturn(properties);
+
+        // When
+        router.start(router.bundleContext);
+
+        // Then
+        assertNotNull(router.camelContext.getExtension(Model.class).getRouteDefinition("loaded"));
+    }
+
+    static class TestKuraRouter extends KuraRouter {
+
+        @Override
+        public void configure() throws Exception {
+            from("direct:start").to("mock:test");
+        }
+
+        @Override
+        protected CamelContext createCamelContext() {
+            return new DefaultCamelContext();
+        }
+
+    }
+
+}
+
diff --git a/components/camel-kura/src/test/resources/log4j2.properties b/components/camel-kura/src/test/resources/log4j2.properties
new file mode 100644
index 0000000..d3198e9
--- /dev/null
+++ b/components/camel-kura/src/test/resources/log4j2.properties
@@ -0,0 +1,30 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+appender.console.type = Console
+appender.console.name = console
+appender.console.layout.type = PatternLayout
+appender.console.layout.pattern = %d %-5p %c{1} - %m %n
+appender.file.type = File
+appender.file.name = file
+appender.file.fileName = target/camel-kura.log
+appender.file.layout.type = PatternLayout
+appender.file.layout.pattern = %d %-5p %c{1} - %m %n
+logger.kura.name = org.apache.camel.component.kura
+logger.kura.level = DEBUG
+rootLogger.level = INFO
+rootLogger.appenderRef.file.ref = file
diff --git a/components/camel-kura/src/test/resources/route.xml b/components/camel-kura/src/test/resources/route.xml
new file mode 100644
index 0000000..3999ef3
--- /dev/null
+++ b/components/camel-kura/src/test/resources/route.xml
@@ -0,0 +1,25 @@
+<?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.
+
+-->
+<routes xmlns="http://camel.apache.org/schema/spring">
+    <route id="loaded">
+        <from uri="direct:bar"/>
+        <to uri="mock:bar"/>
+    </route>
+</routes>
diff --git a/components/pom.xml b/components/pom.xml
index 1914ce9..19a1315 100644
--- a/components/pom.xml
+++ b/components/pom.xml
@@ -31,6 +31,7 @@
     <packaging>pom</packaging>
 
     <modules>
+        <module>camel-kura</module> 
         <module>camel-paxlogging</module>
     </modules>