You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2017/04/13 08:56:01 UTC

[2/2] camel git commit: Component docs

Component docs


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

Branch: refs/heads/master
Commit: 81f7515e545f3ffde83d61a0b52629951f67c233
Parents: 26f1e95
Author: Claus Ibsen <da...@apache.org>
Authored: Thu Apr 13 10:55:52 2017 +0200
Committer: Claus Ibsen <da...@apache.org>
Committed: Thu Apr 13 10:55:52 2017 +0200

----------------------------------------------------------------------
 .../camel-scr/src/main/docs/camel-and-scr.adoc  | 653 ------------------
 components/camel-scr/src/main/docs/scr.adoc     | 655 +++++++++++++++++++
 2 files changed, 655 insertions(+), 653 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/81f7515e/components/camel-scr/src/main/docs/camel-and-scr.adoc
----------------------------------------------------------------------
diff --git a/components/camel-scr/src/main/docs/camel-and-scr.adoc b/components/camel-scr/src/main/docs/camel-and-scr.adoc
deleted file mode 100644
index b4cfe39..0000000
--- a/components/camel-scr/src/main/docs/camel-and-scr.adoc
+++ /dev/null
@@ -1,653 +0,0 @@
-## Working with Camel and SCR
-
-SCR stands for Service Component Runtime and is an implementation of
-OSGi Declarative Services specification. SCR enables any plain old Java
-object to expose and use OSGi services with no boilerplate code.
-
-OSGi framework knows your object by looking at SCR descriptor files in
-its bundle which are typically generated from Java annotations by a
-plugin such as `org.apache.felix:maven-scr-plugin`.
-
-Running Camel in an SCR bundle is a great alternative for Spring DM and
-Blueprint based solutions having significantly fewer lines of code
-between you and the OSGi framework. Using SCR your bundle can remain
-completely in Java world; there is no need to edit XML or properties
-files. This offers you full control over everything and means your IDE
-of choice knows exactly what is going on in your project.
-
-### Camel SCR support
-
-INFO: *Available as of Camel 2.15.0*. 
-Camel-scr bundle is not included in Apache Camel versions prior 2.15.0,
-but the artifact itself can be used with any Camel version since 2.12.0.
-
-`org.apache.camel/camel-scr` bundle provides a base class,
-`AbstractCamelRunner`, which manages a Camel context for you and a
-helper class, `ScrHelper`, for using your SCR properties in unit tests.
-Camel-scr feature for Apache Karaf�defines all features and bundles
-required for running Camel in SCR bundles.
-
-`AbstractCamelRunner`�class ties CamelContext's lifecycle to Service
-Component's lifecycle and handles configuration with help of Camel's
-PropertiesComponent. All you have to do to make a Service Component out
-of your java class is to extend it from `AbstractCamelRunner`�and add
-the following `org.apache.felix.scr.annotations` on class level:
-
-*Add required annotations*
-
-[source,java]
----------------------------------------------------------------------------------------------------------------
-@Component
-@References({
-    @Reference(name = "camelComponent",referenceInterface = ComponentResolver.class,
-        cardinality = ReferenceCardinality.MANDATORY_MULTIPLE, policy = ReferencePolicy.DYNAMIC,
-        policyOption = ReferencePolicyOption.GREEDY, bind = "gotCamelComponent", unbind = "lostCamelComponent")
-})
----------------------------------------------------------------------------------------------------------------
-
-Then implement `getRouteBuilders()` method which returns the Camel
-routes you want to run:
-
-*Implement getRouteBuilders()*
-
-[source,java]
-------------------------------------------------------------------
-    @Override
-    protected List<RoutesBuilder> getRouteBuilders() {
-        List<RoutesBuilder> routesBuilders = new ArrayList<>();
-        routesBuilders.add(new YourRouteBuilderHere(registry));
-        routesBuilders.add(new AnotherRouteBuilderHere(registry));
-        return routesBuilders;
-    }
-------------------------------------------------------------------
-
-And finally provide the default configuration with:
-
-*Default configuration in annotations*
-
-[source,java]
----------------------------------------------------------
-@Properties({
-   @Property(name = "camelContextId", value = "my-test"),
-   @Property(name = "active", value = "true"),
-   @Property(name = "...", value = "..."),
-   ...
-})
----------------------------------------------------------
-
-�
-
-That's all. And if you used `camel-archetype-scr` to generate a project
-all this is already taken care of.
-
-Below is an example of a complete Service Component class, generated by
-`camel-archetype-scr:`
-
-*CamelScrExample.java*
-
-[source,java]
--------------------------------------------------------------------------------------------------------------------------------------------
-// This file was generated from org.apache.camel.archetypes/camel-archetype-scr/2.15-SNAPSHOT
-package example;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.camel.scr.AbstractCamelRunner;
-import example.internal.CamelScrExampleRoute;
-import org.apache.camel.RoutesBuilder;
-import org.apache.camel.spi.ComponentResolver;
-import org.apache.felix.scr.annotations.*;
-
-@Component(label = CamelScrExample.COMPONENT_LABEL, description = CamelScrExample.COMPONENT_DESCRIPTION, immediate = true, metatype = true)
-@Properties({
-    @Property(name = "camelContextId", value = "camel-scr-example"),
-    @Property(name = "camelRouteId", value = "foo/timer-log"),
-    @Property(name = "active", value = "true"),
-    @Property(name = "from", value = "timer:foo?period=5000"),
-    @Property(name = "to", value = "log:foo?showHeaders=true"),
-    @Property(name = "messageOk", value = "Success: {{from}} -> {{to}}"),
-    @Property(name = "messageError", value = "Failure: {{from}} -> {{to}}"),
-    @Property(name = "maximumRedeliveries", value = "0"),
-    @Property(name = "redeliveryDelay", value = "5000"),
-    @Property(name = "backOffMultiplier", value = "2"),
-    @Property(name = "maximumRedeliveryDelay", value = "60000")
-})
-@References({
-    @Reference(name = "camelComponent",referenceInterface = ComponentResolver.class,
-        cardinality = ReferenceCardinality.MANDATORY_MULTIPLE, policy = ReferencePolicy.DYNAMIC,
-        policyOption = ReferencePolicyOption.GREEDY, bind = "gotCamelComponent", unbind = "lostCamelComponent")
-})
-public class CamelScrExample extends AbstractCamelRunner {
-
-    public static final String COMPONENT_LABEL = "example.CamelScrExample";
-    public static final String COMPONENT_DESCRIPTION = "This is the description for camel-scr-example.";
-
-    @Override
-    protected List<RoutesBuilder> getRouteBuilders() {
-        List<RoutesBuilder> routesBuilders = new ArrayList<>();
-        routesBuilders.add(new CamelScrExampleRoute(registry));
-        return routesBuilders;
-    }
-}
--------------------------------------------------------------------------------------------------------------------------------------------
-
-�
-
-`CamelContextId`�and `active`�properties control the CamelContext's name
-(defaults to "camel-runner-default") and whether it will be started or
-not (defaults to "false"), respectively. In addition to these you can
-add and use as many properties as you like. Camel's PropertiesComponent
-handles recursive properties and prefixing with fallback without
-problem.
-
-`AbstractCamelRunner`�will make these properties available to your
-RouteBuilders with help of Camel's PropertiesComponent and it will also
-inject these values into your Service Component's and RouteBuilder's
-fields when their names match. The fields can be declared with any
-visibility level, and many types are supported (String, int, boolean,
-URL, ...).
-
-Below is an example of a RouteBuilder class generated by
-`camel-archetype-scr`:
-
-�
-
-*CamelScrExampleRoute.java*
-
-[source,java]
------------------------------------------------------------------------------------------------
-// This file was generated from org.apache.camel.archetypes/camel-archetype-scr/2.15-SNAPSHOT
-package example.internal;
-
-import org.apache.camel.LoggingLevel;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.impl.SimpleRegistry;
-import org.apache.commons.lang.Validate;
-
-public class CamelScrExampleRoute extends RouteBuilder {
-
-    SimpleRegistry registry;
-
-    // Configured fields
-    private String camelRouteId;
-    private Integer maximumRedeliveries;
-    private Long redeliveryDelay;
-    private Double backOffMultiplier;
-    private Long maximumRedeliveryDelay;
-
-    public CamelScrExampleRoute(final SimpleRegistry registry) {
-        this.registry = registry;
-    }
-
-    @Override
-    public void configure() throws Exception {
-        checkProperties();
-
-        // Add a bean to Camel context registry
-        registry.put("test", "bean");
-
-        errorHandler(defaultErrorHandler()
-            .retryAttemptedLogLevel(LoggingLevel.WARN)
-            .maximumRedeliveries(maximumRedeliveries)
-            .redeliveryDelay(redeliveryDelay)
-            .backOffMultiplier(backOffMultiplier)
-            .maximumRedeliveryDelay(maximumRedeliveryDelay));
-
-        from("{{from}}")
-            .startupOrder(2)
-            .routeId(camelRouteId)
-            .onCompletion()
-                .to("direct:processCompletion")
-            .end()
-            .removeHeaders("CamelHttp*")
-            .to("{{to}}");
-
-
-        from("direct:processCompletion")
-            .startupOrder(1)
-            .routeId(camelRouteId + ".completion")
-            .choice()
-                .when(simple("${exception} == null"))
-                    .log("{{messageOk}}")
-                .otherwise()
-                    .log(LoggingLevel.ERROR, "{{messageError}}")
-            .end();
-        }
-    }
-
-    public void checkProperties() {
-        Validate.notNull(camelRouteId, "camelRouteId property is not set");
-        Validate.notNull(maximumRedeliveries, "maximumRedeliveries property is not set");
-        Validate.notNull(redeliveryDelay, "redeliveryDelay property is not set");
-        Validate.notNull(backOffMultiplier, "backOffMultiplier property is not set");
-        Validate.notNull(maximumRedeliveryDelay, "maximumRedeliveryDelay property is not set");
-    }
-}
------------------------------------------------------------------------------------------------
-
-�
-
-Let's take a look at `CamelScrExampleRoute` in more detail.
-
-�
-
-[source,java]
-----------------------------------------
-    // Configured fields
-    private String camelRouteId;
-    private Integer maximumRedeliveries;
-    private Long redeliveryDelay;
-    private Double backOffMultiplier;
-    private Long maximumRedeliveryDelay;
-----------------------------------------
-
-The values of these fields are set with values from properties by
-matching their names.
-
-�
-
-[source,java]
------------------------------------------------
-        // Add a bean to Camel context registry
-        registry.put("test", "bean");
------------------------------------------------
-
-If you need to add some beans to CamelContext's registry for your
-routes, you can do it like this.
-
-�
-
-[source,java]
------------------------------------------------------------------------------------------------
-    public void checkProperties() {
-        Validate.notNull(camelRouteId, "camelRouteId property is not set");
-        Validate.notNull(maximumRedeliveries, "maximumRedeliveries property is not set");
-        Validate.notNull(redeliveryDelay, "redeliveryDelay property is not set");
-        Validate.notNull(backOffMultiplier, "backOffMultiplier property is not set");
-        Validate.notNull(maximumRedeliveryDelay, "maximumRedeliveryDelay property is not set");
-    }
------------------------------------------------------------------------------------------------
-
-It is a good idea to check that required parameters are set and they
-have meaningful values before allowing the routes to start.
-
-�
-
-[source,java]
-----------------------------------------------------------------
-        from("{{from}}")
-            .startupOrder(2)
-            .routeId(camelRouteId)
-            .onCompletion()
-                .to("direct:processCompletion")
-            .end()
-            .removeHeaders("CamelHttp*")
-            .to("{{to}}");
-
-
-        from("direct:processCompletion")
-            .startupOrder(1)
-            .routeId(camelRouteId + ".completion")
-            .choice()
-                .when(simple("${exception} == null"))
-                    .log("{{messageOk}}")
-                .otherwise()
-                    .log(LoggingLevel.ERROR, "{{messageError}}")
-            .end();
-----------------------------------------------------------------
-
-Note that pretty much everything in the route is configured with
-properties. This essentially makes your RouteBuilder a template. SCR
-allows you to create more instances of your routes just by providing
-alternative configurations. More on this in section _Using Camel SCR
-bundle as a template_.
-
-### AbstractCamelRunner's lifecycle in SCR
-
-1.  When component's configuration policy and mandatory references are
-satisfied SCR calls `activate()`. This creates and sets up a
-CamelContext through the following call chain:
-`activate()`�\u2192�`prepare()`�\u2192�`createCamelContext()`
-\u2192�`setupPropertiesComponent()` \u2192�`configure()` \u2192�`setupCamelContext()`.
-Finally, the context is scheduled to start after a delay defined in
-`AbstractCamelRunner.START_DELAY`�with `runWithDelay()`.
-2.  When Camel components (`ComponentResolver` services, to be exact)
-are registered in OSGi, SCR calls `gotCamelComponent``()` which
-reschedules/delays the CamelContext start further by the same
-`AbstractCamelRunner.START_DELAY`. This in effect makes CamelContext
-wait until all Camel components are loaded or there is a sufficient gap
-between them. The same logic will tell a failed-to-start CamelContext to
-try again whenever we add more Camel components.
-3.  When Camel components are unregistered SCR calls
-`lostCamelComponent``()`. This call does nothing.
-4.  When one of the requirements that caused the call to `activate``()`
-is lost SCR will call `deactivate``()`. This will shutdown the
-CamelContext.
-
-In (non-OSGi) unit tests you should use `prepare()` \u2192�`run()` \u2192�`stop()`
-instead of `activate()` \u2192�`deactivate()` for more fine-grained control.
-Also, this allows us to avoid possible SCR specific operations in tests.
-
-### Using camel-archetype-scr
-
-The easiest way to create an Camel SCR bundle project is to use
-`camel-archetype-scr`�and Maven.
-
-You can generate a project with the following steps:
-
-*Generating a project*
-
-[source,text]
---------------------------------------------------------------------------------------------------------------
-$ mvn archetype:generate -Dfilter=org.apache.camel.archetypes:camel-archetype-scr
-�
-Choose archetype:
-1: local -> org.apache.camel.archetypes:camel-archetype-scr (Creates a new Camel SCR bundle project for Karaf)
-Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): : 1
-Define value for property 'groupId': : example
-[INFO] Using property: groupId = example
-Define value for property 'artifactId': : camel-scr-example
-Define value for property 'version': 1.0-SNAPSHOT: :
-Define value for property 'package': example: :
-[INFO] Using property: archetypeArtifactId = camel-archetype-scr
-[INFO] Using property: archetypeGroupId = org.apache.camel.archetypes
-[INFO] Using property: archetypeVersion = 2.15-SNAPSHOT
-Define value for property 'className': : CamelScrExample
-Confirm properties configuration:
-groupId: example
-artifactId: camel-scr-example
-version: 1.0-SNAPSHOT
-package: example
-archetypeArtifactId: camel-archetype-scr
-archetypeGroupId: org.apache.camel.archetypes
-archetypeVersion: 2.15-SNAPSHOT
-className: CamelScrExample
-Y: :
---------------------------------------------------------------------------------------------------------------
-
-Done!
-
-Now run:
-
-[source,java]
------------
-mvn install
------------
-
-and the bundle is ready to be deployed.
-
-### Unit testing Camel routes
-
-Service Component is a POJO and has no special requirements for
-(non-OSGi) unit testing. There are however some techniques that are
-specific to Camel SCR or just make testing easier.
-
-Below is an example unit test, generated by `camel-archetype-scr`:
-
-[source,java]
-------------------------------------------------------------------------------------------------------
-// This file was generated from org.apache.camel.archetypes/camel-archetype-scr/2.15-SNAPSHOT
-package example;
-
-import java.util.List;
-
-import org.apache.camel.scr.internal.ScrHelper;
-import org.apache.camel.builder.AdviceWithRouteBuilder;
-import org.apache.camel.component.mock.MockComponent;
-import org.apache.camel.component.mock.MockEndpoint;
-import org.apache.camel.model.ModelCamelContext;
-import org.apache.camel.model.RouteDefinition;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TestName;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-public class CamelScrExampleTest {
-
-    Logger log = LoggerFactory.getLogger(getClass());
-
-    @Rule
-    public TestName testName = new TestName();
-
-    CamelScrExample integration;
-    ModelCamelContext context;
-
-    @Before
-    public void setUp() throws Exception {
-        log.info("*******************************************************************");
-        log.info("Test: " + testName.getMethodName());
-        log.info("*******************************************************************");
-
-        // Set property prefix for unit testing
-        System.setProperty(CamelScrExample.PROPERTY_PREFIX, "unit");
-
-        // Prepare the integration
-        integration = new CamelScrExample();
-        integration.prepare(null, ScrHelper.getScrProperties(integration.getClass().getName()));
-        context = integration.getContext();
-
-        // Disable JMX for test
-        context.disableJMX();
-
-        // Fake a component for test
-        context.addComponent("amq", new MockComponent());
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        integration.stop();
-    }
-
-    @Test
-    public void testRoutes() throws Exception {
-        // Adjust routes
-        List<RouteDefinition> routes = context.getRouteDefinitions();
-
-        routes.get(0).adviceWith(context, new AdviceWithRouteBuilder() {
-            @Override
-            public void configure() throws Exception {
-                // Replace "from" endpoint with direct:start
-                replaceFromWith("direct:start");
-                // Mock and skip result endpoint
-                mockEndpoints("log:*");
-            }
-        });
-
-        MockEndpoint resultEndpoint = context.getEndpoint("mock:log:foo", MockEndpoint.class);
-        // resultEndpoint.expectedMessageCount(1); // If you want to just check the number of messages
-        resultEndpoint.expectedBodiesReceived("hello"); // If you want to check the contents
-
-        // Start the integration
-        integration.run();
-
-        // Send the test message
-        context.createProducerTemplate().sendBody("direct:start", "hello");
-
-        resultEndpoint.assertIsSatisfied();
-    }
-}
-------------------------------------------------------------------------------------------------------
-
-�
-
-Now, let's take a look at the interesting bits one by one.
-
-*Using property prefixing*
-
-[source,java]
---------------------------------------------------------------------
-        // Set property prefix for unit testing
-        System.setProperty(CamelScrExample.PROPERTY_PREFIX, "unit");
---------------------------------------------------------------------
-
-This allows you to override parts of the configuration by prefixing
-properties with "unit.". For example, `unit.from` overrides `from` for
-the unit test.
-
-Prefixes can be used to handle the differences between the runtime
-environments where your routes might run. Moving the unchanged bundle
-through development, testing and production environments is a typical
-use case.
-
-�
-
-*Getting test configuration from annotations*
-
-[source,java]
-------------------------------------------------------------------------------------------------
-        integration.prepare(null, ScrHelper.getScrProperties(integration.getClass().getName()));
-------------------------------------------------------------------------------------------------
-
-Here we configure the Service Component in test with the same properties
-that would be used in OSGi environment.
-
-�
-
-*Mocking components for test*
-
-[source,java]
----------------------------------------------------------
-        // Fake a component for test
-        context.addComponent("amq", new MockComponent());
----------------------------------------------------------
-
-Components that are not available in test can be mocked like this to
-allow the route to start.
-
-�
-
-*Adjusting routes for test*
-
-[source,java]
-------------------------------------------------------------------------
-        // Adjust routes
-        List<RouteDefinition> routes = context.getRouteDefinitions();
-
-        routes.get(0).adviceWith(context, new AdviceWithRouteBuilder() {
-            @Override
-            public void configure() throws Exception {
-                // Replace "from" endpoint with direct:start
-                replaceFromWith("direct:start");
-                // Mock and skip result endpoint
-                mockEndpoints("log:*");
-            }
-        });
-------------------------------------------------------------------------
-
-Camel's AdviceWith feature allows routes to be modified for test.
-
-�
-
-*Starting the routes*
-
-[source,java]
---------------------------------
-        // Start the integration
-        integration.run();
---------------------------------
-
-Here we start the Service Component and along with it the routes.
-
-�
-
-*Sending a test message*
-
-[source,java]
----------------------------------------------------------------------------
-        // Send the test message
-        context.createProducerTemplate().sendBody("direct:start", "hello");
----------------------------------------------------------------------------
-
-Here we send a message to a route in test.
-
-### Running the bundle in Apache Karaf
-
-Once the bundle has been built with `mvn install` it's ready to be
-deployed.�To deploy the bundle on Apache Karaf perform the following
-steps on Karaf command line:
-
-*Deploying the bundle in Apache Karaf*
-
-[source,text]
-------------------------------------------------------------------------
-# Add Camel feature repository
-karaf@root> features:chooseurl camel 2.15-SNAPSHOT
-�
-# Install camel-scr feature
-karaf@root> features:install camel-scr
-�
-# Install commons-lang, used in the example route to validate parameters
-karaf@root> osgi:install mvn:commons-lang/commons-lang/2.6
-�
-# Install and start your bundle
-karaf@root> osgi:install -s mvn:example/camel-scr-example/1.0-SNAPSHOT
-�
-# See how it's running
-karaf@root> log:tail -n 10
-�
-Press ctrl-c to stop watching the log.
-------------------------------------------------------------------------
-
-#### Overriding the default configuration
-
-By default, Service Component's configuration PID equals the fully
-qualified name of its class. You can change the example bundle's
-properties with Karaf's�`config:*` commands:
-
-*Override a property*
-
-[source,text]
-----------------------------------------------------------------------------------------
-# Override 'messageOk' property
-karaf@root> config:propset -p example.CamelScrExample messageOk "This is better logging"
-----------------------------------------------------------------------------------------
-
-Or you can change the configuration by editing property files in Karaf's
-`etc` folder.
-
-#### Using Camel SCR bundle as a template
-
-Let's say you have a Camel SCR bundle that implements an integration
-pattern that you use frequently, say, *from \u2192�to*, with success/failure
-logging and redelivery which also happens to be the pattern our example
-route implements. You probably don't want to create a separate bundle
-for every instance. No worries, SCR has you covered.
-
-Create a configuration PID for your Service Component, but add a tail
-with a dash and SCR will use that configuration to create a new instance
-of your component.
-
-*Creating a new Service Component instance*
-
-[source,text]
-------------------------------------------------------------------------
-# Create a PID with a tail
-karaf@root> config:edit example.CamelScrExample-anotherone
-�
-# Override some properties
-karaf@root> config:propset camelContextId my-other-context
-karaf@root> config:propset to "file://removeme?fileName=removemetoo.txt"
-�
-# Save the PID
-karaf@root> config:update
-------------------------------------------------------------------------
-
-This will start a new CamelContext with your overridden properties. How
-convenient.
-
-### Notes
-
-When designing a Service Component to be a template you typically don't
-want it to start without a "tailed" configuration i.e. with the default
-configuration.
-
-To prevent your Service Component from starting with the default
-configuration add `policy = ConfigurationPolicy.REQUIRE `to the class
-level `@Component` annotation.

