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 2022/12/23 13:29:27 UTC

[camel-quarkus] branch java-joor-dsl-native created (now e4e7ebbfbc)

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

nfilotto pushed a change to branch java-joor-dsl-native
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git


      at e4e7ebbfbc Java jOOR DSL native support

This branch includes the following new commits:

     new e4e7ebbfbc Java jOOR DSL native support

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[camel-quarkus] 01/01: Java jOOR DSL native support

Posted by nf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nfilotto pushed a commit to branch java-joor-dsl-native
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git

commit e4e7ebbfbc1818278a3c8306faa300797e6a42bf
Author: Nicolas Filotto <nf...@talend.com>
AuthorDate: Fri Dec 23 14:28:53 2022 +0100

    Java jOOR DSL native support
---
 .../modules/ROOT/examples/others/java-joor-dsl.yml |   6 +-
 .../pages/reference/extensions/java-joor-dsl.adoc  |  14 +-
 extensions-jvm/pom.xml                             |   1 -
 .../java-joor-dsl/deployment/pom.xml               |   0
 .../java/joor/deployment/JavaJoorDslProcessor.java | 191 +++++++++++++++++++++
 .../JavaJoorGeneratedClassBuildItem.java           |  33 ++--
 .../java-joor-dsl/pom.xml                          |   0
 .../java-joor-dsl/runtime/pom.xml                  |   6 +
 .../dsl/java/joor/runtime/JavaJoorDslRecorder.java |  54 ++++++
 .../graal/SubstituteClassRoutesBuilderLoader.java  |  26 ++-
 .../graal/SubstituteJavaRoutesBuilderLoader.java   |  26 ++-
 .../main/resources/META-INF/quarkus-extension.yaml |   0
 extensions/pom.xml                                 |   1 +
 integration-tests-jvm/pom.xml                      |   1 -
 .../java-joor-dsl/pom.xml                          |  27 +++
 .../quarkus/dsl/java/joor/JavaJoorDslResource.java |   0
 .../src/main/resources/application.properties      |   0
 .../src/main/resources/routes/MyRoutes.java        |   0
 .../camel/quarkus/dsl/java/joor/JavaJoorDslIT.java |  16 +-
 .../quarkus/dsl/java/joor/JavaJoorDslTest.java     |   0
 integration-tests/pom.xml                          |   1 +
 21 files changed, 358 insertions(+), 45 deletions(-)

diff --git a/docs/modules/ROOT/examples/others/java-joor-dsl.yml b/docs/modules/ROOT/examples/others/java-joor-dsl.yml
index f11fc9ab86..5ce1a2af0d 100644
--- a/docs/modules/ROOT/examples/others/java-joor-dsl.yml
+++ b/docs/modules/ROOT/examples/others/java-joor-dsl.yml
@@ -2,11 +2,11 @@
 # This file was generated by camel-quarkus-maven-plugin:update-extension-doc-page
 cqArtifactId: camel-quarkus-java-joor-dsl
 cqArtifactIdBase: java-joor-dsl
-cqNativeSupported: false
-cqStatus: Preview
+cqNativeSupported: true
+cqStatus: Stable
 cqDeprecated: false
 cqJvmSince: 1.8.0
-cqNativeSince: n/a
+cqNativeSince: 2.16.0
 cqCamelPartName: java-joor-dsl
 cqCamelPartTitle: Java DSL (runtime compiled)
 cqCamelPartDescription: Camel Java DSL with jOOR
diff --git a/docs/modules/ROOT/pages/reference/extensions/java-joor-dsl.adoc b/docs/modules/ROOT/pages/reference/extensions/java-joor-dsl.adoc
index 10e64f5aa8..2461a370a6 100644
--- a/docs/modules/ROOT/pages/reference/extensions/java-joor-dsl.adoc
+++ b/docs/modules/ROOT/pages/reference/extensions/java-joor-dsl.adoc
@@ -4,17 +4,17 @@
 = Java jOOR DSL
 :linkattrs:
 :cq-artifact-id: camel-quarkus-java-joor-dsl
-:cq-native-supported: false
-:cq-status: Preview
-:cq-status-deprecation: Preview
+:cq-native-supported: true
+:cq-status: Stable
+:cq-status-deprecation: Stable
 :cq-description: Support for parsing Java route definitions at runtime
 :cq-deprecated: false
 :cq-jvm-since: 1.8.0
