You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by nf...@apache.org on 2023/06/16 16:27:27 UTC

[camel-spring-boot] 01/01: CAMEL-19308: Add minimal support of native mode

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

nfilotto pushed a commit to branch CAMEL-19308/add-minimal-aot-support
in repository https://gitbox.apache.org/repos/asf/camel-spring-boot.git

commit 625cf72247b6ac90ef5a0a2a9b27305e7efefc81
Author: Nicolas Filotto <nf...@talend.com>
AuthorDate: Fri Jun 16 18:13:18 2023 +0200

    CAMEL-19308: Add minimal support of native mode
---
 .../camel/springboot/catalog/others.properties     |   1 +
 .../camel/springboot/catalog/others/xml-jaxb.json  |  15 +
 components-starter/camel-xml-jaxb-starter/pom.xml  |  66 +++++
 .../xml/jaxb/springboot/JAXBRuntimeHints.java      | 315 +++++++++++++++++++++
 .../jaxb/springboot/graalvm/JAXBSubstitutions.java | 101 +++++++
 .../src/main/resources/META-INF/LICENSE.txt        | 203 +++++++++++++
 .../src/main/resources/META-INF/NOTICE.txt         |  11 +
 .../src/main/resources/META-INF/spring.provides    |  17 ++
 .../main/resources/META-INF/spring/aot.factories   |   2 +
 .../camel/xml/jaxb/springboot/BeanScope.java       |  25 +-
 .../org/apache/camel/xml/jaxb/springboot/Book.java |  38 ++-
 .../camel/xml/jaxb/springboot/IdentifiedType.java  |  39 ++-
 .../xml/jaxb/springboot/JAXBRuntimeHintsTest.java  |  53 ++++
 .../camel/xml/jaxb/springboot/USAddress.java       | 201 +++++++++++++
 .../apache/camel/xml/jaxb/springboot/jaxb.index    |   1 +
 components-starter/pom.xml                         |   1 +
 .../camel/spring/boot/CamelAutoConfiguration.java  |   8 +-
 .../boot/CamelSpringBootApplicationController.java |   4 +-
 .../camel/spring/boot/SpringPropertiesParser.java  |   7 +-
 .../camel/spring/boot/aot/CamelRuntimeHints.java   |  98 +++++++
 .../camel/spring/boot/aot/ReflectionHelper.java    | 239 ++++++++++++++++
 .../camel/spring/boot/aot/RuntimeHintsHelper.java  |  71 +++++
 .../camel-spring-boot/native-image.properties      |   1 +
 .../spring/boot/aot/CamelRuntimeHintsTest.java     |  52 ++++
 .../spring/boot/aot/ReflectionHelperTest.java      | 142 ++++++++++
 dsl-starter/camel-xml-jaxb-dsl-starter/pom.xml     |   5 +
 .../jaxb/springboot/aot/XMLDSLRuntimeHints.java    |  24 +-
 .../main/resources/META-INF/spring/aot.factories   |   2 +
 pom.xml                                            |   2 +
 29 files changed, 1676 insertions(+), 68 deletions(-)

diff --git a/catalog/camel-catalog-provider-springboot/src/main/resources/org/apache/camel/springboot/catalog/others.properties b/catalog/camel-catalog-provider-springboot/src/main/resources/org/apache/camel/springboot/catalog/others.properties
index 7af10075c1a..240ffc8defe 100644
--- a/catalog/camel-catalog-provider-springboot/src/main/resources/org/apache/camel/springboot/catalog/others.properties
+++ b/catalog/camel-catalog-provider-springboot/src/main/resources/org/apache/camel/springboot/catalog/others.properties
@@ -29,6 +29,7 @@ shiro
 spring-security
 undertow-spring-security
 xml-io-dsl
+xml-jaxb
 xml-jaxb-dsl
 xml-jaxp
 yaml-dsl
