You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2023/10/17 12:38:52 UTC

[camel] branch vx-msg created (now e05ee8ee013)

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

davsclaus pushed a change to branch vx-msg
in repository https://gitbox.apache.org/repos/asf/camel.git


      at e05ee8ee013 CAMEL-19994: camel-platform-http-vertx - Allow access to vertx request object. Add support for pooled exchange like we have in other http components.

This branch includes the following new commits:

     new e05ee8ee013 CAMEL-19994: camel-platform-http-vertx - Allow access to vertx request object. Add support for pooled exchange like we have in other http components.

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] 01/01: CAMEL-19994: camel-platform-http-vertx - Allow access to vertx request object. Add support for pooled exchange like we have in other http components.

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

davsclaus pushed a commit to branch vx-msg
in repository https://gitbox.apache.org/repos/asf/camel.git

commit e05ee8ee0130a9eb608e1dcfa10e08d71ef165ae
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Oct 17 14:38:32 2023 +0200

    CAMEL-19994: camel-platform-http-vertx - Allow access to vertx request object. Add support for pooled exchange like we have in other http components.
---
 components/camel-platform-http-vertx/pom.xml       |   6 +
 .../src/main/docs/platform-http-vertx.adoc         |  20 ++++
 .../component/platform/http/vertx/HttpMessage.java |  66 +++++++++++
 .../http/vertx/VertxPlatformHttpConsumer.java      |  16 ++-
 .../http/vertx/VertxPlatformHttpEngineTest.java    |  30 +++++
 .../vertx/VertxPlatformHttpPooledExchangeTest.java | 126 +++++++++++++++++++++
 6 files changed, 259 insertions(+), 5 deletions(-)

diff --git a/components/camel-platform-http-vertx/pom.xml b/components/camel-platform-http-vertx/pom.xml
index ec47987865f..200bdc6cd3c 100644
--- a/components/camel-platform-http-vertx/pom.xml
+++ b/components/camel-platform-http-vertx/pom.xml
@@ -108,6 +108,12 @@
             <version>${wiremock-version}</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.awaitility</groupId>
+            <artifactId>awaitility</artifactId>
+            <version>${awaitility-version}</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
 </project>
diff --git a/components/camel-platform-http-vertx/src/main/docs/platform-http-vertx.adoc b/components/camel-platform-http-vertx/src/main/docs/platform-http-vertx.adoc
index e4f7ac16dfb..118225964ff 100644
--- a/components/camel-platform-http-vertx/src/main/docs/platform-http-vertx.adoc
+++ b/components/camel-platform-http-vertx/src/main/docs/platform-http-vertx.adoc
@@ -76,3 +76,23 @@ from("platform-http:proxy")
     .toD("http://"
         + "${headers." + Exchange.HTTP_HOST + "}");
 ----