-:cq-native-since: n/a
+:cq-native-since: 2.16.0
 
 ifeval::[{doc-show-badges} == true]
 [.badges]
-[.badge-key]##JVM since##[.badge-supported]##1.8.0## [.badge-key]##Native##[.badge-unsupported]##unsupported##
+[.badge-key]##JVM since##[.badge-supported]##1.8.0## [.badge-key]##Native since##[.badge-supported]##2.16.0##
 endif::[]
 
 Support for parsing Java route definitions at runtime
@@ -29,6 +29,10 @@ Please refer to the above link for usage and configuration details.
 [id="extensions-java-joor-dsl-maven-coordinates"]
 == Maven coordinates
 
+https://{link-quarkus-code-generator}/?extension-search=camel-quarkus-java-joor-dsl[Create a new project with this extension on {link-quarkus-code-generator}, window="_blank"]
+
+Or add the coordinates to your existing project:
+
 [source,xml]
 ----
 <dependency>
diff --git a/extensions-jvm/pom.xml b/extensions-jvm/pom.xml
index 3a62afdaaa..2902ad693e 100644
--- a/extensions-jvm/pom.xml
+++ b/extensions-jvm/pom.xml
@@ -78,7 +78,6 @@
         <module>iota</module>
         <module>irc</module>
         <module>jasypt</module>
-        <module>java-joor-dsl</module>
         <module>jbpm</module>
         <module>jclouds</module>
         <module>jcr</module>
