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 <[email protected]> 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")
