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)