This is an automated email from the ASF dual-hosted git repository.

jamesnetherton pushed a commit to branch 3.15.x
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git

commit a22841c3ba07c5bbfc7c12931c8634bdcd2dbc02
Author: James Netherton <jamesnether...@gmail.com>
AuthorDate: Thu Oct 3 10:01:47 2024 +0100

    Fix build time processing of Kamelets with bean definitions
    
    Fixes #6581
---
 .../kamelet/deployment/KameletProcessor.java       | 30 ++++++++++++++--
 .../quarkus/component/kamelet/KameletRecorder.java |  7 ++++
 integration-tests/kamelet/pom.xml                  | 17 +++++++++
 .../quarkus/component/kamelet/it/KameletBean.java  | 29 +++++++++++++++
 .../component/kamelet/it/KameletResource.java      |  6 ++++
 .../component/kamelet/it/KameletRoutes.java        |  3 ++
 .../src/main/resources/application.properties      |  2 +-
 .../main/resources/kamelets/greeting.kamelet.yaml  | 42 ++++++++++++++++++++++
 .../quarkus/component/kamelet/it/KameletTest.java  | 12 ++++++-
 9 files changed, 144 insertions(+), 4 deletions(-)

diff --git 
a/extensions/kamelet/deployment/src/main/java/org/apache/camel/quarkus/component/kamelet/deployment/KameletProcessor.java
 
b/extensions/kamelet/deployment/src/main/java/org/apache/camel/quarkus/component/kamelet/deployment/KameletProcessor.java
index 1bd217b289..8588bdb1b1 100644
--- 
a/extensions/kamelet/deployment/src/main/java/org/apache/camel/quarkus/component/kamelet/deployment/KameletProcessor.java
+++ 
b/extensions/kamelet/deployment/src/main/java/org/apache/camel/quarkus/component/kamelet/deployment/KameletProcessor.java
@@ -20,14 +20,17 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Optional;
+import java.util.Set;
 
 import io.quarkus.deployment.annotations.BuildProducer;
 import io.quarkus.deployment.annotations.BuildStep;
 import io.quarkus.deployment.annotations.ExecutionTime;
 import io.quarkus.deployment.annotations.Record;
 import io.quarkus.deployment.builditem.FeatureBuildItem;
+import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
 import org.apache.camel.CamelContext;
 import org.apache.camel.ExtendedCamelContext;
 import org.apache.camel.Ordered;
