This is an automated email from the ASF dual-hosted git repository. nfilotto pushed a commit to branch 2.16.x in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
commit 42c3c013c456c1c679e187d35acba206ff603ff7 Author: Nicolas Filotto <essob...@users.noreply.github.com> AuthorDate: Mon Apr 3 08:06:28 2023 +0200 Ref #4716: java-joor-dsl - Add RegisterForReflection support (#4726) All the annotations added to a class managed by the extension `java-joor-dsl` are not considered by Quarkus since it is not part of the Jandex index. This change aims to support the annotation `RegisterForReflection` to easily configure the reflection in Camel-K. * Produce the corresponding `ReflectiveClassBuildItem` and `LambdaCapturingTypeBuildItem` if a `RouteBuilder` is annotated with `RegisterForReflection`. * Add some doc to explain the limitations * Add a unit test to ensure that it works as expected --- .../pages/reference/extensions/java-joor-dsl.adoc | 8 ++++ .../java/joor/deployment/JavaJoorDslProcessor.java | 55 ++++++++++++++++++++++ .../runtime/src/main/doc/limitations.adoc | 3 ++ .../quarkus/dsl/java/joor/JavaJoorDslBean.java} | 20 +++++--- .../quarkus/dsl/java/joor/JavaJoorDslResource.java | 10 +++- .../src/main/resources/routes/MyRoutes.java | 14 +++++- .../quarkus/dsl/java/joor/JavaJoorDslTest.java | 12 ++++- 7 files changed, 112 insertions(+), 10 deletions(-) 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 2461a370a6..edbf914728 100644 --- a/docs/modules/ROOT/pages/reference/extensions/java-joor-dsl.adoc +++ b/docs/modules/ROOT/pages/reference/extensions/java-joor-dsl.adoc @@ -43,3 +43,11 @@ Or add the coordinates to your existing project: ifeval::[{doc-show-user-guide-link} == true] Check the xref:user-guide/index.adoc[User guide] for more information about writing Camel Quarkus applications. endif::[] + +[id="extensions-java-joor-dsl-camel-quarkus-limitations"] +== Camel Quarkus limitations + +The annotations added to the classes to be compiled by the component are ignored by Quarkus. The only annotation that is +partially supported by the extension is the annotation `RegisterForReflection` to ease the configuration of the reflection +for the native mode however please note that the element `registerFullHierarchy` is not supported. + 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 index c27528d110..a782e772c8 100644 --- 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 @@ -33,12 +33,14 @@ 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.LambdaCapturingTypeBuildItem; 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 io.quarkus.runtime.annotations.RegisterForReflection; import org.apache.camel.CamelContext; import org.apache.camel.dsl.java.joor.CompilationUnit; import org.apache.camel.dsl.java.joor.MultiCompile; @@ -67,6 +69,8 @@ public class JavaJoorDslProcessor { @BuildStep(onlyIf = NativeBuild.class) void compileClassesAOT(BuildProducer<JavaJoorGeneratedClassBuildItem> generatedClass, + BuildProducer<ReflectiveClassBuildItem> reflectiveClass, + BuildProducer<LambdaCapturingTypeBuildItem> lambdaCapturingTypeProducer, CurateOutcomeBuildItem curateOutcomeBuildItem) throws Exception { Map<String, Resource> nameToResource = new HashMap<>(); LOG.debug("Loading .java resources"); @@ -104,6 +108,8 @@ public class JavaJoorDslProcessor { generatedClass .produce(new JavaJoorGeneratedClassBuildItem(className, nameToResource.get(className).getLocation(), result.getByteCode(className))); + registerForReflection(reflectiveClass, lambdaCapturingTypeProducer, + result.getClass(className).getAnnotation(RegisterForReflection.class)); } } finally { // Restore the CP @@ -111,6 +117,55 @@ public class JavaJoorDslProcessor { } } + private void registerForReflection(BuildProducer<ReflectiveClassBuildItem> reflectiveClass, + BuildProducer<LambdaCapturingTypeBuildItem> lambdaCapturingTypeProducer, + RegisterForReflection annotation) { + if (annotation == null) { + return; + } + + for (String lambdaCapturingType : annotation.lambdaCapturingTypes()) { + lambdaCapturingTypeProducer.produce(new LambdaCapturingTypeBuildItem(lambdaCapturingType)); + } + boolean methods = annotation.methods(); + boolean fields = annotation.fields(); + boolean ignoreNested = annotation.ignoreNested(); + boolean serialization = annotation.serialization(); + + if (annotation.registerFullHierarchy()) { + LOG.warn( + "The element 'registerFullHierarchy' of the annotation 'RegisterForReflection' is not supported by the extension Camel Java jOOR DSL"); + } + for (Class<?> type : annotation.targets()) { + registerClass(type.getName(), methods, fields, ignoreNested, serialization, reflectiveClass); + } + + for (String className : annotation.classNames()) { + registerClass(className, methods, fields, ignoreNested, serialization, reflectiveClass); + } + } + + private void registerClass(String className, boolean methods, boolean fields, boolean ignoreNested, boolean serialization, + BuildProducer<ReflectiveClassBuildItem> reflectiveClass) { + reflectiveClass.produce(serialization + ? ReflectiveClassBuildItem.serializationClass(className) + : new ReflectiveClassBuildItem(methods, fields, className)); + + if (ignoreNested) { + return; + } + + try { + Class<?>[] declaredClasses = Thread.currentThread().getContextClassLoader().loadClass(className) + .getDeclaredClasses(); + for (Class<?> clazz : declaredClasses) { + registerClass(clazz.getName(), methods, fields, false, serialization, reflectiveClass); + } + } catch (ClassNotFoundException e) { + LOG.warn("Failed to load Class {}", className, e); + } + } + @BuildStep(onlyIf = NativeBuild.class) void registerGeneratedClasses(BuildProducer<GeneratedClassBuildItem> generatedClass, BuildProducer<ReflectiveClassBuildItem> reflectiveClass, diff --git a/extensions/java-joor-dsl/runtime/src/main/doc/limitations.adoc b/extensions/java-joor-dsl/runtime/src/main/doc/limitations.adoc new file mode 100644 index 0000000000..a818c7f8a9 --- /dev/null +++ b/extensions/java-joor-dsl/runtime/src/main/doc/limitations.adoc @@ -0,0 +1,3 @@ +The annotations added to the classes to be compiled by the component are ignored by Quarkus. The only annotation that is +partially supported by the extension is the annotation `RegisterForReflection` to ease the configuration of the reflection +for the native mode however please note that the element `registerFullHierarchy` is not supported. \ No newline at end of file diff --git a/integration-tests/java-joor-dsl/src/main/resources/routes/MyRoutes.java b/integration-tests/java-joor-dsl/src/main/java/org/apache/camel/quarkus/dsl/java/joor/JavaJoorDslBean.java similarity index 70% copy from integration-tests/java-joor-dsl/src/main/resources/routes/MyRoutes.java copy to integration-tests/java-joor-dsl/src/main/java/org/apache/camel/quarkus/dsl/java/joor/JavaJoorDslBean.java index 590dfe1d97..cea1834ff0 100644 --- a/integration-tests/java-joor-dsl/src/main/resources/routes/MyRoutes.java +++ b/integration-tests/java-joor-dsl/src/main/java/org/apache/camel/quarkus/dsl/java/joor/JavaJoorDslBean.java @@ -14,11 +14,17 @@ * 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:joorHello") - .id("my-java-route") - .setBody(exchange -> "Hello " + exchange.getMessage().getBody() + " from jOOR!"); +package org.apache.camel.quarkus.dsl.java.joor; + +public class JavaJoorDslBean { + + public static String hi(String name) { + return String.format("Hi %s", name); } -} \ No newline at end of file + + public static class Inner { + public static String addSource(String value) { + return String.format("%s from jOOR!", value); + } + } +} diff --git a/integration-tests/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 index 1c5cd0bf0e..049f24a358 100644 --- a/integration-tests/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 @@ -76,8 +76,16 @@ public class JavaJoorDslResource { @Path("/hello") @Consumes(MediaType.TEXT_PLAIN) @Produces(MediaType.TEXT_PLAIN) - public String hello(String message) throws Exception { + public String hello(String message) { return producerTemplate.requestBody("direct:joorHello", message, String.class); } + @POST + @Path("/hi") + @Consumes(MediaType.TEXT_PLAIN) + @Produces(MediaType.TEXT_PLAIN) + public String hi(String name) { + return producerTemplate.requestBody("direct:joorHi", name, String.class); + } + } diff --git a/integration-tests/java-joor-dsl/src/main/resources/routes/MyRoutes.java b/integration-tests/java-joor-dsl/src/main/resources/routes/MyRoutes.java index 590dfe1d97..fdcfa82266 100644 --- a/integration-tests/java-joor-dsl/src/main/resources/routes/MyRoutes.java +++ b/integration-tests/java-joor-dsl/src/main/resources/routes/MyRoutes.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 { +import io.quarkus.runtime.annotations.RegisterForReflection; +import org.apache.camel.builder.RouteBuilder; + +@RegisterForReflection(classNames = "org.apache.camel.quarkus.dsl.java.joor.JavaJoorDslBean", ignoreNested = false) +public class MyRoutes extends RouteBuilder { @Override public void configure() throws Exception { from("direct:joorHello") .id("my-java-route") .setBody(exchange -> "Hello " + exchange.getMessage().getBody() + " from jOOR!"); + from("direct:joorHi") + .id("reflection-route") + .process(exchange -> { + Class<?> c = Thread.currentThread().getContextClassLoader().loadClass("org.apache.camel.quarkus.dsl.java.joor.JavaJoorDslBean"); + Object hi = c.getMethod("hi", String.class).invoke(null, exchange.getMessage().getBody()); + Class<?> c2 = Thread.currentThread().getContextClassLoader().loadClass("org.apache.camel.quarkus.dsl.java.joor.JavaJoorDslBean$Inner"); + exchange.getMessage().setBody(c2.getMethod("addSource", String.class).invoke(null, hi)); + }); } } \ No newline at end of file diff --git a/integration-tests/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 index 3fbf057b98..56862ea213 100644 --- a/integration-tests/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 @@ -35,6 +35,16 @@ class JavaJoorDslTest { .body(CoreMatchers.is("Hello Camelus bactrianus from jOOR!")); } + @Test + void joorHi() { + RestAssured.given() + .body("Will Smith") + .post("/java-joor-dsl/hi") + .then() + .statusCode(200) + .body(CoreMatchers.is("Hi Will Smith from jOOR!")); + } + @Test void testMainInstanceWithJavaRoutes() { RestAssured.given() @@ -53,6 +63,6 @@ class JavaJoorDslTest { .get("/java-joor-dsl/main/routes") .then() .statusCode(200) - .body(CoreMatchers.is("my-java-route")); + .body(CoreMatchers.is("my-java-route,reflection-route")); } }