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 2016/05/24 06:50:33 UTC

camel git commit: Added camel-scr docs to Gitbook

Repository: camel
Updated Branches:
  refs/heads/master 79fbb6a3b -> 72e3b27e5


Added camel-scr docs to Gitbook


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

Branch: refs/heads/master
Commit: 72e3b27e504cabb9fe76c5623fd7c0c530b1f5b8
Parents: 79fbb6a
Author: Andrea Cosentino <an...@gmail.com>
Authored: Tue May 24 08:45:25 2016 +0200
Committer: Andrea Cosentino <an...@gmail.com>
Committed: Tue May 24 08:45:25 2016 +0200

----------------------------------------------------------------------
 .../camel-scr/src/main/docs/camel-and-scr.adoc  | 677 +++++++++++++++++++
 docs/user-manual/en/SUMMARY.md                  |   1 +
 2 files changed, 678 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/72e3b27e/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
new file mode 100644
index 0000000..577fd93
--- /dev/null
+++ b/components/camel-scr/src/main/docs/camel-and-scr.adoc
@@ -0,0 +1,677 @@
+[[CamelandSCR-WorkingwithCamelandSCR]]
+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.
+
+[[CamelandSCR-CamelSCRsupport]]
+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_.
+
+[[CamelandSCR-AbstractCamelRunnerlifecycleinSCR]]
+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.
+
+[[CamelandSCR-Usingcamel-archetype-scr]]
+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.
+
+[[CamelandSCR-UnittestingCamelroutes]]
+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.
+
+[[CamelandSCR-RunningthebundleinApacheKaraf]]
+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.
+------------------------------------------------------------------------
+
+[[CamelandSCR-Overridingthedefaultconfiguration]]
+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.
+
+[[CamelandSCR-UsingCamelSCRbundleasatemplate]]
+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.
+
+[Tip]
+====
+
+
+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/72e3b27e/docs/user-manual/en/SUMMARY.md
----------------------------------------------------------------------
diff --git a/docs/user-manual/en/SUMMARY.md b/docs/user-manual/en/SUMMARY.md
index 78f08b2..d34ba40 100644
--- a/docs/user-manual/en/SUMMARY.md
+++ b/docs/user-manual/en/SUMMARY.md
@@ -230,6 +230,7 @@
     * [Saxon](xquery.adoc)
     * [Scp](scp.adoc)
     * [Schematron](schematron.adoc)
+    * [SCR](camel-and-scr.adoc)
     * [SJMS](sjms.adoc)
     * [SJMS Batch](sjms-batch.adoc)
     * [Telegram](telegram.adoc)