You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ja...@apache.org on 2021/07/26 14:41:04 UTC

[camel-quarkus] 01/03: Add native support for transferException

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

jamesnetherton pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git

commit 97be7f960cef7a1abc8e8b8488b1e8eb8577fd8a
Author: James Netherton <ja...@gmail.com>
AuthorDate: Fri Jul 23 11:12:56 2021 +0100

    Add native support for transferException
    
    Fixes #1868
---
 .../modules/ROOT/pages/user-guide/native-mode.adoc | 22 ++-------
 .../deployment/CamelSerializationProcessor.java    | 56 ++++++++++++++--------
 .../quarkus/component/http/it/HttpResource.java    | 45 +++++++++++++++++
 .../camel/quarkus/component/http/it/HttpRoute.java |  5 ++
 .../http/src/main/resources/application.properties |  1 +
 .../camel/quarkus/component/http/it/HttpTest.java  | 18 ++++++-
 .../component/messaging/it/JmsResource.java        | 14 ++++++
 .../quarkus/component/messaging/it/JmsRoutes.java  |  5 ++
 .../quarkus/component/messaging/it/JmsTest.java    |  9 ++++
 9 files changed, 134 insertions(+), 41 deletions(-)

diff --git a/docs/modules/ROOT/pages/user-guide/native-mode.adoc b/docs/modules/ROOT/pages/user-guide/native-mode.adoc
index a995011..009b976 100644
--- a/docs/modules/ROOT/pages/user-guide/native-mode.adoc
+++ b/docs/modules/ROOT/pages/user-guide/native-mode.adoc
@@ -113,24 +113,8 @@ quarkus.index-dependency.commons-lang3.artifact-id = commons-lang3
 ----
 
 [[serialization]]
-== Registration for serialization
-
-If serialization support is requested via `quarkus.camel.native.reflection.serialization-enabled`, the following classes are registered for serialization:
-
-* `java.lang.Boolean`
-* `java.lang.Byte`
-* `java.lang.Character`
-* `java.lang.Float`
-* `java.lang.Double`
-* `java.lang.Integer`
-* `java.lang.Long`
-* `java.lang.Number`
-* `java.lang.String`
-* `java.math.BigInteger`
-* `java.util.Date`
-* `java.util.HashMap`
-* `java.util.LinkedHashMap`
-* `org.apache.camel.support.DefaultExchangeHolder`
+== Registering classes for serialization
 
-Users can register more classes using `@RegisterForReflection(serialization = true)`.
+If serialization support is requested via `quarkus.camel.native.reflection.serialization-enabled`, the classes listed in https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/CamelSerializationProcessor.java[CamelSerializationProcessor.BASE_SERIALIZATION_CLASSES] are automatically registered for serialization.
 
+Users can register more classes using `@RegisterForReflection(serialization = true)`.
diff --git a/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/CamelSerializationProcessor.java b/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/CamelSerializationProcessor.java
index d183db3..26fcfd3 100644
--- a/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/CamelSerializationProcessor.java
+++ b/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/CamelSerializationProcessor.java
@@ -17,16 +17,20 @@
 package org.apache.camel.quarkus.core.deployment;
 
 import java.math.BigInteger;
+import java.util.AbstractCollection;
+import java.util.AbstractList;
 import java.util.AbstractMap;
+import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
-import java.util.stream.Stream;
 
 import io.quarkus.deployment.annotations.BuildProducer;
 import io.quarkus.deployment.annotations.BuildStep;
 import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
+import org.apache.camel.CamelExecutionException;
+import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.quarkus.core.CamelConfig;
 import org.apache.camel.quarkus.core.deployment.spi.CamelSerializationBuildItem;
 import org.apache.camel.support.DefaultExchangeHolder;
