[ https://issues.apache.org/jira/browse/CAMEL-11497?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16606910#comment-16606910 ]
ASF GitHub Bot commented on CAMEL-11497: ---------------------------------------- oscerd closed pull request #2512: CAMEL-11497: Migrate 'Working with Camel and ...' guides and related … URL: https://github.com/apache/camel/pull/2512 This is a PR merged from a forked repository. As GitHub hides the original diff on merge, it is displayed below for the sake of provenance: As this is a foreign pull request (from a fork), the diff is supplied below (as it won't show otherwise due to GitHub magic): diff --git a/docs/user-manual/en/SUMMARY.md b/docs/user-manual/en/SUMMARY.md index e72393ebd95..dc14a25670e 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 00000000000..fa801b30c75 --- /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 00000000000..e9939bb0d10 --- /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 00000000000..beeb78fb632 --- /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 00000000000..43820c9a5bc --- /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 00000000000..36650e84e3b --- /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 00000000000..9541e2d7e61 --- /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 00000000000..7b9283c2579 --- /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 00000000000..e6348a58b39 --- /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 a021f9de312..b5adcfe8864 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 00000000000..54a6c45824e --- /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 00000000000..4f016b14355 --- /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 00000000000..5d937c1eb76 --- /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] ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: us...@infra.apache.org > Migrate the rest of the Confluence content > ------------------------------------------ > > Key: CAMEL-11497 > URL: https://issues.apache.org/jira/browse/CAMEL-11497 > Project: Camel > Issue Type: Sub-task > Components: website > Reporter: Zoran Regvart > Assignee: Önder Sezgin > Priority: Major > Fix For: Future > > > There are still pages in the Confluence that are not migrated to Asciidoctor -- This message was sent by Atlassian JIRA (v7.6.3#76005)