+
+== Access to Request and Response
+
+The Vertx HTTP server has its own API abstraction for HTTP request/response objects which you can access via
+Camel `HttpMessage` as shown in the custom `Processor` below :
+
+[source,java]
+----
+.process(exchange -> {
+    // grab message as HttpMessage
+    HttpMessage message = exchange.getMessage(HttpMessage.class);
+    // use getRequest() / getResponse() to access Vertx directly
+    // you can add custom headers
+    message.getResponse().putHeader("beer", "Heineken");
+    // also access request details and use that in the code
+    String p = message.getRequest().path();
+    message.setBody("request path: " + p);
+});
+----
+
diff --git a/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/HttpMessage.java b/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/HttpMessage.java
new file mode 100644
index 00000000000..cece097b89c
--- /dev/null
+++ b/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/HttpMessage.java
@@ -0,0 +1,66 @@
+/*
+ * 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.component.platform.http.vertx;
+
+import io.vertx.core.http.HttpServerRequest;
+import io.vertx.core.http.HttpServerResponse;
+import org.apache.camel.Exchange;
+import org.apache.camel.support.DefaultMessage;
+import org.apache.camel.util.ObjectHelper;
+
+public class HttpMessage extends DefaultMessage {
+
+    private HttpServerRequest request;
+    private HttpServerResponse response;
+
+    public HttpMessage(Exchange exchange, HttpServerRequest request, HttpServerResponse response) {
+        super(exchange);
+        init(exchange, request, response);
+    }
+
+    public void init(Exchange exchange, HttpServerRequest request, HttpServerResponse response) {
+        setExchange(exchange);
+        this.request = request;
+        this.response = response;
+    }
+
+    @Override
+    public void reset() {
+        super.reset();
+        request = null;
+        response = null;
+    }
+
+    public HttpServerRequest getRequest() {
+        return request;
+    }
+
+    public HttpServerResponse getResponse() {
+        return response;
+    }
+
+    @Override
+    public HttpMessage newInstance() {
+        return new HttpMessage(getExchange(), request, response);
+    }
+
+    @Override
+    public String toString() {
+        // do not use toString on HTTP message
+        return "HttpMessage@" + ObjectHelper.getIdentityHashCode(this);
+    }
+}
diff --git a/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpConsumer.java b/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpConsumer.java
index 4ab809ec411..4b96d86c504 100644
--- a/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpConsumer.java
+++ b/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpConsumer.java
@@ -230,7 +230,16 @@ public class VertxPlatformHttpConsumer extends DefaultConsumer implements Suspen
         final Exchange exchange = createExchange(false);
         exchange.setPattern(ExchangePattern.InOut);
 
-        final Message in = toCamelMessage(ctx, exchange);
+        // reuse existing http message if pooled
+        Message in = exchange.getIn();
+        if (in instanceof HttpMessage hm) {
+            hm.init(exchange, ctx.request(), ctx.response());
+        } else {
+            in = new HttpMessage(exchange, ctx.request(), ctx.response());
+            exchange.setMessage(in);
+        }
+        populateCamelMessage(ctx, exchange, in);
+
         final String charset = ctx.parsedHeaders().contentType().parameter("charset");
         if (charset != null) {
             exchange.setProperty(ExchangePropertyKey.CHARSET_NAME, charset);
@@ -245,9 +254,7 @@ public class VertxPlatformHttpConsumer extends DefaultConsumer implements Suspen
         return exchange;
     }
 
-    protected Message toCamelMessage(RoutingContext ctx, Exchange exchange) {
-        final Message result = exchange.getIn();
-
+    protected void populateCamelMessage(RoutingContext ctx, Exchange exchange, Message result) {
         final HeaderFilterStrategy headerFilterStrategy = getEndpoint().getHeaderFilterStrategy();
         populateCamelHeaders(ctx, result.getHeaders(), exchange, headerFilterStrategy);
         final String mimeType = ctx.parsedHeaders().contentType().value();
@@ -281,7 +288,6 @@ public class VertxPlatformHttpConsumer extends DefaultConsumer implements Suspen
                 result.setBody(null);
             }
         }
-        return result;
     }
 
     protected void populateAttachments(List<FileUpload> uploads, Message message) {
diff --git a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpEngineTest.java b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpEngineTest.java
index 683b2327e1d..633826ad959 100644
--- a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpEngineTest.java
+++ b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpEngineTest.java
@@ -846,6 +846,36 @@ public class VertxPlatformHttpEngineTest {
         }
     }
 
+    @Test
+    public void testVertxRequestResponseObjects() throws Exception {
+        final CamelContext context = createCamelContext();
+
+        try {
+            context.addRoutes(new RouteBuilder() {
+                @Override
+                public void configure() {
+                    from("platform-http:/vertx/objects")
+                            .process(exchange -> {
+                                HttpMessage message = exchange.getMessage(HttpMessage.class);
+                                String p = message.getRequest().path();
+                                message.getResponse().putHeader("beer", "Heineken");
+                                message.setBody("request path: " + p);
+                            });
+                }
+            });
+
+            context.start();
+
+            get("/vertx/objects")
+                    .then()
+                    .statusCode(200)
+                    .header("beer", "Heineken")
+                    .body(is("request path: /vertx/objects"));
+        } finally {
+            context.stop();
+        }
+    }
+
     static CamelContext createCamelContext() throws Exception {
         return createCamelContext(null);
     }
diff --git a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpPooledExchangeTest.java b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpPooledExchangeTest.java
new file mode 100644
index 00000000000..05083e3a2f3
--- /dev/null
+++ b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpPooledExchangeTest.java
@@ -0,0 +1,126 @@
+/*
+ * 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.component.platform.http.vertx;
+
+import java.util.concurrent.TimeUnit;
+
+import io.restassured.RestAssured;
+import org.apache.camel.CamelContext;
+import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.component.platform.http.PlatformHttpComponent;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.impl.engine.PooledExchangeFactory;
+import org.apache.camel.impl.engine.PooledProcessorExchangeFactory;
+import org.apache.camel.spi.PooledObjectFactory;
+import org.apache.camel.test.AvailablePortFinder;
+import org.awaitility.Awaitility;
+import org.junit.jupiter.api.Test;
+
+import static io.restassured.RestAssured.get;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class VertxPlatformHttpPooledExchangeTest {
+
+    @Test
+    public void testEngineSetup() throws Exception {
+        final CamelContext context = createCamelContext();
+        try {
+            context.start();
+
+            assertThat(VertxPlatformHttpRouter.lookup(context)).isNotNull();
+            assertThat(context.getComponent("platform-http")).isInstanceOfSatisfying(PlatformHttpComponent.class, component -> {
+                assertThat(component.getEngine()).isInstanceOf(VertxPlatformHttpEngine.class);
+            });
+
+        } finally {
+            context.stop();
+        }
+    }
+
+    @Test
+    public void testPooledExchange() throws Exception {
+        final CamelContext context = createCamelContext();
+
+        try {
+            context.addRoutes(new RouteBuilder() {
+                @Override
+                public void configure() {
+                    from("platform-http:/vertx/pooled")
+                            .transform().simple("Bye World");
+                }
+            });
+
+            context.start();
+
+            for (int i = 0; i < 3; i++) {
+                get("/vertx/pooled")
+                        .then()
+                        .statusCode(200)
+                        .body(is("Bye World"));
+            }
+
+            MockEndpoint.assertIsSatisfied(context);
+
+            Awaitility.waitAtMost(5, TimeUnit.SECONDS).untilAsserted(() -> {
+                PooledObjectFactory.Statistics stat
+                        = context.getCamelContextExtension().getExchangeFactoryManager().getStatistics();
+                assertEquals(1, stat.getCreatedCounter());
+                assertEquals(2, stat.getAcquiredCounter());
+                assertEquals(3, stat.getReleasedCounter());
+                assertEquals(0, stat.getDiscardedCounter());
+            });
+        } finally {
+            context.stop();
+        }
+    }
+
+    static CamelContext createCamelContext() throws Exception {
+        return createCamelContext(null);
+    }
+
+    private static CamelContext createCamelContext(ServerConfigurationCustomizer customizer) throws Exception {
+        int port = AvailablePortFinder.getNextAvailable();
+        VertxPlatformHttpServerConfiguration conf = new VertxPlatformHttpServerConfiguration();
+        conf.setBindPort(port);
+
+        RestAssured.port = port;
+
+        if (customizer != null) {
+            customizer.customize(conf);
+        }
+
+        CamelContext context = new DefaultCamelContext();
+        context.addService(new VertxPlatformHttpServer(conf));
+
+        ExtendedCamelContext ecc = context.getCamelContextExtension();
+
+        ecc.setExchangeFactory(new PooledExchangeFactory());
+        ecc.setProcessorExchangeFactory(new PooledProcessorExchangeFactory());
+        ecc.getExchangeFactory().setStatisticsEnabled(true);
+        ecc.getProcessorExchangeFactory().setStatisticsEnabled(true);
+
+        return context;
+    }
+
+    interface ServerConfigurationCustomizer {
+        void customize(VertxPlatformHttpServerConfiguration configuration);
+    }
+}