http://git-wip-us.apache.org/repos/asf/camel/blob/81f7515e/components/camel-scr/src/main/docs/scr.adoc
----------------------------------------------------------------------
diff --git a/components/camel-scr/src/main/docs/scr.adoc b/components/camel-scr/src/main/docs/scr.adoc
new file mode 100644
index 0000000..451af6a
--- /dev/null
+++ b/components/camel-scr/src/main/docs/scr.adoc
@@ -0,0 +1,655 @@
+## Working with Camel and SCR
+
+**deprecated**
+
+SCR stands for Service Component Runtime and is an implementation of
+OSGi Declarative Services specification. SCR enables any plain old Java
+object to expose and use OSGi services with no boilerplate code.
+
+OSGi framework knows your object by looking at SCR descriptor files in
+its bundle which are typically generated from Java annotations by a
+plugin such as `org.apache.felix:maven-scr-plugin`.
+
+Running Camel in an SCR bundle is a great alternative for Spring DM and
+Blueprint based solutions having significantly fewer lines of code
+between you and the OSGi framework. Using SCR your bundle can remain
+completely in Java world; there is no need to edit XML or properties
+files. This offers you full control over everything and means your IDE
+of choice knows exactly what is going on in your project.
+
+### Camel SCR support
+
+INFO: *Available as of Camel 2.15.0*. 
+Camel-scr bundle is not included in Apache Camel versions prior 2.15.0,
+but the artifact itself can be used with any Camel version since 2.12.0.
+
+`org.apache.camel/camel-scr` bundle provides a base class,
+`AbstractCamelRunner`, which manages a Camel context for you and a
+helper class, `ScrHelper`, for using your SCR properties in unit tests.
+Camel-scr feature for Apache Karaf�defines all features and bundles
+required for running Camel in SCR bundles.
+
+`AbstractCamelRunner`�class ties CamelContext's lifecycle to Service
+Component's lifecycle and handles configuration with help of Camel's
+PropertiesComponent. All you have to do to make a Service Component out
+of your java class is to extend it from `AbstractCamelRunner`�and add
+the following `org.apache.felix.scr.annotations` on class level:
+
+*Add required annotations*
+
+[source,java]
+---------------------------------------------------------------------------------------------------------------
+@Component
+@References({
+    @Reference(name = "camelComponent",referenceInterface = ComponentResolver.class,
+        cardinality = ReferenceCardinality.MANDATORY_MULTIPLE, policy = ReferencePolicy.DYNAMIC,
+        policyOption = ReferencePolicyOption.GREEDY, bind = "gotCamelComponent", unbind = "lostCamelComponent")
+})
+---------------------------------------------------------------------------------------------------------------
+
+Then implement `getRouteBuilders()` method which returns the Camel
+routes you want to run:
+
+*Implement getRouteBuilders()*
+
+[source,java]
+------------------------------------------------------------------
+    @Override
+    protected List<RoutesBuilder> getRouteBuilders() {
+        List<RoutesBuilder> routesBuilders = new ArrayList<>();
+        routesBuilders.add(new YourRouteBuilderHere(registry));
+        routesBuilders.add(new AnotherRouteBuilderHere(registry));
+        return routesBuilders;
+    }
+------------------------------------------------------------------
+
+And finally provide the default configuration with:
+
+*Default configuration in annotations*
+
+[source,java]
+---------------------------------------------------------
+@Properties({
+   @Property(name = "camelContextId", value = "my-test"),
+   @Property(name = "active", value = "true"),
+   @Property(name = "...", value = "..."),
+   ...
+})
+---------------------------------------------------------
+
+�
+
+That's all. And if you used `camel-archetype-scr` to generate a project
+all this is already taken care of.
+
+Below is an example of a complete Service Component class, generated by
+`camel-archetype-scr:`
+
+*CamelScrExample.java*
+
+[source,java]
+-------------------------------------------------------------------------------------------------------------------------------------------
+// This file was generated from org.apache.camel.archetypes/camel-archetype-scr/2.15-SNAPSHOT
+package example;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.camel.scr.AbstractCamelRunner;
+import example.internal.CamelScrExampleRoute;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.spi.ComponentResolver;
+import org.apache.felix.scr.annotations.*;
+
+@Component(label = CamelScrExample.COMPONENT_LABEL, description = CamelScrExample.COMPONENT_DESCRIPTION, immediate = true, metatype = true)
+@Properties({
+    @Property(name = "camelContextId", value = "camel-scr-example"),
+    @Property(name = "camelRouteId", value = "foo/timer-log"),
+    @Property(name = "active", value = "true"),
+    @Property(name = "from", value = "timer:foo?period=5000"),
+    @Property(name = "to", value = "log:foo?showHeaders=true"),
+    @Property(name = "messageOk", value = "Success: {{from}} -> {{to}}"),
+    @Property(name = "messageError", value = "Failure: {{from}} -> {{to}}"),
+    @Property(name = "maximumRedeliveries", value = "0"),
+    @Property(name = "redeliveryDelay", value = "5000"),
+    @Property(name = "backOffMultiplier", value = "2"),
+    @Property(name = "maximumRedeliveryDelay", value = "60000")
+})
+@References({
+    @Reference(name = "camelComponent",referenceInterface = ComponentResolver.class,
+        cardinality = ReferenceCardinality.MANDATORY_MULTIPLE, policy = ReferencePolicy.DYNAMIC,
+        policyOption = ReferencePolicyOption.GREEDY, bind = "gotCamelComponent", unbind = "lostCamelComponent")
+})
+public class CamelScrExample extends AbstractCamelRunner {
+
+    public static final String COMPONENT_LABEL = "example.CamelScrExample";
+    public static final String COMPONENT_DESCRIPTION = "This is the description for camel-scr-example.";
+
+    @Override
+    protected List<RoutesBuilder> getRouteBuilders() {
+        List<RoutesBuilder> routesBuilders = new ArrayList<>();
+        routesBuilders.add(new CamelScrExampleRoute(registry));
+        return routesBuilders;
+    }
+}
+-------------------------------------------------------------------------------------------------------------------------------------------
+
+�
+
+`CamelContextId`�and `active`�properties control the CamelContext's name
+(defaults to "camel-runner-default") and whether it will be started or
+not (defaults to "false"), respectively. In addition to these you can
+add and use as many properties as you like. Camel's PropertiesComponent
+handles recursive properties and prefixing with fallback without
+problem.
+
+`AbstractCamelRunner`�will make these properties available to your
+RouteBuilders with help of Camel's PropertiesComponent and it will also
+inject these values into your Service Component's and RouteBuilder's
+fields when their names match. The fields can be declared with any
+visibility level, and many types are supported (String, int, boolean,
+URL, ...).
+
+Below is an example of a RouteBuilder class generated by
+`camel-archetype-scr`:
+
+�
+
+*CamelScrExampleRoute.java*
+
+[source,java]
+-----------------------------------------------------------------------------------------------
+// This file was generated from org.apache.camel.archetypes/camel-archetype-scr/2.15-SNAPSHOT
+package example.internal;
+
+import org.apache.camel.LoggingLevel;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.SimpleRegistry;
+import org.apache.commons.lang.Validate;
+
+public class CamelScrExampleRoute extends RouteBuilder {
+
+    SimpleRegistry registry;
+
+    // Configured fields
+    private String camelRouteId;
+    private Integer maximumRedeliveries;
+    private Long redeliveryDelay;
+    private Double backOffMultiplier;
+    private Long maximumRedeliveryDelay;
+
+    public CamelScrExampleRoute(final SimpleRegistry registry) {
+        this.registry = registry;
+    }
+
+    @Override
+    public void configure() throws Exception {
+        checkProperties();
+
+        // Add a bean to Camel context registry
+        registry.put("test", "bean");
+
+        errorHandler(defaultErrorHandler()
+            .retryAttemptedLogLevel(LoggingLevel.WARN)
+            .maximumRedeliveries(maximumRedeliveries)
+            .redeliveryDelay(redeliveryDelay)
+            .backOffMultiplier(backOffMultiplier)
+            .maximumRedeliveryDelay(maximumRedeliveryDelay));
+
+        from("{{from}}")
+            .startupOrder(2)
+            .routeId(camelRouteId)
+            .onCompletion()
+                .to("direct:processCompletion")
+            .end()
+            .removeHeaders("CamelHttp*")
+            .to("{{to}}");
+
+
+        from("direct:processCompletion")
+            .startupOrder(1)
+            .routeId(camelRouteId + ".completion")
+            .choice()
+                .when(simple("${exception} == null"))
+                    .log("{{messageOk}}")
+                .otherwise()
+                    .log(LoggingLevel.ERROR, "{{messageError}}")
+            .end();
+        }
+    }
+
+    public void checkProperties() {
+        Validate.notNull(camelRouteId, "camelRouteId property is not set");
+        Validate.notNull(maximumRedeliveries, "maximumRedeliveries property is not set");
+        Validate.notNull(redeliveryDelay, "redeliveryDelay property is not set");
+        Validate.notNull(backOffMultiplier, "backOffMultiplier property is not set");
+        Validate.notNull(maximumRedeliveryDelay, "maximumRedeliveryDelay property is not set");
+    }
+}
+-----------------------------------------------------------------------------------------------
+
+�
+
+Let's take a look at `CamelScrExampleRoute` in more detail.
+
+�
+
+[source,java]
+----------------------------------------
+    // Configured fields
+    private String camelRouteId;
+    private Integer maximumRedeliveries;
+    private Long redeliveryDelay;
+    private Double backOffMultiplier;
+    private Long maximumRedeliveryDelay;
+----------------------------------------
+
+The values of these fields are set with values from properties by
+matching their names.
+
+�
+
+[source,java]
+-----------------------------------------------
+        // Add a bean to Camel context registry
+        registry.put("test", "bean");
+-----------------------------------------------
+
+If you need to add some beans to CamelContext's registry for your
+routes, you can do it like this.
+
+�
+
+[source,java]
+-----------------------------------------------------------------------------------------------
+    public void checkProperties() {
+        Validate.notNull(camelRouteId, "camelRouteId property is not set");
+        Validate.notNull(maximumRedeliveries, "maximumRedeliveries property is not set");
+        Validate.notNull(redeliveryDelay, "redeliveryDelay property is not set");
+        Validate.notNull(backOffMultiplier, "backOffMultiplier property is not set");
+        Validate.notNull(maximumRedeliveryDelay, "maximumRedeliveryDelay property is not set");
+    }
+-----------------------------------------------------------------------------------------------
+
+It is a good idea to check that required parameters are set and they
+have meaningful values before allowing the routes to start.
+
+�
+
+[source,java]
+----------------------------------------------------------------
+        from("{{from}}")
+            .startupOrder(2)
+            .routeId(camelRouteId)
+            .onCompletion()
+                .to("direct:processCompletion")
+            .end()
+            .removeHeaders("CamelHttp*")
+            .to("{{to}}");
+
+
+        from("direct:processCompletion")
+            .startupOrder(1)
+            .routeId(camelRouteId + ".completion")
+            .choice()
+                .when(simple("${exception} == null"))
+                    .log("{{messageOk}}")
+                .otherwise()
+                    .log(LoggingLevel.ERROR, "{{messageError}}")
+            .end();
+----------------------------------------------------------------
+
+Note that pretty much everything in the route is configured with
+properties. This essentially makes your RouteBuilder a template. SCR
+allows you to create more instances of your routes just by providing
+alternative configurations. More on this in section _Using Camel SCR
+bundle as a template_.
+
+### AbstractCamelRunner's lifecycle in SCR
+
+1.  When component's configuration policy and mandatory references are
+satisfied SCR calls `activate()`. This creates and sets up a
+CamelContext through the following call chain:
+`activate()`�\u2192�`prepare()`�\u2192�`createCamelContext()`
+\u2192�`setupPropertiesComponent()` \u2192�`configure()` \u2192�`setupCamelContext()`.
+Finally, the context is scheduled to start after a delay defined in
+`AbstractCamelRunner.START_DELAY`�with `runWithDelay()`.
+2.  When Camel components (`ComponentResolver` services, to be exact)
+are registered in OSGi, SCR calls `gotCamelComponent``()` which
+reschedules/delays the CamelContext start further by the same
+`AbstractCamelRunner.START_DELAY`. This in effect makes CamelContext
+wait until all Camel components are loaded or there is a sufficient gap
+between them. The same logic will tell a failed-to-start CamelContext to
+try again whenever we add more Camel components.
+3.  When Camel components are unregistered SCR calls
+`lostCamelComponent``()`. This call does nothing.
+4.  When one of the requirements that caused the call to `activate``()`
+is lost SCR will call `deactivate``()`. This will shutdown the
+CamelContext.
+
+In (non-OSGi) unit tests you should use `prepare()` \u2192�`run()` \u2192�`stop()`
+instead of `activate()` \u2192�`deactivate()` for more fine-grained control.
+Also, this allows us to avoid possible SCR specific operations in tests.
+
+### Using camel-archetype-scr
+
+The easiest way to create an Camel SCR bundle project is to use
+`camel-archetype-scr`�and Maven.
+
+You can generate a project with the following steps:
+
+*Generating a project*
+
+[source,text]
+--------------------------------------------------------------------------------------------------------------
+$ mvn archetype:generate -Dfilter=org.apache.camel.archetypes:camel-archetype-scr
+�
+Choose archetype:
+1: local -> org.apache.camel.archetypes:camel-archetype-scr (Creates a new Camel SCR bundle project for Karaf)
+Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): : 1
+Define value for property 'groupId': : example
+[INFO] Using property: groupId = example
+Define value for property 'artifactId': : camel-scr-example
+Define value for property 'version': 1.0-SNAPSHOT: :
+Define value for property 'package': example: :
+[INFO] Using property: archetypeArtifactId = camel-archetype-scr
+[INFO] Using property: archetypeGroupId = org.apache.camel.archetypes
+[INFO] Using property: archetypeVersion = 2.15-SNAPSHOT
+Define value for property 'className': : CamelScrExample
+Confirm properties configuration:
+groupId: example
+artifactId: camel-scr-example
+version: 1.0-SNAPSHOT
+package: example
+archetypeArtifactId: camel-archetype-scr
+archetypeGroupId: org.apache.camel.archetypes
+archetypeVersion: 2.15-SNAPSHOT
+className: CamelScrExample
+Y: :
+--------------------------------------------------------------------------------------------------------------
+
+Done!
+
+Now run:
+
+[source,java]
+-----------
+mvn install
+-----------
+
+and the bundle is ready to be deployed.
+
+### Unit testing Camel routes
+
+Service Component is a POJO and has no special requirements for
+(non-OSGi) unit testing. There are however some techniques that are
+specific to Camel SCR or just make testing easier.
+
+Below is an example unit test, generated by `camel-archetype-scr`:
+
+[source,java]
+------------------------------------------------------------------------------------------------------
+// This file was generated from org.apache.camel.archetypes/camel-archetype-scr/2.15-SNAPSHOT
+package example;
+
+import java.util.List;
+
+import org.apache.camel.scr.internal.ScrHelper;
+import org.apache.camel.builder.AdviceWithRouteBuilder;
+import org.apache.camel.component.mock.MockComponent;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.model.ModelCamelContext;
+import org.apache.camel.model.RouteDefinition;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestName;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class CamelScrExampleTest {
+
+    Logger log = LoggerFactory.getLogger(getClass());
+
+    @Rule
+    public TestName testName = new TestName();
+
+    CamelScrExample integration;
+    ModelCamelContext context;
+
+    @Before
+    public void setUp() throws Exception {
+        log.info("*******************************************************************");
+        log.info("Test: " + testName.getMethodName());
+        log.info("*******************************************************************");
+
+        // Set property prefix for unit testing
+        System.setProperty(CamelScrExample.PROPERTY_PREFIX, "unit");
+
+        // Prepare the integration
+        integration = new CamelScrExample();
+        integration.prepare(null, ScrHelper.getScrProperties(integration.getClass().getName()));
+        context = integration.getContext();
+
+        // Disable JMX for test
+        context.disableJMX();
+
+        // Fake a component for test
+        context.addComponent("amq", new MockComponent());
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        integration.stop();
+    }
+
+    @Test
+    public void testRoutes() throws Exception {
+        // Adjust routes
+        List<RouteDefinition> routes = context.getRouteDefinitions();
+
+        routes.get(0).adviceWith(context, new AdviceWithRouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                // Replace "from" endpoint with direct:start
+                replaceFromWith("direct:start");
+                // Mock and skip result endpoint
+                mockEndpoints("log:*");
+            }
+        });
+
+        MockEndpoint resultEndpoint = context.getEndpoint("mock:log:foo", MockEndpoint.class);
+        // resultEndpoint.expectedMessageCount(1); // If you want to just check the number of messages
+        resultEndpoint.expectedBodiesReceived("hello"); // If you want to check the contents
+
+        // Start the integration
+        integration.run();
+
+        // Send the test message
+        context.createProducerTemplate().sendBody("direct:start", "hello");
+
+        resultEndpoint.assertIsSatisfied();
+    }
+}
+------------------------------------------------------------------------------------------------------
+
+�
+
+Now, let's take a look at the interesting bits one by one.
+
+*Using property prefixing*
+
+[source,java]
+--------------------------------------------------------------------
+        // Set property prefix for unit testing
+        System.setProperty(CamelScrExample.PROPERTY_PREFIX, "unit");
+--------------------------------------------------------------------
+
+This allows you to override parts of the configuration by prefixing
+properties with "unit.". For example, `unit.from` overrides `from` for
+the unit test.
+
+Prefixes can be used to handle the differences between the runtime
+environments where your routes might run. Moving the unchanged bundle
+through development, testing and production environments is a typical
+use case.
+
+�
+
+*Getting test configuration from annotations*
+
+[source,java]
+------------------------------------------------------------------------------------------------
+        integration.prepare(null, ScrHelper.getScrProperties(integration.getClass().getName()));
+------------------------------------------------------------------------------------------------
+
+Here we configure the Service Component in test with the same properties
+that would be used in OSGi environment.
+
+�
+
+*Mocking components for test*
+
+[source,java]
+---------------------------------------------------------
+        // Fake a component for test
+        context.addComponent("amq", new MockComponent());
+---------------------------------------------------------
+
+Components that are not available in test can be mocked like this to
+allow the route to start.
+
+�
+
+*Adjusting routes for test*
+
+[source,java]
+------------------------------------------------------------------------
+        // Adjust routes
+        List<RouteDefinition> routes = context.getRouteDefinitions();
+
+        routes.get(0).adviceWith(context, new AdviceWithRouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                // Replace "from" endpoint with direct:start
+                replaceFromWith("direct:start");
+                // Mock and skip result endpoint
+                mockEndpoints("log:*");
+            }
+        });
+------------------------------------------------------------------------
+
+Camel's AdviceWith feature allows routes to be modified for test.
+
+�
+
+*Starting the routes*
+
+[source,java]
+--------------------------------
+        // Start the integration
+        integration.run();
+--------------------------------
+
+Here we start the Service Component and along with it the routes.
+
+�
+
+*Sending a test message*
+
+[source,java]
+---------------------------------------------------------------------------
+        // Send the test message
+        context.createProducerTemplate().sendBody("direct:start", "hello");
+---------------------------------------------------------------------------
+
+Here we send a message to a route in test.
+
+### Running the bundle in Apache Karaf
+
+Once the bundle has been built with `mvn install` it's ready to be
+deployed.�To deploy the bundle on Apache Karaf perform the following
+steps on Karaf command line:
+
+*Deploying the bundle in Apache Karaf*
+
+[source,text]
+------------------------------------------------------------------------
+# Add Camel feature repository
+karaf@root> features:chooseurl camel 2.15-SNAPSHOT
+�
+# Install camel-scr feature
+karaf@root> features:install camel-scr
+�
+# Install commons-lang, used in the example route to validate parameters
+karaf@root> osgi:install mvn:commons-lang/commons-lang/2.6
+�
+# Install and start your bundle
+karaf@root> osgi:install -s mvn:example/camel-scr-example/1.0-SNAPSHOT
+�
+# See how it's running
+karaf@root> log:tail -n 10
+�
+Press ctrl-c to stop watching the log.
+------------------------------------------------------------------------
+
+#### Overriding the default configuration
+
+By default, Service Component's configuration PID equals the fully
+qualified name of its class. You can change the example bundle's
+properties with Karaf's�`config:*` commands:
+
+*Override a property*
+
+[source,text]
+----------------------------------------------------------------------------------------
+# Override 'messageOk' property
+karaf@root> config:propset -p example.CamelScrExample messageOk "This is better logging"
+----------------------------------------------------------------------------------------
+
+Or you can change the configuration by editing property files in Karaf's
+`etc` folder.
+
+#### Using Camel SCR bundle as a template
+
+Let's say you have a Camel SCR bundle that implements an integration
+pattern that you use frequently, say, *from \u2192�to*, with success/failure
+logging and redelivery which also happens to be the pattern our example
+route implements. You probably don't want to create a separate bundle
+for every instance. No worries, SCR has you covered.
+
+Create a configuration PID for your Service Component, but add a tail
+with a dash and SCR will use that configuration to create a new instance
+of your component.
+
+*Creating a new Service Component instance*
+
+[source,text]
+------------------------------------------------------------------------
+# Create a PID with a tail
+karaf@root> config:edit example.CamelScrExample-anotherone
+�
+# Override some properties
+karaf@root> config:propset camelContextId my-other-context
+karaf@root> config:propset to "file://removeme?fileName=removemetoo.txt"
+�
+# Save the PID
+karaf@root> config:update
+------------------------------------------------------------------------
+
+This will start a new CamelContext with your overridden properties. How
+convenient.
+
+### Notes
+
+When designing a Service Component to be a template you typically don't
+want it to start without a "tailed" configuration i.e. with the default
+configuration.
+
+To prevent your Service Component from starting with the default
+configuration add `policy = ConfigurationPolicy.REQUIRE `to the class
+level `@Component` annotation.