@@ -35,6 +39,36 @@ import org.slf4j.LoggerFactory;
 
 public class CamelSerializationProcessor {
     private static final Logger LOGGER = LoggerFactory.getLogger(CamelSerializationProcessor.class);
+    private static final String[] BASE_SERIALIZATION_CLASSES = {
+            // JDK classes
+            AbstractCollection.class.getName(),
+            AbstractList.class.getName(),
+            AbstractMap.class.getName(),
+            BigInteger.class.getName(),
+            Boolean.class.getName(),
+            Byte.class.getName(),
+            Character.class.getName(),
+            Collections.EMPTY_LIST.getClass().getName(),
+            Date.class.getName(),
+            Double.class.getName(),
+            Exception.class.getName(),
+            Float.class.getName(),
+            HashMap.class.getName(),
+            Integer.class.getName(),
+            LinkedHashMap.class.getName(),
+            Long.class.getName(),
+            Number.class.getName(),
+            RuntimeException.class.getName(),
+            StackTraceElement.class.getName(),
+            StackTraceElement[].class.getName(),
+            String.class.getName(),
+            Throwable.class.getName(),
+
+            // Camel classes
+            CamelExecutionException.class.getName(),
+            DefaultExchangeHolder.class.getName(),
+            RuntimeCamelException.class.getName(),
+    };
 
     @BuildStep
     void produceSerializationBuildItem(CamelConfig config, BuildProducer<CamelSerializationBuildItem> serializationBuildItems) {
@@ -51,27 +85,9 @@ public class CamelSerializationProcessor {
             BuildProducer<ReflectiveClassBuildItem> reflectiveClasses) {
 
         if (!serializationRequests.isEmpty()) {
-            String[] classes = Stream.of(Boolean.class,
-                    Byte.class,
-                    Character.class,
-                    Double.class,
-                    Float.class,
-                    Integer.class,
-                    Long.class,
-                    Number.class,
-                    Date.class,
-                    String.class,
-                    AbstractMap.class,
-                    HashMap.class,
-                    LinkedHashMap.class,
-                    BigInteger.class,
-                    DefaultExchangeHolder.class)
-                    .map(c -> c.getName()).toArray(String[]::new);
-
             //required for serialization of BigInteger
             reflectiveClasses.produce(new ReflectiveClassBuildItem(false, false, byte[].class));
-
-            reflectiveClasses.produce(ReflectiveClassBuildItem.serializationClass(classes));
+            reflectiveClasses.produce(ReflectiveClassBuildItem.serializationClass(BASE_SERIALIZATION_CLASSES));
         }
     }
 }
diff --git a/integration-tests/http/src/main/java/org/apache/camel/quarkus/component/http/it/HttpResource.java b/integration-tests/http/src/main/java/org/apache/camel/quarkus/component/http/it/HttpResource.java
index 4c0e9ef..79b0a4e 100644
--- a/integration-tests/http/src/main/java/org/apache/camel/quarkus/component/http/it/HttpResource.java
+++ b/integration-tests/http/src/main/java/org/apache/camel/quarkus/component/http/it/HttpResource.java
@@ -144,6 +144,18 @@ public class HttpResource {
                 .request(String.class);
     }
 
+    @Path("/ahc/serialized/exception")
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    public String ahcSerializedException(@QueryParam("test-port") int port) {
+        Exchange exchange = producerTemplate
+                .toF("ahc:http://localhost:%d/test/server/serialized/exception?bridgeEndpoint=true&transferException=true",
+                        port)
+                .withHeader(Exchange.HTTP_METHOD, "GET")
+                .send();
+        return exchange.getException().getClass().getName();
+    }
+
     // *****************************
     //
     // camel-ahc-ws
@@ -261,6 +273,17 @@ public class HttpResource {
                 .request(String.class);
     }
 
+    @Path("/http/serialized/exception")
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    public String httpSerializedException(@QueryParam("test-port") int port) {
+        Exchange exchange = producerTemplate
+                .toF("http://localhost:%d/test/server/serialized/exception?bridgeEndpoint=true&transferException=true", port)
+                .withHeader(Exchange.HTTP_METHOD, "GET")
+                .send();
+        return exchange.getException().getClass().getName();
+    }
+
     // *****************************
     //
     // camel-netty-http
@@ -346,6 +369,17 @@ public class HttpResource {
         }
     }
 
+    @Path("/netty-http/serialized/exception")
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    public String nettyHttpSerializedException(@QueryParam("test-port") int port) {
+        Exchange exchange = producerTemplate
+                .toF("netty-http:http://localhost:%d/test/server/serialized/exception?transferException=true", port)
+                .withHeader(Exchange.HTTP_METHOD, "GET")
+                .send();
+        return exchange.getException().getClass().getName();
+    }
+
     // *****************************
     //
     // camel-vertx-http
@@ -432,6 +466,17 @@ public class HttpResource {
                 .request(String.class);
     }
 
