This is an automated email from the ASF dual-hosted git repository. acosentino pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/master by this push: new f303135 CAMEL-11497: Migrate 'Working with Camel and ...' guides and related docs (#2512) f303135 is described below commit f303135d22d7dad4a68102f54ad3ea869d2ce500 Author: Tadayoshi Sato <sato.tadayo...@gmail.com> AuthorDate: Fri Sep 7 18:55:24 2018 +0900 CAMEL-11497: Migrate 'Working with Camel and ...' guides and related docs (#2512) --- docs/user-manual/en/SUMMARY.md | 21 +- docs/user-manual/en/component.adoc | 42 + docs/user-manual/en/examples.adoc | 55 ++ docs/user-manual/en/guice-jms-example.adoc | 61 ++ docs/user-manual/en/guice-maven-plugin.adoc | 160 +++ docs/user-manual/en/guice.adoc | 155 +++ docs/user-manual/en/how-do-i-add-a-component.adoc | 72 ++ ...spring-property-placeholder-with-camel-xml.adoc | 77 ++ docs/user-manual/en/producertemplate.adoc | 103 ++ docs/user-manual/en/route-builder.adoc | 10 +- docs/user-manual/en/uris.adoc | 28 + docs/user-manual/en/using-propertyplaceholder.adoc | 1032 ++++++++++++++++++++ docs/user-manual/en/writing-components.adoc | 158 +++ 13 files changed, 1960 insertions(+), 14 deletions(-) diff --git a/docs/user-manual/en/SUMMARY.md b/docs/user-manual/en/SUMMARY.md index e72393e..dc14a25 100644 --- a/docs/user-manual/en/SUMMARY.md +++ b/docs/user-manual/en/SUMMARY.md @@ -15,6 +15,7 @@ * [Camel Core](camel-core.adoc) * [CamelContext](camelcontext.adoc) * [CEP](cep.adoc) + * [Component](component.adoc) * [Debugger](debugger.adoc) * [Delay Interceptor](delay-interceptor.adoc) * [Dependency Injection](dependency-injection.adoc) @@ -41,14 +42,13 @@ * [OnCompletion](oncompletion.adoc) * [Predicate](predicate.adoc) * [Registry](registry.adoc) - * [Scala DSL](scala-dsl.adoc) + * [RouteBuilder](route-builder.adoc) + * [Routes](routes.adoc) <!-- * [Pluggable Class Resolvers](.adoc) * [Processor](.adoc) - * [RouteBuilder](.adoc) * [RoutePolicy](.adoc) - * [Routes](.adoc) * [ServicePool](.adoc) * [Stream caching](.adoc) * [ToAsync](.adoc) @@ -544,27 +544,28 @@ -* Example +* [Examples](examples.adoc) * [BAM Example](bam-example.adoc) + * [Guice JMS Example](guice-jms-example.adoc) * User Guide * [Camel JAR Dependencies](camel-jar-dependencies.adoc) * [Camel Boot](camel-boot.adoc) - * [Working with Camel and CDI] - * [Working with Camel and Spring] - * [Working with Camel and Guice] + * [Working with Camel and CDI](../../../components/camel-cdi/src/main/docs/cdi.adoc) + * [Working with Camel and Spring](spring.adoc) + * [Working with Camel and Guice](guice.adoc) * [Working with Camel and Karaf](karaf.adoc) * [How Do I Configure Endpoints?] - * [Bean Integration] + * [Bean Integration](bean-integration.adoc) * [Configuring Camel] * [Configuring route startup ordering and autostartup] * [Graceful Shutdown] * [AsyncProcessorAwaitManager] for insight into the routing engine when it has been forced to block threads while exchanges are being processed asynchronous. * [Error handling in Camel](error-handling-in-camel.adoc) - * [How to use Camel property placeholders] + * [How to use Camel property placeholders](using-propertyplaceholder.adoc) * [Tutorials] - * [Examples] + * [Examples](examples.adoc) * [Testing](testing.adoc) * [Test](test.adoc) * [Blueprint Testing](test-blueprint.adoc) diff --git a/docs/user-manual/en/component.adoc b/docs/user-manual/en/component.adoc new file mode 100644 index 0000000..fa801b3 --- /dev/null +++ b/docs/user-manual/en/component.adoc @@ -0,0 +1,42 @@ +[[Component-Components]] +=== Components + +A Component is essentially a factory of link:endpoint.adoc[Endpoint] instances. + +You can explicitly configure Component instances +and add them to a link:camelcontext.adoc[CamelContext] in an IoC +container like Spring or Guice, or they can be auto-discovered using +link:uris.adoc[URIs]. + +[[Component-ComponentsIncluded]] +==== Components Included + +Camel includes the following Component implementations via link:uris.adoc[URIs]. + +[IMPORTANT] +==== +Make sure to read link:how-do-i-configure-endpoints.adoc[How do I configure endpoints?] +to learn more about configuring endpoints. For +example how to refer to beans in the link:registry.adoc[Registry] or how +to use raw values for password options, and using +link:using-propertyplaceholder.adoc[property placeholders] etc. +==== + +===== Core Components + +include::../../../camel-core/readme.adoc[] + +===== Components + +include::../../../components/readme.adoc[] + + +[[Component-SeeAlso]] +==== See Also + +* link:endpoint.adoc[Endpoint] +* link:uris.adoc[URIs] +* link:writing-components.adoc[Writing Components] +* link:how-do-i-add-a-component.adoc[How do I add a component] +* link:how-do-i-configure-endpoints.adoc[How do I configure endpoints?] +* link:using-propertyplaceholder.adoc[Using `PropertyPlaceholder`] diff --git a/docs/user-manual/en/examples.adoc b/docs/user-manual/en/examples.adoc new file mode 100644 index 0000000..e9939bb --- /dev/null +++ b/docs/user-manual/en/examples.adoc @@ -0,0 +1,55 @@ +[[Examples-Examples]] +=== Examples + +Once you have read about link:getting-started.adoc[Getting Started] and +looked at the link:enterprise-integration-patterns.adoc[Enterprise +Integration Patterns], you might want to try out some examples. + +Before starting to work on example you may want to +link:what-are-the-dependencies.adoc[check the requirements for working +with Camel]. Then link:running-examples.adoc[Running Examples] describes +how to get the examples to run + + +[[Examples-Walk-throughs]] +==== Walk-throughs + +* Walk through the code of a +link:walk-through-an-example.adoc[beginner's example] so you can +understand how things fit together using the Java link:dsl.adoc[DSL] to +set up some routes in a simple `main(...)` method. +* Walk through the link:walk-through-another-example.adoc[Spring DSL +example] to look at XML-based routing. +* Walk through the link:console-example.adoc[Console Example] to +practice reading input from the console. + +[NOTE] +==== +The examples listed below are hosted at Apache. We also offer the +link:articles.adoc[Articles] page as a collection of 3rd-party Camel +material - such as tutorials, blog posts, published articles, videos, +podcasts, presentations, and so forth. + +If you have written a Camel-related article, then we are happy to +provide a link to it. You can contact the Camel link:team.adoc[Team] via +our link:mailing-lists.adoc[Mailing Lists], or simply post a tweet with +the words "Apache Camel". +==== + + +[[Examples-Examples.1]] +==== Examples + +Browse the examples from github where each example is documented and up +to date: + +https://github.com/apache/camel/tree/master/examples#welcome-to-the-apache-camel-examples + + +[[Examples-SeeAlso]] +==== See Also + +* link:tutorials.adoc[Tutorials] +* link:cookbook.adoc[Cookbook] +* link:enterprise-integration-patterns.adoc[Enterprise Integration +Patterns] diff --git a/docs/user-manual/en/guice-jms-example.adoc b/docs/user-manual/en/guice-jms-example.adoc new file mode 100644 index 0000000..beeb78f --- /dev/null +++ b/docs/user-manual/en/guice-jms-example.adoc @@ -0,0 +1,61 @@ +[[GuiceJMSExample-GuiceJMSExample]] +=== Guice JMS Example + +*Available as of Camel 1.5 onwards* + +The Guice JMS example is functionally similar to both the +link:walk-through-an-example.adoc[first example] and the +link:spring-example.adoc[Spring Example] but using +link:guice.adoc[Guice] as the Dependency Injection framework. + +In this example we just write RouteBuilder implementations, then we +write a Guice module +https://github.com/apache/camel/blob/master/examples/camel-example-guice-jms/src/main/java/org/apache/camel/example/guice/jms/MyModule.java[MyModule] +to create the CamelContext, bind any RouteBuilder instances and +configure any components and endpoints, then we create a +https://github.com/apache/camel/blob/master/examples/camel-example-guice-jms/src/main/resources/guicejndi.properties[guicejndi.properties] +file to bootstrap Guice and Camel. + +To run the example we currently use the maven exec plugin. For example +from the source or binary distribution the following should work + +[source,brush:,java;,gutter:,false;,theme:,Default] +---- +cd examples/camel-example-guice-jms +mvn compile exec:java +---- + +What this does is boot up the Guice based JNDI provider from +https://github.com/apache/camel/blob/master/examples/camel-example-guice-jms/src/main/resources/guicejndi.properties[guicejndi.properties] +file on the classpath. This then bootstraps the Guice injector and loads +whatever Guice modules are defined in the guicejndi.properties file -- +then injects the remaining properties in the file. + + +[[GuiceJMSExample-ConfiguringComponents]] +==== Configuring Components + +If you see the `jms()` method of the Guice +https://github.com/apache/camel/blob/master/examples/camel-example-guice-jms/src/main/java/org/apache/camel/example/guice/jms/MyModule.java[MyModule] +you will see it is annotated with `@Provides` to indicate to Guice that +it is a provider and it is annotated with `@JndiBind("jms")` to bind it +to the JNDI name `jms` when it is created. + +This method then configures the component. The provider method is +parameterized by the `@Named("activemq.brokerURL")` property which is +injected from the +https://github.com/apache/camel/blob/master/examples/camel-example-guice-jms/src/main/resources/guicejndi.properties[guicejndi.properties] +file. This lets you define the properties which should be environment +specific (such as URLs, machine names, usernames/passwords and so forth) +while leaving all of the other configuration which does not change in +different environments in Java code. + +So you can use link:guice.adoc[Guice] to dependency inject whatever +objects you need to create, be it an link:endpoint.adoc[Endpoint], +link:component.adoc[Component], link:route-builder.adoc[RouteBuilder] or +arbitrary link:bean-integration.adoc[bean used within a route]. Then you +can inject any properties from the jndi.properties file easily -- so that +most of your configuration is all in Java code which is typesafe and +easily refactorable - then leaving some properties to be environment +specific (the guicejndi.properties file) which you can then change based +on development, testing, production, etc. diff --git a/docs/user-manual/en/guice-maven-plugin.adoc b/docs/user-manual/en/guice-maven-plugin.adoc new file mode 100644 index 0000000..43820c9 --- /dev/null +++ b/docs/user-manual/en/guice-maven-plugin.adoc @@ -0,0 +1,160 @@ +[[GuiceMavenPlugin-GuiceMavenPlugin]] +=== Guice Maven Plugin + +The Guice Maven Plugin allows you to run your +link:enterprise-integration-patterns.adoc[Enterprise Integration +Patterns] using link:guice.adoc[Guice] for +link:dependency-injection.adoc[Dependency Injection] inside Maven along +with being able to support link:visualisation.adoc[Visualisation] along +with integration of the link:visualisation.adoc[Visualisation] diagrams +into the standard maven reports for your project. + + +[[GuiceMavenPlugin-GoalsSupported]] +==== Goals Supported + +[width="100%",cols="34%,66%",options="header",] +|======================================================================= +|Goal |Description +|link:guice-run-maven-goal.adoc[guice:run] +|Boots up Camel in the context of a separately initiated Java thread +using the link:guice.adoc[Guice] configuration in the `jndi.properties` +file on the classpath and runs your routing rules + +|link:guice-embedded-maven-goal.adoc[guice:embedded] +|Boots up Camel using the link:guice.adoc[Guice] configuration at +`jndi.properties` on the classpath and runs your routing rules + +|link:guice-dot-maven-goal.adoc[guice:dot] +|Generates DOT files and then HTML, PNG, SVG files for your EIP routing +rules with integration into Maven Reports +|======================================================================= + +[[GuiceMavenPlugin-Addingtheplugintoyourpom.xml]] +==== Adding the plugin to your pom.xml + +Add the following in your `<build><plugins>` section + +[source,xml] +---- +<plugin> + <groupId>org.apache.camel</groupId> + <artifactId>guice-maven-plugin</artifactId> +</plugin> +---- + +You can also specify what Main class to use when running the plugin. By +default this is `org.apache.camel.guice.Main`. + +[source,xml] +---- +<plugin> + <groupId>org.apache.camel</groupId> + <artifactId>guice-maven-plugin</artifactId> + <!-- optional, default value: org.apache.camel.guice.Main --> + <configuration> + <mainClass>mypackage.boot.camel.CamelStartup</mainClass> + </configuration> +</plugin> +---- + +[[GuiceMavenPlugin-MakinguseofanoptionalJNDIpropertiesfile]] +==== Making use of an optional JNDI properties file + +*Available as of Camel 2.13.0* + +Optionally if the name of your JNDI properties file is something else +other than the default `jndi.properties` or if it's not on the default +classpath, then you can make use of the `jndiProperties` option as shown +below: + +[source,xml] +---- +<plugin> + <groupId>org.apache.camel</groupId> + <artifactId>guice-maven-plugin</artifactId> + <configuration> + <jndiProperties>/path/to/my/jndi/properties/my-guice-jndi.properties</jndiProperties> + </configuration> +</plugin> +---- + + +[[GuiceMavenPlugin-Classpath]] +==== Classpath + +The plugin will construct a classpath of any Maven dependency with scope +`compile`. The classpath is output as an `INFO` log statement upon +startup. + + +[[GuiceMavenPlugin-RouteInformation]] +==== Route Information + +Information about the generated routes is available through the GraphViz +report, and also through the log statements generated by the run goal. +If you would like to see this information then add a log4j (or other +commons-logging implementation) config file with the following levels. + +===== src/main/resources/log4.properties + +[source,java] +---- +log4j.rootLogger=INFO, stdout +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n + +log4j.logger.org.apache.camel.impl.DefaultCamelContext=DEBUG, stdout +log4j.additivity.org.apache.camel.impl.DefaultCamelContext=false +---- + +This should produce a log statement similar to: + +.... +670 [org.apache.camel.guice.Main.main()] DEBUG org.apache.camel.impl.DefaultCamelContext - Adding routes from: Routes: [Route[ [From[jms:queue:queueA]] -> [To[jms:queue:queueB], To[jms:queue:queueC]]]] routes: [] +.... + + +[[GuiceMavenPlugin-IntegrationintoMavenReports]] +==== Integration into Maven Reports + +If you add the guice-maven-plugin to your `<reporting>` section of your +pom you will automatically get the +link:visualisation.adoc[Visualisation] reporting generated for your +project as part of the regular maven site generation. + +For example add the following into your pom: + +[source,xml] +---- +<project> + ... + <reporting> + <plugins> + <plugin> + <groupId>org.apache.camel</groupId> + <artifactId>guice-maven-plugin</artifactId> + </plugin> + </plugins> + </reporting> +</project> +---- + +Then when you run: + +.... +mvn site +.... + +Your context will be booted up via the `jndi.properties` files, the DOT +file generated and a nice HTML report created. + +===== GraphViz DOT required + +Note to get the nice HTML, PNG and SVG outputs from the DOT files you +will need to install the http://graphviz.org[GraphViz] DOT executable +and add it to your PATH so that the plugin can invoke DOT to generate +the PNG/SVG files. + +For more details see the link:camel-dot-maven-goal.adoc[guice:dot]. diff --git a/docs/user-manual/en/guice.adoc b/docs/user-manual/en/guice.adoc new file mode 100644 index 0000000..36650e8 --- /dev/null +++ b/docs/user-manual/en/guice.adoc @@ -0,0 +1,155 @@ +[[Guice-CamelGuice]] +=== Camel Guice + +We have support for https://github.com/google/guice[Google Guice] +as a dependency injection framework. + +Maven users will need to add the following dependency to their `pom.xml` +for this component: + +[source,xml] +---- +<dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-guice</artifactId> + <version>x.x.x</version> + <!-- use the same version as your Camel core version --> +</dependency> +---- + +[[Guice-DependencyInjectingCamelwithGuice]] +==== Dependency Injecting Camel with Guice + +The +http://camel.apache.org/maven/current/camel-guice/apidocs/org/apache/camel/guice/GuiceCamelContext.html[GuiceCamelContext] +is designed to work nicely inside Guice. You then need to bind it using +some Guice Module. + +The camel-guice library comes with a number of reusable Guice Modules +you can use if you wish - or you can bind the GuiceCamelContext yourself +in your own module. + +* http://camel.apache.org/maven/current/camel-guice/apidocs/org/apache/camel/guice/CamelModule.html[CamelModule] +is the base module which binds the GuiceCamelContext but leaves it up +you to bind the RouteBuilder instances +* http://camel.apache.org/maven/current/camel-guice/apidocs/org/apache/camel/guice/CamelModuleWithRouteTypes.html[CamelModuleWithRouteTypes] +extends CamelModule so that in the constructor of the module you specify +the RouteBuilder classes or instances to use +* http://camel.apache.org/maven/current/camel-guice/apidocs/org/apache/camel/guice/CamelModuleWithMatchingRoutes.html[CamelModuleWithMatchingRoutes] +extends CamelModule so that all bound RouteBuilder instances will be +injected into the CamelContext or you can supply an optional Matcher to +find RouteBuilder instances matching some kind of predicate. + +So you can specify the exact link:route-builder.adoc[RouteBuilder] +instances you want: + +[source,java] +---- +Injector injector = Guice.createInjector(new CamelModuleWithRouteTypes(MyRouteBuilder.class, AnotherRouteBuilder.class)); +// if required you can lookup the CamelContext +CamelContext camelContext = injector.getInstance(CamelContext.class); +---- + +Or inject them all: + +[source,java] +---- +Injector injector = Guice.createInjector(new CamelModuleWithRouteTypes()); +// if required you can lookup the CamelContext +CamelContext camelContext = injector.getInstance(CamelContext.class); +---- + +You can then use Guice in the usual way to inject the route instances or +any other dependent objects. + +[[Guice-BootstrappingwithJNDI]] +==== Bootstrapping with JNDI + +A common pattern used in J2EE is to bootstrap your application or root +objects by looking them up in JNDI. This has long been the approach when +working with JMS for example - looking up the JMS ConnectionFactory in +JNDI for example. + +You can follow a similar pattern with Guice using the +https://code.google.com/archive/p/guiceyfruit/wikis/JNDI.wiki[GuiceyFruit JNDI +Provider] which lets you bootstrap Guice from a `jndi.properties` file +which can include the Guice Modules to create along with environment +specific properties you can inject into your modules and objects. + +If the `jndi.properties` is conflict with other component, you can +specify the jndi properties file name in the Guice Main with option `-j` +or `-jndiProperties` with the properties file location to let Guice Main +to load right jndi properties file. + +[[Guice-ConfiguringComponent,EndpointorRouteBuilderinstances]] +==== Configuring Component, Endpoint or RouteBuilder instances + +You can use Guice to dependency inject whatever objects +you need to create, be it an link:endpoint.adoc[Endpoint], +link:component.adoc[Component], link:route-builder.adoc[RouteBuilder] or +arbitrary link:bean-integration.adoc[bean used within a route]. + +The easiest way to do this is to create your own Guice Module class +which extends one of the above module classes and add a provider method +for each object you wish to create. A provider method is annotated with +`@Provides` as follows: + +[source,java] +---- +public class MyModule extends CamelModuleWithMatchingRoutes { + + @Provides + @JndiBind("jms") + JmsComponent jms(@Named("activemq.brokerURL") String brokerUrl) { + return JmsComponent.jmsComponent(new ActiveMQConnectionFactory(brokerUrl)); + } +} +---- + +You can optionally annotate the method with `@JndiBind` to bind the +object to JNDI at some name if the object is a component, endpoint or +bean you wish to refer to by name in your routes. + +You can inject any environment specific properties (such as URLs, +machine names, usernames/passwords and so forth) from the +`jndi.properties` file easily using the `@Named` annotation as shown +above. This allows most of your configuration to be in Java code which +is typesafe and easily refactorable - then leaving some properties to be +environment specific (the `jndi.properties` file) which you can then +change based on development, testing, production, etc. + +[[Guice-CreatingmultipleRouteBuilderinstancespertype]] +==== Creating multiple RouteBuilder instances per type + +It is sometimes useful to create multiple instances of a particular +link:route-builder.adoc[RouteBuilder] with different configurations. + +To do this just create multiple provider methods for each configuration; +or create a single provider method that returns a collection of +RouteBuilder instances. + +For example: + +[source,java] +---- +import org.apache.camel.guice.CamelModuleWithMatchingRoutes; +import com.google.common.collect.Lists; + +public class MyModule extends CamelModuleWithMatchingRoutes { + + @Provides + @JndiBind("foo") + Collection<RouteBuilder> foo(@Named("fooUrl") String fooUrl) { + return Lists.newArrayList(new MyRouteBuilder(fooUrl), new MyRouteBuilder("activemq:CheeseQueue")); + } +} +---- + +[[Guice-SeeAlso]] +==== See Also + +* There are a number of link:examples.adoc[Examples] you can look at to +see Guice and Camel being used such as link:guice-jms-example.adoc[Guice +JMS Example] +* link:guice-maven-plugin.adoc[Guice Maven Plugin] for running your +Guice based routes via Maven diff --git a/docs/user-manual/en/how-do-i-add-a-component.adoc b/docs/user-manual/en/how-do-i-add-a-component.adoc new file mode 100644 index 0000000..9541e2d --- /dev/null +++ b/docs/user-manual/en/how-do-i-add-a-component.adoc @@ -0,0 +1,72 @@ +[[HowdoIaddacomponent-HowdoIaddacomponent]] +=== How do I add a component + +You might first want to read link:writing-components.adoc[Writing +Components] for a background in how to implement a new component. +Typically it means you write an implementation of the +http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/Component.html[Component] +interface, usually deriving from +http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/impl/DefaultComponent.html[DefaultComponent]. + +You can then register your component explicitly via: + +[source,java] +---- +CamelContext context = new DefaultCamelContext(); +context.addComponent("foo", new FooComponent(context)); +---- + +However you can use the auto-discovery feature of Camel where by Camel +will automatically add a link:component.adoc[Component] when an endpoint +URI is used. To do this you would create a file called: + +.... +/META-INF/services/org/apache/camel/component/foo +.... + +with contents: + +[source,java] +---- +class=org.acme.FooComponent +---- + +(You can add other property configurations in there too if you like.) + +Then if you refer to an endpoint as `foo://somethingOrOther` Camel +will auto-discover your component and register it. + +The `FooComponent` can then be auto-injected with resources using the +http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/spi/Injector.html[Injector], +such as to support link:spring.adoc[Spring] based auto-wiring, or to +support `@Resource` (EJB3 style) injection or Guice style `@Inject` +injection. + + +[[HowdoIaddacomponent-WorkingwithSpringXML]] +==== Working with Spring XML + +You can configure a component via Spring using the following mechanism: + +include::../../../components/camel-jms/src/test/resources/org/apache/camel/component/jms/jmsRouteUsingSpring.xml[] + +Which allows you to configure a component using some name (activemq in the +above example), then you can refer to the component using +`activemq:[queue:|topic:]destinationName`. + +If you want to add explicit Spring 2.x XML objects to your XML then you +could use the `xbean-spring` which tries to automate most of the XML +binding work for you; or you could look in camel-spring +at `CamelNamespaceHandler` you'll see how we handle the Spring XML +stuff (warning it's kinda hairy code to look at :smile:). +If you wanted `<fooComponent>` to be a standard part of the core Camel +schema then you'd hack that file to add your component & +link:contributing.adoc[contribute a patch] to the camel XSD. Otherwise +you could write your own namespace & schema if you prefer. + + +[[HowdoIaddacomponent-SeeAlso]] +==== See Also + +* link:writing-components.adoc[Writing Components] +* link:how-do-i-configure-endpoints.adoc[How do I configure endpoints?] diff --git a/docs/user-manual/en/how-do-i-use-spring-property-placeholder-with-camel-xml.adoc b/docs/user-manual/en/how-do-i-use-spring-property-placeholder-with-camel-xml.adoc new file mode 100644 index 0000000..7b9283c --- /dev/null +++ b/docs/user-manual/en/how-do-i-use-spring-property-placeholder-with-camel-xml.adoc @@ -0,0 +1,77 @@ +[[HowdoIuseSpringPropertyPlaceholderwithCamelXML-HowdoIuseSpringPropertyPlaceholderwithCamelXML]] +=== How do I use Spring Property Placeholder with Camel XML + +We do *NOT* yet support the `${something}` notation inside arbitrary +Camel XML. For example at the time of writing this is *NOT* supported +(due Spring limitations). + +*IS NOT SUPPORTED* + +[source,xml] +---- +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd + http://activemq.apache.org/camel/schema/spring http://activemq.apache.org/camel/schema/spring/camel-spring.xsd + "> + + <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/> + + <camelContext xmlns="http://activemq.apache.org/camel/schema/spring"> + <route> + <from uri="activemq:${someQueueName}"/> + <to uri="mock:results"/> + </route> + </camelContext> + +</beans> +---- + +However you can use the `<endpoint/>` element to define endpoints which +does support the property resolving which you can then refer to by name, +using the <<ref-component,Ref>> component as shown below (notice the `ref:` +in the URI): + +*SUPPORTED* + +[source,xml] +---- +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd + http://activemq.apache.org/camel/schema/spring http://activemq.apache.org/camel/schema/spring/camel-spring.xsd + "> + + <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/> + + <camelContext xmlns="http://activemq.apache.org/camel/schema/spring"> + <endpoint id="input1" uri="activemq:${someQueueName}"/> + + <route> + <from uri="ref:input1"/> + <to uri="activemq:OutputQueue"/> + </route> + </camelContext> + +</beans> +---- + +Camel does not yet fully support property placeholders as there is a +limitation in Spring. See JIRA +http://jira.springframework.org/browse/SPR-4466[SPR-4466] + +===== Bridge Spring and Camel property placeholders + +From Camel 2.10 onwards you can bridge Spring and Camel property +placeholders, see link:using-propertyplaceholder.adoc[Using +PropertyPlaceholder] for more details. + +Here is a trick that you can use to define the uri in a property file +using Spring injection and Camel endpoint: +http://cmoulliard.blogspot.com/2009/05/trick-to-pass-uri-declared-in-property.html. + +From Camel 2.3 onwards there is a <<properties-component,Properties>> +component build in Camel core which allows you to use properties in the +same way as Spring property placeholders, and even more. diff --git a/docs/user-manual/en/producertemplate.adoc b/docs/user-manual/en/producertemplate.adoc new file mode 100644 index 0000000..e6348a5 --- /dev/null +++ b/docs/user-manual/en/producertemplate.adoc @@ -0,0 +1,103 @@ +[[ProducerTemplate-ProducerTemplate]] +=== ProducerTemplate + +The ProducerTemplate interface allows you to send message exchanges to +endpoints in a variety of different ways to make it easy to work with +Camel link:endpoint.adoc[Endpoint] instances from Java code. + +It can be configured with a default endpoint if you just want to send +lots of messages to the same endpoint; or you can specify an +link:endpoint.adoc[Endpoint] or uri as the first parameter. + +The `sendBody()` method allows you to send any object to an endpoint +easily. + +[source,java] +---- +ProducerTemplate template = exchange.getContext().createProducerTemplate(); + +// send to default endpoint +template.sendBody("<hello>world!</hello>"); + +// send to a specific queue +template.sendBody("activemq:MyQueue", "<hello>world!</hello>"); + +// send with a body and header +template.sendBodyAndHeader("activemq:MyQueue", + "<hello>world!</hello>", + "CustomerRating", "Gold"); +---- + +You can also supply an `Exchange` or a `Processor` to customize the exchange. + + +[[ProducerTemplate-requestmethods]] +==== `request*()` methods + +The `send*()` methods use the default Message Exchange Pattern (InOnly, +InOut etc) as the endpoint. If you want to explicitly perform a +request/response (InOut) you can use the `request*()` methods instead of +the `send*()` methods. + +E.g. let's invoke an endpoint and get the response: + +[source,java] +---- +Object response = template.requestBody("<hello/>"); + +// you can cast the response directly +String ret = template.requestBody("<hello/>", String.class); + +// or specify the endpoint directly +String ret = template.requestBody("cxf:bean:HelloWorldService", "<hello/>", String.class); +---- + + +[[ProducerTemplate-Fluentinterface]] +==== Fluent interface + +*Available as of Camel 2.18.0* + +The FluentProducerTemplate provides a fluent syntax to +ProducerTemplate. + +Examples: + +*Set headers and body* + +[source,java] +---- +Integer result = FluentProducerTemplate.on(context) + .withHeader("key-1", "value-1") + .withHeader("key-2", "value-2") + .withBody("Hello") + .to("direct:inout") + .request(Integer.class); +---- + +*Use a processor* + +[source,java] +---- +Integer result = FluentProducerTemplate.on(context) + .withProcessor(exchange -> exchange.getIn().setBody("Hello World")) + .to("direct:exception") + .request(Integer.class); +---- + +*Customize template* + +[source,java] +---- +Object result = FluentProducerTemplate.on(context) + .withTemplateCustomizer( + template -> { + template.setExecutorService(myExecutor); + template.setMaximumCacheSize(10); + } + ) + .withBody("the body") + .to("direct:start") + .request(); + +---- diff --git a/docs/user-manual/en/route-builder.adoc b/docs/user-manual/en/route-builder.adoc index a021f9d..b5adcfe 100644 --- a/docs/user-manual/en/route-builder.adoc +++ b/docs/user-manual/en/route-builder.adoc @@ -1,9 +1,11 @@ [[RouteBuilder-RouteBuilder]] -RouteBuilder -~~~~~~~~~~~~ -The RouteBuilder is a base class which is derived from to create routing rules using the DSL. Instances of RouteBuilder are then added to the CamelContext. +=== RouteBuilder + +The RouteBuilder is a base class which is derived from to create routing rules using the DSL. +Instances of RouteBuilder are then added to the CamelContext. + +==== See Also -See Also * link:camelcontext.adoc[CamelContext] * link:routes.adoc[Routes] * link:architecture.adoc[Architecture] diff --git a/docs/user-manual/en/uris.adoc b/docs/user-manual/en/uris.adoc new file mode 100644 index 0000000..54a6c45 --- /dev/null +++ b/docs/user-manual/en/uris.adoc @@ -0,0 +1,28 @@ +[[URIs-URIs]] +=== URIs + +Camel makes extensive use of URIs to allow you to refer to endpoints +which are lazily created by a link:component.adoc[Component] if you +refer to them within link:routes.adoc[Routes]. + +[IMPORTANT] +==== +Make sure to read +link:how-do-i-configure-endpoints.adoc[How do I configure endpoints] +to learn more about configuring endpoints. For +example how to refer to beans in the link:registry.adoc[Registry] or how +to use raw values for password options, and using +link:using-propertyplaceholder.adoc[property placeholders] etc. +==== + + +[[URIs-CurrentSupportedURIs]] +==== Current Supported URIs + +===== Core Components + +include::../../../camel-core/readme.adoc[] + +===== Components + +include::../../../components/readme.adoc[] diff --git a/docs/user-manual/en/using-propertyplaceholder.adoc b/docs/user-manual/en/using-propertyplaceholder.adoc new file mode 100644 index 0000000..4f016b1 --- /dev/null +++ b/docs/user-manual/en/using-propertyplaceholder.adoc @@ -0,0 +1,1032 @@ +[[UsingPropertyPlaceholder-UsingPropertyPlaceholder]] +=== Using `PropertyPlaceholder` + +*Available as of Camel 2.3* + +Camel now provides a new `PropertiesComponent` in `camel-core` which +allows you to use property placeholders when defining Camel +link:endpoint.adoc[Endpoint] URIs. This works much like you would do if +using Spring's `<property-placeholder>` tag. However Spring has a +limitation that prevents third-party frameworks from fully leveraging +Spring property placeholders. + +For more details see: +link:how-do-i-use-spring-property-placeholder-with-camel-xml.adoc[How do +I use Spring Property Placeholder with Camel XML]. + +[[UsingPropertyPlaceholder-BridgingSpringandCamelPropertyPlaceholders]] +===== Bridging Spring and Camel Property Placeholders + +From *Camel 2.10*: Spring's property placeholder can be bridged with +Camel's. See below for more details. + +The property placeholder is typically used when trying to do any of the +following: + +* Lookup or creating endpoints +* Lookup of beans in the link:registry.adoc[Registry] +* Additional supported in Spring XML (see below in examples) +* Using Blueprint `PropertyPlaceholder` with Camel +<<properties-component,Properties>> component +* Using `@PropertyInject` to inject a property in a POJO +* *Camel 2.14.1* Using default value if a property does not exists +* *Camel 2.14.1* Include out of the box functions, to lookup property +values from OS environment variables, JVM system properties, or the +service idiom +* *Camel 2.14.1* Using custom functions, which can be plugged into the +property component + +[[UsingPropertyPlaceholder-Format]] +==== Format + +The value of a Camel property can be obtained by specifying its key name +within a property placeholder, using the following format: `{{key}}` + +For example: +.... +{{file.uri}} +.... + +where `file.uri` is the property key. + +Property placeholders can be used to specify parts, or all, of an +endpoint's URI by embedding one or more placeholders in the URI's string +definition. + +From *Camel 2.14.1*: you can specify a default value to use if a +property with the key does not exists, e.g., `file.url:/some/path` +where the default value is the text after the colon, e.g., +`/some/path`. + +From *Camel 2.14.1*: do _not_ use a colon in the property key. The colon +character is used as a token separator when providing a default value. + +[[UsingPropertyPlaceholder-UsingPropertyResolver]] +==== Using `PropertyResolver` + +Camel provides a pluggable mechanism that allows third-parties to +specify their own resolver to use for the lookup of properties. + +Camel provides a default implementation +`org.apache.camel.component.properties.DefaultPropertiesResolver` +which is capable of loading properties from the file system, classpath +or link:registry.adoc[Registry]. To indicate which source to use the +location must contain the appropriate prefix. + +The list of prefixes is: + +[width="100%",cols="50%,50%",options="header",] +|======================================================================= +|Prefix |Description +|`ref:` |Lookup in the link:registry.adoc[Registry.] + +|`file:` |Load the from file system. + +|`classpath:` |Load from the classpath (this is also the default if no +prefix is provided). + +|`blueprint:` |Use a specific OSGi blueprint placeholder service. +|======================================================================= + +[[UsingPropertyPlaceholder-DefiningLocation]] +==== Defining Location + +The `PropertiesResolver` must be configured with the location(s) to +use when resolving properties. One or more locations can be given. +Specifying multiple locations can be done a couple of ways: using either +a single comma separated string, or an array of strings. + +[source,java] +---- +pc.setLocation("com/mycompany/myprop.properties,com/mycompany/other.properties"); +pc.setLocation(new String[] {"com/mycompany/myprop.properties", "com/mycompany/other.properties"}); +---- + +From *Camel 2.19.0*: you can set which location can be discarded if +missing by setting `optional=true`, (`false` by default). + +Example: + +[source,java] +---- +pc.setLocations("com/mycompany/override.properties;optional=true,com/mycompany/defaults.properties"); +---- + + +[[UsingPropertyPlaceholder-UsingSystemandEnvironmentVariablesinLocations]] +==== Using System and Environment Variables in Locations + +*Available as of Camel 2.7* + +The location now supports using placeholders for JVM system properties +and OS environments variables. + +Example: +.... +location=file:${karaf.home}/etc/foo.properties +.... + +In the location above we defined a location using the file scheme using +the JVM system property with key `karaf.home`. + +To use an OS environment variable instead you would have to prefix with +`env`: + +location=file:${env:APP_HOME}/etc/foo.properties + +Where `APP_HOME` is an OS environment variable. + +You can have multiple placeholders in the same location, such as: + +location=file:${env:APP_HOME}/etc/${prop.name}.properties + +[[UsingPropertyPlaceholder-UsingSystemorEnvironmentVariablestoConfigurePropertyPrefixesandSuffixes]] +==== Using System or Environment Variables to Configure Property Prefixes and Suffixes + +From *Camel 2.12.5, 2.13.3, 2.14.0*: `propertyPrefix`, +`propertySuffix` configuration properties support the use of +placeholders for de-referencing JVM system properties and OS +environments variables. + +Example: + +Assume the `PropertiesComponent` is configured with the following +properties file: + +[source,java] +---- +textdev.endpoint = result1 +test.endpoint = result2 +---- + +The same properties file is then referenced from a route definition: + + +[source,java] +---- +PropertiesComponent pc = context.getComponent("properties", +PropertiesComponent.class); pc.setPropertyPrefix("${stage}."); +// ... +context.addRoutes(new RouteBuilder() { + @Override + public void configure() throws Exception { + from("direct:start") + .to("properties:mock:{{endpoint}}"); + } +}); +---- + +By using the configuration options `propertyPrefix` it's possible to +change the target endpoint simply by changing the value of the system +property `stage` either to `dev` (the message will be routed +to `mock:result1`) or `test` (the message will be routed +to `mock:result2`). + +[[UsingPropertyPlaceholder-ConfiguringinJavaDSL]] +==== Configuring in Java DSL + +You have to create and register the `PropertiesComponent` under the +name `properties` such as: + + +[source,java] +---- +PropertiesComponent pc = new PropertiesComponent(); +pc.setLocation("classpath:com/mycompany/myprop.properties"); +context.addComponent("properties", pc); +---- + +[[UsingPropertyPlaceholder-ConfiguringinSpringXML]] +==== Configuring in Spring XML + +Spring XML offers two variations to configure. You can define a spring +bean as a `PropertiesComponent` which resembles the way done in Java +DSL. Or you can use the `<propertyPlaceholder>` tag. + +[source,xml] +---- +<bean id="properties" class="org.apache.camel.component.properties.PropertiesComponent"> + <property name="location" value="classpath:com/mycompany/myprop.properties"/> +</bean> +---- + +Using the `<propertyPlaceholder>` tag makes the configuration a bit +more fresh such as: + +[source,xml] +---- +<camelContext ...> + <propertyPlaceholder id="properties" location="com/mycompany/myprop.properties"/> +</camelContext> +---- + +Setting the properties location through the location tag works just fine +but sometime you have a number of resources to take into account and +starting from **Camel 2.19.0** you can set the properties location with +a dedicated `propertiesLocation`: + +[source,xml] +---- +<camelContext ...> + <propertyPlaceholder id="myPropertyPlaceholder"> + <propertiesLocation resolver="classpath" path="com/my/company/something/my-properties-1.properties" optional="false"/> + <propertiesLocation resolver="classpath" path="com/my/company/something/my-properties-2.properties" optional="false"/> + <propertiesLocation resolver="file" path="${karaf.home}/etc/my-override.properties" optional="true"/> + </propertyPlaceholder> +</camelContext> +---- + +===== Specifying the cache option in XML + +From *Camel 2.10*: Camel supports specifying a value for the `cache` +option both inside the Spring as well as the Blueprint XML. + + +[[UsingPropertyPlaceholder-UsingaPropertiesfromthe]] +==== Using a Properties from the link:registry.adoc[Registry] + +*Available as of Camel 2.4* + +For example in OSGi you may want to expose a service which returns the +properties as a `java.util.Properties` object. + +Then you could setup the link:properties.adoc[Properties] component as +follows: + +[source,xml] +---- +<propertyPlaceholder id="properties" location="ref:myProperties"/> +---- + +Where `myProperties` is the id to use for lookup in the OSGi registry. +Notice we use the `ref:` prefix to tell Camel that it should lookup +the properties for the link:registry.adoc[Registry]. + +[[UsingPropertyPlaceholder-ExamplesUsingPropertiesComponent]] +==== Examples Using Properties Component + +When using property placeholders in the endpoint URIs you can either use +the `properties:` component or define the placeholders directly in the +URI. We will show example of both cases, starting with the former. + +[source,java] +---- +// properties +cool.end=mock:result + +// route +from("direct:start") + .to("properties:{{cool.end}}"); +---- + +You can also use placeholders as a part of the endpoint URI: + +[source,java] +---- +// properties +cool.foo=result + +// route +from("direct:start") + .to("properties:mock:{{cool.foo}}"); +---- + +In the example above the to endpoint will be resolved to +`mock:result`. + +You can also have properties with refer to each other such as: + + +[source,java] +---- +// properties +cool.foo=result +cool.concat=mock:{{cool.foo}} + +// route +from("direct:start") + .to("properties:mock:{{cool.concat}}"); +---- + +Notice how `cool.concat` refer to another property. + +The `properties:` component also offers you to override and provide a +location in the given URI using the `locations` option: + + +[source,java] +---- +from("direct:start") + .to("properties:bar.end?locations=com/mycompany/bar.properties"); +---- + +[[UsingPropertyPlaceholder-Examples]] +==== Examples + +You can also use property placeholders directly in the endpoint URIs +without having to use `properties:`. + + +[source,java] +---- +// properties +cool.foo=result + +// route +from("direct:start") + .to("mock:{{cool.foo}}"); +---- + +And you can use them in multiple wherever you want them: + +[source,java] +---- +// properties +cool.start=direct:start +cool.showid=true +cool.result=result + +// route +from("{{cool.start}}") + .to("log:{{cool.start}}?showBodyType=false&showExchangeId={{cool.showid}}") + .to("mock:{{cool.result}}"); +---- + +You can also your property placeholders when using +link:producertemplate.adoc[ProducerTemplate] for example: + + +[source,java] +---- +template.sendBody("{{cool.start}}", "Hello World"); +---- + + +[[UsingPropertyPlaceholder-Examplewithlanguage]] +==== Example with <<simple-language,Simple>> language + +The <<simple-language,Simple>> language now also support using property +placeholders, for example in the route below: + + +[source,java] +---- +// properties +cheese.quote=Camel rocks + +// route from("direct:start") + .transform().simple("Hi ${body} do you think ${properties:cheese.quote}?"); +---- + +You can also specify the location in the <<simple-language,Simple>> +language for example: + + +[source,java] +---- +// bar.properties +bar.quote=Beer tastes good + +// route +from("direct:start") + .transform().simple("Hi ${body}. ${properties:com/mycompany/bar.properties:bar.quote}."); +---- + + +[[UsingPropertyPlaceholder-AdditionalPropertyPlaceholderSupportinSpringXML]] +==== Additional Property Placeholder Support in Spring XML + +The property placeholders is also supported in many of the Camel Spring +XML tags such as +`<package>`, `<packageScan>`, `<contextScan>`, `<jmxAgent>`, `<endpoint>`, `<routeBuilder>`, `<proxy>` +and the others. + +Example using property placeholders in the `<jmxAgent>` tag: + +[source,xml] +---- +<camelContext xmlns="http://camel.apache.org/schema/spring"> + <propertyPlaceholder id="properties" location="org/apache/camel/spring/jmx.properties"/> + <!-- we can use propery placeholders when we define the JMX agent --> + <jmxAgent id="agent" registryPort="{{myjmx.port}}" disabled="{{myjmx.disabled}}" + usePlatformMBeanServer="{{myjmx.usePlatform}}" createConnector="true" + statisticsLevel="RoutesOnly" useHostIPAddress="true"/> + <route id="foo" autoStartup="false"> + <from uri="seda:start"/> + <to uri="mock:result"/> + </route> +</camelContext> +---- + + +Example using property placeholders in the attributes of `<camelContext>`: + +[source,xml] +---- +<camelContext trace="{{foo.trace}}" xmlns="http://camel.apache.org/schema/spring"> + <propertyPlaceholder id="properties" location="org/apache/camel/spring/processor/myprop.properties"/> + <template id="camelTemplate" defaultEndpoint="{{foo.cool}}"/> + <route> + <from uri="direct:start"/> + <setHeader headerName="{{foo.header}}"> + <simple>${in.body} World!</simple> + </setHeader> + <to uri="mock:result"/> + </route> +</camelContext> +---- + + +[[UsingPropertyPlaceholder-OverridingaPropertySettingUsingaJVMSystemProperty]] +==== Overriding a Property Setting Using a JVM System Property + +*Available as of Camel 2.5* + +It is possible to override a property value at runtime using a JVM +System property without the need to restart the application to pick up +the change. This may also be accomplished from the command line by +creating a JVM System property of the same name as the property it +replaces with a new value. + +Example: + + +[source,java] +---- +PropertiesComponent pc = context.getComponent("properties", PropertiesComponent.class); +pc.setCache(false); +System.setProperty("cool.end", "mock:override"); +System.setProperty("cool.result", "override"); +context.addRoutes(new RouteBuilder() { + @Override + public void configure() throws Exception { + from("direct:start").to("properties:cool.end"); + from("direct:foo").to("properties:mock:{{cool.result}}"); + } +}); +context.start(); +getMockEndpoint("mock:override").expectedMessageCount(2); +template.sendBody("direct:start", "Hello World"); +template.sendBody("direct:foo", "Hello Foo"); +System.clearProperty("cool.end"); +System.clearProperty("cool.result"); +assertMockEndpointsSatisfied(); +---- + + +[[UsingPropertyPlaceholder-UsingPropertyPlaceholdersforAnyKindofAttributeintheXMLDSL]] +==== Using Property Placeholders for Any Kind of Attribute in the XML DSL + +*Available as of Camel 2.7* + +If you use OSGi Blueprint then this only works from *2.11.1* or *2.10.5* +on. + +Previously it was only the `xs:string` type attributes in the XML DSL +that support placeholders. For example often a timeout attribute would +be a `xs:int` type and thus you cannot set a string value as the +placeholder key. This is now possible from Camel 2.7 on using a special +placeholder namespace. + +In the example below we use the `prop` prefix for the namespace +`http://camel.apache.org/schema/placeholder` by which we can use the +`prop` prefix in the attributes in the XML DSLs. Notice how we use +that in the link:multicast.adoc[Multicast] to indicate that the option +`stopOnException` should be the value of the placeholder with the key +`stop`. + +[source,xml] +---- +<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:prop="http://camel.apache.org/schema/placeholder" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> + <!-- Notice in the declaration above, we have defined the prop prefix as the Camel placeholder namespace --> + <bean id="damn" class="java.lang.IllegalArgumentException"> + <constructor-arg index="0" value="Damn"/> + </bean> + <camelContext xmlns="http://camel.apache.org/schema/spring"> + <propertyPlaceholder id="properties" location="classpath:org/apache/camel/component/properties/myprop.properties" + xmlns="http://camel.apache.org/schema/spring"/> + <route> + <from uri="direct:start"/> + <!-- use prop namespace, to define a property placeholder, which maps to option stopOnException={{stop}} --> + <multicast prop:stopOnException="stop"> + <to uri="mock:a"/> + <throwException ref="damn"/> + <to uri="mock:b"/> + </multicast> + </route> + </camelContext> +</beans> +---- + +In our properties file we have the value defined as: +.... +stop=true +.... + + +[[UsingPropertyPlaceholder-UsingPropertyPlaceholderintheJavaDSL]] +==== Using Property Placeholder in the Java DSL + +*Available as of Camel 2.7* + +Likewise we have added support for defining placeholders in the Java DSL +using the new `placeholder` DSL as shown in the following equivalent +example: + +[source,java] +---- +from("direct:start") + // use a property placeholder for the option stopOnException on the Multicast EIP + // which should have the value of {{stop}} key being looked up in the properties file + .multicast() + .placeholder("stopOnException", "stop") + .to("mock:a") + .throwException(new IllegalAccessException("Damn")) + .to("mock:b"); +---- + + +[[UsingPropertyPlaceholder-UsingBlueprintPropertyPlaceholderwithCamelRoutes]] +==== Using Blueprint Property Placeholder with Camel Routes + +*Available as of Camel 2.7* + +Camel supports link:using-osgi-blueprint-with-camel.adoc[Blueprint] +which also offers a property placeholder service. Camel supports +convention over configuration, so all you have to do is to define the +OSGi Blueprint property placeholder in the XML file as shown below: + +[source,xml] +---- +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0" + xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd"> + <!-- OSGI blueprint property placeholder --> + <cm:property-placeholder id="myblueprint.placeholder" persistent-id="camel.blueprint"> + <!-- list some properties as needed --> + <cm:default-properties> + <cm:property name="result" value="mock:result"/> + </cm:default-properties> + </cm:property-placeholder> + <camelContext xmlns="http://camel.apache.org/schema/blueprint"> + <!-- in the route we can use {{ }} placeholders which will lookup in blueprint as Camel + will auto detect the OSGi blueprint property placeholder and use it --> + <route> + <from uri="direct:start"/> + <to uri="mock:foo"/> + <to uri="{{result}}"/> + </route> + </camelContext> +</blueprint> +---- + +By default Camel detects and uses OSGi blueprint property placeholder +service. You can disable this by setting the attribute +`useBlueprintPropertyResolver` to false on the `<camelContext>` +definition. + +===== About placeholder syntaxes + +Notice how we can use the Camel syntax for placeholders `{{ }}` in the +Camel route, which will lookup the value from OSGi blueprint. +The blueprint syntax for placeholders is `${}`. So outside +the `<camelContext>` you must use the `${}` syntax. Where as +inside `<camelContext>` you must use `{{ }}` syntax. OSGi blueprint +allows you to configure the syntax, so you can actually align those if +you want. + +You can also explicit refer to a specific OSGi blueprint property +placeholder by its id. For that you need to use the +Camel's `<propertyPlaceholder>` as shown in the example below: + +[source,xml] +---- +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0" + xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd"> + <!-- OSGI blueprint property placeholder --> + <cm:property-placeholder id="myblueprint.placeholder" persistent-id="camel.blueprint"> + <!-- list some properties as needed --> + <cm:default-properties> + <cm:property name="prefix.result" value="mock:result"/> + </cm:default-properties> + </cm:property-placeholder> + <camelContext xmlns="http://camel.apache.org/schema/blueprint"> + <!-- using Camel properties component and refer to the blueprint property placeholder by its id --> + <propertyPlaceholder id="properties" location="blueprint:myblueprint.placeholder" + prefixToken="[[" suffixToken="]]" propertyPrefix="prefix."/> + <!-- in the route we can use {{ }} placeholders which will lookup in blueprint --> + <route> + <from uri="direct:start"/> + <to uri="mock:foo"/> + <to uri="[[result]]"/> + </route> + </camelContext> +</blueprint> +---- + +Notice how we use the `blueprint` scheme to refer to the OSGi +blueprint placeholder by its id. This allows you to mix and match, for +example you can also have additional schemes in the location. For +example to load a file from the classpath you can do: + +[source,java] +---- +location="blueprint:myblueprint.placeholder,classpath:myproperties.properties" +---- + +Each location is separated by comma. + +[[UsingPropertyPlaceholder-OverridingBlueprintPropertyPlaceholdersOutsideCamelContext]] +==== Overriding Blueprint Property Placeholders Outside CamelContext + +*Available as of Camel 2.10.4* + +When using Blueprint property placeholder in the Blueprint XML file, you +can declare the properties directly in the XML file as shown below: + +include::../../../components/camel-test-blueprint/src/test/resources/org/apache/camel/test/blueprint/configadmin-outside.xml[] + +Notice that we have a `<bean>` which refers to one of the properties. And in +the Camel route we refer to the other using the `{{ }}` notation. + +Now if you want to override these Blueprint properties from an unit +test, you can do this as shown below: + +include::../../../components/camel-test-blueprint/src/test/java/org/apache/camel/test/blueprint/ConfigAdminOverridePropertiesOutsideCamelContextTest.java[] + +To do this we override and implement the +`useOverridePropertiesWithConfigAdmin` method. We can then put the +properties we want to override on the given props parameter. And the +return value _must_ be the persistence-id of +the `<cm:property-placeholder>` tag, which you define in the blueprint +XML file. + +[[UsingPropertyPlaceholder-Usinga.cfgor.propertiesFileForBlueprintPropertyPlaceholders]] +==== Using a `.cfg` or `.properties` File For Blueprint Property Placeholders + +*Available as of Camel 2.10.4* + +When using Blueprint property placeholder in the Blueprint XML file, you +can declare the properties in a .properties or `.cfg` file. If you use +Apache ServiceMix/Karaf then this container has a convention that it +loads the properties from a file in the etc directory with the naming +`etc/pid.cfg`, where `pid` is the persistence-id. + +For example in the blueprint XML file we have the +`persistence-id="stuff"`, which mean it will load the configuration +file as `etc/stuff.cfg`. + +include::../../../components/camel-test-blueprint/src/test/resources/org/apache/camel/test/blueprint/configadmin-loadfile.xml[] + +Now if you want to unit test this blueprint XML file, then you can override +the `loadConfigAdminConfigurationFile` and tell Camel which file to +load as shown below: + +include::../../../components/camel-test-blueprint/src/test/java/org/apache/camel/test/blueprint/ConfigAdminLoadConfigurationFileTest.java[] + +Notice that this method requires to return a `String[]` with 2 values. The +1st value is the path for the configuration file to load. The second +value is the persistence-id of the `<cm:property-placeholder>` tag. + +The `stuff.cfg` file is just a plain properties file with the property +placeholders such as: + +[source,java] +---- +## this is a comment +greeting=Bye +---- + + +[[UsingPropertyPlaceholder-Usinga.cfgfileandOverridingPropertiesforBlueprintPropertyPlaceholders]] +==== Using a `.cfg` file and Overriding Properties for Blueprint Property Placeholders + +You can do both as well. Here is a complete example. First we have the +Blueprint XML file: + +include::../../../components/camel-test-blueprint/src/test/resources/org/apache/camel/test/blueprint/configadmin-loadfileoverride.xml[] + +And in the unit test class we do as follows: + +include::../../../components/camel-test-blueprint/src/test/java/org/apache/camel/test/blueprint/ConfigAdminLoadConfigurationFileAndOverrideTest.java[] + +And the `etc/stuff.cfg` configuration file contains: + +[source,java] +---- +greeting=Bye +echo=Yay +destination=mock:result +---- + + +[[UsingPropertyPlaceholder-BridgingSpringandCamelPropertyPlaceholders]] +==== Bridging Spring and Camel Property Placeholders + +*Available as of Camel 2.10* + +The Spring Framework does not allow third-party frameworks such as +Apache Camel to seamless hook into the Spring property placeholder +mechanism. However you can easily bridge Spring and Camel by declaring a +Spring bean with the type +`org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer`, +which is a Spring +`org.springframework.beans.factory.config.PropertyPlaceholderConfigurer` +type. + +To bridge Spring and Camel you must define a single bean as shown below: + +include::../../../components/camel-spring/src/test/resources/org/apache/camel/component/properties/CamelSpringPropertyPlaceholderConfigurerTest.xml[] + +You *must not* use the spring `<context:property-placeholder>` namespace +at the same time; this is not possible. + +After declaring this bean, you can define property placeholders using +both the Spring style, and the Camel style within the `<camelContext>` +tag as shown below: + +include::../../../components/camel-spring/src/test/resources/org/apache/camel/component/properties/CamelSpringPropertyPlaceholderConfigurerTest.xml[] + +Notice how the hello bean is using pure Spring property placeholders using +the `${}` notation. And in the Camel routes we use the Camel +placeholder notation with `{{ }}`. + +[[UsingPropertyPlaceholder-ClashingSpringPropertyPlaceholderswithCamelsLanguage]] +==== Clashing Spring Property Placeholders with Camels <<simple-language,Simple>> Language + +Take notice when using Spring bridging placeholder then the +spring `${}` syntax clashes with the <<simple-language,Simple>> in +Camel, and therefore take care. + +Example: + +[source,xml] +---- +<setHeader headerName="Exchange.FILE_NAME"> + <simple>{{file.rootdir}}/${in.header.CamelFileName}</simple> +</setHeader> +---- + +clashes with Spring property placeholders, and you should +use `$simple{}` to indicate using the <<simple-language,Simple>> +language in Camel. + + +[source,xml] +---- +<setHeader headerName="Exchange.FILE_NAME"> + <simple>{{file.rootdir}}/$simple{in.header.CamelFileName}</simple> +</setHeader> +---- + +An alternative is to configure the `PropertyPlaceholderConfigurer` +with `ignoreUnresolvablePlaceholders` option to `true`. + +[[UsingPropertyPlaceholder-OverridingPropertiesfromCamelTestKit]] +==== Overriding Properties from Camel Test Kit + +*Available as of Camel 2.10* + +When link:testing.adoc[Testing] with Camel and using the +link:properties.adoc[Properties] component, you may want to be able to +provide the properties to be used from directly within the unit test +source code. This is now possible from Camel 2.10, as the Camel test +kits, e.g., `CamelTestSupport` class offers the following methods + +* `useOverridePropertiesWithPropertiesComponent` +* `ignoreMissingLocationWithPropertiesComponent` + +So for example in your unit test classes, you can override the +`useOverridePropertiesWithPropertiesComponent` method and return a +`java.util.Properties` that contains the properties which should be +preferred to be used. + +include::../../../components/camel-test-blueprint/src/test/java/org/apache/camel/test/blueprint/ConfigAdminOverridePropertiesTest.java[] + +This can be done from any of the Camel Test kits, such as `camel-test`, +`camel-test-spring` and `camel-test-blueprint`. + +The `ignoreMissingLocationWithPropertiesComponent` can be used to +instruct Camel to ignore any locations which was not discoverable. For +example if you run the unit test, in an environment that does not have +access to the location of the properties. + + +[[UsingPropertyPlaceholder-UsingPropertyInject]] +==== Using `@PropertyInject` + +*Available as of Camel 2.12* + +Camel allows to inject property placeholders in POJOs using +the `@PropertyInject` annotation which can be set on fields and setter +methods. For example you can use that with `RouteBuilder` classes, +such as shown below: + +[source,java] +---- +public class MyRouteBuilder extends RouteBuilder { + + @PropertyInject("hello") + private String greeting; + + @Override + public void configure() throws Exception { + from("direct:start") + .transform().constant(greeting) + .to("{{result}}"); + } +} +---- + +Notice we have annotated the greeting field with `@PropertyInject` and +define it to use the key `hello`. Camel will then lookup the property +with this key and inject its value, converted to a String type. + +You can also use multiple placeholders and text in the key, for example +we can do: + +[source,java] +---- +@PropertyInject("Hello {{name}} how are you?") +private String greeting; +---- + +This will lookup the placeholder with they key `name`. + +You can also add a default value if the key does not exists, such as: + +[source,java] +---- +@PropertyInject(value = "myTimeout", defaultValue = "5000") +private int timeout; +---- + + +[[UsingPropertyPlaceholder-UsingOutoftheBoxFunctions]] +==== Using Out of the Box Functions + +*Available as of Camel 2.14.1* + +The link:properties.adoc[Properties] component includes the following +functions out of the box + +* `env` - A function to lookup the property from OS environment +variables. +* `sys` - A function to lookup the property from Java JVM system +properties. +* `service` - A function to lookup the property from OS environment +variables using the service naming idiom. +* `service.host` - **Camel 2.16.1: **A function to lookup the +property from OS environment variables using the service naming idiom +returning the hostname part only. +* `service.port` - **Camel 2.16.1: **A function to lookup the +property from OS environment variables using the service naming idiom +returning the port part only. + +As you can see these functions is intended to make it easy to lookup +values from the environment. As they are provided out of the box, they +can easily be used as shown below: + +[source,xml] +---- +<camelContext xmlns="http://camel.apache.org/schema/blueprint"> + <route> + <from uri="direct:start"/> + <to uri="{{env:SOMENAME}}"/> + <to uri="{{sys:MyJvmPropertyName}}"/> + </route> +</camelContext> +---- + +You can use default values as well, so if the property does not exists, +you can define a default value as shown below, where the default value +is a `log:foo` and `log:bar` value. + + +[source,xml] +---- +<camelContext xmlns="http://camel.apache.org/schema/blueprint"> + <route> + <from uri="direct:start"/> + <to uri="{{env:SOMENAME:log:foo}}"/> + <to uri="{{sys:MyJvmPropertyName:log:bar}}"/> + </route> +</camelContext> +---- + +The service function is for looking up a service which is defined using +OS environment variables using the service naming idiom, to refer to a +service location using `hostname : port` + +* __NAME___SERVICE_HOST +* __NAME___SERVICE_PORT + +in other words the service uses `_SERVICE_HOST` and `_SERVICE_PORT` +as prefix. So if the service is named `FOO`, then the OS environment +variables should be set as + +export $FOO_SERVICE_HOST=myserver export $FOO_SERVICE_PORT=8888 + +For example if the `FOO` service a remote HTTP service, then we can +refer to the service in the Camel endpoint URI, and use +the link:http.adoc[HTTP] component to make the HTTP call: + +[source,xml] +---- +<camelContext xmlns="http://camel.apache.org/schema/blueprint"> + <route> + <from uri="direct:start"/> + <to uri="http://{{service:FOO}}/myapp"/> + </route> +</camelContext> +---- + +And we can use default values if the service has not been defined, for +example to call a service on localhost, maybe for unit testing etc: + +[source,xml] +---- +<camelContext xmlns="http://camel.apache.org/schema/blueprint"> + <route> + <from uri="direct:start"/> + <to uri="http://{{service:FOO:localhost:8080}}/myapp"/> + </route> +</camelContext> +---- + +[[UsingPropertyPlaceholder-UsingCustomFunctions]] +==== Using Custom Functions + +*Available as of Camel 2.14.1* + +The link:properties.adoc[Properties] component allow to plugin 3rd party +functions which can be used during parsing of the property placeholders. +These functions are then able to do custom logic to resolve the +placeholders, such as looking up in databases, do custom computations, +or whatnot. The name of the function becomes the prefix used in the +placeholder. This is best illustrated in the example code below + +[source,xml] +---- +<bean id="beerFunction" class="MyBeerFunction"/> +<camelContext xmlns="http://camel.apache.org/schema/blueprint"> + <propertyPlaceholder id="properties" location="none" ignoreMissingLocation="true"> + <propertiesFunction ref="beerFunction"/> + </propertyPlaceholder> + <route> + <from uri="direct:start"/> + <to uri="{{beer:FOO}}"/> + <to uri="{{beer:BAR}}"/> + </route> +</camelContext> +---- + +Here we have a Camel XML route where we have defined +the `<propertyPlaceholder>` to use a custom function, which we refer +to be the bean id - e.g., the `beerFunction`. As the beer function +uses `beer` as its name, then the placeholder syntax can trigger the +beer function by starting with `beer:value`. + +The implementation of the function is only two methods as shown below: + +[source,java] +---- +public static final class MyBeerFunction implements PropertiesFunction { + @Override + public String getName() { + return "beer"; + } + @Override + public String apply(String remainder) { + return "mock:" + remainder.toLowerCase(); + } +} +---- + +The function must implement +the `org.apache.camel.component.properties.PropertiesFunction` +interface. The method `getName` is the name of the function, e.g., +`beer`. And the `apply` method is where we implement the custom +logic to do. As the sample code is from an unit test, it just returns a +value to refer to a mock endpoint. + +To register a custom function from Java code is as shown below: + +[source,java] +---- +PropertiesComponent pc = context.getComponent("properties", PropertiesComponent.class); +pc.addFunction(new MyBeerFunction()); +---- + + +[[UsingPropertyPlaceholder-SeeAlso]] +==== See Also + +* <<properties-component,Properties>> component diff --git a/docs/user-manual/en/writing-components.adoc b/docs/user-manual/en/writing-components.adoc new file mode 100644 index 0000000..5d937c1 --- /dev/null +++ b/docs/user-manual/en/writing-components.adoc @@ -0,0 +1,158 @@ +[[WritingComponents-WritingComponents]] +=== Writing Components + +Apache Camel is designed to make it very easy to drop in new components +whether they be routing components, transformers, transports etc. The +idea of a component is to be a factory and manager of +link:endpoint.adoc[Endpoints]. + +Here are the main steps to writing a component: + +* Write a POJO which implements the +http://activemq.apache.org/camel/maven/current/camel-core/apidocs/org/apache/camel/Component.html[Component] +interface. The simplest approach is just to derive from +http://activemq.apache.org/camel/maven/current/camel-core/apidocs/org/apache/camel/impl/DefaultComponent.html[DefaultComponent]. +* To support auto-discovery of your component add a file to +`META-INF/services/org/apache/camel/component/FOO` where FOO is the URI +scheme for your component and any related endpoints created on the fly. +The latter file should contain the definition of the component class. +For example if your component is implemented by the +`com.example.CustomComponent` class, the service file should contain the +following line -- `class=com.example.CustomComponent`. + +Users can then either explicitly create your component, configure it and +register with a +http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/CamelContext.html[CamelContext] +or users can use a URI which auto-creates your component. + +[[WritingComponents-WritingEndpoints]] +==== Writing Endpoints + +When implementing an link:endpoint.adoc[Endpoint] you typically may +implement one or more of the following methods: + +* http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/Endpoint.html#createProducer()[createProducer()] +will create a +http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/Producer.html[Producer] +for sending message exchanges to the endpoint +* http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/Endpoint.html#createConsumer(org.apache.camel.Processor)[createConsumer()] +implements the link:event-driven-consumer.adoc[Event Driven Consumer] +pattern for consuming message exchanges from the endpoint via a +http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/Processor.html[Processor] +when creating a +http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/Consumer.html[Consumer] +* http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/Endpoint.html#createPollingConsumer()[createPollingConsumer()] +implements the link:polling-consumer.adoc[Polling Consumer] pattern for +consuming message exchanges from the endpoint via a +http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/PollingConsumer.html[PollingConsumer] + +Typically you just derive from +http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/impl/DefaultEndpoint.html[DefaultEndpoint] +and implement the +http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/Endpoint.html#createProducer()[createProducer()] +and / or +http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/Endpoint.html#createConsumer(org.apache.camel.Processor)[createConsumer()] +methods. The +http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/Endpoint.html#createPollingConsumer()[createPollingConsumer()] +method will be created by default for you in the +http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/impl/DefaultEndpoint.html[DefaultEndpoint] +class. + +If your endpoint is a polling-centric component you can derive from +http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/impl/DefaultPollingEndpoint.html[DefaultPollingEndpoint] +and then implement +http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/Endpoint.html#createPollingConsumer()[createPollingConsumer()]; +the +http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/Endpoint.html#createConsumer(org.apache.camel.Processor)[createConsumer()] +method will be created for you which avoids you having to write any +polling code. + +[[WritingComponents-AnnotatingyourEndpoint]] +==== Annotating your Endpoint + +As of *Camel 2.12* if you want to benefit from the automatic generation +of HTML documentation for all the parameters on your endpoint as part of +the maven site reports, you need to +link:endpoint-annotations.adoc[annotate your Endpoint's parameters]. + +So this means you add a `@UriEndpoint` annotation to your Endpoint class +and then annotate each parameter you wish to be configured via the URI +configuration mechanism with `@UriParam` (or `@UriParams` for nested +configuration objects). + +In addition its recommended that your Component implementation inherit +from the UriEndpointComponent base class as that means your Component +will automatically generate better metadata for the +link:componentconfiguration.adoc[ComponentConfiguration] API. + +Refer to the link:endpoint-annotations.adoc[Endpoint Annotations guide +for details]. + +[[WritingComponents-UsingaProcessor]] +==== Using a Processor + +If you are writing a simple endpoint which just processes messages in +some way, you can just implement a link:processor.adoc[Processor] and +link:processor.adoc[use that to create an endpoint]. + +[[WritingComponents-Dependencyinjectionandauto-discovery]] +==== Dependency injection and auto-discovery + +When using auto-discovery the CamelContext will default to its +link:injector.adoc[Injector] implementation to inject any required or +optional dependencies on the component. This allows you to use +auto-discovery of components via link:uris.adoc[URIs] while still +getting the benefits of dependency injection. + +For example your component can depend on a JDBC DataSource or JMS +ConnectionFactory which can be provided in the ApplicationContext in +Spring or Module in Guice. + +So you can if you prefer configure your Component using an IoC framework +like Spring or Guice; then add it to the CamelContext. Or you can let +the Component auto-inject itself as the endpoints are auto-discovered. + +[[WritingComponents-Options]] +==== Options + +If your component has options you can let it have public getters/setters +and Camel will automatically set the properties when the endpoint is +created. If you however want to take the matter in your own hands, then +you must remove the option from the given parameter list as Camel will +validate that all options are used. If not Camel will throw a +ResolveEndpointFailedException stating some of the options are unknown. + +The parameters is provided by Camel in the createEndpoint method from +DefaultComponent: + +[source,java] +---- +protected abstract Endpoint<E> createEndpoint(String uri, String remaining, Map parameters) +---- + +The code is an example from the <<seda-component,SEDA>> component that removes the size +parameter: + +[source,java] +---- + public BlockingQueue<Exchange> createQueue(String uri, Map parameters) { + int size = 1000; + Object value = parameters.remove("size"); + if (value != null) { + Integer i = convertTo(Integer.class, value); + if (i != null) { + size = i; + } + } + return new LinkedBlockingQueue<Exchange>(size); + } +---- + +[[WritingComponents-SeeAlso]] +==== See Also + +* link:configuring-camel.adoc[Configuring Camel] +* link:endpoint.adoc[Endpoint] +* link:component.adoc[Component] +* http://camel.apache.org/creating-a-new-camel-component.html[Creating a +new Camel Component with Maven]