diff --git a/catalog/camel-catalog-provider-springboot/src/main/resources/org/apache/camel/springboot/catalog/others/xml-jaxb.json b/catalog/camel-catalog-provider-springboot/src/main/resources/org/apache/camel/springboot/catalog/others/xml-jaxb.json
new file mode 100644
index 00000000000..fb3fe104749
--- /dev/null
+++ b/catalog/camel-catalog-provider-springboot/src/main/resources/org/apache/camel/springboot/catalog/others/xml-jaxb.json
@@ -0,0 +1,15 @@
+{
+  "other": {
+    "kind": "other",
+    "name": "xml-jaxb",
+    "title": "Xml Jaxb",
+    "description": "Camel XML JAXB",
+    "deprecated": false,
+    "firstVersion": "3.1.0",
+    "label": "dsl",
+    "supportLevel": "Stable",
+    "groupId": "org.apache.camel.springboot",
+    "artifactId": "camel-xml-jaxb-starter",
+    "version": "4.0.0-SNAPSHOT"
+  }
+}
diff --git a/components-starter/camel-xml-jaxb-starter/pom.xml b/components-starter/camel-xml-jaxb-starter/pom.xml
new file mode 100644
index 00000000000..be459406cdb
--- /dev/null
+++ b/components-starter/camel-xml-jaxb-starter/pom.xml
@@ -0,0 +1,66 @@
+<?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/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.camel.springboot</groupId>
+    <artifactId>components-starter</artifactId>
+    <version>4.0.0-SNAPSHOT</version>
+  </parent>
+  <artifactId>camel-xml-jaxb-starter</artifactId>
+  <packaging>jar</packaging>
+  <description>Spring-Boot Starter for Camel JAXB Support</description>
+  <dependencies>
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter</artifactId>
+      <version>${spring-boot-version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-xml-jaxb</artifactId>
+      <version>${camel-version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.graalvm.sdk</groupId>
+      <artifactId>graal-sdk</artifactId>
+      <version>${graal-sdk-version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-test</artifactId>
+      <version>${spring-boot-version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-core-test</artifactId>
+      <version>${spring-version}</version>
+      <scope>test</scope>
+    </dependency>
+    <!--START OF GENERATED CODE-->
+    <dependency>
+      <groupId>org.apache.camel.springboot</groupId>
+      <artifactId>camel-core-starter</artifactId>
+    </dependency>
+    <!--END OF GENERATED CODE-->
+  </dependencies>
+</project>
diff --git a/components-starter/camel-xml-jaxb-starter/src/main/java/org/apache/camel/xml/jaxb/springboot/JAXBRuntimeHints.java b/components-starter/camel-xml-jaxb-starter/src/main/java/org/apache/camel/xml/jaxb/springboot/JAXBRuntimeHints.java
new file mode 100644
index 00000000000..d8002c20ecf
--- /dev/null
+++ b/components-starter/camel-xml-jaxb-starter/src/main/java/org/apache/camel/xml/jaxb/springboot/JAXBRuntimeHints.java
@@ -0,0 +1,315 @@
+/*
+ * 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.xml.jaxb.springboot;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.lang.annotation.Annotation;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+
+import jakarta.xml.bind.annotation.XmlAccessOrder;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlAnyAttribute;
+import jakarta.xml.bind.annotation.XmlAnyElement;
+import jakarta.xml.bind.annotation.XmlAttachmentRef;
+import jakarta.xml.bind.annotation.XmlAttribute;
+import jakarta.xml.bind.annotation.XmlElement;
+import jakarta.xml.bind.annotation.XmlElementDecl;
+import jakarta.xml.bind.annotation.XmlElementRef;
+import jakarta.xml.bind.annotation.XmlElementRefs;
+import jakarta.xml.bind.annotation.XmlElementWrapper;
+import jakarta.xml.bind.annotation.XmlElements;
+import jakarta.xml.bind.annotation.XmlEnum;
+import jakarta.xml.bind.annotation.XmlEnumValue;
+import jakarta.xml.bind.annotation.XmlID;
+import jakarta.xml.bind.annotation.XmlIDREF;
+import jakarta.xml.bind.annotation.XmlInlineBinaryData;
+import jakarta.xml.bind.annotation.XmlList;
+import jakarta.xml.bind.annotation.XmlMimeType;
+import jakarta.xml.bind.annotation.XmlMixed;
+import jakarta.xml.bind.annotation.XmlNs;
+import jakarta.xml.bind.annotation.XmlRegistry;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlSchema;
+import jakarta.xml.bind.annotation.XmlSchemaType;
+import jakarta.xml.bind.annotation.XmlSchemaTypes;
+import jakarta.xml.bind.annotation.XmlSeeAlso;
+import jakarta.xml.bind.annotation.XmlTransient;
+import jakarta.xml.bind.annotation.XmlType;
+import jakarta.xml.bind.annotation.XmlValue;
+import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapters;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.aot.hint.MemberCategory;
+import org.springframework.aot.hint.RuntimeHints;
+import org.springframework.aot.hint.RuntimeHintsRegistrar;
+import org.springframework.aot.hint.TypeReference;
+import org.springframework.asm.ClassReader;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+import org.springframework.util.ReflectionUtils;
+
+import static org.apache.camel.spring.boot.aot.ReflectionHelper.applyIfMatch;
+import static org.apache.camel.spring.boot.aot.ReflectionHelper.getClassesByAnnotations;
+import static org.apache.camel.spring.boot.aot.RuntimeHintsHelper.registerClassHierarchy;
+
+final class JAXBRuntimeHints implements RuntimeHintsRegistrar {
+
+    /**
+     * The logger.
+     */
+    private static final Logger LOG = LoggerFactory.getLogger(JAXBRuntimeHints.class);
+
+    private static final List<Class<? extends Annotation>> JAXB_ROOT_ANNOTATIONS = List.of(
+            XmlRootElement.class, XmlType.class, XmlRegistry.class, XmlJavaTypeAdapter.class, XmlSeeAlso.class);
+
+    private static final List<Class<? extends Annotation>> JAXB_ANNOTATIONS = List.of(
+            XmlAccessorType.class,
+            XmlAnyAttribute.class,
+            XmlAnyElement.class,
+            XmlAttachmentRef.class,
+            XmlAttribute.class,
+            XmlElement.class,
+            XmlElementDecl.class,
+            XmlElementRef.class,
+            XmlElementRefs.class,
+            XmlElements.class,
+            XmlElementWrapper.class,
+            XmlEnum.class,
+            XmlEnumValue.class,
+            XmlID.class,
+            XmlIDREF.class,
+            XmlInlineBinaryData.class,
+            XmlList.class,
+            XmlMimeType.class,
+            XmlMixed.class,
+            XmlNs.class,
+            XmlRegistry.class,
+            XmlRootElement.class,
+            XmlSchema.class,
+            XmlSchemaType.class,
+            XmlSchemaTypes.class,
+            XmlSeeAlso.class,
+            XmlTransient.class,
+            XmlType.class,
+            XmlValue.class,
+            XmlJavaTypeAdapter.class,
+            XmlJavaTypeAdapters.class);
+
+    private static final List<String> NATIVE_PROXY_DEFINITIONS = List.of(
+            "org.glassfish.jaxb.core.marshaller.CharacterEscapeHandler",
+            "com.sun.xml.txw2.output.CharacterEscapeHandler",
+            "org.glassfish.jaxb.core.v2.schemagen.episode.Bindings",
+            "org.glassfish.jaxb.core.v2.schemagen.episode.SchemaBindings",
+            "org.glassfish.jaxb.core.v2.schemagen.episode.Klass",
+            "org.glassfish.jaxb.core.v2.schemagen.episode.Package",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.Annotated",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.Annotation",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.Any",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.Appinfo",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.AttrDecls",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.AttributeType",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.ComplexContent",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.ComplexExtension",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.ComplexRestriction",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.ComplexType",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.ComplexTypeHost",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.ComplexTypeModel",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.ContentModelContainer",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.Documentation",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.Element",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.ExplicitGroup",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.ExtensionType",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.FixedOrDefault",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.Import",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.List",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.LocalAttribute",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.LocalElement",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.NestedParticle",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.NoFixedFacet",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.Occurs",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.Particle",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.Redefinable",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.Schema",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.SchemaTop",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.SimpleContent",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.SimpleDerivation",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.SimpleExtension",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.SimpleRestriction",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.SimpleRestrictionModel",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.SimpleType",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.SimpleTypeHost",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.TopLevelAttribute",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.TopLevelElement",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.TypeDefParticle",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.TypeHost",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.Union",
+            "org.glassfish.jaxb.runtime.v2.schemagen.xmlschema.Wildcard",
+            "com.sun.xml.txw2.TypedXmlWriter");
+    private static final List<String> JAXB_RUNTIME_CLASSES = List.of("org.glassfish.jaxb.runtime.v2.ContextFactory",
+            "com.sun.xml.internal.stream.XMLInputFactoryImpl",
+            "com.sun.xml.internal.stream.XMLOutputFactoryImpl",
+            "com.sun.org.apache.xpath.internal.functions.FuncNot",
+            "org.glassfish.jaxb.core.v2.model.nav.ReflectionNavigator",
+            "org.glassfish.jaxb.runtime.v2.runtime.property.SingleElementLeafProperty",
+            "org.glassfish.jaxb.runtime.v2.runtime.property.ArrayElementLeafProperty",
+            "org.glassfish.jaxb.runtime.v2.runtime.property.SingleElementNodeProperty",
+            "org.glassfish.jaxb.runtime.v2.runtime.property.SingleReferenceNodeProperty",
+            "org.glassfish.jaxb.runtime.v2.runtime.property.SingleMapNodeProperty",
+            "org.glassfish.jaxb.runtime.v2.runtime.property.ArrayElementNodeProperty",
+            "org.glassfish.jaxb.runtime.v2.runtime.property.ArrayReferenceNodeProperty",
+            "com.sun.org.apache.xerces.internal.impl.dv.xs.SchemaDVFactoryImpl", XmlAccessOrder.class.getName());
+
+
+    @Override
+    public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
+        List<Class<?>> classes = getClassesByAnnotations(classLoader, JAXB_ROOT_ANNOTATIONS);
+        for (Class<?> c : classes) {
+            if (c.isAnnotationPresent(XmlSeeAlso.class)) {
+                XmlSeeAlso annotation = c.getAnnotation(XmlSeeAlso.class);
+                for (Class<?> type : annotation.value()) {
+                    hints.reflection().registerType(type, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS);
+                }
+            }
+            applyIfMatch(c, XmlJavaTypeAdapter.class, XmlJavaTypeAdapter::value,
+                    type -> hints.reflection().registerType(type, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS,
+                    MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.DECLARED_FIELDS));
+            hints.reflection().registerType(c, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS,
+                    MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.DECLARED_FIELDS);
+        }
+        boolean classDetected = false;
+        for (String className : getClassesFromIndexes(classLoader)) {
+            registerClassHierarchy(hints, classLoader, className, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS,
+                    MemberCategory.INTROSPECT_DECLARED_METHODS, MemberCategory.DECLARED_FIELDS
+            );
+            classDetected = true;
+        }
+        if (classes.isEmpty() && !classDetected) {
+            return;
+        }
+        // Register all JAXB indexes
+        hints.resources().registerPattern("*/jaxb.index");
+
+        hints.reflection().registerTypeIfPresent(classLoader, "jakarta.xml.bind.annotation.W3CDomHandler",
+                MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS);
+        for (Class<?> c : JAXB_ANNOTATIONS) {
+            hints.reflection().registerType(c, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS,
+                    MemberCategory.INVOKE_DECLARED_METHODS);
+        }
+        hints.proxies().registerJdkProxy(TypeReference.of(XmlSeeAlso.class), TypeReference.of("org.glassfish.jaxb.core.v2.model.annotation.Locatable"));
+        for (String className : NATIVE_PROXY_DEFINITIONS) {
+            hints.proxies().registerJdkProxy(TypeReference.of(className));
+        }
+        for (String className : JAXB_RUNTIME_CLASSES) {
+            hints.reflection().registerTypeIfPresent(classLoader, className,
+                    MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_METHODS);
+        }
+        // Register the JAXB resource bundles
+        hints.reflection().registerTypeIfPresent(classLoader, "jakarta.xml.bind.Messages");
+        hints.resources().registerPattern("jakarta/xml/bind/Messages.properties");
+        hints.reflection().registerTypeIfPresent(classLoader, "jakarta.xml.bind.helpers.Messages");
+        hints.resources().registerPattern("jakarta/xml/bind/helpers/Messages.properties");
+    }
+
+    private static List<String> getClassesFromIndexes(ClassLoader classLoader) {
+        List<String> classNames = new ArrayList<>();
+        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(classLoader);
+        try {
+            for (Resource resource : resolver.getResources("classpath*:**/jaxb.index")) {
+                String filename = resource.getFilename();
+                if (filename == null || filename.isBlank()) {
+                    continue;
+                }
+                String packageName = getPackageName(resource, "jaxb.index");
+                if (packageName == null) {
+                    LOG.debug("The package name could not be found for the resource {}", resource);
+                    continue;
+                }
+                try (BufferedReader reader = new BufferedReader(new StringReader(resource.getContentAsString(StandardCharsets.UTF_8)))) {
+                    String line = reader.readLine();
+                    while (line != null) {
+                        if (line.startsWith("#") || line.isBlank()) {
+                            line = reader.readLine();
+                            continue;
+                        }
+                        String className = "%s%s".formatted(packageName, line.trim());
+                        LOG.debug("Found the class {} to register", className);
+                        classNames.add(className);
+                        line = reader.readLine();
+                    }
+                }
+            }
+        } catch (IOException e) {
+            LOG.debug("Could not load the JAXB indexes: {}", e.getMessage());
+        }
+        return classNames;
+    }
+
+    /**
+     * Give the package name of the given resource.
+     *
+     * @param resource the resource for which the package name is expected.
+     * @param fileName the name of file corresponding to the resource
+     * @return the package name if it could be found, {@code null} otherwise.
+     * @throws IOException an error occurs while trying to retrieve the package name.
+     */
+    private static String getPackageName(Resource resource, String fileName) throws IOException {
+        URL url = resource.getURL();
+        String protocol = url.getProtocol();
+        String packageName = null;
+        if ("jar".equals(protocol)) {
+            String path = url.getPath();
+            String suffix = ".jar!/";
+            int index = path.indexOf(suffix);
+            if (index == -1) {
+                LOG.trace("The jar suffix could not be found in {}", path);
+            } else {
+                packageName = path.substring(index + suffix.length(), path.length() - fileName.length());
+            }
+        } else if (resource.isFile()) {
+            File file = resource.getFile();
+            File[] files = file.getParentFile().listFiles((dir, name) -> name.endsWith(".class"));
+            if (files != null && files.length > 0) {
+                try (InputStream is = new FileInputStream(files[0])) {
+                    ClassReader reader = new ClassReader(is);
+                    String className = reader.getClassName();
+                    int index = className.lastIndexOf('/');
+                    if (index == -1) {
+                        packageName = "";
+                    } else {
+                        packageName = className.substring(0, index + 1);
+                    }
+                }
+            } else {
+                LOG.trace("No class file could be found in {}", file.getParentFile());
+            }
+        }
+        if (packageName != null) {
+            packageName = packageName.replace('/', '.');
+        }
+        return packageName;
+    }
+}
diff --git a/components-starter/camel-xml-jaxb-starter/src/main/java/org/apache/camel/xml/jaxb/springboot/graalvm/JAXBSubstitutions.java b/components-starter/camel-xml-jaxb-starter/src/main/java/org/apache/camel/xml/jaxb/springboot/graalvm/JAXBSubstitutions.java
new file mode 100644
index 00000000000..b44441ff002
--- /dev/null
+++ b/components-starter/camel-xml-jaxb-starter/src/main/java/org/apache/camel/xml/jaxb/springboot/graalvm/JAXBSubstitutions.java
@@ -0,0 +1,101 @@
+/*
+ * 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.xml.jaxb.springboot.graalvm;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+import jakarta.xml.bind.annotation.XmlSeeAlso;
+
+import com.oracle.svm.core.annotate.Alias;
+import com.oracle.svm.core.annotate.Substitute;
+import com.oracle.svm.core.annotate.TargetClass;
+import org.glassfish.jaxb.core.v2.model.annotation.Locatable;
+import org.glassfish.jaxb.runtime.v2.model.annotation.LocatableAnnotation;
+import org.glassfish.jaxb.runtime.v2.model.annotation.RuntimeInlineAnnotationReader;
+
+class JAXBSubstitutions {
+}
+
+@TargetClass(RuntimeInlineAnnotationReader.class)
+final class SubstituteRuntimeInlineAnnotationReader {
+
+    @Alias
+    private Map<Class<? extends Annotation>,Map<Package,Annotation>> packageCache;
+
+    @Substitute
+    public <A extends Annotation> A getFieldAnnotation(Class<A> annotation, Field field, Locatable srcPos) {
+        return field.getAnnotation(annotation);
+    }
+
+    @Substitute
+    public Annotation[] getAllFieldAnnotations(Field field, Locatable srcPos) {
+        return field.getAnnotations();
+    }
+
+    @Substitute
+    public <A extends Annotation> A getClassAnnotation(Class<A> a, Class clazz, Locatable srcPos) {
+        A ann = ((Class<?>) clazz).getAnnotation(a);
+        return (ann != null && ann.annotationType() == XmlSeeAlso.class) ? LocatableAnnotation.create(ann, srcPos) : ann;
+    }
+
+    @Substitute
+    public <A extends Annotation> A getMethodAnnotation(Class<A> annotation, Method method, Locatable srcPos) {
+        return method.getAnnotation(annotation);
+    }
+
+    @Substitute
+    public Annotation[] getAllMethodAnnotations(Method method, Locatable srcPos) {
+        return method.getAnnotations();
+    }
+
+    @Substitute
+    public <A extends Annotation> A getMethodParameterAnnotation(Class<A> annotation, Method method, int paramIndex,
+                                                                 Locatable srcPos) {
+        Annotation[] pa = method.getParameterAnnotations()[paramIndex];
+        for(Annotation a : pa) {
+            if (a.annotationType() == annotation)
+                return (A) a;
+        }
+        return null;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Substitute
+    public <A extends Annotation> A getPackageAnnotation(Class<A> a, Class clazz, Locatable srcPos) {
+        Package p = clazz.getPackage();
+        if (p == null) {
+            return null;
+        }
+
+        Map<Package, Annotation> cache = packageCache.get(a);
+        if (cache == null) {
+            cache = new HashMap<>();
+            packageCache.put(a, cache);
+        }
+        if (cache.containsKey(p)) {
+            return (A) cache.get(p);
+        } else {
+            A ann = p.getAnnotation(a);
+            cache.put(p, ann);
+            return ann;
+        }
+    }
+}
diff --git a/components-starter/camel-xml-jaxb-starter/src/main/resources/META-INF/LICENSE.txt b/components-starter/camel-xml-jaxb-starter/src/main/resources/META-INF/LICENSE.txt
new file mode 100644
index 00000000000..6b0b1270ff0
--- /dev/null
+++ b/components-starter/camel-xml-jaxb-starter/src/main/resources/META-INF/LICENSE.txt
@@ -0,0 +1,203 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
+
diff --git a/components-starter/camel-xml-jaxb-starter/src/main/resources/META-INF/NOTICE.txt b/components-starter/camel-xml-jaxb-starter/src/main/resources/META-INF/NOTICE.txt
new file mode 100644
index 00000000000..2e215bf2e6b
--- /dev/null
+++ b/components-starter/camel-xml-jaxb-starter/src/main/resources/META-INF/NOTICE.txt
@@ -0,0 +1,11 @@
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for the Apache Camel distribution.                    ==
+   =========================================================================
+
+   This product includes software developed by
+   The Apache Software Foundation (http://www.apache.org/).
+
+   Please read the different LICENSE files present in the licenses directory of
+   this distribution.
diff --git a/components-starter/camel-xml-jaxb-starter/src/main/resources/META-INF/spring.provides b/components-starter/camel-xml-jaxb-starter/src/main/resources/META-INF/spring.provides
new file mode 100644
index 00000000000..298e504419c
--- /dev/null
+++ b/components-starter/camel-xml-jaxb-starter/src/main/resources/META-INF/spring.provides
@@ -0,0 +1,17 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+provides: camel-xml-jaxb
diff --git a/components-starter/camel-xml-jaxb-starter/src/main/resources/META-INF/spring/aot.factories b/components-starter/camel-xml-jaxb-starter/src/main/resources/META-INF/spring/aot.factories
new file mode 100644
index 00000000000..fefd74c5e6a
--- /dev/null
+++ b/components-starter/camel-xml-jaxb-starter/src/main/resources/META-INF/spring/aot.factories
@@ -0,0 +1,2 @@
+org.springframework.aot.hint.RuntimeHintsRegistrar=\
+org.apache.camel.xml.jaxb.springboot.JAXBRuntimeHints
diff --git a/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringPropertiesParser.java b/components-starter/camel-xml-jaxb-starter/src/test/java/org/apache/camel/xml/jaxb/springboot/BeanScope.java
similarity index 58%
copy from core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringPropertiesParser.java
copy to components-starter/camel-xml-jaxb-starter/src/test/java/org/apache/camel/xml/jaxb/springboot/BeanScope.java
index ac3cb4d7e5b..6d1716bd875 100644
--- a/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringPropertiesParser.java
+++ b/components-starter/camel-xml-jaxb-starter/src/test/java/org/apache/camel/xml/jaxb/springboot/BeanScope.java
@@ -14,25 +14,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.spring.boot;
+package org.apache.camel.xml.jaxb.springboot;
 
-import org.apache.camel.component.properties.DefaultPropertiesParser;
-import org.apache.camel.component.properties.PropertiesLookup;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.core.env.Environment;
+import jakarta.xml.bind.annotation.XmlEnum;
 
-class SpringPropertiesParser extends DefaultPropertiesParser {
+@XmlEnum
+public enum BeanScope {
+    Singleton,
+    Request,
+    Prototype;
 
-    // Members
-
-    @Autowired
-    private Environment env;
-
-    // Overridden
-
-    @Override
-    public String parseProperty(String key, String value, PropertiesLookup properties) {
-        return env.getProperty(key);
+    BeanScope() {
     }
-
 }
diff --git a/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringPropertiesParser.java b/components-starter/camel-xml-jaxb-starter/src/test/java/org/apache/camel/xml/jaxb/springboot/Book.java
similarity index 51%
copy from core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringPropertiesParser.java
copy to components-starter/camel-xml-jaxb-starter/src/test/java/org/apache/camel/xml/jaxb/springboot/Book.java
index ac3cb4d7e5b..72829dcdef5 100644
--- a/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringPropertiesParser.java
+++ b/components-starter/camel-xml-jaxb-starter/src/test/java/org/apache/camel/xml/jaxb/springboot/Book.java
@@ -14,25 +14,35 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.spring.boot;
+package org.apache.camel.xml.jaxb.springboot;
 
-import org.apache.camel.component.properties.DefaultPropertiesParser;
-import org.apache.camel.component.properties.PropertiesLookup;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.core.env.Environment;
+import jakarta.xml.bind.annotation.XmlAttribute;
+import jakarta.xml.bind.annotation.XmlElement;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlTransient;
+import jakarta.xml.bind.annotation.XmlType;
 
-class SpringPropertiesParser extends DefaultPropertiesParser {
+@XmlRootElement(name = "book")
+@XmlType(propOrder = { "id", "name", "date" })
+public class Book extends IdentifiedType {
+    private String name;
+    private String author;
 
-    // Members
-
-    @Autowired
-    private Environment env;
+    @XmlElement(name = "title")
+    public void setName(String name) {
+        this.name = name;
+    }
 
-    // Overridden
+    @XmlTransient
+    public void setAuthor(String author) {
+        this.author = author;
+    }
 
-    @Override
-    public String parseProperty(String key, String value, PropertiesLookup properties) {
-        return env.getProperty(key);
+    public String getName() {
+        return name;
     }
 
+    public String getAuthor() {
+        return author;
+    }
 }
diff --git a/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringPropertiesParser.java b/components-starter/camel-xml-jaxb-starter/src/test/java/org/apache/camel/xml/jaxb/springboot/IdentifiedType.java
similarity index 53%
copy from core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringPropertiesParser.java
copy to components-starter/camel-xml-jaxb-starter/src/test/java/org/apache/camel/xml/jaxb/springboot/IdentifiedType.java
index ac3cb4d7e5b..82fb5facf37 100644
--- a/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringPropertiesParser.java
+++ b/components-starter/camel-xml-jaxb-starter/src/test/java/org/apache/camel/xml/jaxb/springboot/IdentifiedType.java
@@ -14,25 +14,36 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.spring.boot;
+package org.apache.camel.xml.jaxb.springboot;
 
-import org.apache.camel.component.properties.DefaultPropertiesParser;
-import org.apache.camel.component.properties.PropertiesLookup;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.core.env.Environment;
+import jakarta.xml.bind.annotation.XmlAccessType;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlAttribute;
+import jakarta.xml.bind.annotation.XmlID;
+import jakarta.xml.bind.annotation.XmlType;
 
-class SpringPropertiesParser extends DefaultPropertiesParser {
+import org.apache.camel.spi.Metadata;
 
-    // Members
+@XmlType(
+        name = "identifiedType"
+)
+@XmlAccessorType(XmlAccessType.FIELD)
+public abstract class IdentifiedType {
+    @XmlAttribute
+    @XmlID
+    @Metadata(
+            description = "The id of this node"
+    )
+    private String id;
 
-    @Autowired
-    private Environment env;
-
-    // Overridden
+    public IdentifiedType() {
+    }
 
-    @Override
-    public String parseProperty(String key, String value, PropertiesLookup properties) {
-        return env.getProperty(key);
+    public String getId() {
+        return this.id;
     }
 
+    public void setId(String value) {
+        this.id = value;
+    }
 }
diff --git a/components-starter/camel-xml-jaxb-starter/src/test/java/org/apache/camel/xml/jaxb/springboot/JAXBRuntimeHintsTest.java b/components-starter/camel-xml-jaxb-starter/src/test/java/org/apache/camel/xml/jaxb/springboot/JAXBRuntimeHintsTest.java
new file mode 100644
index 00000000000..61aa398db01
--- /dev/null
+++ b/components-starter/camel-xml-jaxb-starter/src/test/java/org/apache/camel/xml/jaxb/springboot/JAXBRuntimeHintsTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.xml.jaxb.springboot;
+
+import jakarta.xml.bind.annotation.adapters.CollapsedStringAdapter;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.aot.hint.RuntimeHints;
+import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Unit tests for {@link JAXBRuntimeHints}.
+ */
+class JAXBRuntimeHintsTest {
+    private final RuntimeHints hints = new RuntimeHints();
+
+    @BeforeEach
+    void init() {
+        new JAXBRuntimeHints().registerHints(hints, getClass().getClassLoader());
+    }
+
+    @Test
+    void shouldRegisterHintsForJAXB() throws Exception {
+        assertThat(RuntimeHintsPredicates.resource().forResource("jakarta/xml/bind/Messages.properties")).accepts(hints);
+        assertThat(RuntimeHintsPredicates.resource().forResource("org/apache/camel/spring/boot/aot/jaxb.index")).accepts(hints);
+        assertThat(RuntimeHintsPredicates.reflection().onType(Book.class)).accepts(hints);
+        assertThat(RuntimeHintsPredicates.reflection().onMethod(Book.class, "getName")).accepts(hints);
+        assertThat(RuntimeHintsPredicates.reflection().onType(IdentifiedType.class)).accepts(hints);
+        assertThat(RuntimeHintsPredicates.reflection().onMethod(IdentifiedType.class, "setId")).accepts(hints);
+        assertThat(RuntimeHintsPredicates.resource().forResource("org/apache/camel/core/xml/util/jsse/jaxb.index")).accepts(hints);
+        assertThat(RuntimeHintsPredicates.reflection().onType(BeanScope.class)).accepts(hints);
+        assertThat(RuntimeHintsPredicates.reflection().onMethod("org.glassfish.jaxb.core.v2.model.nav.ReflectionNavigator", "getInstance")).accepts(hints);
+        assertThat(RuntimeHintsPredicates.reflection().onType(USAddress.class)).accepts(hints);
+        assertThat(RuntimeHintsPredicates.reflection().onType(CollapsedStringAdapter.class)).accepts(hints);
+    }
+}
diff --git a/components-starter/camel-xml-jaxb-starter/src/test/java/org/apache/camel/xml/jaxb/springboot/USAddress.java b/components-starter/camel-xml-jaxb-starter/src/test/java/org/apache/camel/xml/jaxb/springboot/USAddress.java
new file mode 100644
index 00000000000..2e481659c5c
--- /dev/null
+++ b/components-starter/camel-xml-jaxb-starter/src/test/java/org/apache/camel/xml/jaxb/springboot/USAddress.java
@@ -0,0 +1,201 @@
+/*
+ * 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.xml.jaxb.springboot;
+
+import java.math.BigDecimal;
+
+import jakarta.xml.bind.annotation.XmlAccessType;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlAttribute;
+import jakarta.xml.bind.annotation.XmlElement;
+import jakarta.xml.bind.annotation.XmlType;
+import jakarta.xml.bind.annotation.adapters.CollapsedStringAdapter;
+import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "USAddress", propOrder = {
+        "name",
+        "street",
+        "city",
+        "state",
+        "zip"
+})
+public class USAddress {
+
+    @XmlElement(required = true)
+    protected String name;
+    @XmlElement(required = true)
+    protected String street;
+    @XmlElement(required = true)
+    protected String city;
+    @XmlElement(required = true)
+    protected String state;
+    @XmlElement(required = true)
+    protected BigDecimal zip;
+    @XmlAttribute
+    @XmlJavaTypeAdapter(CollapsedStringAdapter.class)
+    protected String country;
+
+    /**
+     * Gets the value of the name property.
+     *
+     * @return
+     *     possible object is
+     *     {@link String }
+     *
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Sets the value of the name property.
+     *
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *
+     */
+    public void setName(String value) {
+        this.name = value;
+    }
+
+    /**
+     * Gets the value of the street property.
+     *
+     * @return
+     *     possible object is
+     *     {@link String }
+     *
+     */
+    public String getStreet() {
+        return street;
+    }
+
+    /**
+     * Sets the value of the street property.
+     *
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *
+     */
+    public void setStreet(String value) {
+        this.street = value;
+    }
+
+    /**
+     * Gets the value of the city property.
+     *
+     * @return
+     *     possible object is
+     *     {@link String }
+     *
+     */
+    public String getCity() {
+        return city;
+    }
+
+    /**
+     * Sets the value of the city property.
+     *
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *
+     */
+    public void setCity(String value) {
+        this.city = value;
+    }
+
+    /**
+     * Gets the value of the state property.
+     *
+     * @return
+     *     possible object is
+     *     {@link String }
+     *
+     */
+    public String getState() {
+        return state;
+    }
+
+    /**
+     * Sets the value of the state property.
+     *
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *
+     */
+    public void setState(String value) {
+        this.state = value;
+    }
+
+    /**
+     * Gets the value of the zip property.
+     *
+     * @return
+     *     possible object is
+     *     {@link java.math.BigDecimal }
+     *
+     */
+    public BigDecimal getZip() {
+        return zip;
+    }
+
+    /**
+     * Sets the value of the zip property.
+     *
+     * @param value
+     *     allowed object is
+     *     {@link java.math.BigDecimal }
+     *
+     */
+    public void setZip(BigDecimal value) {
+        this.zip = value;
+    }
+
+    /**
+     * Gets the value of the country property.
+     *
+     * @return
+     *     possible object is
+     *     {@link String }
+     *
+     */
+    public String getCountry() {
+        if (country == null) {
+            return "US";
+        } else {
+            return country;
+        }
+    }
+
+    /**
+     * Sets the value of the country property.
+     *
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *
+     */
+    public void setCountry(String value) {
+        this.country = value;
+    }
+
+}
diff --git a/components-starter/camel-xml-jaxb-starter/src/test/resources/org/apache/camel/xml/jaxb/springboot/jaxb.index b/components-starter/camel-xml-jaxb-starter/src/test/resources/org/apache/camel/xml/jaxb/springboot/jaxb.index
new file mode 100644
index 00000000000..f56c7c8af9a
--- /dev/null
+++ b/components-starter/camel-xml-jaxb-starter/src/test/resources/org/apache/camel/xml/jaxb/springboot/jaxb.index
@@ -0,0 +1 @@
+BeanScope
\ No newline at end of file
diff --git a/components-starter/pom.xml b/components-starter/pom.xml
index a09ce8228c7..3d82859b5e1 100644
--- a/components-starter/pom.xml
+++ b/components-starter/pom.xml
@@ -417,6 +417,7 @@
     <module>camel-workday-starter</module>
     <module>camel-xchange-starter</module>
     <module>camel-xj-starter</module>
+    <module>camel-xml-jaxb-starter</module>
     <module>camel-xml-jaxp-starter</module>
     <module>camel-xmlsecurity-starter</module>
     <module>camel-xmpp-starter</module>
diff --git a/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelAutoConfiguration.java b/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelAutoConfiguration.java
index b6d77a32b09..2934b2a00c0 100644
--- a/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelAutoConfiguration.java
+++ b/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelAutoConfiguration.java
@@ -23,7 +23,6 @@ import java.util.Map;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.ConsumerTemplate;
-import org.apache.camel.ExtendedCamelContext;
 import org.apache.camel.FluentProducerTemplate;
 import org.apache.camel.ProducerTemplate;
 import org.apache.camel.RuntimeCamelException;
@@ -39,6 +38,7 @@ import org.apache.camel.spi.CliConnectorFactory;
 import org.apache.camel.spi.PackageScanClassResolver;
 import org.apache.camel.spi.PackageScanResourceResolver;
 import org.apache.camel.spi.StartupStepRecorder;
+import org.apache.camel.spring.boot.aot.CamelRuntimeHints;
 import org.apache.camel.spring.spi.ApplicationContextBeanRepository;
 import org.apache.camel.spring.spi.CamelBeanPostProcessor;
 import org.apache.camel.support.DefaultRegistry;
@@ -56,6 +56,7 @@ import org.springframework.context.ApplicationContext;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Import;
+import org.springframework.context.annotation.ImportRuntimeHints;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.context.annotation.Role;
 import org.springframework.core.OrderComparator;
@@ -63,6 +64,7 @@ import org.springframework.core.env.ConfigurableEnvironment;
 import org.springframework.core.env.Environment;
 import org.springframework.core.env.MutablePropertySources;
 
+@ImportRuntimeHints(CamelRuntimeHints.class)
 @Configuration(proxyBeanMethods = false)
 @EnableConfigurationProperties(CamelConfigurationProperties.class)
 @Import(TypeConversionConfiguration.class)
@@ -279,8 +281,8 @@ public class CamelAutoConfiguration {
 
     @Bean
     @ConditionalOnMissingBean(PropertiesParser.class)
-    PropertiesParser propertiesParser() {
-        return new SpringPropertiesParser();
+    PropertiesParser propertiesParser(Environment env) {
+        return new SpringPropertiesParser(env);
     }
 
     // We explicitly declare the destroyMethod to be "" as the Spring @Bean
diff --git a/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelSpringBootApplicationController.java b/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelSpringBootApplicationController.java
index a912b42bdab..7f9faa134fd 100644
--- a/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelSpringBootApplicationController.java
+++ b/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelSpringBootApplicationController.java
@@ -67,8 +67,10 @@ public class CamelSpringBootApplicationController {
         run();
     }
 
+    // The method cannot to be private to prevent a failure at startup in native mode
+    // Refer to https://github.com/spring-projects/spring-framework/pull/30654 for more details
     @PreDestroy
-    private void destroy() {
+    void destroy() {
         main.completed();
     }
 
diff --git a/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringPropertiesParser.java b/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringPropertiesParser.java
index ac3cb4d7e5b..d05f5bd2e34 100644
--- a/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringPropertiesParser.java
+++ b/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringPropertiesParser.java
@@ -18,15 +18,16 @@ package org.apache.camel.spring.boot;
 
 import org.apache.camel.component.properties.DefaultPropertiesParser;
 import org.apache.camel.component.properties.PropertiesLookup;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.env.Environment;
 
 class SpringPropertiesParser extends DefaultPropertiesParser {
 
     // Members
+    private final Environment env;
 
-    @Autowired
-    private Environment env;
+    SpringPropertiesParser(Environment env) {
+        this.env = env;
+    }
 
     // Overridden
 
diff --git a/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/aot/CamelRuntimeHints.java b/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/aot/CamelRuntimeHints.java
new file mode 100644
index 00000000000..89c61475d48
--- /dev/null
+++ b/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/aot/CamelRuntimeHints.java
@@ -0,0 +1,98 @@
+/*
+ * 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.spring.boot.aot;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.StringReader;
+import java.nio.charset.StandardCharsets;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.aot.hint.MemberCategory;
+import org.springframework.aot.hint.RuntimeHints;
+import org.springframework.aot.hint.RuntimeHintsRegistrar;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+
+import static org.apache.camel.spring.boot.aot.RuntimeHintsHelper.registerClassHierarchy;
+
+/**
+ * {@code CamelRuntimeHints} provide the basic hints for the native compilation of a Camel application.
+ */
+public final class CamelRuntimeHints implements RuntimeHintsRegistrar {
+
+    /**
+     * The logger.
+     */
+    private static final Logger LOG = LoggerFactory.getLogger(CamelRuntimeHints.class);
+
+    @Override
+    public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
+        // Give access to the catalog
+        hints.resources().registerPattern("org/apache/camel/main/*.properties");
+        // Register all the camel services
+        registerCamelServices(hints, classLoader);
+        // Register collections
+        hints.reflection().registerType(java.util.List.class, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS,
+            MemberCategory.INVOKE_PUBLIC_METHODS);
+        hints.reflection().registerType(java.util.Collection.class, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS,
+            MemberCategory.INVOKE_PUBLIC_METHODS);
+    }
+
+    /**
+     * Register all the Camel services that could be found in the given classloader.
+     *
+     * @param hints       the hints contributed so far for the deployment unit
+     * @param classLoader the ClassLoader to load classpath resources with,
+     *                    or {@code null} for using the thread context class loader
+     *                    at the time of actual resource access
+     */
+    private static void registerCamelServices(RuntimeHints hints, ClassLoader classLoader) {
+        hints.resources().registerPattern("META-INF/services/org/apache/camel/*");
+        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(classLoader);
+        try {
+            for (Resource resource : resolver.getResources("classpath*:META-INF/services/org/apache/camel/**")) {
+                String filename = resource.getFilename();
+                if (filename == null || filename.isBlank() || filename.endsWith(".properties")) {
+                    continue;
+                }
+                try (BufferedReader reader = new BufferedReader(new StringReader(resource.getContentAsString(StandardCharsets.UTF_8)))) {
+                    String line = reader.readLine();
+                    String prefixClass = "class=";
+                    while (line != null) {
+                        if (line.startsWith("#") || line.isBlank()) {
+                            line = reader.readLine();
+                            continue;
+                        }
+                        String className = line.trim();
+                        if (line.startsWith(prefixClass)) {
+                            className = line.substring(prefixClass.length());
+                        }
+                        LOG.debug("Found the class {} to register", className);
+                        registerClassHierarchy(hints, classLoader, className, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS,
+                                MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.INVOKE_PUBLIC_METHODS,
+                                MemberCategory.INTROSPECT_DECLARED_METHODS, MemberCategory.INTROSPECT_PUBLIC_METHODS);
+                        line = reader.readLine();
+                    }
+                }
+            }
+        } catch (IOException e) {
+            LOG.debug("Could not load the Camel services: {}", e.getMessage());
+        }
+    }
+}
diff --git a/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/aot/ReflectionHelper.java b/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/aot/ReflectionHelper.java
new file mode 100644
index 00000000000..b94d85706ed
--- /dev/null
+++ b/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/aot/ReflectionHelper.java
@@ -0,0 +1,239 @@
+/*
+ * 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.spring.boot.aot;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Parameter;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
+import org.springframework.core.io.ByteArrayResource;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+import org.springframework.core.type.AnnotationMetadata;
+import org.springframework.core.type.ClassMetadata;
+import org.springframework.core.type.classreading.MetadataReader;
+import org.springframework.core.type.classreading.MetadataReaderFactory;
+import org.springframework.core.type.filter.AnnotationTypeFilter;
+import org.springframework.core.type.filter.TypeFilter;
+import org.springframework.util.ClassUtils;
+import org.springframework.util.ReflectionUtils;
+
+/**
+ * {@code ReflectionHelper} utility class providing methods needed for the native mode.
+ */
+public final class ReflectionHelper {
+
+    /**
+     * The logger.
+     */
+    private static final Logger LOG = LoggerFactory.getLogger(ReflectionHelper.class);
+
+    private ReflectionHelper() {
+
+    }
+
+    /**
+     * Apply a specific action anytime the annotation is found in the class according to the type of target supported
+     * by the annotation which can be either {@link ElementType#TYPE}, {@link ElementType#CONSTRUCTOR},
+     * {@link ElementType#METHOD}, {@link ElementType#FIELD}, or {@link ElementType#PARAMETER}.
+     *
+     * @param c the target class
+     * @param a the target type of annotation
+     * @param getter the method allowing to extract the excepted values from the annotation
+     * @param onMatch the action to perform in case of a match
+     * @param <A> the type of the target annotation
+     * @param <T> the type of the content extracted from the annotation found
+     */
+    public static <A extends Annotation, T> void applyIfMatch(Class<?> c, Class<A> a, Function<A, T> getter,
+                                                              Consumer<T> onMatch) {
+        Set<ElementType> targets = null;
+        if (a.isAnnotationPresent(Target.class)) {
+            targets = Collections.newSetFromMap(new EnumMap<>(ElementType.class));
+            targets.addAll(Arrays.asList(a.getAnnotation(Target.class).value()));
+        }
+        if ((targets == null || targets.contains(ElementType.TYPE)) && c.isAnnotationPresent(a)) {
+            onMatch.accept(getter.apply(c.getAnnotation(a)));
+        }
+        boolean checkConstructors = targets == null || targets.contains(ElementType.CONSTRUCTOR);
+        boolean checkParameters = targets == null || targets.contains(ElementType.PARAMETER);
+        if (checkConstructors || checkParameters) {
+            for (Constructor<?> constructor : c.getDeclaredConstructors()) {
+                if (checkConstructors && constructor.isAnnotationPresent(a)) {
+                    onMatch.accept(getter.apply(constructor.getAnnotation(a)));
+                }
+                if (checkParameters) {
+                    for (Parameter parameter : constructor.getParameters()) {
+                        if (parameter.isAnnotationPresent(a)) {
+                            onMatch.accept(getter.apply(parameter.getAnnotation(a)));
+                        }
+                    }
+                }
+            }
+        }
+        if (targets == null || targets.contains(ElementType.FIELD)) {
+            ReflectionUtils.doWithFields(c,
+                field -> onMatch.accept(getter.apply(field.getAnnotation(a))), field -> field.isAnnotationPresent(a));
+        }
+        boolean checkMethods = targets == null || targets.contains(ElementType.METHOD);
+        if (checkMethods || checkParameters) {
+            ReflectionUtils.doWithMethods(
+                c,
+                method -> {
+                    if (checkMethods && method.isAnnotationPresent(a)) {
+                        onMatch.accept(getter.apply(method.getAnnotation(a)));
+                    }
+                    if (checkParameters) {
+                        for (Parameter parameter : method.getParameters()) {
+                            if (parameter.isAnnotationPresent(a)) {
+                                onMatch.accept(getter.apply(parameter.getAnnotation(a)));
+                            }
+                        }
+                    }
+                }
+            );
+        }
+    }
+
+    /**
+     * Give all the classes available in the given class loader that are annotated with at least one of the annotations.
+     *
+     * @param classLoader the class loader from which the classes to find are loaded
+     * @param annotations the target annotations
+     * @return the list of classes that are annotated with at least one of the annotations.
+     */
+    public static List<Class<?>> getClassesByAnnotations(ClassLoader classLoader, List<Class<? extends Annotation>> annotations) {
+        return getClassesByFilters(classLoader, annotations.stream().map(AnnotationTypeFilter::new).collect(Collectors.toList()));
+    }
+
+    /**
+     * Give all the classes available in the given class loader that match with at least one of the filters.
+     *
+     * @param classLoader the class loader from which the classes to find are loaded
+     * @param includeFilters the filters to apply the classes found
+     * @return a list of classes that match with at least one of the given filters
+     */
+    public static List<Class<?>> getClassesByFilters(ClassLoader classLoader, List<TypeFilter> includeFilters) {
+        ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false) {
+            @Override
+            protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
+                return true;
+            }
+        };
+        provider.setResourceLoader(new PathMatchingResourcePatternResolver(classLoader));
+        provider.setMetadataReaderFactory(new SafeMetadataReaderFactory(provider.getMetadataReaderFactory()));
+        provider.addExcludeFilter(
+            (metadata, factory) -> {
+                String className = metadata.getClassMetadata().getClassName();
+                return className.startsWith("org.springframework.") || className.startsWith("java.") || className.startsWith("jakarta.");
+            });
+        for (TypeFilter filter : includeFilters) {
+            provider.addIncludeFilter(filter);
+        }
+        return provider.findCandidateComponents("")
+                .stream()
+                .map(b -> asClass(b, classLoader))
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * Convert the given bean into a class.
+     * @param bean the bean to convert.
+     * @param classLoader the classloader from which the class of the bean is loaded
+     * @return the class corresponding to the bean if it could be found, {@code null} otherwise.
+     */
+    private static Class<?> asClass(BeanDefinition bean, ClassLoader classLoader) {
+        String beanClassName = bean.getBeanClassName();
+        if (beanClassName == null) {
+            LOG.debug("The name of the class corresponding to the bean '{}' could not be found", bean);
+        } else {
+            try {
+                return ClassUtils.forName(beanClassName, classLoader);
+            } catch (ClassNotFoundException | NoClassDefFoundError e) {
+                LOG.debug("The class corresponding to the bean '{}' could not be found: {}", bean, e.getMessage());
+            }
+        }
+        return null;
+    }
+
+    /**
+     * {@code SafeMetadataReaderFactory} is a specific {@link MetadataReaderFactory} whose methods never throw any
+     * exceptions, if an error occurs while calling the underlying {@link MetadataReaderFactory} a debug message is
+     * logged and the default result is returned.
+     */
+    private static class SafeMetadataReaderFactory implements MetadataReaderFactory {
+
+        /**
+         * The instance of the default result in case of an error.
+         */
+        private static final MetadataReader DEFAULT = new MetadataReader() {
+            @Override
+            public Resource getResource() {
+                return new ByteArrayResource(new byte[0]);
+            }
+
+            @Override
+            public ClassMetadata getClassMetadata() {
+                return AnnotationMetadata.introspect(Object.class);
+            }
+
+            @Override
+            public AnnotationMetadata getAnnotationMetadata() {
+                return AnnotationMetadata.introspect(Object.class);
+            }
+        };
+        private final MetadataReaderFactory delegate;
+
+        SafeMetadataReaderFactory(MetadataReaderFactory delegate) {
+            this.delegate = delegate;
+        }
+
+        @Override
+        public MetadataReader getMetadataReader(String className) {
+            try {
+                return delegate.getMetadataReader(className);
+            } catch (Exception | NoClassDefFoundError e) {
+                LOG.debug("Could not get the metadata of the class {}", className);
+            }
+            return DEFAULT;
+        }
+
+        @Override
+        public MetadataReader getMetadataReader(Resource resource) {
+            try {
+                return delegate.getMetadataReader(resource);
+            } catch (Exception | NoClassDefFoundError e) {
+                LOG.debug("Could not get the metadata of the resource {}", resource);
+            }
+            return DEFAULT;
+        }
+    }
+}
diff --git a/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/aot/RuntimeHintsHelper.java b/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/aot/RuntimeHintsHelper.java
new file mode 100644
index 00000000000..d759cc8b3f4
--- /dev/null
+++ b/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/aot/RuntimeHintsHelper.java
@@ -0,0 +1,71 @@
+/*
+ * 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.spring.boot.aot;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.aot.hint.MemberCategory;
+import org.springframework.aot.hint.RuntimeHints;
+import org.springframework.util.ClassUtils;
+
+public final class RuntimeHintsHelper {
+
+    /**
+     * The logger.
+     */
+    private static final Logger LOG = LoggerFactory.getLogger(RuntimeHintsHelper.class);
+
+    private RuntimeHintsHelper() {
+    }
+
+
+    /**
+     * Register the given class and all its parent classes by applying the given member categories.
+     *
+     * @param hints            the hints contributed so far for the deployment unit
+     * @param classLoader      the ClassLoader to load classpath resources with,
+     *                         or {@code null} for using the thread context class loader
+     *                         at the time of actual resource access
+     * @param className        the name of the class to register
+     * @param memberCategories the member categories to apply
+     */
+    public static void registerClassHierarchy(RuntimeHints hints, ClassLoader classLoader, String className,
+                                              MemberCategory... memberCategories) {
+        try {
+            registerClassHierarchy(hints, ClassUtils.forName(className, classLoader), memberCategories);
+        } catch (ClassNotFoundException | NoClassDefFoundError e) {
+            LOG.debug("The class {} cannot be found", className);
+        }
+    }
+
+    /**
+     * Register the given class and all its parent classes by applying the given member categories.
+     *
+     * @param hints            the hints contributed so far for the deployment unit
+     * @param clazz            the class to register
+     * @param memberCategories the member categories to apply
+     */
+    public static void registerClassHierarchy(RuntimeHints hints, Class<?> clazz, MemberCategory... memberCategories) {
+        if (clazz.isInterface() || clazz.isArray()) {
+            return;
+        }
+        while (clazz != Object.class) {
+            hints.reflection().registerType(clazz, memberCategories);
+            clazz = clazz.getSuperclass();
+        }
+    }
+}
diff --git a/core/camel-spring-boot/src/main/resources/META-INF/native-image/org.apache.camel.springboot/camel-spring-boot/native-image.properties b/core/camel-spring-boot/src/main/resources/META-INF/native-image/org.apache.camel.springboot/camel-spring-boot/native-image.properties
new file mode 100644
index 00000000000..a974103baf7
--- /dev/null
+++ b/core/camel-spring-boot/src/main/resources/META-INF/native-image/org.apache.camel.springboot/camel-spring-boot/native-image.properties
@@ -0,0 +1 @@
+Args = -H:+AddAllCharsets
\ No newline at end of file
diff --git a/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/aot/CamelRuntimeHintsTest.java b/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/aot/CamelRuntimeHintsTest.java
new file mode 100644
index 00000000000..d942ac47c30
--- /dev/null
+++ b/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/aot/CamelRuntimeHintsTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.spring.boot.aot;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.language.simple.SimpleLanguage;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.aot.hint.RuntimeHints;
+import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Unit tests for {@link CamelRuntimeHints}.
+ */
+class CamelRuntimeHintsTest {
+
+    private final RuntimeHints hints = new RuntimeHints();
+
+    @BeforeEach
+    void init() {
+        new CamelRuntimeHints().registerHints(hints, getClass().getClassLoader());
+    }
+
+    @Test
+    void shouldRegisterHintsForCamelServices() throws Exception {
+        assertThat(RuntimeHintsPredicates.resource().forResource("META-INF/services/org/apache/camel/language/simple")).accepts(hints);
+        assertThat(RuntimeHintsPredicates.reflection().onConstructor(SimpleLanguage.class.getConstructor())).accepts(hints);
+        assertThat(RuntimeHintsPredicates.reflection().onMethod(SimpleLanguage.class.getMethod("init"))).accepts(hints);
+        assertThat(RuntimeHintsPredicates.reflection().onMethod(SimpleLanguage.class.getMethod("setCamelContext", CamelContext.class))).accepts(hints);
+    }
+
+    @Test
+    void shouldRegisterHintsForCamelCatalog() {
+        assertThat(RuntimeHintsPredicates.resource().forResource("org/apache/camel/main/components.properties")).accepts(hints);
+    }
+}
diff --git a/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/aot/ReflectionHelperTest.java b/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/aot/ReflectionHelperTest.java
new file mode 100644
index 00000000000..c01e26e115f
--- /dev/null
+++ b/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/aot/ReflectionHelperTest.java
@@ -0,0 +1,142 @@
+/*
+ * 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.spring.boot.aot;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Unit tests for {@link ReflectionHelperTest}.
+ */
+class ReflectionHelperTest {
+
+    private final AtomicInteger counter = new AtomicInteger();
+
+    @Test
+    void shouldAlwaysApply() {
+        ReflectionHelper.applyIfMatch(Foo.class, All.class, a -> null, x -> counter.incrementAndGet());
+        assertThat(counter.get()).isEqualTo(11);
+    }
+
+    @Test
+    void shouldNeverApply() {
+        ReflectionHelper.applyIfMatch(Foo.class, None.class, a -> null, x -> counter.incrementAndGet());
+        assertThat(counter.get()).isZero();
+    }
+
+    @Test
+    void shouldApplyToClassOnly() {
+        ReflectionHelper.applyIfMatch(Foo.class, OnlyType.class, a -> null, x -> counter.incrementAndGet());
+        assertThat(counter.get()).isEqualTo(1);
+    }
+
+    @Test
+    void shouldApplyToOneSpecificConstructor() {
+        ReflectionHelper.applyIfMatch(Foo.class, OnlyConstructor.class, a -> null, x -> counter.incrementAndGet());
+        assertThat(counter.get()).isEqualTo(1);
+    }
+
+    @Test
+    void shouldApplyToOneSpecificField() {
+        ReflectionHelper.applyIfMatch(Foo.class, OnlyField.class, a -> null, x -> counter.incrementAndGet());
+        assertThat(counter.get()).isEqualTo(1);
+    }
+
+    @Test
+    void shouldApplyToOneSpecificMethod() {
+        ReflectionHelper.applyIfMatch(Foo.class, OnlyMethod.class, a -> null, x -> counter.incrementAndGet());
+        assertThat(counter.get()).isEqualTo(1);
+    }
+
+    @Test
+    void shouldApplyToSpecificParameters() {
+        ReflectionHelper.applyIfMatch(Foo.class, OnlyParameter.class, a -> null, x -> counter.incrementAndGet());
+        assertThat(counter.get()).isEqualTo(2);
+    }
+
+    @OnlyType
+    @All
+    public static class Foo {
+
+        @All
+        private String someField1;
+        @OnlyField
+        @All
+        private String someField2;
+
+        @All
+        private Foo() {}
+
+        @OnlyConstructor
+        @All
+        private Foo(@OnlyParameter @All String someParam1, @All String someParam2) {}
+
+        @All
+        private void someMethod1(@All String someParam1, @All @OnlyParameter String someParam2) {}
+
+        @OnlyMethod
+        @All
+        private void someMethod2() {}
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface All {
+
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface None {
+
+    }
+
+    @Target(ElementType.TYPE)
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface OnlyType {
+
+    }
+
+    @Target(ElementType.FIELD)
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface OnlyField {
+
+    }
+
+    @Target(ElementType.CONSTRUCTOR)
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface OnlyConstructor {
+
+    }
+
+    @Target(ElementType.METHOD)
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface OnlyMethod {
+
+    }
+
+    @Target(ElementType.PARAMETER)
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface OnlyParameter {
+
+    }
+}
diff --git a/dsl-starter/camel-xml-jaxb-dsl-starter/pom.xml b/dsl-starter/camel-xml-jaxb-dsl-starter/pom.xml
index aec33256ef6..e7527e5b0d7 100644
--- a/dsl-starter/camel-xml-jaxb-dsl-starter/pom.xml
+++ b/dsl-starter/camel-xml-jaxb-dsl-starter/pom.xml
@@ -49,5 +49,10 @@
             <artifactId>camel-xml-jaxb-dsl</artifactId>
             <version>${camel-version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel.springboot</groupId>
+            <artifactId>camel-xml-jaxb-starter</artifactId>
+            <version>${camel-version}</version>
+        </dependency>
     </dependencies>
 </project>
\ No newline at end of file
diff --git a/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringPropertiesParser.java b/dsl-starter/camel-xml-jaxb-dsl-starter/src/main/java/org/apache/camel/dsl/xml/jaxb/springboot/aot/XMLDSLRuntimeHints.java
similarity index 59%
copy from core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringPropertiesParser.java
copy to dsl-starter/camel-xml-jaxb-dsl-starter/src/main/java/org/apache/camel/dsl/xml/jaxb/springboot/aot/XMLDSLRuntimeHints.java
index ac3cb4d7e5b..75abf68a13c 100644
--- a/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringPropertiesParser.java
+++ b/dsl-starter/camel-xml-jaxb-dsl-starter/src/main/java/org/apache/camel/dsl/xml/jaxb/springboot/aot/XMLDSLRuntimeHints.java
@@ -14,25 +14,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.spring.boot;
+package org.apache.camel.dsl.xml.jaxb.springboot.aot;
 
-import org.apache.camel.component.properties.DefaultPropertiesParser;
-import org.apache.camel.component.properties.PropertiesLookup;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.core.env.Environment;
+import java.util.ArrayList;
 
-class SpringPropertiesParser extends DefaultPropertiesParser {
-
-    // Members
-
-    @Autowired
-    private Environment env;
-
-    // Overridden
+import org.springframework.aot.hint.MemberCategory;
+import org.springframework.aot.hint.RuntimeHints;
+import org.springframework.aot.hint.RuntimeHintsRegistrar;
 
+final class XMLDSLRuntimeHints implements RuntimeHintsRegistrar {
     @Override
-    public String parseProperty(String key, String value, PropertiesLookup properties) {
-        return env.getProperty(key);
+    public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
+        hints.reflection().registerType(ArrayList.class, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
     }
-
 }
diff --git a/dsl-starter/camel-xml-jaxb-dsl-starter/src/main/resources/META-INF/spring/aot.factories b/dsl-starter/camel-xml-jaxb-dsl-starter/src/main/resources/META-INF/spring/aot.factories
new file mode 100644
index 00000000000..0c240e4c506
--- /dev/null
+++ b/dsl-starter/camel-xml-jaxb-dsl-starter/src/main/resources/META-INF/spring/aot.factories
@@ -0,0 +1,2 @@
+org.springframework.aot.hint.RuntimeHintsRegistrar=\
+org.apache.camel.dsl.xml.jaxb.springboot.aot.XMLDSLRuntimeHints
diff --git a/pom.xml b/pom.xml
index 6c82f016d13..b933255d8ac 100644
--- a/pom.xml
+++ b/pom.xml
@@ -109,6 +109,7 @@
 
         <!-- Spring-Boot target version -->
         <spring-boot-version>3.1.0</spring-boot-version>
+        <spring-version>6.0.9</spring-version>
 
         <!-- Camel target version -->
         <camel-version>4.0.0-SNAPSHOT</camel-version>
@@ -119,6 +120,7 @@
         <arquillian-version>1.7.0.Alpha10</arquillian-version>
         <avro-version>1.11.0</avro-version>
         <groovy-version>4.0.12</groovy-version>
+        <graal-sdk-version>22.3.2</graal-sdk-version>
         <jakarta-jaxb-version>4.0.0</jakarta-jaxb-version>
         <jaxb-version>2.3.0</jaxb-version>
         <maven-compiler-plugin-version>3.11.0</maven-compiler-plugin-version>