+    @Path("/vertx-http/serialized/exception")
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    public String vertxHttpSerializedException(@QueryParam("test-port") int port) {
+        Exchange exchange = producerTemplate
+                .toF("vertx-http:http://localhost:%d/test/server/serialized/exception?transferException=true", port)
+                .withHeader(Exchange.HTTP_METHOD, "GET")
+                .send();
+        return exchange.getException().getClass().getName();
+    }
+
     // *****************************
     //
     // Send dynamic tests
diff --git a/integration-tests/http/src/main/java/org/apache/camel/quarkus/component/http/it/HttpRoute.java b/integration-tests/http/src/main/java/org/apache/camel/quarkus/component/http/it/HttpRoute.java
index a1a9a05..ed7c891 100644
--- a/integration-tests/http/src/main/java/org/apache/camel/quarkus/component/http/it/HttpRoute.java
+++ b/integration-tests/http/src/main/java/org/apache/camel/quarkus/component/http/it/HttpRoute.java
@@ -22,6 +22,7 @@ import java.io.InputStream;
 
 import javax.inject.Named;
 
+import io.quarkus.runtime.annotations.RegisterForReflection;
 import org.apache.camel.Exchange;
 import org.apache.camel.Processor;
 import org.apache.camel.builder.RouteBuilder;
@@ -30,12 +31,16 @@ import org.apache.camel.support.jsse.KeyStoreParameters;
 import org.apache.camel.support.jsse.SSLContextParameters;
 import org.apache.camel.support.jsse.TrustManagersParameters;
 
