You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by gg...@apache.org on 2023/06/07 12:09:35 UTC
[camel] branch main updated: [CAMEL-18189] Add documentation about support
This is an automated email from the ASF dual-hosted git repository.
ggrzybek pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new 2d912c91799 [CAMEL-18189] Add documentation about <bean> support
2d912c91799 is described below
commit 2d912c91799a18c2c17e8617de592171ee62eee0
Author: Grzegorz Grzybek <gr...@gmail.com>
AuthorDate: Wed Jun 7 12:51:03 2023 +0200
[CAMEL-18189] Add documentation about <bean> support
---
.../modules/ROOT/pages/camel-jbang.adoc | 149 +++++++++++++++++++++
.../java/org/apache/camel/main/KameletMain.java | 1 +
.../org/apache/camel/main/KameletMainTest.java | 16 +++
.../java/org/apache/camel/main/app/Greeter.java | 15 ++-
.../org/apache/camel/main/xml/spring-camel2.xml | 44 ++++++
.../src/main/docs/java-xml-io-dsl.adoc | 58 ++++++++
6 files changed, 282 insertions(+), 1 deletion(-)
diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc b/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
index 94c7acdb2cf..8ef85480537 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
@@ -438,6 +438,13 @@ If you do not want Camel JBang to download over the internet, you can turn this
camel run foo.java --download=false
----
+If you do not want Camel JBang to use your existing Maven settings file, you can use:
+
+[source,bash]
+----
+camel run foo.java --maven-settings=false
+----
+
[#_adding_custom_jars]
=== Adding custom JARs
@@ -1589,6 +1596,8 @@ And these annotations should work on all runtimes
- `@org.apache.camel.BindToRegistry` on a method to create a bean by invoking the method.
- `@org.apache.camel.Converter` on class level to auto-register the xref:type-converter.adoc[type converters] from the class.
+IMPORTANT: You can use `@BeanInject` annotation to refer to existing bean annotated with `@BindToRegistry`, however this is possibe if the dependency is registered before the dependant.
+
==== Using Spring Boot dependency injection
You can use the following Spring Boot annotations:
@@ -1607,6 +1616,146 @@ You can use the following Quarkus annotations:
- `@org.eclipse.microprofile.config.inject.ConfigProperty` to inject a xref:using-propertyplaceholder.adoc[property placeholder]. Such as a property defined in `application.properties`.
- `@javax.enterprise.inject.Produces` on a method to create a bean by invoking the method. `@javax.inject.Named` can be used to specify the bean id.
+==== Using beans in Camel XML DSL
+
+Since Camel *4.0.0*, when using xref:components:others:java-xml-io-dsl.adoc[XML DSL] we can declare additional beans in similar way as in xref:components:others:yaml-dsl.adoc[YAML DSL]. Such beans will be added to xref:registry.adoc[Registry] and can be referred to for example from routes.
+
+[source,xml]
+----
+<camel>
+
+ <bean name="beanFromMap" type="com.acme.MyBean">
+ <properties>
+ <property key="foo" value="bar" />
+ </properties>
+ </bean>
+
+</camel>
+----
+
+The properties of the bean can be defined using either nested `<property>` and `<properties>` elements or using dotted properties style, as shown in the example below:
+
+[source,xml]
+----
+<camel>
+
+ <!-- nested properties style -->
+ <bean name="beanFromMap" type="com.acme.MyBean">
+ <properties>
+ <property key="field1" value="f1_p" />
+ <property key="field2" value="f2_p" />
+ <property key="nested">
+ <properties>
+ <property key="field1" value="nf1_p" />
+ <property key="field2" value="nf2_p" />
+ </properties>
+ </property>
+ </properties>
+ </bean>
+
+ <!-- dotted properties style -->
+ <bean name="beanFromProps" type="com.acme.MyBean">
+ <properties>
+ <property key="field1" value="f1_p" />
+ <property key="field2" value="f2_p" />
+ <property key="nested.field1" value="nf1_p" />
+ <property key="nested.field2" value="nf2_p" />
+ </properties>
+ </bean>
+
+</camel>
+----
+
+==== Using Spring beans in Camel XML DSL
+
+Since Camel *4.0.0*, when using xref:components:others:java-xml-io-dsl.adoc[XML DSL], we can also declare _beans_ using Spring Beans XML namespace. All these beans will be added to xref:registry.adoc[Registry].
+
+This will not make the application managed by Spring Framework / Spring Boot. Simply Camel will leverage existing support for generic bean definition including:
+
+* dependency injection
+* constructor injection
+* dependency cycles
+* wiring existing Camel objects (like `org.apache.camel.CamelContext`)
+
+xref:components:others:java-xml-io-dsl.adoc[XML DSL] allows to use XML documents that define routes, rests and route templates. Since Camel *4.0.0* these documents may use new root XML element (either `<camel>` or `<beans>` to resemble Spring XML DSL), where other Camel elements (like `<routes>`) are contained.
+
+Here's an example `camel.xml` file, which defines both the routes and beans used (referred to) by the route definition:
+
+.camel.xml
+[source,xml]
+----
+<camel>
+
+ <beans xmlns="http://www.springframework.org/schema/beans">
+ <bean id="messageString" class="java.lang.String">
+ <constructor-arg index="0" value="Hello"/>
+ </bean>
+
+ <bean id="greeter" class="org.apache.camel.main.app.Greeter">
+ <description>Spring Bean</description>
+ <property name="message">
+ <bean class="org.apache.camel.main.app.GreeterMessage">
+ <property name="msg" ref="messageString"/>
+ </bean>
+ </property>
+ </bean>
+ </beans>
+
+ <route id="my-route">
+ <from uri="direct:start"/>
+ <bean ref="greeter"/>
+ <to uri="mock:finish"/>
+ </route>
+
+</camel>
+----
+
+This document contains embedded `<beans>` element using Spring Beans XML namespace (`http://www.springframework.org/schema/beans`) - Camel passes this element directly to Spring `org.springframework.beans.factory.xml.XmlBeanDefinitionReader` and all read beans are used to populate xref:registry.adoc[Camel Registry].
+
+The beans declared this way may use references to some predefined Camel beans. Currently these are handled:
+
+* "CamelContext" - an instance of current `org.apache.camel.CamelContext`
+* "MainConfiguration" - an instance of `org.apache.camel.main.MainConfigurationProperties` used for `org.apache.camel.main.KameletMain`
+
+So we can use this XML fragment without actually defining what `CamelContext` is.
+
+[source,xml]
+----
+<camel>
+
+ <beans xmlns="http://www.springframework.org/schema/beans">
+ <bean id="greeter" class="org.apache.camel.main.app.Greeter">
+ <property name="camelContext" ref="CamelContext"/>
+ <!-- ... -->
+ </bean>
+ </beans>
+
+ <route id="my-route">
+ <from uri="direct:start"/>
+ <bean ref="greeter"/>
+ <to uri="mock:finish"/>
+ </route>
+
+</camel>
+----
+
+What's more, we can declare some additional beans that can affect internal mechanics of `CamelContext` being run. `org.apache.camel.main.DefaultConfigurationConfigurer` is used by xref:components:others:main.adoc[Camel Main] to configure `CamelContext` using beans found in xref:registry.adoc[Camel Registry].
+
+For example we can customize used `org.apache.camel.spi.UuidGenerator` with this XML fragment to replace UUID generator used by Camel (which defaults to `org.apache.camel.support.DefaultUuidGenerator`):
+
+[source,xml]
+----
+<camel>
+
+ <beans xmlns="http://www.springframework.org/schema/beans">
+ <bean id="customUUIDGenerator" class="org.apache.camel.support.ShortUuidGenerator" />
+ </beans>
+
+</camel>
+----
+
+That's it - Camel context will then look up for the instances of `org.apache.camel.spi.UuidGenerator` and if one is found, it'll be used by Camel.
+
=== Debugging
There are two kinds of debugging:
diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
index e72f650bb03..955d9fe38a6 100644
--- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
+++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
@@ -616,6 +616,7 @@ public class KameletMain extends MainCommandLineSupport {
beanFactory.setAllowCircularReferences(true); // for now
// register some existing beans (the list may change)
+ // would be nice to keep the documentation up to date: docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
Set<String> infraBeanNames = Set.of("CamelContext", "MainConfiguration");
beanFactory.registerSingleton("CamelContext", camelContext);
beanFactory.registerSingleton("MainConfiguration", config);
diff --git a/dsl/camel-kamelet-main/src/test/java/org/apache/camel/main/KameletMainTest.java b/dsl/camel-kamelet-main/src/test/java/org/apache/camel/main/KameletMainTest.java
index 33257f6c3f2..854bf77b9c0 100644
--- a/dsl/camel-kamelet-main/src/test/java/org/apache/camel/main/KameletMainTest.java
+++ b/dsl/camel-kamelet-main/src/test/java/org/apache/camel/main/KameletMainTest.java
@@ -54,6 +54,22 @@ public class KameletMainTest {
});
}
+ @Test
+ public void testRouteWithSpringBeansAndCamelDependencies() throws Exception {
+ doTestMain("classpath:org/apache/camel/main/xml/spring-camel2.xml", (main, camelContext) -> {
+ try {
+ MockEndpoint endpoint = camelContext.getEndpoint("mock:finish", MockEndpoint.class);
+ endpoint.expectedBodiesReceived("Hello World (" + System.identityHashCode(camelContext) + ")");
+
+ main.getCamelTemplate().sendBody("direct:start", "I'm World");
+
+ endpoint.assertIsSatisfied();
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+ });
+ }
+
protected void doTestMain(String includes, BiConsumer<KameletMain, CamelContext> consumer) throws Exception {
KameletMain main = new KameletMain();
diff --git a/dsl/camel-kamelet-main/src/test/java/org/apache/camel/main/app/Greeter.java b/dsl/camel-kamelet-main/src/test/java/org/apache/camel/main/app/Greeter.java
index 1ec8ef91036..52d29755c1c 100644
--- a/dsl/camel-kamelet-main/src/test/java/org/apache/camel/main/app/Greeter.java
+++ b/dsl/camel-kamelet-main/src/test/java/org/apache/camel/main/app/Greeter.java
@@ -16,6 +16,7 @@
*/
package org.apache.camel.main.app;
+import org.apache.camel.CamelContext;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.util.StringHelper;
@@ -28,6 +29,8 @@ public class Greeter implements Processor {
private Integer number;
+ private CamelContext camelContext;
+
public void setMessage(GreeterMessage message) {
this.message = message;
}
@@ -40,10 +43,20 @@ public class Greeter implements Processor {
this.bean = bean;
}
+ public void setCamelContext(CamelContext camelContext) {
+ this.camelContext = camelContext;
+ }
+
@Override
public void process(Exchange exchange) throws Exception {
String msg = exchange.getIn().getBody(String.class);
- exchange.getIn().setBody(message.getMsg() + " " + StringHelper.after(msg, "I'm ") + " (" + number + ")");
+ if (camelContext != null) {
+ exchange.getIn().setBody(message.getMsg() + " " + StringHelper.after(msg, "I'm ")
+ + " (" + System.identityHashCode(camelContext) + ")");
+ } else {
+ exchange.getIn().setBody(message.getMsg() + " " + StringHelper.after(msg, "I'm ")
+ + " (" + number + ")");
+ }
}
}
diff --git a/dsl/camel-kamelet-main/src/test/resources/org/apache/camel/main/xml/spring-camel2.xml b/dsl/camel-kamelet-main/src/test/resources/org/apache/camel/main/xml/spring-camel2.xml
new file mode 100644
index 00000000000..e39caba291c
--- /dev/null
+++ b/dsl/camel-kamelet-main/src/test/resources/org/apache/camel/main/xml/spring-camel2.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<camel>
+
+ <beans xmlns="http://www.springframework.org/schema/beans">
+
+ <bean id="messageString" class="java.lang.String">
+ <constructor-arg index="0" value="Hello"/>
+ </bean>
+
+ <bean id="greeter" class="org.apache.camel.main.app.Greeter">
+ <property name="camelContext" ref="CamelContext"/>
+ <property name="message">
+ <bean class="org.apache.camel.main.app.GreeterMessage">
+ <property name="msg" ref="messageString"/>
+ </bean>
+ </property>
+ </bean>
+ </beans>
+
+ <route id="r2">
+ <from uri="direct:start"/>
+ <bean ref="greeter"/>
+ <to uri="mock:finish"/>
+ </route>
+
+</camel>
diff --git a/dsl/camel-xml-io-dsl/src/main/docs/java-xml-io-dsl.adoc b/dsl/camel-xml-io-dsl/src/main/docs/java-xml-io-dsl.adoc
index 823923e973a..d2f5d7b66fc 100644
--- a/dsl/camel-xml-io-dsl/src/main/docs/java-xml-io-dsl.adoc
+++ b/dsl/camel-xml-io-dsl/src/main/docs/java-xml-io-dsl.adoc
@@ -57,6 +57,64 @@ kamel run my-route.xml
camel run my-route.xml
----
+*Since Camel 4.0.0*
+
+It is now possible with `xml-io-dsl` to declare some beans to be bound to xref:manual::registry.adoc[Camel Registry] in similar way as with xref:yaml-dsl.adoc[YAML DSL]. Beans may be declared in XML and have their properties (also nested) defined. For example:
+
+[source,xml]
+----
+<camel>
+
+ <bean name="beanFromProps" type="com.acme.MyBean">
+ <properties>
+ <property key="field1" value="f1_p" />
+ <property key="field2" value="f2_p" />
+ <property key="nested.field1" value="nf1_p" />
+ <property key="nested.field2" value="nf2_p" />
+ </properties>
+ </bean>
+
+</camel>
+----
+
+While keeping all the benefits of fast XML parser used by `xml-io-dsl`, Camel can also process XML elements declared in other XML namespaces and process them separately. With this mechanism it is possible to include XML elements using Spring's `http://www.springframework.org/schema/beans` namespace.
+
+This brings the flexibility of Spring Beans into xref:components:others:main.adoc[Camel Main] without actually running any Spring Application Context (or Spring Boot). When elements from Spring namespace are found, they are used to populate and configure an instance of `org.springframework.beans.factory.support.DefaultListableBeanFactory` and leverage Spring dependency injection to wire the beans together. These beans are then exposed through normal xref:manual::registry.adoc[Camel Regis [...]
+
+Here's an example `camel.xml` file, which defines both the routes and beans used (referred to) by the route definition:
+
+.camel.xml
+[source,xml]
+----
+<camel>
+
+ <beans xmlns="http://www.springframework.org/schema/beans">
+ <bean id="messageString" class="java.lang.String">
+ <constructor-arg index="0" value="Hello"/>
+ </bean>
+
+ <bean id="greeter" class="org.apache.camel.main.app.Greeter">
+ <description>Spring Bean</description>
+ <property name="message">
+ <bean class="org.apache.camel.main.app.GreeterMessage">
+ <property name="msg" ref="messageString"/>
+ </bean>
+ </property>
+ </bean>
+ </beans>
+
+ <route id="my-route">
+ <from uri="direct:start"/>
+ <bean ref="greeter"/>
+ <to uri="mock:finish"/>
+ </route>
+
+</camel>
+----
+
+A `my-route` route is referring to `greeter` bean which is defined using Spring `<bean>` element.
+
+More examples can be found in xref:manual:ROOT:camel-jbang.adoc#_using_spring_beans_in_camel_xml_dsl[Camel JBang] page.
== See Also