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

aldettinger pushed a commit to branch ql4j-bean-binding
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git

commit d7937e18c0fb192fb23e6f219bb6a505e6171de9
Author: aldettinger <[email protected]>
AuthorDate: Tue Mar 24 11:22:51 2026 +0100

    langchain4j-agent: Reinstate some of the camel-quarkus-langchain4j tests
---
 .../deployment/QuarkusLangchain4jPresent.java      |   4 +-
 .../SupportQuarkusLangchain4jProcessor.java        |  28 +++++
 .../langchain4j-agent-bean-binding-ql4j/pom.xml    | 135 +++++++++++++++++++++
 .../agent/AiServiceResolvedByInterface.java        |  34 ++++++
 .../langchain4j/agent/AiServiceResolvedByName.java |  35 ++++++
 .../Langchain4jAgentBeanBindingQl4jResource.java   |  34 ++++++
 .../Langchain4jAgentBeanBindingQl4jRoutes.java     |  18 +++
 .../src/main/resources/application.properties      |  18 +++
 .../it/Langchain4jAgentBeanBindingQl4jTest.java    |  45 +++++++
 integration-tests-jvm/pom.xml                      |   1 +
 10 files changed, 351 insertions(+), 1 deletion(-)

diff --git 
a/extensions-support/langchain4j/deployment/src/main/java/org/apache/camel/quarkus/component/support/langchain4j/deployment/QuarkusLangchain4jPresent.java
 
b/extensions-support/langchain4j/deployment/src/main/java/org/apache/camel/quarkus/component/support/langchain4j/deployment/QuarkusLangchain4jPresent.java
index 7741e015dc..f76d56e9c7 100644
--- 
a/extensions-support/langchain4j/deployment/src/main/java/org/apache/camel/quarkus/component/support/langchain4j/deployment/QuarkusLangchain4jPresent.java
+++ 
b/extensions-support/langchain4j/deployment/src/main/java/org/apache/camel/quarkus/component/support/langchain4j/deployment/QuarkusLangchain4jPresent.java
@@ -18,11 +18,13 @@ package 
org.apache.camel.quarkus.component.support.langchain4j.deployment;
 
 import java.util.function.BooleanSupplier;
 