@@ -89,6 +92,7 @@ class KameletProcessor {
     @BuildStep
     CamelContextCustomizerBuildItem configureTemplates(
             List<KameletResourceBuildItem> resources,
+            BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
             KameletRecorder recorder) throws Exception {
 
         List<RouteTemplateDefinition> definitions = new ArrayList<>();
@@ -97,9 +101,13 @@ class KameletProcessor {
             ExtendedCamelContext ecc = context.getCamelContextExtension();
 
             for (KameletResourceBuildItem item : resources) {
-                LOGGER.debugf("Loading kamelet from: %s)", item.getResource());
+                Resource resource = item.getResource();
+                if (!resource.exists()) {
+                    throw new IllegalStateException("Unable to load kamelet 
from: " + resource.getLocation());
+                }
 
-                Collection<RoutesBuilder> rbs = 
PluginHelper.getRoutesLoader(ecc).findRoutesBuilders(item.getResource());
+                LOGGER.debugf("Loading kamelet from: %s", resource);
+                Collection<RoutesBuilder> rbs = 
PluginHelper.getRoutesLoader(ecc).findRoutesBuilders(resource);
                 for (RoutesBuilder rb : rbs) {
                     RouteBuilder routeBuilder = (RouteBuilder) rb;
                     routeBuilder.configure();
@@ -135,6 +143,24 @@ class KameletProcessor {
             if (definition.getRoute() != null && 
definition.getRoute().getOutputs() != null) {
                 definition.getRoute().getOutputs().forEach(o -> 
o.setCamelContext(null));
             }
+
+            if (definition.getTemplateBeans() != null) {
+                Set<String> beanClassNames = new HashSet<>();
+                definition.getTemplateBeans().forEach(bean -> {
+                    bean.setResource(resource);
+
+                    String beanType = bean.getType();
+                    if (beanType != null && beanType.startsWith("#class:")) {
+                        String className = 
beanType.substring("#class:".length());
+                        beanClassNames.add(className);
+                    }
+                });
+
+                
reflectiveClass.produce(ReflectiveClassBuildItem.builder(beanClassNames.toArray(new
 String[0]))
+                        .fields()
+                        .methods()
+                        .build());
+            }
         });
 
         return new CamelContextCustomizerBuildItem(
diff --git 
a/extensions/kamelet/runtime/src/main/java/org/apache/camel/quarkus/component/kamelet/KameletRecorder.java
 
b/extensions/kamelet/runtime/src/main/java/org/apache/camel/quarkus/component/kamelet/KameletRecorder.java
index b431298fc0..2763ca5a58 100644
--- 
a/extensions/kamelet/runtime/src/main/java/org/apache/camel/quarkus/component/kamelet/KameletRecorder.java
+++ 
b/extensions/kamelet/runtime/src/main/java/org/apache/camel/quarkus/component/kamelet/KameletRecorder.java
@@ -63,6 +63,13 @@ public class KameletRecorder {
                         if (definition.getRoute() != null && 
definition.getRoute().getOutputs() != null) {
                             definition.getRoute().getOutputs().forEach(o -> 
o.setCamelContext(context));
                         }
+
+                        if (definition.getTemplateBeans() != null) {
+                            definition.getTemplateBeans()
+                                    .stream()
+                                    .filter(bean -> bean.getResource() 
instanceof EmptyKameletResource)
+                                    .forEach(bean -> 
bean.setResource(resourceLoader.resolveResource(location)));
+                        }
                     }
                     
context.getCamelContextExtension().getContextPlugin(Model.class).addRouteTemplateDefinitions(definitions);
                 } catch (Exception e) {
diff --git a/integration-tests/kamelet/pom.xml 
b/integration-tests/kamelet/pom.xml
index a266ae339f..e461be2830 100644
--- a/integration-tests/kamelet/pom.xml
+++ b/integration-tests/kamelet/pom.xml
@@ -51,6 +51,10 @@
             <groupId>org.apache.camel.quarkus</groupId>
             <artifactId>camel-quarkus-xml-io-dsl</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-seda</artifactId>
+        </dependency>
         <dependency>
             <groupId>io.quarkus</groupId>
             <artifactId>quarkus-resteasy</artifactId>
@@ -167,6 +171,19 @@
                         </exclusion>
                     </exclusions>
                 </dependency>
+                <dependency>
+                    <groupId>org.apache.camel.quarkus</groupId>
+                    <artifactId>camel-quarkus-seda-deployment</artifactId>
+                    <version>${project.version}</version>
+                    <type>pom</type>
+                    <scope>test</scope>
+                    <exclusions>
+                        <exclusion>
+                            <groupId>*</groupId>
+                            <artifactId>*</artifactId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
                 <dependency>
                     <groupId>org.apache.camel.quarkus</groupId>
                     <artifactId>camel-quarkus-timer-deployment</artifactId>
diff --git 
a/integration-tests/kamelet/src/main/java/org/apache/camel/quarkus/component/kamelet/it/KameletBean.java
 
b/integration-tests/kamelet/src/main/java/org/apache/camel/quarkus/component/kamelet/it/KameletBean.java
new file mode 100644
index 0000000000..475c1a3eeb
--- /dev/null
+++ 
b/integration-tests/kamelet/src/main/java/org/apache/camel/quarkus/component/kamelet/it/KameletBean.java
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+package org.apache.camel.quarkus.component.kamelet.it;
+
+public class KameletBean {
+    private final String greeting;
+
+    public KameletBean(String greeting) {
+        this.greeting = greeting;
+    }
+
+    public String getGreeting() {
+        return greeting;
+    }
+}
diff --git 
a/integration-tests/kamelet/src/main/java/org/apache/camel/quarkus/component/kamelet/it/KameletResource.java
 
b/integration-tests/kamelet/src/main/java/org/apache/camel/quarkus/component/kamelet/it/KameletResource.java
index 37a73e5539..f9bb2f9af7 100644
--- 
a/integration-tests/kamelet/src/main/java/org/apache/camel/quarkus/component/kamelet/it/KameletResource.java
+++ 
b/integration-tests/kamelet/src/main/java/org/apache/camel/quarkus/component/kamelet/it/KameletResource.java
@@ -103,4 +103,10 @@ public class KameletResource {
         return 
fluentProducerTemplate.to("direct:kamelet-location-at-runtime").withBody(name).request(String.class);
     }
 
+    @Path("/greeting")
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    public String greeting() {
+        return consumerTemplate.receiveBody("seda:greeting", 10000, 
String.class);
+    }
 }
diff --git 
a/integration-tests/kamelet/src/main/java/org/apache/camel/quarkus/component/kamelet/it/KameletRoutes.java
 
b/integration-tests/kamelet/src/main/java/org/apache/camel/quarkus/component/kamelet/it/KameletRoutes.java
index e8b812ebb0..afb8520dac 100644
--- 
a/integration-tests/kamelet/src/main/java/org/apache/camel/quarkus/component/kamelet/it/KameletRoutes.java
+++ 
b/integration-tests/kamelet/src/main/java/org/apache/camel/quarkus/component/kamelet/it/KameletRoutes.java
@@ -64,6 +64,9 @@ public class KameletRoutes extends RouteBuilder {
 
         from("direct:kamelet-location-at-runtime")
                 
.kamelet("upper?location=classpath:kamelets-runtime/upper-kamelet.xml");
+
+        from("kamelet:greeting")
+                .to("seda:greeting");
     }
 
     @RegisterForReflection
diff --git 
a/integration-tests/kamelet/src/main/resources/application.properties 
b/integration-tests/kamelet/src/main/resources/application.properties
index cff0cd1934..0b6ffc878c 100644
--- a/integration-tests/kamelet/src/main/resources/application.properties
+++ b/integration-tests/kamelet/src/main/resources/application.properties
@@ -16,7 +16,7 @@
 ## ---------------------------------------------------------------------------
 camel.kamelet.setBodyFromProperties.bodyValueFromProperty=Camel Quarkus 
Kamelet Property
 
-quarkus.camel.kamelet.identifiers = injector,logger
+quarkus.camel.kamelet.identifiers = injector,logger,greeting
 
 # this is needed to actually test that kamelet are preloaded at build time:
 camel.component.kamelet.location = file:/invalid
diff --git 
a/integration-tests/kamelet/src/main/resources/kamelets/greeting.kamelet.yaml 
b/integration-tests/kamelet/src/main/resources/kamelets/greeting.kamelet.yaml
new file mode 100644
index 0000000000..aff771f2c3
--- /dev/null
+++ 
b/integration-tests/kamelet/src/main/resources/kamelets/greeting.kamelet.yaml
@@ -0,0 +1,42 @@
+#
+# 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.
+#
+
+apiVersion: camel.apache.org/v1
+kind: Kamelet
+metadata:
+  name: greeting
+  labels:
+    camel.apache.org/kamelet.type: "source"
+    camel.apache.org/kamelet.name: "greeting"
+    camel.apache.org/kamelet.version: "v1"
+    camel.apache.org/kamelet.revision: "1"
+spec:
+  definition:
+    title: "Greeting"
+    description: "Print a greeting"
+  dependencies:
+    - "camel:timer"
+  template:
+    beans:
+      - name: greetingBean
+        type: 
"#class:org.apache.camel.quarkus.component.kamelet.it.KameletBean"
+        constructors:
+          0: "Hello World"
+    from:
+      uri: timer:greet?repeatCount=1&delay=-1
+      steps:
+        - to: "bean:{{greetingBean}}?method=getGreeting"
diff --git 
a/integration-tests/kamelet/src/test/java/org/apache/camel/quarkus/component/kamelet/it/KameletTest.java
 
b/integration-tests/kamelet/src/test/java/org/apache/camel/quarkus/component/kamelet/it/KameletTest.java
index 5aafba9df6..e95c0efdf9 100644
--- 
a/integration-tests/kamelet/src/test/java/org/apache/camel/quarkus/component/kamelet/it/KameletTest.java
+++ 
b/integration-tests/kamelet/src/test/java/org/apache/camel/quarkus/component/kamelet/it/KameletTest.java
@@ -93,7 +93,8 @@ class KameletTest {
     public void testDiscovered() {
         Response resp = RestAssured.given()
                 .contentType(ContentType.JSON)
-                .when().get("/kamelet/list");
+                .when()
+                .get("/kamelet/list");
         resp.then().statusCode(200);
 
         ArrayList<String> jsonAsArrayList = resp.body()
@@ -102,6 +103,7 @@ class KameletTest {
         assertTrue(jsonAsArrayList.contains("injector"));
         assertTrue(jsonAsArrayList.contains("logger"));
         assertTrue(jsonAsArrayList.contains("custom-log"));
+        assertTrue(jsonAsArrayList.contains("greeting"));
     }
 
     @Test
@@ -112,4 +114,12 @@ class KameletTest {
                 .statusCode(200)
                 .body(is("HELLO"));
     }
+
+    @Test
+    public void testKameletWithBean() {
+        RestAssured.get("/kamelet/greeting")
+                .then()
+                .statusCode(200)
+                .body(is("Hello World"));
+    }
 }

Reply via email to