diff --git a/extensions-jvm/java-joor-dsl/deployment/pom.xml b/extensions/java-joor-dsl/deployment/pom.xml
similarity index 100%
rename from extensions-jvm/java-joor-dsl/deployment/pom.xml
rename to extensions/java-joor-dsl/deployment/pom.xml
diff --git a/extensions/java-joor-dsl/deployment/src/main/java/org/apache/camel/quarkus/dsl/java/joor/deployment/JavaJoorDslProcessor.java b/extensions/java-joor-dsl/deployment/src/main/java/org/apache/camel/quarkus/dsl/java/joor/deployment/JavaJoorDslProcessor.java
new file mode 100644
index 0000000000..9838eace30
--- /dev/null
+++ b/extensions/java-joor-dsl/deployment/src/main/java/org/apache/camel/quarkus/dsl/java/joor/deployment/JavaJoorDslProcessor.java
@@ -0,0 +1,191 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.camel.quarkus.dsl.java.joor.deployment;
+
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+import io.quarkus.deployment.annotations.BuildProducer;
+import io.quarkus.deployment.annotations.BuildStep;
+import io.quarkus.deployment.annotations.ExecutionTime;
+import io.quarkus.deployment.annotations.Record;
+import io.quarkus.deployment.builditem.FeatureBuildItem;
+import io.quarkus.deployment.builditem.GeneratedClassBuildItem;
+import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
+import io.quarkus.deployment.pkg.builditem.CurateOutcomeBuildItem;
+import io.quarkus.deployment.pkg.steps.NativeBuild;
+import io.quarkus.maven.dependency.ResolvedDependency;
+import io.quarkus.paths.PathCollection;
+import io.quarkus.runtime.RuntimeValue;
+import org.apache.camel.CamelContext;
+import org.apache.camel.dsl.java.joor.CompilationUnit;
+import org.apache.camel.dsl.java.joor.MultiCompile;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.impl.engine.DefaultPackageScanResourceResolver;
+import org.apache.camel.quarkus.core.deployment.main.CamelMainHelper;
+import org.apache.camel.quarkus.core.deployment.spi.CamelContextBuildItem;
+import org.apache.camel.quarkus.dsl.java.joor.runtime.JavaJoorDslRecorder;
+import org.apache.camel.spi.Resource;
+import org.apache.camel.support.ResourceHelper;
+import org.apache.camel.util.AntPathMatcher;
+import org.apache.camel.util.FileUtil;
+import org.apache.camel.util.IOHelper;
+import org.apache.camel.util.StringHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class JavaJoorDslProcessor {
+
+    private static final Logger LOG = LoggerFactory.getLogger(JavaJoorDslProcessor.class);
+    private static final String FEATURE = "camel-java-joor-dsl";
+
+    private static final Pattern PACKAGE_PATTERN = Pattern.compile(
+            "^\\s*package\\s+([a-zA-Z][\\.\\w]*)\\s*;.*$", Pattern.MULTILINE);
+
+    @BuildStep
+    FeatureBuildItem feature() {
+        return new FeatureBuildItem(FEATURE);
+    }
+
+    @BuildStep(onlyIf = NativeBuild.class)
+    void loadClassesAOT(BuildProducer<JavaJoorGeneratedClassBuildItem> generatedClass) throws Exception {
+        String[] excludes = CamelMainHelper.routesExcludePattern().toArray(String[]::new);
+        LOG.debug("Loading .class resources");
+        try (DefaultPackageScanResourceResolver resolver = new DefaultPackageScanResourceResolver()) {
+            resolver.setCamelContext(new DefaultCamelContext());
+            for (String include : CamelMainHelper.routesIncludePattern().collect(Collectors.toList())) {
+                for (Resource resource : resolver.findResources(include)) {
+                    if (AntPathMatcher.INSTANCE.anyMatch(excludes, resource.getLocation())
+                            || !resource.getLocation().endsWith(".class")) {
+                        continue;
+                    }
+                    try (InputStream is = resource.getInputStream()) {
+                        generatedClass
+                                .produce(new JavaJoorGeneratedClassBuildItem(asClassName(resource), resource.getLocation(),
+                                        is.readAllBytes()));
+                    }
+                }
+            }
+        }
+    }
+
+    @BuildStep(onlyIf = NativeBuild.class)
+    void compileClassesAOT(BuildProducer<JavaJoorGeneratedClassBuildItem> generatedClass,
+            CurateOutcomeBuildItem curateOutcomeBuildItem) throws Exception {
+        String[] excludes = CamelMainHelper.routesExcludePattern().toArray(String[]::new);
+        Map<String, Resource> nameToResource = new HashMap<>();
+        LOG.debug("Loading .java resources");
+        CompilationUnit unit = CompilationUnit.input();
+        try (DefaultPackageScanResourceResolver resolver = new DefaultPackageScanResourceResolver()) {
+            resolver.setCamelContext(new DefaultCamelContext());
+            for (String include : CamelMainHelper.routesIncludePattern().collect(Collectors.toList())) {
+                for (Resource resource : resolver.findResources(include)) {
+                    if (AntPathMatcher.INSTANCE.anyMatch(excludes, resource.getLocation())
+                            || !resource.getLocation().endsWith(".java")) {
+                        continue;
+                    }
+                    try (InputStream is = resource.getInputStream()) {
+                        String content = IOHelper.loadText(is);
+                        String name = determineName(resource, content);
+                        unit.addClass(name, content);
+                        nameToResource.put(name, resource);
+                    }
+                }
+            }
+        }
+        if (nameToResource.isEmpty()) {
+            return;
+        }
+        // Temporary workaround until being able to provide the CL somehow to the method MultiCompile.compileUnit
+        String previousCP = System.getProperty("java.class.path");
+        try {
+            String cp = curateOutcomeBuildItem.getApplicationModel().getDependencies().stream()
+                    .map(ResolvedDependency::getResolvedPaths)
+                    .flatMap(PathCollection::stream)
+                    .map(Objects::toString)
+                    .collect(Collectors.joining(System.getProperty("path.separator")));
+            System.setProperty("java.class.path", cp);
+            LOG.debug("Compiling unit: {}", unit);
+            CompilationUnit.Result result = MultiCompile.compileUnit(unit);
+            for (String className : result.getClassNames()) {
+                generatedClass
+                        .produce(new JavaJoorGeneratedClassBuildItem(className, nameToResource.get(className).getLocation(),
+                                result.getByteCode(className)));
+            }
+        } finally {
+            // Restore the CP
+            System.setProperty("java.class.path", previousCP);
+        }
+    }
+
+    @BuildStep(onlyIf = NativeBuild.class)
+    void registerGeneratedClasses(BuildProducer<GeneratedClassBuildItem> generatedClass,
+            BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
+            List<JavaJoorGeneratedClassBuildItem> classes) {
+
+        for (JavaJoorGeneratedClassBuildItem clazz : classes) {
+            generatedClass.produce(new GeneratedClassBuildItem(true, clazz.getName(), clazz.getClassData()));
+            reflectiveClass.produce(new ReflectiveClassBuildItem(false, false, clazz.getName()));
+        }
+    }
+
+    @BuildStep(onlyIf = NativeBuild.class)
+    @Record(value = ExecutionTime.STATIC_INIT)
+    void registerRoutesBuilder(List<JavaJoorGeneratedClassBuildItem> classes,
+            CamelContextBuildItem context,
+            JavaJoorDslRecorder recorder) throws Exception {
+        RuntimeValue<CamelContext> camelContext = context.getCamelContext();
+        for (JavaJoorGeneratedClassBuildItem clazz : classes) {
+            recorder.registerRoutesBuilder(camelContext, clazz.getName(), clazz.getLocation());
+        }
+    }
+
+    private static String determineName(Resource resource, String content) {
+        String loc = resource.getLocation();
+        // strip scheme to compute the name
+        String scheme = ResourceHelper.getScheme(loc);
+        if (scheme != null) {
+            loc = loc.substring(scheme.length());
+        }
+        final String name = FileUtil.onlyName(loc, true);
+        final Matcher matcher = PACKAGE_PATTERN.matcher(content);
+
+        return matcher.find()
+                ? matcher.group(1) + "." + name
+                : name;
+    }
+
+    private static String asClassName(Resource resource) {
+        String className = resource.getLocation();
+        if (className.contains(":")) {
+            // remove scheme such as classpath:foo.class
+            className = StringHelper.after(className, ":");
+        }
+        className = className.replace('/', '.');
+        if (className.endsWith(".class")) {
+            className = className.substring(0, className.length() - 6);
+        }
+        return className;
+    }
+}
diff --git a/extensions-jvm/java-joor-dsl/deployment/src/main/java/org/apache/camel/quarkus/dsl/java/joor/deployment/JavaJoorDslProcessor.java b/extensions/java-joor-dsl/deployment/src/main/java/org/apache/camel/quarkus/dsl/java/joor/deployment/JavaJoorGeneratedClassBuildItem.java
similarity index 59%
rename from extensions-jvm/java-joor-dsl/deployment/src/main/java/org/apache/camel/quarkus/dsl/java/joor/deployment/JavaJoorDslProcessor.java
rename to extensions/java-joor-dsl/deployment/src/main/java/org/apache/camel/quarkus/dsl/java/joor/deployment/JavaJoorGeneratedClassBuildItem.java
index e9a1cde731..742d856145 100644
--- a/extensions-jvm/java-joor-dsl/deployment/src/main/java/org/apache/camel/quarkus/dsl/java/joor/deployment/JavaJoorDslProcessor.java
+++ b/extensions/java-joor-dsl/deployment/src/main/java/org/apache/camel/quarkus/dsl/java/joor/deployment/JavaJoorGeneratedClassBuildItem.java
@@ -14,24 +14,31 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package org.apache.camel.quarkus.dsl.java.joor.deployment;
 
