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

davsclaus pushed a commit to branch fix/CAMEL-23939
in repository https://gitbox.apache.org/repos/asf/camel.git

commit d73e82c1f5d0cb912f2c23741d47b271bd7213a5
Author: Claus Ibsen <[email protected]>
AuthorDate: Wed Jul 8 22:21:32 2026 +0200

    CAMEL-23939: Fix Kamelet dependencies ignored in Camel CLI
    
    When running via Camel CLI, Kamelet-declared dependencies (e.g.
    camel:jackson-avro) are downloaded into a child classloader but
    DelegatingSchemaResolver is loaded by the parent classloader and
    cannot see them, causing NoClassDefFoundError.
    
    Fix by adding a reflection-based fallback: direct instantiation is
    tried first (works on flat classpaths like Spring Boot), and on
    NoClassDefFoundError the resolver is loaded via CamelContext's
    ClassResolver which can see dynamically downloaded JARs.
    
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
    Signed-off-by: Claus Ibsen <[email protected]>
---
 .../format/schema/DelegatingSchemaResolver.java    | 70 ++++++++++++++++++++--
 1 file changed, 64 insertions(+), 6 deletions(-)

diff --git 
a/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/utils/format/schema/DelegatingSchemaResolver.java
 
b/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/utils/format/schema/DelegatingSchemaResolver.java
index aa317448fbbe..b7794305d5f5 100644
--- 
a/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/utils/format/schema/DelegatingSchemaResolver.java
+++ 
b/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/utils/format/schema/DelegatingSchemaResolver.java
@@ -17,6 +17,8 @@
 
 package org.apache.camel.component.kamelet.utils.format.schema;
 
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
 import org.apache.camel.Exchange;
 import org.apache.camel.Processor;
 import org.apache.camel.component.jackson.avro.transform.AvroSchemaResolver;
@@ -31,13 +33,30 @@ import org.apache.camel.util.ObjectHelper;
  * determine the schema resolver (Avro or Json). Delegates to schema resolver 
and sets proper content class and schema
  * properties on the delegate.
  */
-public class DelegatingSchemaResolver implements Processor {
+public class DelegatingSchemaResolver implements Processor, CamelContextAware {
+
+    private static final String AVRO_SCHEMA_RESOLVER = 
"org.apache.camel.component.jackson.avro.transform.AvroSchemaResolver";
+    private static final String PROTOBUF_SCHEMA_RESOLVER
+            = 
"org.apache.camel.component.jackson.protobuf.transform.ProtobufSchemaResolver";
+    private static final String JSON_SCHEMA_RESOLVER = 
"org.apache.camel.component.jackson.transform.JsonSchemaResolver";
+
+    private CamelContext camelContext;
     private String mimeType;
     private String targetMimeType;
 
     private String schema;
     private String contentClass;
 
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
     @Override
     public void process(Exchange exchange) throws Exception {
         if (ObjectHelper.isEmpty(mimeType)) {
@@ -65,19 +84,41 @@ public class DelegatingSchemaResolver implements Processor {
             case PROTOBUF:
             case PROTOBUF_BINARY:
             case PROTOBUF_STRUCT:
+                return createSchemaResolver(PROTOBUF_SCHEMA_RESOLVER);
+            case AVRO:
+            case AVRO_BINARY:
+            case AVRO_STRUCT:
+                return createSchemaResolver(AVRO_SCHEMA_RESOLVER);
+            case JSON:
+            case STRUCT:
+                return createSchemaResolver(JSON_SCHEMA_RESOLVER);
+            default:
+                return null;
+        }
+    }
+
+    private Processor createSchemaResolver(String className) {
+        try {
+            return doCreateSchemaResolver(className);
+        } catch (NoClassDefFoundError e) {
+            // fallback to dynamic class resolution (e.g. Camel CLI with 
downloaded dependencies)
+            return doCreateSchemaResolverReflection(className);
+        }
+    }
+
+    private Processor doCreateSchemaResolver(String className) {
+        switch (className) {
+            case PROTOBUF_SCHEMA_RESOLVER:
                 ProtobufSchemaResolver protobufSchemaResolver = new 
ProtobufSchemaResolver();
                 protobufSchemaResolver.setSchema(this.schema);
                 protobufSchemaResolver.setContentClass(this.contentClass);
                 return protobufSchemaResolver;
-            case AVRO:
-            case AVRO_BINARY:
-            case AVRO_STRUCT:
+            case AVRO_SCHEMA_RESOLVER:
                 AvroSchemaResolver avroSchemaResolver = new 
AvroSchemaResolver();
                 avroSchemaResolver.setSchema(this.schema);
                 avroSchemaResolver.setContentClass(this.contentClass);
                 return avroSchemaResolver;
-            case JSON:
-            case STRUCT:
+            case JSON_SCHEMA_RESOLVER:
                 JsonSchemaResolver jsonSchemaResolver = new 
JsonSchemaResolver();
                 jsonSchemaResolver.setSchema(this.schema);
                 jsonSchemaResolver.setContentClass(this.contentClass);
@@ -87,6 +128,23 @@ public class DelegatingSchemaResolver implements Processor {
         }
     }
 
+    private Processor doCreateSchemaResolverReflection(String className) {
+        try {
+            Class<?> clazz;
+            if (camelContext != null) {
+                clazz = 
camelContext.getClassResolver().resolveMandatoryClass(className);
+            } else {
+                clazz = 
Thread.currentThread().getContextClassLoader().loadClass(className);
+            }
+            Object instance = clazz.getDeclaredConstructor().newInstance();
+            clazz.getMethod("setSchema", String.class).invoke(instance, 
this.schema);
+            clazz.getMethod("setContentClass", String.class).invoke(instance, 
this.contentClass);
+            return (Processor) instance;
+        } catch (Exception e) {
+            throw new RuntimeException("Cannot create schema resolver: " + 
className, e);
+        }
+    }
+
     public String getMimeType() {
         return mimeType;
     }

Reply via email to