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; }
