This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch fix/CAMEL-24978 in repository https://gitbox.apache.org/repos/asf/camel.git
commit f523e8b30dcb4ff214c26a214e8c3ff549ef0295 Author: Claus Ibsen <[email protected]> AuthorDate: Wed Sep 23 22:17:30 2026 +0200 CAMEL-24978: camel-rest-openapi, camel-rest-postman - Invoke the operation once after the route is restarted The consumer is created again when a route is restarted, which added another processor advice to the route, so every request was invoked once per restart. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> Signed-off-by: Claus Ibsen <[email protected]> --- .../vertx/PlatformHttpRestOpenApiConsumerTest.java | 40 ++++++++++++++++++++++ .../vertx/PlatformHttpRestPostmanConsumerTest.java | 40 ++++++++++++++++++++++ .../rest/openapi/RestOpenApiEndpoint.java | 5 +++ .../rest/postman/RestPostmanEndpoint.java | 5 +++ 4 files changed, 90 insertions(+) diff --git a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java index fb7cca2564d5..14e03ca2f7f8 100644 --- a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java +++ b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java @@ -16,6 +16,8 @@ */ package org.apache.camel.component.platform.http.vertx; +import java.util.concurrent.atomic.AtomicInteger; + import org.apache.camel.CamelContext; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; @@ -24,6 +26,7 @@ import org.junit.jupiter.api.Test; import static io.restassured.RestAssured.given; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalToCompressingWhiteSpace; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; public class PlatformHttpRestOpenApiConsumerTest { @@ -270,4 +273,41 @@ public class PlatformHttpRestOpenApiConsumerTest { } } + @Test + public void testRestOpenApiRouteRestart() throws Exception { + final CamelContext context = VertxPlatformHttpEngineTest.createCamelContext(); + final AtomicInteger counter = new AtomicInteger(); + + try { + context.addRoutes(new RouteBuilder() { + @Override + public void configure() { + from("rest-openapi:classpath:openapi-v3.json?missingOperation=ignore").routeId("api") + .to("mock:result"); + + from("direct:getPetById") + .process(e -> counter.incrementAndGet()) + .setBody().constant("{\"pet\": \"tony the tiger\"}"); + } + }); + + VertxPlatformHttpEngineTest.startCamelContext(context); + + // restart the route, which creates the consumer again + context.getRouteController().stopRoute("api"); + context.getRouteController().startRoute("api"); + + given() + .when() + .get("/api/v3/pet/123") + .then() + .statusCode(200) + .body(equalTo("{\"pet\": \"tony the tiger\"}")); + + // the operation must only be invoked once + assertEquals(1, counter.get()); + } finally { + context.stop(); + } + } } diff --git a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestPostmanConsumerTest.java b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestPostmanConsumerTest.java index ae2f889441b5..c3d004f03861 100644 --- a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestPostmanConsumerTest.java +++ b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestPostmanConsumerTest.java @@ -16,6 +16,8 @@ */ package org.apache.camel.component.platform.http.vertx; +import java.util.concurrent.atomic.AtomicInteger; + import org.apache.camel.CamelContext; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; @@ -258,4 +260,42 @@ class PlatformHttpRestPostmanConsumerTest { context.stop(); } } + + @Test + void shouldInvokeRequestOnceAfterRouteRestart() throws Exception { + final CamelContext context = VertxPlatformHttpEngineTest.createCamelContext(); + final AtomicInteger counter = new AtomicInteger(); + + try { + context.addRoutes(new RouteBuilder() { + @Override + public void configure() { + from("rest-postman:classpath:postman-petstore.json?missingRequest=ignore").routeId("api") + .to("mock:result"); + + from("direct:getPetById") + .process(e -> counter.incrementAndGet()) + .setBody().constant("{\"pet\": \"tony the tiger\"}"); + } + }); + + VertxPlatformHttpEngineTest.startCamelContext(context); + + // restart the route, which creates the consumer again + context.getRouteController().stopRoute("api"); + context.getRouteController().startRoute("api"); + + given() + .when() + .get("/api/v3/pet/123") + .then() + .statusCode(200) + .body(equalTo("{\"pet\": \"tony the tiger\"}")); + + // the operation must only be invoked once + assertThat(counter.get()).isEqualTo(1); + } finally { + context.stop(); + } + } } diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java index 0abb19e54be0..19fedc8c7ca0 100644 --- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java +++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java @@ -240,6 +240,11 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint { if (advice != null) { ip.removeAdvice(advice); } + // remove the advice from a previous start of the route, as the consumer is created again when restarted + RestOpenApiProcessorAdvice existing = ip.getAdvice(RestOpenApiProcessorAdvice.class); + if (existing != null) { + ip.removeAdvice(existing); + } ip.addAdvice(new RestOpenApiProcessorAdvice(openApiProcessor)); } diff --git a/components/camel-rest-postman/src/main/java/org/apache/camel/component/rest/postman/RestPostmanEndpoint.java b/components/camel-rest-postman/src/main/java/org/apache/camel/component/rest/postman/RestPostmanEndpoint.java index f7e0da531bb4..0f54879cbab6 100644 --- a/components/camel-rest-postman/src/main/java/org/apache/camel/component/rest/postman/RestPostmanEndpoint.java +++ b/components/camel-rest-postman/src/main/java/org/apache/camel/component/rest/postman/RestPostmanEndpoint.java @@ -209,6 +209,11 @@ public class RestPostmanEndpoint extends DefaultEndpoint { if (advice != null) { ip.removeAdvice(advice); } + // remove the advice from a previous start of the route, as the consumer is created again when restarted + RestPostmanProcessorAdvice existing = ip.getAdvice(RestPostmanProcessorAdvice.class); + if (existing != null) { + ip.removeAdvice(existing); + } ip.addAdvice(new RestPostmanProcessorAdvice(restPostmanProcessor)); }
