This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch camel-3.x in repository https://gitbox.apache.org/repos/asf/camel.git
commit c9cc984b479b2e40fa9c10a8bbe740f96a409fd9 Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Tue Mar 21 12:07:38 2023 +0100 CAMEL-19176: camel-platform-http - Add listener for added/removed http endpoints --- .../component/platform/http/HttpEndpointModel.java | 13 ++++- .../platform/http/PlatformHttpComponent.java | 57 +++++++++++++++++++--- .../platform/http/PlatformHttpEndpoint.java | 2 +- .../platform/http/PlatformHttpListener.java | 35 +++++++++++++ .../apache/camel/main/http/VertxHttpServer.java | 4 +- 5 files changed, 100 insertions(+), 11 deletions(-) diff --git a/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/HttpEndpointModel.java b/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/HttpEndpointModel.java index 5b53a7eadfd..ab2c5061167 100644 --- a/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/HttpEndpointModel.java +++ b/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/HttpEndpointModel.java @@ -19,6 +19,7 @@ package org.apache.camel.component.platform.http; import java.util.Locale; import java.util.Objects; +import org.apache.camel.Consumer; import org.apache.camel.util.StringHelper; /** @@ -28,14 +29,20 @@ public class HttpEndpointModel implements Comparable<HttpEndpointModel> { private final String uri; private String verbs; + private final Consumer consumer; public HttpEndpointModel(String uri) { - this(uri, null); + this(uri, null, null); } public HttpEndpointModel(String uri, String verbs) { + this(uri, verbs, null); + } + + public HttpEndpointModel(String uri, String verbs, Consumer consumer) { this.uri = uri; addVerb(verbs); + this.consumer = consumer; } public String getUri() { @@ -46,6 +53,10 @@ public class HttpEndpointModel implements Comparable<HttpEndpointModel> { return verbs; } + public Consumer getConsumer() { + return consumer; + } + public void addVerb(String verb) { if (verb != null) { if (this.verbs == null) { diff --git a/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpComponent.java b/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpComponent.java index 714109041dd..a8929c482be 100644 --- a/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpComponent.java +++ b/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpComponent.java @@ -16,7 +16,9 @@ */ package org.apache.camel.component.platform.http; +import java.util.ArrayList; import java.util.Collections; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; @@ -48,6 +50,7 @@ import org.slf4j.LoggerFactory; */ @Component("platform-http") public class PlatformHttpComponent extends DefaultComponent implements RestConsumerFactory, RestApiConsumerFactory { + private static final Logger LOG = LoggerFactory.getLogger(PlatformHttpComponent.class); @Metadata(label = "advanced", description = "An HTTP Server engine implementation to serve the requests") @@ -55,6 +58,8 @@ public class PlatformHttpComponent extends DefaultComponent implements RestConsu private final Set<HttpEndpointModel> httpEndpoints = new TreeSet<>(); + private final List<PlatformHttpListener> listeners = new ArrayList<>(); + private volatile boolean localEngine; private final Object lock = new Object(); @@ -84,7 +89,7 @@ public class PlatformHttpComponent extends DefaultComponent implements RestConsu // reuse the createConsumer method we already have. The api need to use GET and match on uri prefix Consumer consumer = doCreateConsumer(camelContext, processor, "GET", contextPath, null, null, null, configuration, parameters, true); - addHttpEndpoint(contextPath, "GET"); + addHttpEndpoint(contextPath, "GET", consumer); return consumer; } @@ -99,12 +104,12 @@ public class PlatformHttpComponent extends DefaultComponent implements RestConsu parameters, false); if (uriTemplate != null) { if (uriTemplate.startsWith("/")) { - addHttpEndpoint(basePath + uriTemplate, verb); + addHttpEndpoint(basePath + uriTemplate, verb, consumer); } else { - addHttpEndpoint(basePath + "/" + uriTemplate, verb); + addHttpEndpoint(basePath + "/" + uriTemplate, verb, consumer); } } else { - addHttpEndpoint(basePath, verb); + addHttpEndpoint(basePath, verb, consumer); } return consumer; } @@ -112,21 +117,59 @@ public class PlatformHttpComponent extends DefaultComponent implements RestConsu /** * Adds a known http endpoint managed by this component. */ - public void addHttpEndpoint(String uri, String verbs) { + public void addHttpEndpoint(String uri, String verbs, Consumer consumer) { + boolean updated = false; + HttpEndpointModel model = httpEndpoints.stream().filter(e -> e.getUri().equals(uri)).findFirst().orElse(null); if (model == null) { - model = new HttpEndpointModel(uri, verbs); + model = new HttpEndpointModel(uri, verbs, consumer); httpEndpoints.add(model); } else { + updated = true; model.addVerb(verbs); } + + for (PlatformHttpListener listener : listeners) { + try { + if (updated) { + listener.updateHttpEndpoint(model); + } else { + listener.registerHttpEndpoint(model); + } + } catch (Exception e) { + LOG.warn("Error adding listener due to " + e.getMessage() + ". This exception is ignored", e); + } + } } /** * Removes a known http endpoint managed by this component. */ public void removeHttpEndpoint(String uri) { - httpEndpoints.stream().filter(e -> e.getUri().equals(uri)).findFirst().ifPresent(httpEndpoints::remove); + httpEndpoints.stream().filter(e -> e.getUri().equals(uri)).findFirst().ifPresent(model -> { + httpEndpoints.remove(model); + for (PlatformHttpListener listener : listeners) { + try { + listener.unregisterHttpEndpoint(model); + } catch (Exception e) { + LOG.warn("Error removing listener due to " + e.getMessage() + ". This exception is ignored", e); + } + } + }); + } + + /** + * Adds a {@link PlatformHttpListener} listener. + */ + public void addPlatformHttpListener(PlatformHttpListener listener) { + this.listeners.add(listener); + } + + /** + * Removes an existing {@link PlatformHttpListener} listener. + */ + public void removePlatformHttpListener(PlatformHttpListener listener) { + this.listeners.remove(listener); } /** diff --git a/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpEndpoint.java b/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpEndpoint.java index 34db08833ef..7c958ce7e09 100644 --- a/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpEndpoint.java +++ b/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpEndpoint.java @@ -108,7 +108,7 @@ public class PlatformHttpEndpoint extends DefaultEndpoint implements AsyncEndpoi protected void doStart() throws Exception { super.doStart(); ServiceHelper.startService(delegatedConsumer); - getComponent().addHttpEndpoint(getPath(), httpMethodRestrict); + getComponent().addHttpEndpoint(getPath(), httpMethodRestrict, delegatedConsumer); } @Override diff --git a/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpListener.java b/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpListener.java new file mode 100644 index 00000000000..5304838f756 --- /dev/null +++ b/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpListener.java @@ -0,0 +1,35 @@ +/* + * 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; + +public interface PlatformHttpListener { + + /** + * Callback when a new HTTP endpoint is added. + */ + void registerHttpEndpoint(HttpEndpointModel model); + + /** + * Callback when an existing HTTP endpoint is updated. + */ + void updateHttpEndpoint(HttpEndpointModel model); + + /** + * Callback when an existing HTTP endpoint is removed. + */ + void unregisterHttpEndpoint(HttpEndpointModel model); +} diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/http/VertxHttpServer.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/http/VertxHttpServer.java index 22b4274be90..ad8be611078 100644 --- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/http/VertxHttpServer.java +++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/http/VertxHttpServer.java @@ -290,7 +290,7 @@ public final class VertxHttpServer { dev.handler(handler); devSub.handler(handler); - phc.addHttpEndpoint("/q/dev", null); + phc.addHttpEndpoint("/q/dev", null, null); } public static void registerHealthCheck(CamelContext camelContext) { @@ -366,7 +366,7 @@ public final class VertxHttpServer { live.handler(handler); ready.handler(handler); - phc.addHttpEndpoint("/q/health", null); + phc.addHttpEndpoint("/q/health", null, null); } private static void healthCheckStatus(StringBuilder sb, boolean up) {