+import static 
org.apache.camel.quarkus.component.support.langchain4j.deployment.SupportQuarkusLangchain4jProcessor.REGISTER_AI_SERVICES_DOTNAME;
+
 public class QuarkusLangchain4jPresent implements BooleanSupplier {
     @Override
     public boolean getAsBoolean() {
         try {
-            
Thread.currentThread().getContextClassLoader().loadClass("io.quarkiverse.langchain4j.RegisterAiService");
+            
Thread.currentThread().getContextClassLoader().loadClass(REGISTER_AI_SERVICES_DOTNAME.toString());
             return true;
         } catch (ClassNotFoundException e) {
             return false;
diff --git 
a/extensions-support/langchain4j/deployment/src/main/java/org/apache/camel/quarkus/component/support/langchain4j/deployment/SupportQuarkusLangchain4jProcessor.java
 
b/extensions-support/langchain4j/deployment/src/main/java/org/apache/camel/quarkus/component/support/langchain4j/deployment/SupportQuarkusLangchain4jProcessor.java
index 22c19056de..e27426991a 100644
--- 
a/extensions-support/langchain4j/deployment/src/main/java/org/apache/camel/quarkus/component/support/langchain4j/deployment/SupportQuarkusLangchain4jProcessor.java
+++ 
b/extensions-support/langchain4j/deployment/src/main/java/org/apache/camel/quarkus/component/support/langchain4j/deployment/SupportQuarkusLangchain4jProcessor.java
@@ -23,6 +23,7 @@ import dev.langchain4j.guardrail.Guardrail;
 import dev.langchain4j.guardrail.InputGuardrail;
 import dev.langchain4j.guardrail.OutputGuardrail;
 import io.quarkus.arc.deployment.SyntheticBeanBuildItem;
+import io.quarkus.arc.deployment.UnremovableBeanBuildItem;
 import io.quarkus.deployment.annotations.BuildProducer;
 import io.quarkus.deployment.annotations.BuildStep;
 import io.quarkus.deployment.annotations.BuildSteps;
@@ -32,15 +33,26 @@ import 
io.quarkus.deployment.builditem.CombinedIndexBuildItem;
 import io.quarkus.deployment.builditem.SystemPropertyBuildItem;
 import jakarta.inject.Singleton;
 import 
org.apache.camel.quarkus.component.support.langchain4j.QuarkusLangchain4jRecorder;
+import org.jboss.jandex.AnnotationInstance;
+import org.jboss.jandex.AnnotationTarget;
 import org.jboss.jandex.ClassInfo;
 import org.jboss.jandex.DotName;
 import org.jboss.jandex.IndexView;
+import org.jboss.logging.Logger;
+
+import static 
io.quarkus.arc.deployment.UnremovableBeanBuildItem.beanClassNames;
 
 /**
  * Build steps required only when Quarkus LangChain4j is detected.
  */
 @BuildSteps(onlyIf = QuarkusLangchain4jPresent.class)
 class SupportQuarkusLangchain4jProcessor {
+
+    public static final DotName REGISTER_AI_SERVICES_DOTNAME = DotName
+            .createSimple("io.quarkiverse.langchain4j.RegisterAiService");
+
+    private static final Logger LOG = 
Logger.getLogger(SupportQuarkusLangchain4jProcessor.class);
+
     @BuildStep
     SystemPropertyBuildItem enforceJaxRsHttpClient() {
         return new 
SystemPropertyBuildItem("langchain4j.http.clientBuilderFactory",
@@ -85,4 +97,20 @@ class SupportQuarkusLangchain4jProcessor {
                     }
                 });
     }
+
+    @BuildStep
+    void markAiServicesAsUnremovable(
+            CombinedIndexBuildItem indexBuildItem,
+            BuildProducer<UnremovableBeanBuildItem> unremovableBeans) {
+        LOG.debug("Discovering classes annotated with @RegisterAiService to 
mark implementation beans as unremovable");
+
+        for (AnnotationInstance instance : 
indexBuildItem.getIndex().getAnnotations(REGISTER_AI_SERVICES_DOTNAME)) {
+            if (instance.target().kind() == AnnotationTarget.Kind.CLASS) {
+                String declarativeAiServiceClassName = 
instance.target().asClass().name().toString();
+                LOG.debugf("Marking Quarkus Ai service implementation class 
for %s as unremovable",
+                        declarativeAiServiceClassName);
+                
unremovableBeans.produce(beanClassNames(declarativeAiServiceClassName + 
"$$QuarkusImpl"));
+            }
+        }
+    }
 }
diff --git a/integration-tests-jvm/langchain4j-agent-bean-binding-ql4j/pom.xml 
b/integration-tests-jvm/langchain4j-agent-bean-binding-ql4j/pom.xml
new file mode 100644
index 0000000000..451f6af20c
--- /dev/null
+++ b/integration-tests-jvm/langchain4j-agent-bean-binding-ql4j/pom.xml
@@ -0,0 +1,135 @@
+<?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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.camel.quarkus</groupId>
+        <artifactId>camel-quarkus-build-parent-it</artifactId>
+        <version>3.35.0-SNAPSHOT</version>
+        <relativePath>../../poms/build-parent-it/pom.xml</relativePath>
+    </parent>
+
+    
<artifactId>camel-quarkus-integration-test-langchain4j-agent-bean-binding-ql4j</artifactId>
+    <name>Camel Quarkus :: Integration Tests :: LangChain4j Agent Bean Binding 
QL4J</name>
+    <description>Integration tests for Camel Quarkus LangChain4j Agent 
extension using bean binding with Quarkus LangChain4j</description>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>io.quarkiverse.langchain4j</groupId>
+                <artifactId>quarkus-langchain4j-bom</artifactId>
+                <version>${quarkiverse-langchain4j.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-bean</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-direct</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-langchain4j-agent</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-rest</artifactId>
+        </dependency>
+
+        <!-- Quarkus-langchain4j dependencies-->
+        <dependency>
+            <groupId>io.quarkiverse.langchain4j</groupId>
+            <artifactId>quarkus-langchain4j-ollama</artifactId>
+        </dependency>
+
+        <!-- test dependencies -->
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.rest-assured</groupId>
+            <artifactId>rest-assured</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <profiles>
+        <profile>
+            <id>virtualDependencies</id>
+            <activation>
+                <property>
+                    <name>!noVirtualDependencies</name>
+                </property>
+            </activation>
+            <dependencies>
+                <!-- The following dependencies guarantee that this module is 
built after them. You can update them by running `mvn process-resources 
-Pformat -N` from the source tree root directory -->
+                <dependency>
+                    <groupId>org.apache.camel.quarkus</groupId>
+                    <artifactId>camel-quarkus-bean-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-direct-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-langchain4j-agent-deployment</artifactId>
+                    <version>${project.version}</version>
+                    <type>pom</type>
+                    <scope>test</scope>
+                    <exclusions>
+                        <exclusion>
+                            <groupId>*</groupId>
+                            <artifactId>*</artifactId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
+            </dependencies>
+        </profile>
+    </profiles>
+</project>
diff --git 
a/integration-tests-jvm/langchain4j-agent-bean-binding-ql4j/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/AiServiceResolvedByInterface.java
 
b/integration-tests-jvm/langchain4j-agent-bean-binding-ql4j/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/AiServiceResolvedByInterface.java
new file mode 100644
index 0000000000..38fbed79ff
--- /dev/null
+++ 
b/integration-tests-jvm/langchain4j-agent-bean-binding-ql4j/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/AiServiceResolvedByInterface.java
@@ -0,0 +1,34 @@
+package org.apache.camel.quarkus.component.langchain4j.agent;
+
+import java.util.function.Supplier;
+
+import dev.langchain4j.data.message.AiMessage;
+import dev.langchain4j.model.chat.ChatModel;
+import dev.langchain4j.model.chat.request.ChatRequest;
+import dev.langchain4j.model.chat.response.ChatResponse;
+import dev.langchain4j.service.UserMessage;
+import io.quarkiverse.langchain4j.RegisterAiService;
+import jakarta.enterprise.context.ApplicationScoped;
+import org.apache.camel.Handler;
+
+@ApplicationScoped
+@RegisterAiService(chatLanguageModelSupplier = 
AiServiceResolvedByInterface.AiServiceResolvedByInterfaceModelSupplier.class)
+public interface AiServiceResolvedByInterface {
+
+    public static class AiServiceResolvedByInterfaceModelSupplier implements 
Supplier<ChatModel> {
+        @Override
+        public ChatModel get() {
+            return new ChatModel() {
+                @Override
+                public ChatResponse doChat(ChatRequest chatRequest) {
+                    return ChatResponse.builder().aiMessage(new 
AiMessage("AiServiceResolvedByInterface has been resolved"))
+                            .build();
+                }
+            };
+        }
+    }
+
+    @UserMessage("Any prompt")
+    @Handler
+    String chat(String input);
+}
diff --git 
a/integration-tests-jvm/langchain4j-agent-bean-binding-ql4j/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/AiServiceResolvedByName.java
 
b/integration-tests-jvm/langchain4j-agent-bean-binding-ql4j/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/AiServiceResolvedByName.java
new file mode 100644
index 0000000000..43fc349105
--- /dev/null
+++ 
b/integration-tests-jvm/langchain4j-agent-bean-binding-ql4j/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/AiServiceResolvedByName.java
@@ -0,0 +1,35 @@
+package org.apache.camel.quarkus.component.langchain4j.agent;
+
+import java.util.function.Supplier;
+
+import dev.langchain4j.data.message.AiMessage;
+import dev.langchain4j.model.chat.ChatModel;
+import dev.langchain4j.model.chat.request.ChatRequest;
+import dev.langchain4j.model.chat.response.ChatResponse;
+import dev.langchain4j.service.UserMessage;
+import io.quarkiverse.langchain4j.RegisterAiService;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Named;
+import org.apache.camel.Handler;
+
+@ApplicationScoped
+@Named("aiServiceResolvedByName")
+@RegisterAiService(chatLanguageModelSupplier = 
AiServiceResolvedByName.AiServiceResolvedByNameModelSupplier.class)
+public interface AiServiceResolvedByName {
+
+    public static class AiServiceResolvedByNameModelSupplier implements 
Supplier<ChatModel> {
+        @Override
+        public ChatModel get() {
+            return new ChatModel() {
+                @Override
+                public ChatResponse doChat(ChatRequest chatRequest) {
+                    return ChatResponse.builder().aiMessage(new 
AiMessage("AiServiceResolvedByName has been resolved")).build();
+                }
+            };
+        }
+    }
+
+    @UserMessage("Any prompt")
+    @Handler
+    String chatByName(String input);
+}
diff --git 
a/integration-tests-jvm/langchain4j-agent-bean-binding-ql4j/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/Langchain4jAgentBeanBindingQl4jResource.java
 
b/integration-tests-jvm/langchain4j-agent-bean-binding-ql4j/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/Langchain4jAgentBeanBindingQl4jResource.java
new file mode 100644
index 0000000000..102d9822bb
--- /dev/null
+++ 
b/integration-tests-jvm/langchain4j-agent-bean-binding-ql4j/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/Langchain4jAgentBeanBindingQl4jResource.java
@@ -0,0 +1,34 @@
+package org.apache.camel.quarkus.component.langchain4j.agent;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+import org.apache.camel.ProducerTemplate;
+
+@Path("/langchain4j-agent-bean-binding-ql4j")
+@ApplicationScoped
+public class Langchain4jAgentBeanBindingQl4jResource {
+
+    @Inject
+    ProducerTemplate producerTemplate;
+
+    @Path("/ai-service-should-be-resolvable-by-interface")
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    public String aiServiceShouldBeResolvableByInterface() {
+        return 
producerTemplate.requestBody("direct:ai-service-should-be-resolvable-by-interface",
 "dummy-body-by-interface",
+                String.class);
+    }
+
+    @Path("/ai-service-should-be-resolvable-by-name")
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    public String aiServiceShouldBeResolvableByName() {
+        return 
producerTemplate.requestBody("direct:ai-service-should-be-resolvable-by-name", 
"dummy-body-by-name",
+                String.class);
+    }
+
+}
diff --git 
a/integration-tests-jvm/langchain4j-agent-bean-binding-ql4j/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/Langchain4jAgentBeanBindingQl4jRoutes.java
 
b/integration-tests-jvm/langchain4j-agent-bean-binding-ql4j/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/Langchain4jAgentBeanBindingQl4jRoutes.java
new file mode 100644
index 0000000000..b5c1791bc8
--- /dev/null
+++ 
b/integration-tests-jvm/langchain4j-agent-bean-binding-ql4j/src/main/java/org/apache/camel/quarkus/component/langchain4j/agent/Langchain4jAgentBeanBindingQl4jRoutes.java
@@ -0,0 +1,18 @@
+package org.apache.camel.quarkus.component.langchain4j.agent;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import org.apache.camel.builder.RouteBuilder;
+
+@ApplicationScoped
+public class Langchain4jAgentBeanBindingQl4jRoutes extends RouteBuilder {
+
+    @Override
+    public void configure() {
+
+        from("direct:ai-service-should-be-resolvable-by-interface")
+                .bean(AiServiceResolvedByInterface.class);
+
+        from("direct:ai-service-should-be-resolvable-by-name")
+                .bean("aiServiceResolvedByName");
+    }
+}
diff --git 
a/integration-tests-jvm/langchain4j-agent-bean-binding-ql4j/src/main/resources/application.properties
 
b/integration-tests-jvm/langchain4j-agent-bean-binding-ql4j/src/main/resources/application.properties
new file mode 100644
index 0000000000..c1b68a1d27
--- /dev/null
+++ 
b/integration-tests-jvm/langchain4j-agent-bean-binding-ql4j/src/main/resources/application.properties
@@ -0,0 +1,18 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+quarkus.devservices.enabled=false
\ No newline at end of file
diff --git 
a/integration-tests-jvm/langchain4j-agent-bean-binding-ql4j/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentBeanBindingQl4jTest.java
 
b/integration-tests-jvm/langchain4j-agent-bean-binding-ql4j/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentBeanBindingQl4jTest.java
new file mode 100644
index 0000000000..eccc3d10e4
--- /dev/null
+++ 
b/integration-tests-jvm/langchain4j-agent-bean-binding-ql4j/src/test/java/org/apache/camel/quarkus/component/langchain4j/agent/it/Langchain4jAgentBeanBindingQl4jTest.java
@@ -0,0 +1,45 @@
+/*
+ * 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.langchain4j.agent.it;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.restassured.RestAssured;
+import org.junit.jupiter.api.Test;
+
+import static org.hamcrest.Matchers.is;
+
+@QuarkusTest
+class Langchain4jAgentBeanBindingQl4jTest {
+
+    @Test
+    void aiServiceShouldBeResolvedByInterface() {
+        RestAssured.given()
+                
.get("/langchain4j-agent-bean-binding-ql4j/ai-service-should-be-resolvable-by-interface")
+                .then()
+                .statusCode(200)
+                .body(is("AiServiceResolvedByInterface has been resolved"));
+    }
+
+    @Test
+    void aiServiceShouldBeResolvedByName() {
+        RestAssured.given()
+                
.get("/langchain4j-agent-bean-binding-ql4j/ai-service-should-be-resolvable-by-name")
+                .then()
+                .statusCode(200)
+                .body(is("AiServiceResolvedByName has been resolved"));
+    }
+}
diff --git a/integration-tests-jvm/pom.xml b/integration-tests-jvm/pom.xml
index a1a692967a..a1f1237b89 100644
--- a/integration-tests-jvm/pom.xml
+++ b/integration-tests-jvm/pom.xml
@@ -76,6 +76,7 @@
         <module>json-patch</module>
         <module>jsonapi</module>
         <module>junit-test-framework</module>
+        <module>langchain4j-agent-bean-binding-ql4j</module>
         <module>langchain4j-agent-ql4j</module>
         <module>ldif</module>
         <module>lucene</module>

Reply via email to