This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new bd63a7eb8213 CAMEL-22742: camel-core - Rest DSL contract first should
have jmx statistics (#20101)
bd63a7eb8213 is described below
commit bd63a7eb8213997a4da3a93328e8885e5b3f623f
Author: Claus Ibsen <[email protected]>
AuthorDate: Mon Dec 1 10:58:30 2025 +0100
CAMEL-22742: camel-core - Rest DSL contract first should have jmx
statistics (#20101)
* CAMEL-22742: camel-core - Rest DSL contract first should have jmx
statistics
---
components/camel-platform-http-vertx/pom.xml | 5 ++
...RestOpenApiConsumerRestDslRouteMetricsTest.java | 100 +++++++++++++++++++++
...PlatformHttpRestOpenApiConsumerRestDslTest.java | 5 +-
.../vertx/PlatformHttpRestOpenApiConsumerTest.java | 15 +++-
.../platform/http/DefaultPlatformHttpConsumer.java | 16 +++-
.../http/spi/PlatformHttpConsumerAware.java | 9 ++
.../rest/openapi/RestOpenApiComponent.java | 7 +-
.../rest/openapi/RestOpenApiEndpoint.java | 73 +++++++++++++--
.../rest/openapi/RestOpenApiProcessor.java | 63 ++++++-------
.../org/apache/camel/spi/InternalProcessor.java | 7 ++
.../camel/impl/engine/CamelInternalProcessor.java | 7 ++
.../apache/camel/model/rest/RestDefinition.java | 3 +-
12 files changed, 263 insertions(+), 47 deletions(-)
diff --git a/components/camel-platform-http-vertx/pom.xml
b/components/camel-platform-http-vertx/pom.xml
index da2d92f45a2c..bd724651ccaa 100644
--- a/components/camel-platform-http-vertx/pom.xml
+++ b/components/camel-platform-http-vertx/pom.xml
@@ -69,6 +69,11 @@
<artifactId>camel-test-junit5</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-management</artifactId>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-http</artifactId>
diff --git
a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerRestDslRouteMetricsTest.java
b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerRestDslRouteMetricsTest.java
new file mode 100644
index 000000000000..a9d9aa34a750
--- /dev/null
+++
b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerRestDslRouteMetricsTest.java
@@ -0,0 +1,100 @@
+/*
+ * 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 org.apache.camel.CamelContext;
+import org.apache.camel.api.management.ManagedCamelContext;
+import org.apache.camel.api.management.mbean.ManagedRouteMBean;
+import org.apache.camel.builder.RouteBuilder;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import static io.restassured.RestAssured.given;
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class PlatformHttpRestOpenApiConsumerRestDslRouteMetricsTest {
+
+ @Test
+ public void testRouteMetrics() throws Exception {
+ final CamelContext context =
VertxPlatformHttpEngineTest.createCamelContext();
+
+ try {
+ context.addRoutes(new RouteBuilder() {
+ @Override
+ public void configure() {
+
rest().openApi().specification("openapi-v3.json").missingOperation("ignore").routeId("myRest");
+
+ from("direct:getPetById").routeId("getPetById")
+ .process(e -> {
+ assertEquals("123",
e.getMessage().getHeader("petId"));
+ })
+ .setBody().constant("{\"pet\": \"tony the
tiger\"}");
+
+ from("direct:findPetsByStatus").routeId("findPetsByStatus")
+ .process(e -> {
+ assertEquals("sold",
e.getMessage().getHeader("status"));
+ })
+ .setBody().constant("{\"pet\": \"jack the
lion\"}");
+ }
+ });
+
+ context.start();
+
+ ManagedRouteMBean mr
+ =
context.getCamelContextExtension().getContextPlugin(ManagedCamelContext.class).getManagedRoute("myRest");
+ assertNotNull(mr);
+ ManagedRouteMBean mr2 =
context.getCamelContextExtension().getContextPlugin(ManagedCamelContext.class)
+ .getManagedRoute("getPetById");
+ assertNotNull(mr2);
+ ManagedRouteMBean mr3 =
context.getCamelContextExtension().getContextPlugin(ManagedCamelContext.class)
+ .getManagedRoute("findPetsByStatus");
+ assertNotNull(mr3);
+
+ Assertions.assertEquals(0, mr.getExchangesTotal());
+ Assertions.assertEquals(0, mr2.getExchangesTotal());
+ Assertions.assertEquals(0, mr3.getExchangesTotal());
+
+ given()
+ .when()
+ .get("/api/v3/pet/123")
+ .then()
+ .statusCode(200)
+ .body(equalTo("{\"pet\": \"tony the tiger\"}"));
+
+ Assertions.assertEquals(1, mr.getExchangesTotal());
+ Assertions.assertEquals(1, mr2.getExchangesTotal());
+ Assertions.assertEquals(0, mr3.getExchangesTotal());
+
+ given()
+ .when()
+ .get("/api/v3/pet/findByStatus?status=sold")
+ .then()
+ .statusCode(200)
+ .body(equalTo("{\"pet\": \"jack the lion\"}"));
+
+ Assertions.assertEquals(2, mr.getExchangesTotal());
+ Assertions.assertEquals(1, mr2.getExchangesTotal());
+ Assertions.assertEquals(1, mr3.getExchangesTotal());
+
+ } finally {
+ context.stop();
+ }
+ }
+
+}
diff --git
a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerRestDslTest.java
b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerRestDslTest.java
index b81eaff10d43..c02c22a3b53b 100644
---
a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerRestDslTest.java
+++
b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerRestDslTest.java
@@ -147,9 +147,10 @@ public class PlatformHttpRestOpenApiConsumerRestDslTest {
context.start();
fail();
- } catch (IllegalArgumentException e) {
+ } catch (Exception e) {
Assertions.assertTrue(
- e.getMessage().startsWith("OpenAPI specification has 18
unmapped operations to corresponding routes"));
+ e.getCause().getMessage()
+ .startsWith("OpenAPI specification has 18 unmapped
operations to corresponding routes"));
} finally {
context.stop();
}
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 9a28f9ce5ba8..fe8276b81a45 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
@@ -18,6 +18,7 @@ package org.apache.camel.component.platform.http.vertx;
import org.apache.camel.CamelContext;
import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@@ -37,7 +38,7 @@ public class PlatformHttpRestOpenApiConsumerTest {
@Override
public void configure() {
from("rest-openapi:classpath:openapi-v3.json?missingOperation=ignore")
- .log("dummy");
+ .to("mock:result");
from("direct:getPetById")
.setBody().constant("{\"pet\": \"tony the
tiger\"}");
@@ -46,6 +47,9 @@ public class PlatformHttpRestOpenApiConsumerTest {
context.start();
+ MockEndpoint mock = context.getEndpoint("mock:result",
MockEndpoint.class);
+ mock.expectedMessageCount(1);
+
given()
.when()
.get("/api/v3/pet/123")
@@ -53,6 +57,8 @@ public class PlatformHttpRestOpenApiConsumerTest {
.statusCode(200)
.body(equalTo("{\"pet\": \"tony the tiger\"}"));
+ mock.assertIsSatisfied();
+
} finally {
context.stop();
}
@@ -69,7 +75,7 @@ public class PlatformHttpRestOpenApiConsumerTest {
@Override
public void configure() {
from("rest-openapi:classpath:openapi-v3.json")
- .log("dummy");
+ .stop(); // use stop if you dont need to do
anything after rest-dsl
from("direct:getPetById")
.setBody().constant("{\"pet\": \"tony the
tiger\"}");
@@ -144,9 +150,10 @@ public class PlatformHttpRestOpenApiConsumerTest {
context.start();
fail();
- } catch (IllegalArgumentException e) {
+ } catch (Exception e) {
Assertions.assertTrue(
- e.getMessage().startsWith("OpenAPI specification has 18
unmapped operations to corresponding routes"));
+ e.getCause().getMessage()
+ .startsWith("OpenAPI specification has 18 unmapped
operations to corresponding routes"));
} finally {
context.stop();
}
diff --git
a/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/DefaultPlatformHttpConsumer.java
b/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/DefaultPlatformHttpConsumer.java
index 9a1dba53f902..6644cb70939c 100644
---
a/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/DefaultPlatformHttpConsumer.java
+++
b/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/DefaultPlatformHttpConsumer.java
@@ -16,6 +16,7 @@
*/
package org.apache.camel.component.platform.http;
+import org.apache.camel.AfterPropertiesConfigured;
import org.apache.camel.Endpoint;
import org.apache.camel.Processor;
import org.apache.camel.Suspendable;
@@ -26,10 +27,11 @@ import org.apache.camel.support.DefaultConsumer;
import org.apache.camel.support.service.ServiceHelper;
public class DefaultPlatformHttpConsumer extends DefaultConsumer
- implements PlatformHttpConsumerAware, Suspendable, SuspendableService {
+ implements PlatformHttpConsumer, PlatformHttpConsumerAware,
Suspendable, SuspendableService {
private PlatformHttpConsumer platformHttpConsumer;
private boolean register = true;
+ private AfterPropertiesConfigured afterConfiguredListener;
public DefaultPlatformHttpConsumer(Endpoint endpoint, Processor processor)
{
super(endpoint, processor);
@@ -62,12 +64,24 @@ public class DefaultPlatformHttpConsumer extends
DefaultConsumer
return platformHttpConsumer;
}
+ @Override
+ public void registerAfterConfigured(AfterPropertiesConfigured listener) {
+ this.afterConfiguredListener = listener;
+ }
+
@Override
protected void doInit() throws Exception {
platformHttpConsumer =
getEndpoint().createPlatformHttpConsumer(getProcessor());
configurePlatformHttpConsumer(platformHttpConsumer);
super.doInit();
+
ServiceHelper.initService(platformHttpConsumer);
+
+ // signal that the platform-http consumer now has been configured
+ // (rest-dsl can continue to initialize and start so it's ready when
this consumer is started)
+ if (afterConfiguredListener != null) {
+
afterConfiguredListener.afterPropertiesConfigured(getEndpoint().getCamelContext());
+ }
}
protected void configurePlatformHttpConsumer(PlatformHttpConsumer
platformHttpConsumer) {
diff --git
a/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/spi/PlatformHttpConsumerAware.java
b/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/spi/PlatformHttpConsumerAware.java
index 4f691aebfec2..337abd600ed7 100644
---
a/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/spi/PlatformHttpConsumerAware.java
+++
b/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/spi/PlatformHttpConsumerAware.java
@@ -16,6 +16,8 @@
*/
package org.apache.camel.component.platform.http.spi;
+import org.apache.camel.AfterPropertiesConfigured;
+
/**
* An interface to represent an object that has been injected with {@link
PlatformHttpConsumer}.
*/
@@ -26,4 +28,11 @@ public interface PlatformHttpConsumerAware {
*/
PlatformHttpConsumer getPlatformHttpConsumer();
+ /**
+ * Registers a listener that is called after the {@link
PlatformHttpConsumer} has set options from properties.
+ * <p/>
+ * For example used by camel-rest-openapi
+ */
+ void registerAfterConfigured(AfterPropertiesConfigured listener);
+
}
diff --git
a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
index 095fdfd48d39..c6d391e2cd9b 100644
---
a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
+++
b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiComponent.java
@@ -19,6 +19,7 @@ package org.apache.camel.component.rest.openapi;
import java.util.Map;
import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
import org.apache.camel.Endpoint;
import org.apache.camel.SSLContextParametersAware;
import org.apache.camel.spi.Metadata;
@@ -141,7 +142,7 @@ public final class RestOpenApiComponent extends
DefaultComponent implements SSLC
@Metadata(label = "consumer", description = "Sets the context-path to use
for servicing the OpenAPI specification")
private String apiContextPath;
@Metadata(description = "To use a custom strategy for how to process Rest
DSL requests", label = "consumer,advanced")
- private RestOpenapiProcessorStrategy restOpenapiProcessorStrategy = new
DefaultRestOpenapiProcessorStrategy();
+ private RestOpenapiProcessorStrategy restOpenapiProcessorStrategy;
@Metadata(description = "Enable usage of global SSL context parameters.",
label = "security")
private boolean useGlobalSslContextParameters;
@Metadata(description = "Customize TLS parameters used by the component.
If not set defaults to the TLS parameters set in the Camel context ",
@@ -195,6 +196,10 @@ public final class RestOpenApiComponent extends
DefaultComponent implements SSLC
}
bindingPackageScan = base;
}
+ if (restOpenapiProcessorStrategy == null) {
+ restOpenapiProcessorStrategy = new
DefaultRestOpenapiProcessorStrategy();
+ CamelContextAware.trySetCamelContext(restOpenapiProcessorStrategy,
getCamelContext());
+ }
}
public String getBasePath() {
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 20429aa8e895..d5bad5e27235 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
@@ -51,14 +51,18 @@ import org.apache.camel.Category;
import org.apache.camel.Component;
import org.apache.camel.Consumer;
import org.apache.camel.Endpoint;
+import org.apache.camel.Exchange;
import org.apache.camel.ExchangePattern;
import org.apache.camel.NoSuchBeanException;
+import org.apache.camel.Ordered;
import org.apache.camel.Processor;
import org.apache.camel.Producer;
import org.apache.camel.component.platform.http.spi.PlatformHttpConsumerAware;
import
org.apache.camel.component.rest.openapi.validator.DefaultRequestValidator;
import org.apache.camel.component.rest.openapi.validator.RequestValidator;
import org.apache.camel.component.rest.openapi.validator.RestOpenApiOperation;
+import org.apache.camel.spi.CamelInternalProcessorAdvice;
+import org.apache.camel.spi.InternalProcessor;
import org.apache.camel.spi.Metadata;
import org.apache.camel.spi.Resource;
import org.apache.camel.spi.RestConfiguration;
@@ -69,6 +73,7 @@ import org.apache.camel.spi.UriPath;
import org.apache.camel.support.CamelContextHelper;
import org.apache.camel.support.DefaultEndpoint;
import org.apache.camel.support.ResourceHelper;
+import org.apache.camel.support.processor.RestBindingAdvice;
import org.apache.camel.util.IOHelper;
import org.apache.camel.util.ObjectHelper;
import org.apache.camel.util.UnsafeUriCharactersEncoder;
@@ -210,15 +215,33 @@ public final class RestOpenApiEndpoint extends
DefaultEndpoint {
public Consumer createConsumer(final Processor processor) throws Exception
{
OpenAPI doc = loadSpecificationFrom(getCamelContext(),
specificationUri);
String path = determineBasePath(doc);
- RestOpenApiProcessor target
- = new RestOpenApiProcessor(this, doc, path, apiContextPath,
processor, restOpenapiProcessorStrategy);
- CamelContextAware.trySetCamelContext(target, getCamelContext());
- Consumer consumer = createConsumerFor(path, target);
- target.setConsumer(consumer);
+
+ RestOpenApiProcessor openApiProcessor
+ = new RestOpenApiProcessor(this, doc, path, apiContextPath,
restOpenapiProcessorStrategy);
+ CamelContextAware.trySetCamelContext(openApiProcessor,
getCamelContext());
+
+ // use an advice to call the processor that is responsible for routing
to the route that matches the
+ // operation id, and also do validation of the incoming request
+ // the camel route is invoked AFTER the rest-dsl is complete
+ if (processor instanceof InternalProcessor ip) {
+ // remove existing rest binding advice because
RestOpenApiProcessorAdvice has its own binding
+ RestBindingAdvice advice = ip.getAdvice(RestBindingAdvice.class);
+ if (advice != null) {
+ ip.removeAdvice(advice);
+ }
+ ip.addAdvice(new RestOpenApiProcessorAdvice(openApiProcessor));
+ }
+
+ Consumer consumer = createConsumerFor(path, openApiProcessor,
processor);
+ openApiProcessor.setConsumer(consumer);
+ if (consumer instanceof PlatformHttpConsumerAware phca) {
+ phca.registerAfterConfigured(openApiProcessor);
+ }
return consumer;
}
- protected Consumer createConsumerFor(String basePath, RestOpenApiProcessor
processor) throws Exception {
+ private Consumer createConsumerFor(String basePath, RestOpenApiProcessor
openApiProcessor, Processor processor)
+ throws Exception {
RestOpenApiConsumerFactory factory = null;
String cname = null;
if (getConsumerComponentName() != null) {
@@ -305,7 +328,7 @@ public final class RestOpenApiEndpoint extends
DefaultEndpoint {
}
Consumer consumer = factory.createConsumer(getCamelContext(),
processor, basePath, config, copy);
if (consumer instanceof PlatformHttpConsumerAware phca) {
- processor.setPlatformHttpConsumer(phca);
+ openApiProcessor.setPlatformHttpConsumer(phca);
}
configureConsumer(consumer);
return consumer;
@@ -516,7 +539,6 @@ public final class RestOpenApiEndpoint extends
DefaultEndpoint {
return new RestOpenApiProducer(endpoint.createProducer(), hasHost,
requestValidator);
}
- @Deprecated
String determineBasePath(final OpenAPI openapi) {
if (isNotEmpty(basePath)) {
return basePath;
@@ -950,4 +972,39 @@ public final class RestOpenApiEndpoint extends
DefaultEndpoint {
return expression.toString();
}
+
+ private static class RestOpenApiProcessorAdvice implements
CamelInternalProcessorAdvice<Object>, Ordered {
+
+ private final RestOpenApiProcessor openApiProcessor;
+
+ public RestOpenApiProcessorAdvice(RestOpenApiProcessor
openApiProcessor) {
+ this.openApiProcessor = openApiProcessor;
+ }
+
+ @Override
+ public boolean hasState() {
+ return false;
+ }
+
+ @Override
+ public Object before(Exchange exchange) throws Exception {
+ try {
+ openApiProcessor.process(exchange);
+ } catch (Exception e) {
+ exchange.setException(e);
+ }
+ return null;
+ }
+
+ @Override
+ public void after(Exchange exchange, Object data) throws Exception {
+ // noop
+ }
+
+ @Override
+ public int getOrder() {
+ // should be lowest so all existing advices are triggered first
+ return Ordered.LOWEST;
+ }
+ }
}
diff --git
a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
index 61ea55d6ef65..531b401a7d00 100644
---
a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
+++
b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
@@ -27,18 +27,14 @@ import org.apache.camel.*;
import org.apache.camel.component.platform.http.spi.PlatformHttpConsumerAware;
import org.apache.camel.http.base.HttpHelper;
import org.apache.camel.spi.RestConfiguration;
+import org.apache.camel.support.AsyncProcessorSupport;
import org.apache.camel.support.RestConsumerContextPathMatcher;
-import org.apache.camel.support.processor.DelegateAsyncProcessor;
import org.apache.camel.support.processor.RestBindingAdvice;
import org.apache.camel.support.processor.RestBindingAdviceFactory;
import org.apache.camel.support.processor.RestBindingConfiguration;
import org.apache.camel.support.service.ServiceHelper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-public class RestOpenApiProcessor extends DelegateAsyncProcessor implements
CamelContextAware {
-
- private static final Logger LOG =
LoggerFactory.getLogger(RestOpenApiProcessor.class);
+public class RestOpenApiProcessor extends AsyncProcessorSupport implements
CamelContextAware, AfterPropertiesConfigured {
// just use the most common verbs
private static final List<String> METHODS = Arrays.asList("GET", "HEAD",
"POST", "PUT", "DELETE", "PATCH");
@@ -55,8 +51,7 @@ public class RestOpenApiProcessor extends
DelegateAsyncProcessor implements Came
private OpenApiUtils openApiUtils;
public RestOpenApiProcessor(RestOpenApiEndpoint endpoint, OpenAPI openAPI,
String basePath, String apiContextPath,
- Processor processor,
RestOpenapiProcessorStrategy restOpenapiProcessorStrategy) {
- super(processor);
+ RestOpenapiProcessorStrategy
restOpenapiProcessorStrategy) {
this.endpoint = endpoint;
this.basePath = basePath;
// ensure starts with leading slash
@@ -95,9 +90,6 @@ public class RestOpenApiProcessor extends
DelegateAsyncProcessor implements Came
public boolean process(Exchange exchange, AsyncCallback callback) {
// use HTTP_URI as this works for all runtimes
String path = exchange.getMessage().getHeader(Exchange.HTTP_PATH,
String.class);
- // if (path != null) {
- // path = URISupport.stripQuery(path);
- // }
if (path != null && path.startsWith(basePath)) {
path = path.substring(basePath.length());
}
@@ -147,9 +139,16 @@ public class RestOpenApiProcessor extends
DelegateAsyncProcessor implements Came
@Override
protected void doInit() throws Exception {
super.doInit();
- this.openApiUtils = new OpenApiUtils(camelContext,
endpoint.getBindingPackageScan(), openAPI.getComponents());
CamelContextAware.trySetCamelContext(restOpenapiProcessorStrategy,
getCamelContext());
+ }
+ @Override
+ public void afterPropertiesConfigured(CamelContext camelContext) {
+ // this method is triggered by platformHttpConsumer when it has been
initialized and would be possible
+ // to know the actual url of the http server that would service the
incoming requests
+ // this is required to build the paths with all the details
+
+ this.openApiUtils = new OpenApiUtils(camelContext,
endpoint.getBindingPackageScan(), openAPI.getComponents());
// register all openapi paths
for (var e : openAPI.getPaths().entrySet()) {
String path = e.getKey(); // path
@@ -174,23 +173,38 @@ public class RestOpenApiProcessor extends
DelegateAsyncProcessor implements Came
camelContext.getRestRegistry().addRestService(consumer, true,
url, path, basePath, null, v, bc.getConsumes(),
bc.getProduces(), bc.getType(), bc.getOutType(),
routeId, desc);
- RestBindingAdvice binding =
RestBindingAdviceFactory.build(camelContext, bc);
-
- ServiceHelper.buildService(binding);
- paths.add(new RestOpenApiConsumerPath(v, path, o.getValue(),
binding));
+ try {
+ RestBindingAdvice binding =
RestBindingAdviceFactory.build(camelContext, bc);
+ ServiceHelper.buildService(binding);
+ paths.add(new RestOpenApiConsumerPath(v, path,
o.getValue(), binding));
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
}
}
openApiUtils.clear(); // no longer needed
+ for (var p : paths) {
+ if (p instanceof RestOpenApiConsumerPath rcp) {
+ ServiceHelper.startService(rcp.getBinding());
+ }
+ }
+
restOpenapiProcessorStrategy.setMissingOperation(endpoint.getMissingOperation());
restOpenapiProcessorStrategy.setMockIncludePattern(endpoint.getMockIncludePattern());
ServiceHelper.initService(restOpenapiProcessorStrategy);
- // validate openapi contract
- restOpenapiProcessorStrategy.validateOpenApi(openAPI, basePath,
platformHttpConsumer);
+ try {
+ // validate openapi contract
+ restOpenapiProcessorStrategy.validateOpenApi(openAPI, basePath,
platformHttpConsumer);
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+
+ ServiceHelper.startService(restOpenapiProcessorStrategy);
}
- private RestBindingConfiguration createRestBindingConfiguration(Operation
o) throws Exception {
+ private RestBindingConfiguration createRestBindingConfiguration(Operation
o) {
RestConfiguration config = camelContext.getRestConfiguration();
RestConfiguration.RestBindingMode mode = config.getBindingMode();
@@ -222,17 +236,6 @@ public class RestOpenApiProcessor extends
DelegateAsyncProcessor implements Came
return bc;
}
- @Override
- protected void doStart() throws Exception {
- super.doStart();
- ServiceHelper.startService(restOpenapiProcessorStrategy);
- for (var p : paths) {
- if (p instanceof RestOpenApiConsumerPath rcp) {
- ServiceHelper.startService(rcp.getBinding());
- }
- }
- }
-
@Override
protected void doStop() throws Exception {
super.doStop();
diff --git
a/core/camel-api/src/main/java/org/apache/camel/spi/InternalProcessor.java
b/core/camel-api/src/main/java/org/apache/camel/spi/InternalProcessor.java
index 9716f3c6cdfa..8b4136a0efb1 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/InternalProcessor.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/InternalProcessor.java
@@ -54,6 +54,13 @@ public interface InternalProcessor extends AsyncProcessor {
*/
<T> T getAdvice(Class<T> type);
+ /**
+ * Removes an {@link CamelInternalProcessorAdvice} advice from the list of
advices.
+ *
+ * @param advice the advice to remove
+ */
+ void removeAdvice(CamelInternalProcessorAdvice<?> advice);
+
/**
* Adds advice for handling {@link RoutePolicy} for the route
*/
diff --git
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/CamelInternalProcessor.java
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/CamelInternalProcessor.java
index c2b0e649127a..9c3fa20dd89a 100644
---
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/CamelInternalProcessor.java
+++
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/CamelInternalProcessor.java
@@ -169,6 +169,13 @@ public class CamelInternalProcessor extends
DelegateAsyncProcessor implements In
}
}
+ @Override
+ public void removeAdvice(CamelInternalProcessorAdvice<?> advice) {
+ if (advices.remove(advice) && advice.hasState()) {
+ statefulAdvices--;
+ }
+ }
+
@Override
public <T> T getAdvice(Class<T> type) {
for (CamelInternalProcessorAdvice<?> task : advices) {
diff --git
a/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java
b/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java
index 379d02acb6cc..ee8e1d7bc827 100644
---
a/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java
+++
b/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java
@@ -65,6 +65,7 @@ import static
org.apache.camel.support.CamelContextHelper.parseText;
public class RestDefinition extends
OptionalIdentifiedDefinition<RestDefinition> implements ResourceAware {
public static final String MISSING_VERB = "Must add verb first, such as
get/post/delete";
+
@XmlAttribute
private String path;
@XmlAttribute
@@ -1044,7 +1045,7 @@ public class RestDefinition extends
OptionalIdentifiedDefinition<RestDefinition>
if (openApi.getRouteId() != null) {
route.routeId(parseText(camelContext, openApi.getRouteId()));
}
- // add dummy empty stop
+ // the route must have an output so use a dummy stop
route.getOutputs().add(new StopDefinition());
// local configuration can override global