+@RegisterForReflection(targets = IllegalStateException.class, serialization = true)
 public class HttpRoute extends RouteBuilder {
     @Override
     public void configure() {
         from("netty-http:http://0.0.0.0:{{camel.netty-http.test-port}}/test/server/hello")
                 .transform().constant("Netty Hello World");
 
+        from("netty-http:http://0.0.0.0:{{camel.netty-http.test-port}}/test/server/serialized/exception?transferException=true")
+                .throwException(new IllegalStateException("Forced exception"));
+
         from("netty-http:http://0.0.0.0:{{camel.netty-http.compression-test-port}}/compressed?compression=true")
                 .transform().constant("Netty Hello World Compressed");
 
diff --git a/integration-tests/http/src/main/resources/application.properties b/integration-tests/http/src/main/resources/application.properties
index 610075a..ba7b64f 100644
--- a/integration-tests/http/src/main/resources/application.properties
+++ b/integration-tests/http/src/main/resources/application.properties
@@ -19,6 +19,7 @@
 # Quarkus
 #
 quarkus.native.resources.includes = jsse/*,restcountries/*
+quarkus.camel.native.reflection.serialization-enabled = true
 
 # Basic authentication configuration
 quarkus.security.users.embedded.enabled=true
diff --git a/integration-tests/http/src/test/java/org/apache/camel/quarkus/component/http/it/HttpTest.java b/integration-tests/http/src/test/java/org/apache/camel/quarkus/component/http/it/HttpTest.java
index 79b3f59..52007c1 100644
--- a/integration-tests/http/src/test/java/org/apache/camel/quarkus/component/http/it/HttpTest.java
+++ b/integration-tests/http/src/test/java/org/apache/camel/quarkus/component/http/it/HttpTest.java
@@ -133,7 +133,7 @@ class HttpTest {
 
     @ParameterizedTest
     @MethodSource("getHttpComponentNames")
-    public void compression(String component) throws Exception {
+    public void compression(String component) {
         final int port = ConfigProvider.getConfig().getValue("camel.netty-http.compression-test-port", Integer.class);
         RestAssured
                 .given()
@@ -145,8 +145,22 @@ class HttpTest {
                 .body(is("Netty Hello World Compressed"));
     }
 
+    @ParameterizedTest
+    @MethodSource("getHttpComponentNames")
+    public void transferException(String component) {
+        final int port = ConfigProvider.getConfig().getValue("camel.netty-http.test-port", Integer.class);
+        RestAssured
+                .given()
+                .queryParam("test-port", port)
+                .when()
+                .get("/test/client/{component}/serialized/exception", component)
+                .then()
+                .statusCode(200)
+                .body(is("java.lang.IllegalStateException"));
+    }
+
     @Test
-    public void basicNettyHttpServer() throws Exception {
+    public void basicNettyHttpServer() {
         final int port = ConfigProvider.getConfig().getValue("camel.netty-http.test-port", Integer.class);
         RestAssured
                 .given()
diff --git a/integration-tests/messaging/src/main/java/org/apache/camel/quarkus/component/messaging/it/JmsResource.java b/integration-tests/messaging/src/main/java/org/apache/camel/quarkus/component/messaging/it/JmsResource.java
index 55415ed..164c3ac 100644
--- a/integration-tests/messaging/src/main/java/org/apache/camel/quarkus/component/messaging/it/JmsResource.java
+++ b/integration-tests/messaging/src/main/java/org/apache/camel/quarkus/component/messaging/it/JmsResource.java
@@ -47,6 +47,7 @@ import org.apache.camel.ConsumerTemplate;
 import org.apache.camel.Exchange;
 import org.apache.camel.Message;
 import org.apache.camel.ProducerTemplate;
+import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.component.jms.JmsMessage;
 import org.apache.camel.component.mock.MockEndpoint;
 
@@ -269,6 +270,19 @@ public class JmsResource {
         return Response.ok().entity(result).build();
     }
 
+    @Path("/jms/transfer/exception")
+    @Produces(MediaType.TEXT_PLAIN)
+    @GET
+    public Response testTransferException() throws InterruptedException {
+        try {
+            producerTemplate.requestBody("jms:queue:transferException?transferException=true", "bad payload");
+        } catch (RuntimeCamelException e) {
+            Class<? extends Throwable> exception = e.getCause().getClass();
+            return Response.ok().entity(exception.getName()).build();
+        }
+        return Response.serverError().build();
+    }
+
     @Path("/jms/topic")
     @Consumes(MediaType.TEXT_PLAIN)
     @POST
diff --git a/integration-tests/messaging/src/main/java/org/apache/camel/quarkus/component/messaging/it/JmsRoutes.java b/integration-tests/messaging/src/main/java/org/apache/camel/quarkus/component/messaging/it/JmsRoutes.java
index 86c153b..a1f0a2c 100644
--- a/integration-tests/messaging/src/main/java/org/apache/camel/quarkus/component/messaging/it/JmsRoutes.java
+++ b/integration-tests/messaging/src/main/java/org/apache/camel/quarkus/component/messaging/it/JmsRoutes.java
@@ -16,6 +16,7 @@
  */
 package org.apache.camel.quarkus.component.messaging.it;
 
+import io.quarkus.runtime.annotations.RegisterForReflection;
 import org.apache.camel.Exchange;
 import org.apache.camel.Processor;
 import org.apache.camel.builder.ErrorHandlerBuilder;
@@ -23,6 +24,7 @@ import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.jta.JtaTransactionErrorHandlerBuilder;
 import org.apache.camel.processor.errorhandler.RedeliveryPolicy;
 
+@RegisterForReflection(targets = IllegalStateException.class, serialization = true)
 public class JmsRoutes extends RouteBuilder {
 
     @Override
@@ -61,6 +63,9 @@ public class JmsRoutes extends RouteBuilder {
         from("jms:queue:transferExchange?transferExchange=true")
                 .to("mock:transferExchangeResult");
 
+        from("jms:queue:transferException?transferException=true")
+                .throwException(new IllegalStateException("Forced exception"));
+
         from("jms:queue:objectTest")
                 .to("mock:objectTestResult");
 
diff --git a/integration-tests/messaging/src/test/java/org/apache/camel/quarkus/component/messaging/it/JmsTest.java b/integration-tests/messaging/src/test/java/org/apache/camel/quarkus/component/messaging/it/JmsTest.java
index cd68ddd..d9737d3 100644
--- a/integration-tests/messaging/src/test/java/org/apache/camel/quarkus/component/messaging/it/JmsTest.java
+++ b/integration-tests/messaging/src/test/java/org/apache/camel/quarkus/component/messaging/it/JmsTest.java
@@ -173,6 +173,15 @@ class JmsTest {
     }
 
     @Test
+    public void testJmsTransferException() {
+        RestAssured.given()
+                .get("/messaging/jms/transfer/exception")
+                .then()
+                .statusCode(200)
+                .body(is("java.lang.IllegalStateException"));
+    }
+
+    @Test
     public void testJmsTransaction() {
         RestAssured.given()
                 .get("/messaging/jms/transaction")