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.grzy...@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
 

Reply via email to