This is an automated email from the ASF dual-hosted git repository. cdeppisch pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel.git
commit 16bb0ed1a8d82390adad42caebc2784d0dcad48e Author: Christoph Deppisch <cdeppi...@redhat.com> AuthorDate: Wed Jul 17 10:47:34 2024 +0200 chore(camel-jbang): Fix classloader for downloaded plugin dependencies When Camel JBang plugin is called the dependencies are downloaded on demand with the MavenDependencyDownloader service. We need to ensure that the Yaml instance uses the updated classloader of the loaded plugin. This avoids class not found exceptions when serializing/deserializing in a loaded plugin. --- .../apache/camel/dsl/jbang/core/common/YamlHelper.java | 16 ++++++++++++++++ .../org/apache/camel/dsl/jbang/core/commands/k/Bind.java | 2 +- .../jbang/core/commands/kubernetes/KubernetesHelper.java | 11 +++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/YamlHelper.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/YamlHelper.java index ee0b5ecd8f4..3460c80d7c7 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/YamlHelper.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/YamlHelper.java @@ -20,7 +20,9 @@ import java.util.Collection; import java.util.Map; import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.LoaderOptions; import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.constructor.CustomClassLoaderConstructor; import org.yaml.snakeyaml.introspector.Property; import org.yaml.snakeyaml.nodes.NodeTuple; import org.yaml.snakeyaml.nodes.Tag; @@ -36,6 +38,15 @@ public final class YamlHelper { * fresh instance for every YAML stream. */ public static Yaml yaml() { + return yaml(null); + } + + /** + * Creates new Yaml instance. The implementation provided by Snakeyaml is not thread-safe. It is better to create a + * fresh instance for every YAML stream. Uses the given class loader as base constructor. This is mandatory when + * additional classes have been downloaded via Maven for instance when loading a Camel JBang plugin. + */ + public static Yaml yaml(ClassLoader classLoader) { Representer representer = new Representer(new DumperOptions()) { @Override protected NodeTuple representJavaBeanProperty( @@ -50,6 +61,11 @@ public final class YamlHelper { } }; representer.getPropertyUtils().setSkipMissingProperties(true); + + if (classLoader != null) { + return new Yaml(new CustomClassLoaderConstructor(classLoader, new LoaderOptions()), representer); + } + return new Yaml(representer); } } diff --git a/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/Bind.java b/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/Bind.java index 82007dc2868..59e3a18ebc2 100644 --- a/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/Bind.java +++ b/dsl/camel-jbang/camel-jbang-plugin-k/src/main/java/org/apache/camel/dsl/jbang/core/commands/k/Bind.java @@ -186,7 +186,7 @@ public class Bind extends KubernetesBaseCommand { return delegate.dumpPipe(pipe); } - Pipe pipeResource = KubernetesHelper.yaml().loadAs(pipe, Pipe.class); + Pipe pipeResource = KubernetesHelper.yaml(this.getClass().getClassLoader()).loadAs(pipe, Pipe.class); final AtomicBoolean updated = new AtomicBoolean(false); client(Pipe.class).resource(pipeResource).createOr(it -> { updated.set(true); diff --git a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesHelper.java b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesHelper.java index 9b83a2bbeae..26ad4c4235b 100644 --- a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesHelper.java +++ b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesHelper.java @@ -101,6 +101,17 @@ public final class KubernetesHelper { return YamlHelper.yaml(); } + /** + * Creates new Yaml instance. The implementation provided by Snakeyaml is not thread-safe. It is better to create a + * fresh instance for every YAML stream. Uses the given class loader as base constructor. This is mandatory when + * additional classes have been downloaded via Maven for instance when loading a Camel JBang plugin. + * + * @return + */ + public static Yaml yaml(ClassLoader classLoader) { + return YamlHelper.yaml(classLoader); + } + public static ObjectMapper json() { return OBJECT_MAPPER; }