-import io.quarkus.deployment.annotations.BuildStep;
-import io.quarkus.deployment.builditem.FeatureBuildItem;
-import io.quarkus.deployment.pkg.steps.NativeBuild;
+import io.quarkus.builder.item.MultiBuildItem;
+
+public final class JavaJoorGeneratedClassBuildItem extends MultiBuildItem {
+
+    final String name;
+    final String location;
+    final byte[] classData;
 
-public class JavaJoorDslProcessor {
-    private static final String FEATURE = "camel-java-joor-dsl";
+    public JavaJoorGeneratedClassBuildItem(String name, String location, byte[] classData) {
+        this.name = name;
+        this.location = location;
+        this.classData = classData;
+    }
+
+    public String getName() {
+        return this.name;
+    }
 
-    @BuildStep
-    FeatureBuildItem feature() {
-        return new FeatureBuildItem(FEATURE);
+    public byte[] getClassData() {
+        return this.classData;
     }
 
-    @BuildStep(onlyIf = NativeBuild.class)
-    void nativeUnsupported() {
-        throw new RuntimeException("The " + FEATURE + " extension is not supported in native mode "
-                + "as loading Java code at runtime is not supported on GraalVM");
+    public String getLocation() {
+        return location;
     }
 }
diff --git a/extensions-jvm/java-joor-dsl/pom.xml b/extensions/java-joor-dsl/pom.xml
similarity index 100%
rename from extensions-jvm/java-joor-dsl/pom.xml
rename to extensions/java-joor-dsl/pom.xml
diff --git a/extensions-jvm/java-joor-dsl/runtime/pom.xml b/extensions/java-joor-dsl/runtime/pom.xml
similarity index 93%
rename from extensions-jvm/java-joor-dsl/runtime/pom.xml
rename to extensions/java-joor-dsl/runtime/pom.xml
index 344a028c85..d4d1794a11 100644
--- a/extensions-jvm/java-joor-dsl/runtime/pom.xml
+++ b/extensions/java-joor-dsl/runtime/pom.xml
@@ -32,6 +32,7 @@
 
     <properties>
         <camel.quarkus.jvmSince>1.8.0</camel.quarkus.jvmSince>
+        <camel.quarkus.nativeSince>2.16.0</camel.quarkus.nativeSince>
     </properties>
 
     <dependencies>
@@ -43,6 +44,11 @@
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-java-joor-dsl</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.graalvm.nativeimage</groupId>
+            <artifactId>svm</artifactId>
+            <scope>provided</scope>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/extensions/java-joor-dsl/runtime/src/main/java/org/apache/camel/quarkus/dsl/java/joor/runtime/JavaJoorDslRecorder.java b/extensions/java-joor-dsl/runtime/src/main/java/org/apache/camel/quarkus/dsl/java/joor/runtime/JavaJoorDslRecorder.java
new file mode 100644
index 0000000000..6e45aa2e90
--- /dev/null
+++ b/extensions/java-joor-dsl/runtime/src/main/java/org/apache/camel/quarkus/dsl/java/joor/runtime/JavaJoorDslRecorder.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.dsl.java.joor.runtime;
+
+import java.lang.reflect.Modifier;
+
+import io.quarkus.runtime.RuntimeValue;
+import io.quarkus.runtime.annotations.Recorder;
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.spi.ResourceAware;
+import org.apache.camel.support.ResourceHelper;
+import org.apache.camel.util.ObjectHelper;
+
+@Recorder
+public class JavaJoorDslRecorder {
+    public void registerRoutesBuilder(RuntimeValue<CamelContext> context, String className, String location) throws Exception {
+        Class<?> clazz = Class.forName(className);
+        boolean skip = clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers())
+                || Modifier.isPrivate(clazz.getModifiers());
+        // must have a default no-arg constructor to be able to create an instance
+        boolean ctr = ObjectHelper.hasDefaultNoArgConstructor(clazz);
+        if (ctr && !skip) {
+            // create a new instance of the class
+            try {
+                Object obj = context.getValue().getInjector().newInstance(clazz);
+                if (obj instanceof RoutesBuilder) {
+                    // inject context and resource
+                    CamelContextAware.trySetCamelContext(obj, context.getValue());
+                    ResourceAware.trySetResource(obj, ResourceHelper.fromString(location, ""));
+                    context.getValue().addRoutes((RoutesBuilder) obj);
+                }
+            } catch (Exception e) {
+                throw new RuntimeCamelException("Cannot create instance of class: " + className, e);
+            }
+        }
+    }
+}
diff --git a/integration-tests-jvm/java-joor-dsl/src/main/resources/routes/MyRoutes.java b/extensions/java-joor-dsl/runtime/src/main/java/org/apache/camel/quarkus/dsl/java/joor/runtime/graal/SubstituteClassRoutesBuilderLoader.java
similarity index 55%
copy from integration-tests-jvm/java-joor-dsl/src/main/resources/routes/MyRoutes.java
copy to extensions/java-joor-dsl/runtime/src/main/java/org/apache/camel/quarkus/dsl/java/joor/runtime/graal/SubstituteClassRoutesBuilderLoader.java
index 3292e12586..53272ea5cf 100644
--- a/integration-tests-jvm/java-joor-dsl/src/main/resources/routes/MyRoutes.java
+++ b/extensions/java-joor-dsl/runtime/src/main/java/org/apache/camel/quarkus/dsl/java/joor/runtime/graal/SubstituteClassRoutesBuilderLoader.java
@@ -14,11 +14,23 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-public class MyRoutes extends org.apache.camel.builder.RouteBuilder {
-    @Override
-    public void configure() throws Exception {
-        from("direct:start")
-            .id("my-java-route")
-            .log("Hello Java !!!");
+package org.apache.camel.quarkus.dsl.java.joor.runtime.graal;
+
+import java.util.Collection;
+import java.util.List;
+
+import com.oracle.svm.core.annotate.Substitute;
+import com.oracle.svm.core.annotate.TargetClass;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.dsl.java.joor.ClassRoutesBuilderLoader;
+import org.apache.camel.spi.Resource;
+
+@TargetClass(ClassRoutesBuilderLoader.class)
+final class SubstituteClassRoutesBuilderLoader {
+
+    @Substitute
+    protected Collection<RoutesBuilder> doLoadRoutesBuilders(Collection<Resource> resources) throws Exception {
+        // Do nothing as it is already done
+        return List.of();
     }
-}
\ No newline at end of file
+}
diff --git a/integration-tests-jvm/java-joor-dsl/src/main/resources/routes/MyRoutes.java b/extensions/java-joor-dsl/runtime/src/main/java/org/apache/camel/quarkus/dsl/java/joor/runtime/graal/SubstituteJavaRoutesBuilderLoader.java
similarity index 55%
copy from integration-tests-jvm/java-joor-dsl/src/main/resources/routes/MyRoutes.java
copy to extensions/java-joor-dsl/runtime/src/main/java/org/apache/camel/quarkus/dsl/java/joor/runtime/graal/SubstituteJavaRoutesBuilderLoader.java
index 3292e12586..9fdc7d75e6 100644
--- a/integration-tests-jvm/java-joor-dsl/src/main/resources/routes/MyRoutes.java
+++ b/extensions/java-joor-dsl/runtime/src/main/java/org/apache/camel/quarkus/dsl/java/joor/runtime/graal/SubstituteJavaRoutesBuilderLoader.java
@@ -14,11 +14,23 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-public class MyRoutes extends org.apache.camel.builder.RouteBuilder {
-    @Override
-    public void configure() throws Exception {
-        from("direct:start")
-            .id("my-java-route")
-            .log("Hello Java !!!");
+package org.apache.camel.quarkus.dsl.java.joor.runtime.graal;
+
+import java.util.Collection;
+import java.util.List;
+
+import com.oracle.svm.core.annotate.Substitute;
+import com.oracle.svm.core.annotate.TargetClass;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.dsl.java.joor.JavaRoutesBuilderLoader;
+import org.apache.camel.spi.Resource;
+
+@TargetClass(JavaRoutesBuilderLoader.class)
+final class SubstituteJavaRoutesBuilderLoader {
+
+    @Substitute
+    protected Collection<RoutesBuilder> doLoadRoutesBuilders(Collection<Resource> resources) throws Exception {
+        // Do nothing as it is already done
+        return List.of();
     }
-}
\ No newline at end of file
+}
diff --git a/extensions-jvm/java-joor-dsl/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/java-joor-dsl/runtime/src/main/resources/META-INF/quarkus-extension.yaml
similarity index 100%
rename from extensions-jvm/java-joor-dsl/runtime/src/main/resources/META-INF/quarkus-extension.yaml
rename to extensions/java-joor-dsl/runtime/src/main/resources/META-INF/quarkus-extension.yaml
diff --git a/extensions/pom.xml b/extensions/pom.xml
index d124bde3cb..98e2d02638 100644
--- a/extensions/pom.xml
+++ b/extensions/pom.xml
@@ -130,6 +130,7 @@
         <module>jackson-avro</module>
         <module>jackson-protobuf</module>
         <module>jacksonxml</module>
+        <module>java-joor-dsl</module>
         <module>jaxb</module>
         <module>jcache</module>
         <module>jdbc</module>
diff --git a/integration-tests-jvm/pom.xml b/integration-tests-jvm/pom.xml
index e57e8ddd24..119130ec32 100644
--- a/integration-tests-jvm/pom.xml
+++ b/integration-tests-jvm/pom.xml
@@ -77,7 +77,6 @@
         <module>iota</module>
         <module>irc</module>
         <module>jasypt</module>
-        <module>java-joor-dsl</module>
         <module>jbpm</module>
         <module>jclouds</module>
         <module>jcr</module>
diff --git a/integration-tests-jvm/java-joor-dsl/pom.xml b/integration-tests/java-joor-dsl/pom.xml
similarity index 81%
rename from integration-tests-jvm/java-joor-dsl/pom.xml
rename to integration-tests/java-joor-dsl/pom.xml
index ab125fb449..8cb8575122 100644
--- a/integration-tests-jvm/java-joor-dsl/pom.xml
+++ b/integration-tests/java-joor-dsl/pom.xml
@@ -100,6 +100,33 @@
                 </dependency>
             </dependencies>
         </profile>
+        <profile>
+            <id>native</id>
+            <activation>
+                <property>
+                    <name>native</name>
+                </property>
+            </activation>
+            <properties>
+                <quarkus.package.type>native</quarkus.package.type>
+            </properties>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-failsafe-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <goals>
+                                    <goal>integration-test</goal>
+                                    <goal>verify</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
     </profiles>
 
 </project>
diff --git a/integration-tests-jvm/java-joor-dsl/src/main/java/org/apache/camel/quarkus/dsl/java/joor/JavaJoorDslResource.java b/integration-tests/java-joor-dsl/src/main/java/org/apache/camel/quarkus/dsl/java/joor/JavaJoorDslResource.java
similarity index 100%
rename from integration-tests-jvm/java-joor-dsl/src/main/java/org/apache/camel/quarkus/dsl/java/joor/JavaJoorDslResource.java
rename to integration-tests/java-joor-dsl/src/main/java/org/apache/camel/quarkus/dsl/java/joor/JavaJoorDslResource.java
diff --git a/integration-tests-jvm/java-joor-dsl/src/main/resources/application.properties b/integration-tests/java-joor-dsl/src/main/resources/application.properties
similarity index 100%
rename from integration-tests-jvm/java-joor-dsl/src/main/resources/application.properties
rename to integration-tests/java-joor-dsl/src/main/resources/application.properties
diff --git a/integration-tests-jvm/java-joor-dsl/src/main/resources/routes/MyRoutes.java b/integration-tests/java-joor-dsl/src/main/resources/routes/MyRoutes.java
similarity index 100%
copy from integration-tests-jvm/java-joor-dsl/src/main/resources/routes/MyRoutes.java
copy to integration-tests/java-joor-dsl/src/main/resources/routes/MyRoutes.java
diff --git a/integration-tests-jvm/java-joor-dsl/src/main/resources/routes/MyRoutes.java b/integration-tests/java-joor-dsl/src/test/java/org/apache/camel/quarkus/dsl/java/joor/JavaJoorDslIT.java
similarity index 77%
rename from integration-tests-jvm/java-joor-dsl/src/main/resources/routes/MyRoutes.java
rename to integration-tests/java-joor-dsl/src/test/java/org/apache/camel/quarkus/dsl/java/joor/JavaJoorDslIT.java
index 3292e12586..a3a3a97b02 100644
--- a/integration-tests-jvm/java-joor-dsl/src/main/resources/routes/MyRoutes.java
+++ b/integration-tests/java-joor-dsl/src/test/java/org/apache/camel/quarkus/dsl/java/joor/JavaJoorDslIT.java
@@ -14,11 +14,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-public class MyRoutes extends org.apache.camel.builder.RouteBuilder {
-    @Override
-    public void configure() throws Exception {
-        from("direct:start")
-            .id("my-java-route")
-            .log("Hello Java !!!");
-    }
-}
\ No newline at end of file
+package org.apache.camel.quarkus.dsl.java.joor;
+
+import io.quarkus.test.junit.QuarkusIntegrationTest;
+
+@QuarkusIntegrationTest
+class JavaJoorDslIT extends JavaJoorDslTest {
+
+}
diff --git a/integration-tests-jvm/java-joor-dsl/src/test/java/org/apache/camel/quarkus/dsl/java/joor/JavaJoorDslTest.java b/integration-tests/java-joor-dsl/src/test/java/org/apache/camel/quarkus/dsl/java/joor/JavaJoorDslTest.java
similarity index 100%
rename from integration-tests-jvm/java-joor-dsl/src/test/java/org/apache/camel/quarkus/dsl/java/joor/JavaJoorDslTest.java
rename to integration-tests/java-joor-dsl/src/test/java/org/apache/camel/quarkus/dsl/java/joor/JavaJoorDslTest.java
diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml
index c578f45ff1..88a23ea4ea 100644
--- a/integration-tests/pom.xml
+++ b/integration-tests/pom.xml
@@ -113,6 +113,7 @@
         <module>influxdb</module>
         <module>jackson-avro</module>
         <module>jackson-protobuf</module>
+        <module>java-joor-dsl</module>
         <module>jaxb</module>
         <module>jcache</module>
         <module>jdbc</module>