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
commit 65df9848c8ba4cd479d98537a4ec30bc699b8759 Author: Claus Ibsen <[email protected]> AuthorDate: Mon Jul 10 11:10:17 2023 +0200 CAMEL-19593: camel-platform-http-main - Standalone developer web console for camel-main --- bom/camel-bom/pom.xml | 5 + catalog/camel-allcomponents/pom.xml | 5 + .../main/camel-main-configuration-metadata.json | 11 + .../org/apache/camel/catalog/others.properties | 1 + .../camel/catalog/others/platform-http-main.json | 15 + components/camel-platform-http-main/pom.xml | 94 ++++ .../services/org/apache/camel/other.properties | 7 + .../services/org/apache/camel/platform-http-server | 2 + .../generated/resources/platform-http-main.json | 15 + .../src/main/docs/platform-http-main.adoc | 28 ++ .../http/main/DefaultMainHttpServerFactory.java | 61 +++ .../platform/http/main/MainHttpServer.java | 551 +++++++++++++-------- .../http/vertx/VertxPlatformHttpServer.java | 34 +- .../VertxPlatformHttpServerConfiguration.java | 7 +- .../http/vertx/VertxPlatformHttpServerSupport.java | 2 +- .../test/main/junit5/CamelMainTestSupport.java | 4 +- components/pom.xml | 1 + ...ttpServerConfigurationPropertiesConfigurer.java | 103 ++++ .../camel-main-configuration-metadata.json | 11 + ...he.camel.main.HttpServerConfigurationProperties | 2 + core/camel-main/src/main/docs/main.adoc | 19 + .../org/apache/camel/main/BaseMainSupport.java | 94 +++- .../main/HttpServerConfigurationProperties.java | 264 ++++++++++ .../camel/main/MainConfigurationProperties.java | 22 + .../java/org/apache/camel/main/MainConstants.java | 30 ++ .../apache/camel/main/MainHttpServerFactory.java | 33 ++ .../main/MainPropertyPlaceholderWithEnvTest.java | 14 +- .../MainPropertyPlaceholderWithSystemTest.java | 33 +- .../ROOT/pages/camel-4-migration-guide.adoc | 13 + dsl/camel-kamelet-main/pom.xml | 9 +- .../apache/camel/main/http/VertxHttpServer.java | 14 +- parent/pom.xml | 5 + .../maven/packaging/PrepareCamelMainMojo.java | 5 + 33 files changed, 1225 insertions(+), 289 deletions(-) diff --git a/bom/camel-bom/pom.xml b/bom/camel-bom/pom.xml index 84519375140..c8ee54d2f7d 100644 --- a/bom/camel-bom/pom.xml +++ b/bom/camel-bom/pom.xml @@ -1522,6 +1522,11 @@ <artifactId>camel-platform-http</artifactId> <version>${project.version}</version> </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-platform-http-main</artifactId> + <version>${project.version}</version> + </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-platform-http-vertx</artifactId> diff --git a/catalog/camel-allcomponents/pom.xml b/catalog/camel-allcomponents/pom.xml index 8a76cb7cd7f..95406d375d2 100644 --- a/catalog/camel-allcomponents/pom.xml +++ b/catalog/camel-allcomponents/pom.xml @@ -1308,6 +1308,11 @@ <artifactId>camel-platform-http</artifactId> <version>${project.version}</version> </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-platform-http-main</artifactId> + <version>${project.version}</version> + </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-platform-http-vertx</artifactId> diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json index b0ef1361e58..2d16d3f2fc2 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json @@ -1,6 +1,7 @@ { "groups": [ { "name": "camel.main", "description": "Camel Main configurations", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties" }, + { "name": "camel.server", "description": "Camel Embedded HTTP Server (only for standalone; not Spring Boot or Quarkus) configurations", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties" }, { "name": "camel.threadpool", "description": "Camel Thread Pool configurations", "sourceType": "org.apache.camel.main.ThreadPoolConfigurationProperties" }, { "name": "camel.health", "description": "Camel Health Check configurations", "sourceType": "org.apache.camel.main.HealthConfigurationProperties" }, { "name": "camel.rest", "description": "Camel Rest-DSL configurations", "sourceType": "org.apache.camel.spi.RestConfiguration" }, @@ -202,6 +203,16 @@ { "name": "camel.rest.skipBindingOnErrorCode", "description": "Whether to skip binding output if there is a custom HTTP error code, and instead use the response body as-is. This option is default true.", "sourceType": "org.apache.camel.spi.RestConfiguration", "type": "boolean", "javaType": "boolean", "defaultValue": true }, { "name": "camel.rest.useXForwardHeaders", "description": "Whether to use X-Forward headers to set host etc. for Swagger. This option is default true.", "sourceType": "org.apache.camel.spi.RestConfiguration", "type": "boolean", "javaType": "boolean", "defaultValue": true }, { "name": "camel.rest.xmlDataFormat", "description": "Sets a custom xml data format to be used. Important: This option is only for setting a custom name of the data format, not to refer to an existing data format instance.", "sourceType": "org.apache.camel.spi.RestConfiguration", "type": "string", "javaType": "java.lang.String" }, + { "name": "camel.server.devConsoleEnabled", "description": "Whether to enable developer console (not intended for production use). Dev console must also be enabled on CamelContext. For example by setting camel.context.dev-console=true in application.properties, or via code camelContext.setDevConsole(true); If enabled then you can access a basic developer console on context-path: \/q\/dev.", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "boolean", "j [...] + { "name": "camel.server.enabled", "description": "Whether embedded HTTP server is enabled. By default, the server is not enabled.", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" }, + { "name": "camel.server.healthCheckEnabled", "description": "Whether to enable health-check console. If enabled then you can access health-check status on context-path: \/q\/health", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" }, + { "name": "camel.server.host", "description": "Hostname to use for binding embedded HTTP server", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "string", "javaType": "java.lang.String", "defaultValue": "0.0.0.0" }, + { "name": "camel.server.maxBodySize", "description": "Maximum HTTP body size the embedded HTTP server can accept.", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "integer", "javaType": "java.lang.Long" }, + { "name": "camel.server.path", "description": "Context-path to use for embedded HTTP server", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "string", "javaType": "java.lang.String", "defaultValue": "\/" }, + { "name": "camel.server.port", "description": "Port to use for binding embedded HTTP server", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "integer", "javaType": "int", "defaultValue": 8080 }, + { "name": "camel.server.uploadEnabled", "description": "Whether to enable file upload via HTTP (not intended for production use). This functionality is for development to be able to reload Camel routes and code with source changes (if reload is enabled). If enabled then you can upload\/delete files via HTTP PUT\/DELETE on context-path: \/q\/upload\/{name}. You must also configure the uploadSourceDir option.", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "t [...] + { "name": "camel.server.uploadSourceDir", "description": "Source directory when upload is enabled.", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "string", "javaType": "java.lang.String" }, + { "name": "camel.server.useGlobalSslContextParameters", "description": "Whether to use global SSL configuration for securing the embedded HTTP server.", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" }, { "name": "camel.threadpool.allowCoreThreadTimeOut", "description": "Sets default whether to allow core threads to timeout", "sourceType": "org.apache.camel.main.ThreadPoolConfigurationProperties", "type": "boolean", "javaType": "java.lang.Boolean", "defaultValue": "false" }, { "name": "camel.threadpool.config", "description": "Adds a configuration for a specific thread pool profile (inherits default values)", "sourceType": "org.apache.camel.main.ThreadPoolConfigurationProperties", "type": "object", "javaType": "java.util.Map" }, { "name": "camel.threadpool.keepAliveTime", "description": "Sets the default keep alive time for inactive threads", "sourceType": "org.apache.camel.main.ThreadPoolConfigurationProperties", "type": "integer", "javaType": "java.lang.Long" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others.properties b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others.properties index 222d2f13b83..19f74621977 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others.properties +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others.properties @@ -32,6 +32,7 @@ microprofile-health observation openapi-java opentelemetry +platform-http-main platform-http-vertx reactive-executor-tomcat reactive-executor-vertx diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others/platform-http-main.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others/platform-http-main.json new file mode 100644 index 00000000000..61506219628 --- /dev/null +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others/platform-http-main.json @@ -0,0 +1,15 @@ +{ + "other": { + "kind": "other", + "name": "platform-http-main", + "title": "Platform Http Main", + "description": "Platform HTTP for standalone Camel Main applications", + "deprecated": false, + "firstVersion": "4.0.0", + "label": "http", + "supportLevel": "Preview", + "groupId": "org.apache.camel", + "artifactId": "camel-platform-http-main", + "version": "4.0.0-SNAPSHOT" + } +} diff --git a/components/camel-platform-http-main/pom.xml b/components/camel-platform-http-main/pom.xml new file mode 100644 index 00000000000..14394201c35 --- /dev/null +++ b/components/camel-platform-http-main/pom.xml @@ -0,0 +1,94 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + 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. + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.camel</groupId> + <artifactId>components</artifactId> + <version>4.0.0-SNAPSHOT</version> + </parent> + + <artifactId>camel-platform-http-main</artifactId> + <packaging>jar</packaging> + <name>Camel :: Platform HTTP :: Main</name> + <description>Platform HTTP for standalone Camel Main applications</description> + + <properties> + <firstVersion>4.0.0</firstVersion> + <label>http</label> + </properties> + + <dependencies> + + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-main</artifactId> + </dependency> + <!-- use vertx as http engine --> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-platform-http-vertx</artifactId> + <exclusions> + <!-- avoid WARN logs from netty --> + <exclusion> + <groupId>io.netty</groupId> + <artifactId>netty-resolver-dns</artifactId> + </exclusion> + </exclusions> + </dependency> + + <!-- test dependencies --> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-test-junit5</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-http</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-jackson</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-log</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.assertj</groupId> + <artifactId>assertj-core</artifactId> + <version>${assertj-version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>io.rest-assured</groupId> + <artifactId>rest-assured</artifactId> + <version>${rest-assured-version}</version> + <scope>test</scope> + </dependency> + </dependencies> + +</project> diff --git a/components/camel-platform-http-main/src/generated/resources/META-INF/services/org/apache/camel/other.properties b/components/camel-platform-http-main/src/generated/resources/META-INF/services/org/apache/camel/other.properties new file mode 100644 index 00000000000..15e970adf75 --- /dev/null +++ b/components/camel-platform-http-main/src/generated/resources/META-INF/services/org/apache/camel/other.properties @@ -0,0 +1,7 @@ +# Generated by camel build tools - do NOT edit this file! +name=platform-http-main +groupId=org.apache.camel +artifactId=camel-platform-http-main +version=4.0.0-SNAPSHOT +projectName=Camel :: Platform HTTP :: Main +projectDescription=Platform HTTP for standalone Camel Main applications diff --git a/components/camel-platform-http-main/src/generated/resources/META-INF/services/org/apache/camel/platform-http-server b/components/camel-platform-http-main/src/generated/resources/META-INF/services/org/apache/camel/platform-http-server new file mode 100644 index 00000000000..bab087493dd --- /dev/null +++ b/components/camel-platform-http-main/src/generated/resources/META-INF/services/org/apache/camel/platform-http-server @@ -0,0 +1,2 @@ +# Generated by camel build tools - do NOT edit this file! +class=org.apache.camel.component.platform.http.main.DefaultMainHttpServerFactory diff --git a/components/camel-platform-http-main/src/generated/resources/platform-http-main.json b/components/camel-platform-http-main/src/generated/resources/platform-http-main.json new file mode 100644 index 00000000000..61506219628 --- /dev/null +++ b/components/camel-platform-http-main/src/generated/resources/platform-http-main.json @@ -0,0 +1,15 @@ +{ + "other": { + "kind": "other", + "name": "platform-http-main", + "title": "Platform Http Main", + "description": "Platform HTTP for standalone Camel Main applications", + "deprecated": false, + "firstVersion": "4.0.0", + "label": "http", + "supportLevel": "Preview", + "groupId": "org.apache.camel", + "artifactId": "camel-platform-http-main", + "version": "4.0.0-SNAPSHOT" + } +} diff --git a/components/camel-platform-http-main/src/main/docs/platform-http-main.adoc b/components/camel-platform-http-main/src/main/docs/platform-http-main.adoc new file mode 100644 index 00000000000..f8e37126f04 --- /dev/null +++ b/components/camel-platform-http-main/src/main/docs/platform-http-main.adoc @@ -0,0 +1,28 @@ += Platform Http Main Component +:doctitle: Platform Http Main +:shortname: platform-http-main +:artifactid: camel-platform-http-main +:description: Platform HTTP for standalone Camel Main applications +:since: 4.0 +:supportlevel: Preview +:tabs-sync-option: + +*Since Camel {since}* + +The camel-platform-http-main is an embedded HTTP server for `camel-main` standalone applications. + +The embedded HTTP server is using VertX from the `camel-platform-http-vertx` dependency. + +== Enabling + +The HTTP server for `camel-main` (is default disabled), and you need to explicit enable this +by setting `camel.server.enabled=true` in application.properties. + +== Auto detection from classpath + +To use this implementation all you need to do is to add the `camel-platform-http-main` dependency to the classpath, +and the platform http component should auto-detect this. + +== See More + +- xref:platform-http-vertx.adoc[Platform HTTP Vert.x] diff --git a/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/DefaultMainHttpServerFactory.java b/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/DefaultMainHttpServerFactory.java new file mode 100644 index 00000000000..f5bac97f9ec --- /dev/null +++ b/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/DefaultMainHttpServerFactory.java @@ -0,0 +1,61 @@ +/* + * 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.main; + +import org.apache.camel.CamelContext; +import org.apache.camel.CamelContextAware; +import org.apache.camel.Service; +import org.apache.camel.main.HttpServerConfigurationProperties; +import org.apache.camel.main.MainConstants; +import org.apache.camel.main.MainHttpServerFactory; +import org.apache.camel.spi.annotations.JdkService; + +@JdkService(MainConstants.PLATFORM_HTTP_SERVER) +public class DefaultMainHttpServerFactory implements CamelContextAware, MainHttpServerFactory { + + private CamelContext camelContext; + + @Override + public CamelContext getCamelContext() { + return camelContext; + } + + @Override + public void setCamelContext(CamelContext camelContext) { + this.camelContext = camelContext; + } + + @Override + public Service newHttpServer(HttpServerConfigurationProperties configuration) { + MainHttpServer server = new MainHttpServer(); + + server.setCamelContext(camelContext); + server.setHost(configuration.getHost()); + server.setPort(configuration.getPort()); + server.setPath(configuration.getPath()); + if (configuration.getMaxBodySize() != null) { + server.setMaxBodySize(configuration.getMaxBodySize()); + } + server.setUseGlobalSslContextParameters(configuration.isUseGlobalSslContextParameters()); + server.setDevConsoleEnabled(configuration.isDevConsoleEnabled()); + server.setHealthCheckEnabled(configuration.isHealthCheckEnabled()); + server.setUploadEnabled(configuration.isUploadEnabled()); + server.setUploadSourceDir(configuration.getUploadSourceDir()); + + return server; + } +} diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/http/VertxHttpServer.java b/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/MainHttpServer.java similarity index 67% copy from dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/http/VertxHttpServer.java copy to components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/MainHttpServer.java index 87af11329e9..1faf36fc704 100644 --- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/http/VertxHttpServer.java +++ b/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/MainHttpServer.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.main.http; +package org.apache.camel.component.platform.http.main; import java.io.File; import java.io.FileOutputStream; @@ -29,7 +29,6 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; import io.vertx.core.Handler; @@ -40,9 +39,11 @@ import io.vertx.ext.web.RoutingContext; import io.vertx.ext.web.handler.BodyHandler; import io.vertx.ext.web.impl.BlockingHandlerDecorator; import org.apache.camel.CamelContext; +import org.apache.camel.CamelContextAware; import org.apache.camel.Exchange; -import org.apache.camel.RuntimeCamelException; +import org.apache.camel.NonManagedService; import org.apache.camel.StartupListener; +import org.apache.camel.StaticService; import org.apache.camel.component.platform.http.HttpEndpointModel; import org.apache.camel.component.platform.http.PlatformHttpComponent; import org.apache.camel.component.platform.http.vertx.VertxPlatformHttpRouter; @@ -53,9 +54,11 @@ import org.apache.camel.console.DevConsoleRegistry; import org.apache.camel.health.HealthCheck; import org.apache.camel.health.HealthCheckHelper; import org.apache.camel.health.HealthCheckRegistry; -import org.apache.camel.main.util.CamelJBangSettingsHelper; import org.apache.camel.spi.CamelEvent; import org.apache.camel.support.SimpleEventNotifierSupport; +import org.apache.camel.support.jsse.SSLContextParameters; +import org.apache.camel.support.service.ServiceHelper; +import org.apache.camel.support.service.ServiceSupport; import org.apache.camel.util.AntPathMatcher; import org.apache.camel.util.FileUtil; import org.apache.camel.util.IOHelper; @@ -65,252 +68,233 @@ import org.apache.camel.util.json.JsonObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -/** - * To setup vertx http server in the running Camel application - */ -public final class VertxHttpServer { +public class MainHttpServer extends ServiceSupport implements CamelContextAware, StaticService, NonManagedService { + + private static final Logger LOG = LoggerFactory.getLogger(MainHttpServer.class); + + private VertxPlatformHttpServer server; + private VertxPlatformHttpRouter router; - static VertxPlatformHttpRouter router; - static VertxPlatformHttpServer server; - static PlatformHttpComponent phc; + private CamelContext camelContext; + private PlatformHttpComponent platformHttpComponent; - private static final Logger LOG = LoggerFactory.getLogger(VertxHttpServer.class); - private static final AtomicBoolean REGISTERED = new AtomicBoolean(); - private static final AtomicBoolean CONSOLE = new AtomicBoolean(); - private static final AtomicBoolean HEALTH_CHECK = new AtomicBoolean(); - private static final AtomicBoolean UPLOAD = new AtomicBoolean(); + private VertxPlatformHttpServerConfiguration configuration = new VertxPlatformHttpServerConfiguration(); + private boolean devConsoleEnabled; + private boolean healthCheckEnabled; + private boolean uploadEnabled; + private String uploadSourceDir; - private VertxHttpServer() { + @Override + public CamelContext getCamelContext() { + return camelContext; } - public static void setPlatformHttpComponent(PlatformHttpComponent phc) { - VertxHttpServer.phc = phc; + @Override + public void setCamelContext(CamelContext camelContext) { + this.camelContext = camelContext; } - public static void registerServer(CamelContext camelContext, boolean stub) { - if (REGISTERED.compareAndSet(false, true)) { - doRegisterServer(camelContext, 8080, stub); - } + public VertxPlatformHttpServerConfiguration getConfiguration() { + return configuration; } - public static void registerServer(CamelContext camelContext, int port, boolean stub) { - if (REGISTERED.compareAndSet(false, true)) { - doRegisterServer(camelContext, port, stub); - } + public void setConfiguration(VertxPlatformHttpServerConfiguration configuration) { + this.configuration = configuration; } - private static void doRegisterServer(CamelContext camelContext, int port, boolean stub) { - // need to capture we use http-server - CamelJBangSettingsHelper.writeSettings("camel.jbang.platform-http.port", Integer.toString(port)); + public boolean isDevConsoleEnabled() { + return devConsoleEnabled; + } - if (stub) { - return; - } + /** + * Whether developer web console is enabled (q/dev) + */ + public void setDevConsoleEnabled(boolean devConsoleEnabled) { + this.devConsoleEnabled = devConsoleEnabled; + } - try { - VertxPlatformHttpServerConfiguration config = new VertxPlatformHttpServerConfiguration(); - config.setPort(port); - server = new VertxPlatformHttpServer(config); - camelContext.addService(server); - server.start(); - router = VertxPlatformHttpRouter.lookup(camelContext); - if (phc == null) { - phc = camelContext.getComponent("platform-http", PlatformHttpComponent.class); - } + public boolean isHealthCheckEnabled() { + return healthCheckEnabled; + } - // after camel is started then add event notifier - camelContext.addStartupListener(new StartupListener() { + /** + * Whether health-check is enabled (q/health) + */ + public void setHealthCheckEnabled(boolean healthCheckEnabled) { + this.healthCheckEnabled = healthCheckEnabled; + } - private volatile Set<HttpEndpointModel> last; + public boolean isUploadEnabled() { + return uploadEnabled; + } - @Override - public void onCamelContextStarted(CamelContext context, boolean alreadyStarted) throws Exception { - camelContext.getManagementStrategy().addEventNotifier(new SimpleEventNotifierSupport() { + /** + * Whether file upload is enabled (only for development) (q/upload) + */ + public void setUploadEnabled(boolean uploadEnabled) { + this.uploadEnabled = uploadEnabled; + } - @Override - public boolean isEnabled(CamelEvent event) { - return event instanceof CamelEvent.CamelContextStartedEvent - || event instanceof CamelEvent.RouteReloadedEvent; - } + public String getUploadSourceDir() { + return uploadSourceDir; + } - @Override - public void notify(CamelEvent event) throws Exception { - // when reloading then there may be more routes in the same batch, so we only want - // to log the summary at the end - if (event instanceof CamelEvent.RouteReloadedEvent) { - CamelEvent.RouteReloadedEvent re = (CamelEvent.RouteReloadedEvent) event; - if (re.getIndex() < re.getTotal()) { - return; - } - } + /** + * Directory for upload. + */ + public void setUploadSourceDir(String uploadSourceDir) { + this.uploadSourceDir = uploadSourceDir; + } - Set<HttpEndpointModel> endpoints = phc.getHttpEndpoints(); - if (endpoints.isEmpty()) { - return; - } + public int getPort() { + return configuration.getBindPort(); + } - // log only if changed - if (last == null || last.size() != endpoints.size() || !last.containsAll(endpoints)) { - LOG.info("HTTP endpoints summary"); - for (HttpEndpointModel u : endpoints) { - String line = "http://0.0.0.0:" + port + u.getUri(); - if (u.getVerbs() != null) { - line += " (" + u.getVerbs() + ")"; - } - LOG.info(" {}", line); - } - } + public void setPort(int port) { + configuration.setBindPort(port); + } - // use a defensive copy of last known endpoints - last = new HashSet<>(endpoints); - } - }); - } - }); + public String getHost() { + return configuration.getBindHost(); + } - } catch (Exception e) { - throw RuntimeCamelException.wrapRuntimeException(e); - } + public void setHost(String host) { + configuration.setBindHost(host); } - public static void registerConsole(CamelContext camelContext) { - if (CONSOLE.compareAndSet(false, true)) { - doRegisterConsole(camelContext); - } + public String getPath() { + return configuration.getPath(); } - private static void doRegisterConsole(CamelContext context) { - Route dev = router.route("/q/dev"); - dev.method(HttpMethod.GET); - dev.produces("text/plain"); - dev.produces("application/json"); - Route devSub = router.route("/q/dev/*"); - devSub.method(HttpMethod.GET); - devSub.produces("text/plain"); - devSub.produces("application/json"); + public void setPath(String path) { + configuration.setPath(path); + } - Handler<RoutingContext> handler = new Handler<RoutingContext>() { - @Override - public void handle(RoutingContext ctx) { - String acp = ctx.request().getHeader("Accept"); - int pos1 = acp != null ? acp.indexOf("html") : Integer.MAX_VALUE; - if (pos1 == -1) { - pos1 = Integer.MAX_VALUE; - } - int pos2 = acp != null ? acp.indexOf("json") : Integer.MAX_VALUE; - if (pos2 == -1) { - pos2 = Integer.MAX_VALUE; - } - final boolean html = pos1 < pos2; - final boolean json = pos2 < pos1; - final DevConsole.MediaType mediaType = json ? DevConsole.MediaType.JSON : DevConsole.MediaType.TEXT; + public Long getMaxBodySize() { + return configuration.getMaxBodySize(); + } - ctx.response().putHeader("content-type", "text/plain"); + public void setMaxBodySize(Long maxBodySize) { + configuration.setMaxBodySize(maxBodySize); + } - DevConsoleRegistry dcr = context.getCamelContextExtension().getContextPlugin(DevConsoleRegistry.class); - if (dcr == null || !dcr.isEnabled()) { - ctx.end("Developer Console is not enabled"); - return; - } + public SSLContextParameters getSslContextParameters() { + return configuration.getSslContextParameters(); + } - String path = StringHelper.after(ctx.request().path(), "/q/dev/"); - String s = path; - if (s != null && s.contains("/")) { - s = StringHelper.before(s, "/"); - } - String id = s; + public void setSslContextParameters(SSLContextParameters sslContextParameters) { + configuration.setSslContextParameters(sslContextParameters); + } - // index/home should list each console - if (id == null || id.isEmpty() || id.equals("index")) { - StringBuilder sb = new StringBuilder(); - JsonObject root = new JsonObject(); + public boolean isUseGlobalSslContextParameters() { + return configuration.isUseGlobalSslContextParameters(); + } - dcr.stream().forEach(c -> { - if (json) { - JsonObject jo = new JsonObject(); - jo.put("id", c.getId()); - jo.put("displayName", c.getDisplayName()); - jo.put("description", c.getDescription()); - root.put(c.getId(), jo); - } else { - String link = c.getId(); - String eol = "\n"; - if (html) { - link = "<a href=\"dev/" + link + "\">" + c.getId() + "</a>"; - eol = "<br/>\n"; - } - sb.append(link).append(": ").append(c.getDescription()).append(eol); - // special for top in processor mode - if ("top".equals(c.getId())) { - link = link.replace("top", "top/*"); - sb.append(link).append(": ").append("Display the top processors").append(eol); + public void setUseGlobalSslContextParameters(boolean useGlobalSslContextParameters) { + configuration.setUseGlobalSslContextParameters(useGlobalSslContextParameters); + } + + public VertxPlatformHttpServerConfiguration.Cors getCors() { + return configuration.getCors(); + } + + public void setCors(VertxPlatformHttpServerConfiguration.Cors corsConfiguration) { + configuration.setCors(corsConfiguration); + } + + public VertxPlatformHttpServerConfiguration.BodyHandler getBodyHandler() { + return configuration.getBodyHandler(); + } + + public void setBodyHandler(VertxPlatformHttpServerConfiguration.BodyHandler bodyHandler) { + configuration.setBodyHandler(bodyHandler); + } + + public VertxPlatformHttpRouter getRouter() { + return router; + } + + @Override + protected void doStart() throws Exception { + ObjectHelper.notNull(camelContext, "CamelContext"); + + server = new VertxPlatformHttpServer(configuration); + camelContext.addService(server); + ServiceHelper.startService(server); + router = VertxPlatformHttpRouter.lookup(camelContext); + platformHttpComponent = camelContext.getComponent("platform-http", PlatformHttpComponent.class); + + setupConsoles(); + setupStartupSummary(); + } + + protected void setupConsoles() { + if (devConsoleEnabled) { + setupDevConsole(); + } + if (healthCheckEnabled) { + setupHealthCheckConsole(); + } + if (uploadEnabled) { + if (uploadSourceDir == null) { + throw new IllegalArgumentException("UploadSourceDir must be configured when uploadEnabled=true"); + } + setupUploadConsole(uploadSourceDir); + } + } + + protected void setupStartupSummary() throws Exception { + camelContext.addStartupListener(new StartupListener() { + + private volatile Set<HttpEndpointModel> last; + + @Override + public void onCamelContextStarted(CamelContext context, boolean alreadyStarted) throws Exception { + camelContext.getManagementStrategy().addEventNotifier(new SimpleEventNotifierSupport() { + + @Override + public boolean isEnabled(CamelEvent event) { + return event instanceof CamelEvent.CamelContextStartedEvent + || event instanceof CamelEvent.RouteReloadedEvent; + } + + @Override + public void notify(CamelEvent event) throws Exception { + // when reloading then there may be more routes in the same batch, so we only want + // to log the summary at the end + if (event instanceof CamelEvent.RouteReloadedEvent) { + CamelEvent.RouteReloadedEvent re = (CamelEvent.RouteReloadedEvent) event; + if (re.getIndex() < re.getTotal()) { + return; } } - }); - if (sb.length() > 0) { - String out = sb.toString(); - if (html) { - ctx.response().putHeader("content-type", "text/html"); + + Set<HttpEndpointModel> endpoints = platformHttpComponent.getHttpEndpoints(); + if (endpoints.isEmpty()) { + return; } - ctx.end(out); - } else if (!root.isEmpty()) { - ctx.response().putHeader("content-type", "application/json"); - String out = root.toJson(); - ctx.end(out); - } - } else { - Map<String, Object> params = new HashMap<>(); - ctx.queryParams().forEach(params::put); - params.put(Exchange.HTTP_PATH, path); - StringBuilder sb = new StringBuilder(); - JsonObject root = new JsonObject(); - // sort according to index by given id - dcr.stream().sorted((o1, o2) -> { - int p1 = id.indexOf(o1.getId()); - int p2 = id.indexOf(o2.getId()); - return Integer.compare(p1, p2); - }).forEach(c -> { - boolean include = "all".equals(id) || c.getId().equalsIgnoreCase(id); - if (include && c.supportMediaType(mediaType)) { - Object out = c.call(mediaType, params); - if (out != null && mediaType == DevConsole.MediaType.TEXT) { - sb.append(c.getDisplayName()).append(":"); - sb.append("\n\n"); - sb.append(out); - sb.append("\n\n"); - } else if (out != null && mediaType == DevConsole.MediaType.JSON) { - root.put(c.getId(), out); + // log only if changed + if (last == null || last.size() != endpoints.size() || !last.containsAll(endpoints)) { + LOG.info("HTTP endpoints summary"); + for (HttpEndpointModel u : endpoints) { + String line = "http://0.0.0.0:" + (server != null ? server.getPort() : getPort()) + u.getUri(); + if (u.getVerbs() != null) { + line += " (" + u.getVerbs() + ")"; + } + LOG.info(" {}", line); } } - }); - if (sb.length() > 0) { - String out = sb.toString(); - ctx.end(out); - } else if (!root.isEmpty()) { - ctx.response().putHeader("content-type", "application/json"); - String out = root.toJson(); - ctx.end(out); - } else { - ctx.end("Developer Console not found: " + id); + + // use a defensive copy of last known endpoints + last = new HashSet<>(endpoints); } - } + }); } - }; - // use blocking handler as the task can take longer time to complete - dev.handler(new BlockingHandlerDecorator(handler, true)); - devSub.handler(new BlockingHandlerDecorator(handler, true)); - - phc.addHttpEndpoint("/q/dev", null, null); - } - - public static void registerHealthCheck(CamelContext camelContext) { - if (HEALTH_CHECK.compareAndSet(false, true)) { - doRegisterHealthCheck(camelContext); - } + }); } - private static void doRegisterHealthCheck(CamelContext context) { + protected void setupHealthCheckConsole() { final Route health = router.route("/q/health"); health.method(HttpMethod.GET); health.produces("application/json"); @@ -332,17 +316,17 @@ public final class VertxHttpServer { Collection<HealthCheck.Result> res; if (all) { - res = HealthCheckHelper.invoke(context); + res = HealthCheckHelper.invoke(camelContext); } else if (liv) { - res = HealthCheckHelper.invokeLiveness(context); + res = HealthCheckHelper.invokeLiveness(camelContext); } else { - res = HealthCheckHelper.invokeReadiness(context); + res = HealthCheckHelper.invokeReadiness(camelContext); } StringBuilder sb = new StringBuilder(); sb.append("{\n"); - HealthCheckRegistry registry = HealthCheckRegistry.get(context); + HealthCheckRegistry registry = HealthCheckRegistry.get(camelContext); String level = ctx.request().getParam("exposureLevel"); if (level == null) { level = registry.getExposureLevel(); @@ -378,7 +362,12 @@ public final class VertxHttpServer { live.handler(new BlockingHandlerDecorator(handler, true)); ready.handler(new BlockingHandlerDecorator(handler, true)); - phc.addHttpEndpoint("/q/health", null, null); + platformHttpComponent.addHttpEndpoint("/q/health", null, null); + } + + @Override + protected void doStop() throws Exception { + ServiceHelper.stopAndShutdownService(server); } private static void healthCheckStatus(StringBuilder sb, boolean up) { @@ -472,13 +461,137 @@ public final class VertxHttpServer { return trace; } - public static void registerUploadSourceDir(CamelContext camelContext, String dir) { - if (UPLOAD.compareAndSet(false, true)) { - doRegisterUploadSourceDir(camelContext, dir); - } + protected void setupDevConsole() { + Route dev = router.route("/q/dev"); + dev.method(HttpMethod.GET); + dev.produces("text/plain"); + dev.produces("application/json"); + Route devSub = router.route("/q/dev/*"); + devSub.method(HttpMethod.GET); + devSub.produces("text/plain"); + devSub.produces("application/json"); + + Handler<RoutingContext> handler = new Handler<RoutingContext>() { + @Override + public void handle(RoutingContext ctx) { + String acp = ctx.request().getHeader("Accept"); + int pos1 = acp != null ? acp.indexOf("html") : Integer.MAX_VALUE; + if (pos1 == -1) { + pos1 = Integer.MAX_VALUE; + } + int pos2 = acp != null ? acp.indexOf("json") : Integer.MAX_VALUE; + if (pos2 == -1) { + pos2 = Integer.MAX_VALUE; + } + final boolean html = pos1 < pos2; + final boolean json = pos2 < pos1; + final DevConsole.MediaType mediaType = json ? DevConsole.MediaType.JSON : DevConsole.MediaType.TEXT; + + ctx.response().putHeader("content-type", "text/plain"); + + if (!camelContext.isDevConsole()) { + ctx.end("Developer Console is not enabled on CamelContext. Set camel.context.dev-console=true in application.properties"); + } + DevConsoleRegistry dcr = camelContext.getCamelContextExtension().getContextPlugin(DevConsoleRegistry.class); + if (dcr == null || !dcr.isEnabled()) { + ctx.end("Developer Console is not enabled"); + return; + } + + String path = StringHelper.after(ctx.request().path(), "/q/dev/"); + String s = path; + if (s != null && s.contains("/")) { + s = StringHelper.before(s, "/"); + } + String id = s; + + // index/home should list each console + if (id == null || id.isEmpty() || id.equals("index")) { + StringBuilder sb = new StringBuilder(); + JsonObject root = new JsonObject(); + + dcr.stream().forEach(c -> { + if (json) { + JsonObject jo = new JsonObject(); + jo.put("id", c.getId()); + jo.put("displayName", c.getDisplayName()); + jo.put("description", c.getDescription()); + root.put(c.getId(), jo); + } else { + String link = c.getId(); + String eol = "\n"; + if (html) { + link = "<a href=\"dev/" + link + "\">" + c.getId() + "</a>"; + eol = "<br/>\n"; + } + sb.append(link).append(": ").append(c.getDescription()).append(eol); + // special for top in processor mode + if ("top".equals(c.getId())) { + link = link.replace("top", "top/*"); + sb.append(link).append(": ").append("Display the top processors").append(eol); + } + } + }); + if (sb.length() > 0) { + String out = sb.toString(); + if (html) { + ctx.response().putHeader("content-type", "text/html"); + } + ctx.end(out); + } else if (!root.isEmpty()) { + ctx.response().putHeader("content-type", "application/json"); + String out = root.toJson(); + ctx.end(out); + } else { + ctx.end(); + } + } else { + Map<String, Object> params = new HashMap<>(); + ctx.queryParams().forEach(params::put); + params.put(Exchange.HTTP_PATH, path); + StringBuilder sb = new StringBuilder(); + JsonObject root = new JsonObject(); + + // sort according to index by given id + dcr.stream().sorted((o1, o2) -> { + int p1 = id.indexOf(o1.getId()); + int p2 = id.indexOf(o2.getId()); + return Integer.compare(p1, p2); + }).forEach(c -> { + boolean include = "all".equals(id) || c.getId().equalsIgnoreCase(id); + if (include && c.supportMediaType(mediaType)) { + Object out = c.call(mediaType, params); + if (out != null && mediaType == DevConsole.MediaType.TEXT) { + sb.append(c.getDisplayName()).append(":"); + sb.append("\n\n"); + sb.append(out); + sb.append("\n\n"); + } else if (out != null && mediaType == DevConsole.MediaType.JSON) { + root.put(c.getId(), out); + } + } + }); + if (sb.length() > 0) { + String out = sb.toString(); + ctx.end(out); + } else if (!root.isEmpty()) { + ctx.response().putHeader("content-type", "application/json"); + String out = root.toJson(); + ctx.end(out); + } else { + ctx.end("Developer Console not found: " + id); + } + } + } + }; + // use blocking handler as the task can take longer time to complete + dev.handler(new BlockingHandlerDecorator(handler, true)); + devSub.handler(new BlockingHandlerDecorator(handler, true)); + + platformHttpComponent.addHttpEndpoint("/q/dev", null, null); } - private static void doRegisterUploadSourceDir(CamelContext context, final String dir) { + protected void setupUploadConsole(final String dir) { final Route upload = router.route("/q/upload/:filename") .method(HttpMethod.PUT) // need body handler to handle file uploads @@ -556,7 +669,7 @@ public final class VertxHttpServer { upload.handler(new BlockingHandlerDecorator(handler, true)); uploadDelete.handler(new BlockingHandlerDecorator(handler, true)); - phc.addHttpEndpoint("/q/upload", "PUT,DELETE", null); + platformHttpComponent.addHttpEndpoint("/q/upload", "PUT,DELETE", null); } } diff --git a/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpServer.java b/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpServer.java index ff80d94f61e..a7abed73a53 100644 --- a/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpServer.java +++ b/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpServer.java @@ -29,6 +29,9 @@ import io.vertx.ext.web.Router; import io.vertx.ext.web.RoutingContext; import org.apache.camel.CamelContext; import org.apache.camel.CamelContextAware; +import org.apache.camel.StaticService; +import org.apache.camel.api.management.ManagedAttribute; +import org.apache.camel.api.management.ManagedResource; import org.apache.camel.component.platform.http.PlatformHttpConstants; import org.apache.camel.support.CamelContextHelper; import org.apache.camel.support.service.ServiceHelper; @@ -44,7 +47,8 @@ import static org.apache.camel.component.platform.http.vertx.VertxPlatformHttpSe * This class implement a basic Vert.x Web based server that can be used by the {@link VertxPlatformHttpEngine} on * platforms that do not provide Vert.x based http services. */ -public class VertxPlatformHttpServer extends ServiceSupport implements CamelContextAware { +@ManagedResource(description = "Vert.x HTTP Server") +public class VertxPlatformHttpServer extends ServiceSupport implements CamelContextAware, StaticService { private static final Logger LOGGER = LoggerFactory.getLogger(VertxPlatformHttpServer.class); private final VertxPlatformHttpServerConfiguration configuration; @@ -115,6 +119,34 @@ public class VertxPlatformHttpServer extends ServiceSupport implements CamelCont } } + @ManagedAttribute(description = "HTTP port number") + public int getPort() { + if (server != null) { + return server.actualPort(); + } + return configuration.getBindPort(); + } + + @ManagedAttribute(description = "HTTP hostname") + public String getHost() { + return configuration.getBindHost(); + } + + @ManagedAttribute(description = "HTTP context-path") + public String getPath() { + return configuration.getPath(); + } + + @ManagedAttribute(description = "HTTP maximum HTTP body size") + public Long getMaxBodySize() { + return configuration.getMaxBodySize(); + } + + @ManagedAttribute(description = "Should SSL be used from global SSL configuration") + public boolean isUseGlobalSslContextParameters() { + return configuration.isUseGlobalSslContextParameters(); + } + // ******************************* // // Helpers diff --git a/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpServerConfiguration.java b/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpServerConfiguration.java index ef89c92d360..3720b250b59 100644 --- a/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpServerConfiguration.java +++ b/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpServerConfiguration.java @@ -16,7 +16,6 @@ */ package org.apache.camel.component.platform.http.vertx; -import java.math.BigInteger; import java.time.Duration; import java.util.List; @@ -33,7 +32,7 @@ public class VertxPlatformHttpServerConfiguration { private String bindHost = DEFAULT_BIND_HOST; private int bindPort = DEFAULT_BIND_PORT; private String path = DEFAULT_PATH; - private BigInteger maxBodySize; + private Long maxBodySize; private SSLContextParameters sslContextParameters; private boolean useGlobalSslContextParameters; @@ -81,11 +80,11 @@ public class VertxPlatformHttpServerConfiguration { this.path = path; } - public BigInteger getMaxBodySize() { + public Long getMaxBodySize() { return maxBodySize; } - public void setMaxBodySize(BigInteger maxBodySize) { + public void setMaxBodySize(Long maxBodySize) { this.maxBodySize = maxBodySize; } diff --git a/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpServerSupport.java b/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpServerSupport.java index 1964ef021af..23cadb5e79d 100644 --- a/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpServerSupport.java +++ b/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpServerSupport.java @@ -51,7 +51,7 @@ public final class VertxPlatformHttpServerSupport { BodyHandler bodyHandler = BodyHandler.create(); if (configuration.getMaxBodySize() != null) { - bodyHandler.setBodyLimit(configuration.getMaxBodySize().longValueExact()); + bodyHandler.setBodyLimit(configuration.getMaxBodySize()); } bodyHandler.setHandleFileUploads(configuration.getBodyHandler().isHandleFileUploads()); diff --git a/components/camel-test/camel-test-main-junit5/src/main/java/org/apache/camel/test/main/junit5/CamelMainTestSupport.java b/components/camel-test/camel-test-main-junit5/src/main/java/org/apache/camel/test/main/junit5/CamelMainTestSupport.java index 6915073c397..e881930c129 100644 --- a/components/camel-test/camel-test-main-junit5/src/main/java/org/apache/camel/test/main/junit5/CamelMainTestSupport.java +++ b/components/camel-test/camel-test-main-junit5/src/main/java/org/apache/camel/test/main/junit5/CamelMainTestSupport.java @@ -17,8 +17,8 @@ package org.apache.camel.test.main.junit5; import org.apache.camel.CamelContext; -import org.apache.camel.main.BaseMainSupport; import org.apache.camel.main.MainConfigurationProperties; +import org.apache.camel.main.MainConstants; import org.apache.camel.spi.Registry; import org.apache.camel.test.junit5.CamelTestSupport; import org.slf4j.Logger; @@ -95,7 +95,7 @@ public abstract class CamelMainTestSupport extends CamelTestSupport { final String locations = getPropertyPlaceholderLocationsFromFileName(); if (locations == null) { LOG.debug("Use the default property placeholder location"); - return BaseMainSupport.DEFAULT_PROPERTY_PLACEHOLDER_LOCATION; + return MainConstants.DEFAULT_PROPERTY_PLACEHOLDER_LOCATION; } LOG.debug("Use the following property placeholder locations: {}", locations); return locations; diff --git a/components/pom.xml b/components/pom.xml index 85be12185c9..a849027aaa4 100644 --- a/components/pom.xml +++ b/components/pom.xml @@ -236,6 +236,7 @@ <module>camel-pgevent</module> <module>camel-platform-http</module> <module>camel-platform-http-vertx</module> + <module>camel-platform-http-main</module> <module>camel-plc4x</module> <module>camel-printer</module> <module>camel-protobuf</module> diff --git a/core/camel-main/src/generated/java/org/apache/camel/main/HttpServerConfigurationPropertiesConfigurer.java b/core/camel-main/src/generated/java/org/apache/camel/main/HttpServerConfigurationPropertiesConfigurer.java new file mode 100644 index 00000000000..07c8e29295b --- /dev/null +++ b/core/camel-main/src/generated/java/org/apache/camel/main/HttpServerConfigurationPropertiesConfigurer.java @@ -0,0 +1,103 @@ +/* Generated by camel build tools - do NOT edit this file! */ +package org.apache.camel.main; + +import java.util.Map; + +import org.apache.camel.CamelContext; +import org.apache.camel.spi.ExtendedPropertyConfigurerGetter; +import org.apache.camel.spi.PropertyConfigurerGetter; +import org.apache.camel.spi.ConfigurerStrategy; +import org.apache.camel.spi.GeneratedPropertyConfigurer; +import org.apache.camel.util.CaseInsensitiveMap; +import org.apache.camel.main.HttpServerConfigurationProperties; + +/** + * Generated by camel build tools - do NOT edit this file! + */ +@SuppressWarnings("unchecked") +public class HttpServerConfigurationPropertiesConfigurer extends org.apache.camel.support.component.PropertyConfigurerSupport implements GeneratedPropertyConfigurer, PropertyConfigurerGetter { + + @Override + public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) { + org.apache.camel.main.HttpServerConfigurationProperties target = (org.apache.camel.main.HttpServerConfigurationProperties) obj; + switch (ignoreCase ? name.toLowerCase() : name) { + case "devconsoleenabled": + case "DevConsoleEnabled": target.setDevConsoleEnabled(property(camelContext, boolean.class, value)); return true; + case "enabled": + case "Enabled": target.setEnabled(property(camelContext, boolean.class, value)); return true; + case "healthcheckenabled": + case "HealthCheckEnabled": target.setHealthCheckEnabled(property(camelContext, boolean.class, value)); return true; + case "host": + case "Host": target.setHost(property(camelContext, java.lang.String.class, value)); return true; + case "maxbodysize": + case "MaxBodySize": target.setMaxBodySize(property(camelContext, java.lang.Long.class, value)); return true; + case "path": + case "Path": target.setPath(property(camelContext, java.lang.String.class, value)); return true; + case "port": + case "Port": target.setPort(property(camelContext, int.class, value)); return true; + case "uploadenabled": + case "UploadEnabled": target.setUploadEnabled(property(camelContext, boolean.class, value)); return true; + case "uploadsourcedir": + case "UploadSourceDir": target.setUploadSourceDir(property(camelContext, java.lang.String.class, value)); return true; + case "useglobalsslcontextparameters": + case "UseGlobalSslContextParameters": target.setUseGlobalSslContextParameters(property(camelContext, boolean.class, value)); return true; + default: return false; + } + } + + @Override + public Class<?> getOptionType(String name, boolean ignoreCase) { + switch (ignoreCase ? name.toLowerCase() : name) { + case "devconsoleenabled": + case "DevConsoleEnabled": return boolean.class; + case "enabled": + case "Enabled": return boolean.class; + case "healthcheckenabled": + case "HealthCheckEnabled": return boolean.class; + case "host": + case "Host": return java.lang.String.class; + case "maxbodysize": + case "MaxBodySize": return java.lang.Long.class; + case "path": + case "Path": return java.lang.String.class; + case "port": + case "Port": return int.class; + case "uploadenabled": + case "UploadEnabled": return boolean.class; + case "uploadsourcedir": + case "UploadSourceDir": return java.lang.String.class; + case "useglobalsslcontextparameters": + case "UseGlobalSslContextParameters": return boolean.class; + default: return null; + } + } + + @Override + public Object getOptionValue(Object obj, String name, boolean ignoreCase) { + org.apache.camel.main.HttpServerConfigurationProperties target = (org.apache.camel.main.HttpServerConfigurationProperties) obj; + switch (ignoreCase ? name.toLowerCase() : name) { + case "devconsoleenabled": + case "DevConsoleEnabled": return target.isDevConsoleEnabled(); + case "enabled": + case "Enabled": return target.isEnabled(); + case "healthcheckenabled": + case "HealthCheckEnabled": return target.isHealthCheckEnabled(); + case "host": + case "Host": return target.getHost(); + case "maxbodysize": + case "MaxBodySize": return target.getMaxBodySize(); + case "path": + case "Path": return target.getPath(); + case "port": + case "Port": return target.getPort(); + case "uploadenabled": + case "UploadEnabled": return target.isUploadEnabled(); + case "uploadsourcedir": + case "UploadSourceDir": return target.getUploadSourceDir(); + case "useglobalsslcontextparameters": + case "UseGlobalSslContextParameters": return target.isUseGlobalSslContextParameters(); + default: return null; + } + } +} + diff --git a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json index b0ef1361e58..2d16d3f2fc2 100644 --- a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json +++ b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json @@ -1,6 +1,7 @@ { "groups": [ { "name": "camel.main", "description": "Camel Main configurations", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties" }, + { "name": "camel.server", "description": "Camel Embedded HTTP Server (only for standalone; not Spring Boot or Quarkus) configurations", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties" }, { "name": "camel.threadpool", "description": "Camel Thread Pool configurations", "sourceType": "org.apache.camel.main.ThreadPoolConfigurationProperties" }, { "name": "camel.health", "description": "Camel Health Check configurations", "sourceType": "org.apache.camel.main.HealthConfigurationProperties" }, { "name": "camel.rest", "description": "Camel Rest-DSL configurations", "sourceType": "org.apache.camel.spi.RestConfiguration" }, @@ -202,6 +203,16 @@ { "name": "camel.rest.skipBindingOnErrorCode", "description": "Whether to skip binding output if there is a custom HTTP error code, and instead use the response body as-is. This option is default true.", "sourceType": "org.apache.camel.spi.RestConfiguration", "type": "boolean", "javaType": "boolean", "defaultValue": true }, { "name": "camel.rest.useXForwardHeaders", "description": "Whether to use X-Forward headers to set host etc. for Swagger. This option is default true.", "sourceType": "org.apache.camel.spi.RestConfiguration", "type": "boolean", "javaType": "boolean", "defaultValue": true }, { "name": "camel.rest.xmlDataFormat", "description": "Sets a custom xml data format to be used. Important: This option is only for setting a custom name of the data format, not to refer to an existing data format instance.", "sourceType": "org.apache.camel.spi.RestConfiguration", "type": "string", "javaType": "java.lang.String" }, + { "name": "camel.server.devConsoleEnabled", "description": "Whether to enable developer console (not intended for production use). Dev console must also be enabled on CamelContext. For example by setting camel.context.dev-console=true in application.properties, or via code camelContext.setDevConsole(true); If enabled then you can access a basic developer console on context-path: \/q\/dev.", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "boolean", "j [...] + { "name": "camel.server.enabled", "description": "Whether embedded HTTP server is enabled. By default, the server is not enabled.", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" }, + { "name": "camel.server.healthCheckEnabled", "description": "Whether to enable health-check console. If enabled then you can access health-check status on context-path: \/q\/health", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" }, + { "name": "camel.server.host", "description": "Hostname to use for binding embedded HTTP server", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "string", "javaType": "java.lang.String", "defaultValue": "0.0.0.0" }, + { "name": "camel.server.maxBodySize", "description": "Maximum HTTP body size the embedded HTTP server can accept.", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "integer", "javaType": "java.lang.Long" }, + { "name": "camel.server.path", "description": "Context-path to use for embedded HTTP server", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "string", "javaType": "java.lang.String", "defaultValue": "\/" }, + { "name": "camel.server.port", "description": "Port to use for binding embedded HTTP server", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "integer", "javaType": "int", "defaultValue": 8080 }, + { "name": "camel.server.uploadEnabled", "description": "Whether to enable file upload via HTTP (not intended for production use). This functionality is for development to be able to reload Camel routes and code with source changes (if reload is enabled). If enabled then you can upload\/delete files via HTTP PUT\/DELETE on context-path: \/q\/upload\/{name}. You must also configure the uploadSourceDir option.", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "t [...] + { "name": "camel.server.uploadSourceDir", "description": "Source directory when upload is enabled.", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "string", "javaType": "java.lang.String" }, + { "name": "camel.server.useGlobalSslContextParameters", "description": "Whether to use global SSL configuration for securing the embedded HTTP server.", "sourceType": "org.apache.camel.main.HttpServerConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" }, { "name": "camel.threadpool.allowCoreThreadTimeOut", "description": "Sets default whether to allow core threads to timeout", "sourceType": "org.apache.camel.main.ThreadPoolConfigurationProperties", "type": "boolean", "javaType": "java.lang.Boolean", "defaultValue": "false" }, { "name": "camel.threadpool.config", "description": "Adds a configuration for a specific thread pool profile (inherits default values)", "sourceType": "org.apache.camel.main.ThreadPoolConfigurationProperties", "type": "object", "javaType": "java.util.Map" }, { "name": "camel.threadpool.keepAliveTime", "description": "Sets the default keep alive time for inactive threads", "sourceType": "org.apache.camel.main.ThreadPoolConfigurationProperties", "type": "integer", "javaType": "java.lang.Long" }, diff --git a/core/camel-main/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.main.HttpServerConfigurationProperties b/core/camel-main/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.main.HttpServerConfigurationProperties new file mode 100644 index 00000000000..83ca23e8fdc --- /dev/null +++ b/core/camel-main/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.main.HttpServerConfigurationProperties @@ -0,0 +1,2 @@ +# Generated by camel build tools - do NOT edit this file! +class=org.apache.camel.main.HttpServerConfigurationPropertiesConfigurer diff --git a/core/camel-main/src/main/docs/main.adoc b/core/camel-main/src/main/docs/main.adoc index 1b1b80022aa..b499f201672 100644 --- a/core/camel-main/src/main/docs/main.adoc +++ b/core/camel-main/src/main/docs/main.adoc @@ -145,6 +145,25 @@ The camel.main supports 118 options, which are listed below. |=== +=== Camel Embedded HTTP Server (only for standalone; not Spring Boot or Quarkus) configurations +The camel.server supports 10 options, which are listed below. + +[width="100%",cols="2,5,^1,2",options="header"] +|=== +| Name | Description | Default | Type +| *camel.server.devConsoleEnabled* | Whether to enable developer console (not intended for production use). Dev console must also be enabled on CamelContext. For example by setting camel.context.dev-console=true in application.properties, or via code camelContext.setDevConsole(true); If enabled then you can access a basic developer console on context-path: /q/dev. | false | boolean +| *camel.server.enabled* | Whether embedded HTTP server is enabled. By default, the server is not enabled. | false | boolean +| *camel.server.healthCheck{zwsp}Enabled* | Whether to enable health-check console. If enabled then you can access health-check status on context-path: /q/health | false | boolean +| *camel.server.host* | Hostname to use for binding embedded HTTP server | 0.0.0.0 | String +| *camel.server.maxBodySize* | Maximum HTTP body size the embedded HTTP server can accept. | | Long +| *camel.server.path* | Context-path to use for embedded HTTP server | / | String +| *camel.server.port* | Port to use for binding embedded HTTP server | 8080 | int +| *camel.server.uploadEnabled* | Whether to enable file upload via HTTP (not intended for production use). This functionality is for development to be able to reload Camel routes and code with source changes (if reload is enabled). If enabled then you can upload/delete files via HTTP PUT/DELETE on context-path: /q/upload/\{name}. You must also configure the uploadSourceDir option. | false | boolean +| *camel.server.uploadSourceDir* | Source directory when upload is enabled. | | String +| *camel.server.useGlobalSsl{zwsp}ContextParameters* | Whether to use global SSL configuration for securing the embedded HTTP server. | false | boolean +|=== + + === Camel Thread Pool configurations The camel.threadpool supports 8 options, which are listed below. diff --git a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java index aeb9df75289..238bb7ef8cc 100644 --- a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java +++ b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java @@ -42,6 +42,7 @@ import org.apache.camel.Configuration; import org.apache.camel.NoSuchLanguageException; import org.apache.camel.PropertiesLookupListener; import org.apache.camel.RuntimeCamelException; +import org.apache.camel.Service; import org.apache.camel.StartupStep; import org.apache.camel.console.DevConsole; import org.apache.camel.console.DevConsoleRegistry; @@ -95,11 +96,6 @@ import static org.apache.camel.util.StringHelper.matches; */ public abstract class BaseMainSupport extends BaseService { - public static final String DEFAULT_PROPERTY_PLACEHOLDER_LOCATION = "classpath:application.properties;optional=true"; - public static final String INITIAL_PROPERTIES_LOCATION = "camel.main.initial-properties-location"; - public static final String OVERRIDE_PROPERTIES_LOCATION = "camel.main.override-properties-location"; - public static final String PROPERTY_PLACEHOLDER_LOCATION = "camel.main.property-placeholder-location"; - private static final Logger LOG = LoggerFactory.getLogger(BaseMainSupport.class); protected final List<MainListener> listeners = new ArrayList<>(); @@ -108,7 +104,7 @@ public abstract class BaseMainSupport extends BaseService { protected OrderedLocationProperties wildcardProperties = new OrderedLocationProperties(); protected RoutesCollector routesCollector = new DefaultRoutesCollector(); protected String propertyPlaceholderLocations; - protected String defaultPropertyPlaceholderLocation = DEFAULT_PROPERTY_PLACEHOLDER_LOCATION; + protected String defaultPropertyPlaceholderLocation = MainConstants.DEFAULT_PROPERTY_PLACEHOLDER_LOCATION; protected Properties initialProperties; protected Properties overrideProperties; protected boolean standalone = true; @@ -342,7 +338,7 @@ public abstract class BaseMainSupport extends BaseService { String locations = propertyPlaceholderLocations; if (locations == null) { locations - = MainHelper.lookupPropertyFromSysOrEnv(PROPERTY_PLACEHOLDER_LOCATION) + = MainHelper.lookupPropertyFromSysOrEnv(MainConstants.PROPERTY_PLACEHOLDER_LOCATION) .orElse(defaultPropertyPlaceholderLocation); } if (locations != null) { @@ -350,7 +346,7 @@ public abstract class BaseMainSupport extends BaseService { } if (!Objects.equals(locations, "false")) { pc.addLocation(locations); - if (DEFAULT_PROPERTY_PLACEHOLDER_LOCATION.equals(locations)) { + if (MainConstants.DEFAULT_PROPERTY_PLACEHOLDER_LOCATION.equals(locations)) { LOG.debug("Using properties from: {}", locations); } else { // if not default location then log at INFO @@ -359,12 +355,12 @@ public abstract class BaseMainSupport extends BaseService { } } - final Properties ip = tryLoadProperties(initialProperties, INITIAL_PROPERTIES_LOCATION, camelContext); + final Properties ip = tryLoadProperties(initialProperties, MainConstants.INITIAL_PROPERTIES_LOCATION, camelContext); if (ip != null) { pc.setInitialProperties(ip); } - final Properties op = tryLoadProperties(overrideProperties, OVERRIDE_PROPERTIES_LOCATION, camelContext); + final Properties op = tryLoadProperties(overrideProperties, MainConstants.OVERRIDE_PROPERTIES_LOCATION, camelContext); if (op != null) { pc.setOverrideProperties(op); } @@ -946,6 +942,7 @@ public abstract class BaseMainSupport extends BaseService { OrderedLocationProperties beansProperties = new OrderedLocationProperties(); OrderedLocationProperties devConsoleProperties = new OrderedLocationProperties(); OrderedLocationProperties globalOptions = new OrderedLocationProperties(); + OrderedLocationProperties httpServerProperties = new OrderedLocationProperties(); for (String key : prop.stringPropertyNames()) { String loc = prop.getLocation(key); if (key.startsWith("camel.context.")) { @@ -1020,6 +1017,12 @@ public abstract class BaseMainSupport extends BaseService { String option = key.substring(20); validateOptionAndValue(key, option, value); globalOptions.put(loc, optionKey(option), value); + } else if (key.startsWith("camel.server.")) { + // grab the value + String value = prop.getProperty(key); + String option = key.substring(13); + validateOptionAndValue(key, option, value); + httpServerProperties.put(loc, optionKey(option), value); } } @@ -1041,12 +1044,10 @@ public abstract class BaseMainSupport extends BaseService { LOG.debug("Auto-configuring CamelContext from loaded properties: {}", contextProperties.size()); setPropertiesOnTarget(camelContext, camelContext, contextProperties, "camel.context.", mainConfigurationProperties.isAutoConfigurationFailFast(), true, autoConfiguredProperties); - setPropertiesOnTarget(camelContext, camelContext.getCamelContextExtension(), contextProperties, - "camel.context.extension", + "camel.context.", mainConfigurationProperties.isAutoConfigurationFailFast(), true, autoConfiguredProperties); } - if (!restProperties.isEmpty() || mainConfigurationProperties.hasRestConfiguration()) { RestConfigurationProperties rest = mainConfigurationProperties.rest(); LOG.debug("Auto-configuring Rest DSL from loaded properties: {}", restProperties.size()); @@ -1054,13 +1055,17 @@ public abstract class BaseMainSupport extends BaseService { mainConfigurationProperties.isAutoConfigurationFailFast(), true, autoConfiguredProperties); camelContext.setRestConfiguration(rest); } - + if (!httpServerProperties.isEmpty() || mainConfigurationProperties.hasHttpServerConfiguration()) { + LOG.debug("Auto-configuring HTTP Server from loaded properties: {}", httpServerProperties.size()); + setHttpServerProperties(camelContext, httpServerProperties, + mainConfigurationProperties.isAutoConfigurationFailFast(), + autoConfiguredProperties); + } if (!vaultProperties.isEmpty() || mainConfigurationProperties.hasVaultConfiguration()) { LOG.debug("Auto-configuring Vault from loaded properties: {}", vaultProperties.size()); setVaultProperties(camelContext, vaultProperties, mainConfigurationProperties.isAutoConfigurationFailFast(), autoConfiguredProperties); } - if (!threadPoolProperties.isEmpty() || mainConfigurationProperties.hasThreadPoolConfiguration()) { LOG.debug("Auto-configuring Thread Pool from loaded properties: {}", threadPoolProperties.size()); MainSupportModelConfigurer.setThreadPoolProperties(camelContext, mainConfigurationProperties, threadPoolProperties, @@ -1145,6 +1150,11 @@ public abstract class BaseMainSupport extends BaseService { LOG.warn("Property not auto-configured: camel.lra.{}={}", k, v); }); } + if (!httpServerProperties.isEmpty()) { + httpServerProperties.forEach((k, v) -> { + LOG.warn("Property not auto-configured: camel.server.{}={}", k, v); + }); + } // and call after all properties are set DefaultConfigurationConfigurer.afterPropertiesSet(camelContext); @@ -1323,6 +1333,30 @@ public abstract class BaseMainSupport extends BaseService { } } + private void setHttpServerProperties( + CamelContext camelContext, OrderedLocationProperties properties, + boolean failIfNotSet, OrderedLocationProperties autoConfiguredProperties) + throws Exception { + + HttpServerConfigurationProperties server = mainConfigurationProperties.httpServer(); + + setPropertiesOnTarget(camelContext, server, properties, "camel.server.", + mainConfigurationProperties.isAutoConfigurationFailFast(), true, autoConfiguredProperties); + + if (!server.isEnabled()) { + // http server is disabled + return; + } + + // auto-detect camel-platform-http-main on classpath + MainHttpServerFactory sf = resolveMainHttpServerFactory(camelContext); + // create http server as a service managed by camel context + Service http = sf.newHttpServer(server); + // force eager starting as embedded http server is used for + // container platform to check readiness and need to be started eager + camelContext.addService(http, true, true); + } + private void setVaultProperties( CamelContext camelContext, OrderedLocationProperties properties, boolean failIfNotSet, OrderedLocationProperties autoConfiguredProperties) @@ -1514,9 +1548,9 @@ public abstract class BaseMainSupport extends BaseService { Properties propENV = MainHelper.loadEnvironmentVariablesAsProperties(new String[] { "camel.main." }); // special handling of these so remove them // ENV variables cannot use dash so replace with dot - propENV.remove(INITIAL_PROPERTIES_LOCATION.replace('-', '.')); - propENV.remove(OVERRIDE_PROPERTIES_LOCATION.replace('-', '.')); - propENV.remove(PROPERTY_PLACEHOLDER_LOCATION.replace('-', '.')); + propENV.remove(MainConstants.INITIAL_PROPERTIES_LOCATION.replace('-', '.')); + propENV.remove(MainConstants.OVERRIDE_PROPERTIES_LOCATION.replace('-', '.')); + propENV.remove(MainConstants.PROPERTY_PLACEHOLDER_LOCATION.replace('-', '.')); if (!propENV.isEmpty()) { prop.putAll("ENV", propENV); } @@ -1525,12 +1559,12 @@ public abstract class BaseMainSupport extends BaseService { if (mainConfigurationProperties.isAutoConfigurationSystemPropertiesEnabled()) { Properties propJVM = MainHelper.loadJvmSystemPropertiesAsProperties(new String[] { "camel.main." }); // special handling of these so remove them - propJVM.remove(INITIAL_PROPERTIES_LOCATION); - propJVM.remove(StringHelper.dashToCamelCase(INITIAL_PROPERTIES_LOCATION)); - propJVM.remove(OVERRIDE_PROPERTIES_LOCATION); - propJVM.remove(StringHelper.dashToCamelCase(OVERRIDE_PROPERTIES_LOCATION)); - propJVM.remove(PROPERTY_PLACEHOLDER_LOCATION); - propJVM.remove(StringHelper.dashToCamelCase(PROPERTY_PLACEHOLDER_LOCATION)); + propJVM.remove(MainConstants.INITIAL_PROPERTIES_LOCATION); + propJVM.remove(StringHelper.dashToCamelCase(MainConstants.INITIAL_PROPERTIES_LOCATION)); + propJVM.remove(MainConstants.OVERRIDE_PROPERTIES_LOCATION); + propJVM.remove(StringHelper.dashToCamelCase(MainConstants.OVERRIDE_PROPERTIES_LOCATION)); + propJVM.remove(MainConstants.PROPERTY_PLACEHOLDER_LOCATION); + propJVM.remove(StringHelper.dashToCamelCase(MainConstants.PROPERTY_PLACEHOLDER_LOCATION)); if (!propJVM.isEmpty()) { prop.putAll("SYS", propJVM); } @@ -1831,6 +1865,18 @@ public abstract class BaseMainSupport extends BaseService { return answer; } + private static MainHttpServerFactory resolveMainHttpServerFactory(CamelContext camelContext) throws Exception { + // lookup in service registry first + MainHttpServerFactory answer = camelContext.getRegistry().findSingleByType(MainHttpServerFactory.class); + if (answer == null) { + answer = camelContext.getCamelContextExtension().getBootstrapFactoryFinder() + .newInstance(MainConstants.PLATFORM_HTTP_SERVER, MainHttpServerFactory.class) + .orElseThrow(() -> new IllegalArgumentException( + "Cannot find MainHttpServerFactory on classpath. Add camel-platform-http-main to classpath.")); + } + return answer; + } + private static final class PropertyPlaceholderListener implements PropertiesLookupListener { private final OrderedLocationProperties olp; diff --git a/core/camel-main/src/main/java/org/apache/camel/main/HttpServerConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/HttpServerConfigurationProperties.java new file mode 100644 index 00000000000..debafab296d --- /dev/null +++ b/core/camel-main/src/main/java/org/apache/camel/main/HttpServerConfigurationProperties.java @@ -0,0 +1,264 @@ +/* + * 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.main; + +import org.apache.camel.spi.BootstrapCloseable; +import org.apache.camel.spi.Configurer; +import org.apache.camel.spi.Metadata; + +/** + * Configuration for embedded HTTP server for standalone Camel applications (not Spring Boot / Quarkus). + */ +@Configurer(bootstrap = true) +public class HttpServerConfigurationProperties implements BootstrapCloseable { + + private MainConfigurationProperties parent; + + @Metadata + private boolean enabled; + @Metadata(defaultValue = "0.0.0.0") + private String host = "0.0.0.0"; + @Metadata(defaultValue = "8080") + private int port = 8080; + @Metadata(defaultValue = "/") + private String path = "/"; + private Long maxBodySize; + private boolean useGlobalSslContextParameters; + + private boolean devConsoleEnabled; + private boolean healthCheckEnabled; + private boolean uploadEnabled; + private String uploadSourceDir; + + public HttpServerConfigurationProperties(MainConfigurationProperties parent) { + this.parent = parent; + } + + public MainConfigurationProperties end() { + return parent; + } + + @Override + public void close() { + parent = null; + } + + public boolean isEnabled() { + return enabled; + } + + /** + * Whether embedded HTTP server is enabled. By default, the server is not enabled. + */ + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public String getHost() { + return host; + } + + /** + * Hostname to use for binding embedded HTTP server + */ + public void setHost(String host) { + this.host = host; + } + + public int getPort() { + return port; + } + + /** + * Port to use for binding embedded HTTP server + */ + public void setPort(int port) { + this.port = port; + } + + public String getPath() { + return path; + } + + /** + * Context-path to use for embedded HTTP server + */ + public void setPath(String path) { + this.path = path; + } + + public Long getMaxBodySize() { + return maxBodySize; + } + + /** + * Maximum HTTP body size the embedded HTTP server can accept. + */ + public void setMaxBodySize(Long maxBodySize) { + this.maxBodySize = maxBodySize; + } + + public boolean isUseGlobalSslContextParameters() { + return useGlobalSslContextParameters; + } + + /** + * Whether to use global SSL configuration for securing the embedded HTTP server. + */ + public void setUseGlobalSslContextParameters(boolean useGlobalSslContextParameters) { + this.useGlobalSslContextParameters = useGlobalSslContextParameters; + } + + public boolean isDevConsoleEnabled() { + return devConsoleEnabled; + } + + /** + * Whether to enable developer console (not intended for production use). Dev console must also be enabled on + * CamelContext. For example by setting camel.context.dev-console=true in application.properties, or via code + * <tt>camelContext.setDevConsole(true);</tt> If enabled then you can access a basic developer console on + * context-path: /q/dev. + */ + public void setDevConsoleEnabled(boolean devConsoleEnabled) { + this.devConsoleEnabled = devConsoleEnabled; + } + + public boolean isHealthCheckEnabled() { + return healthCheckEnabled; + } + + /** + * Whether to enable health-check console. If enabled then you can access health-check status on context-path: + * /q/health + */ + public void setHealthCheckEnabled(boolean healthCheckEnabled) { + this.healthCheckEnabled = healthCheckEnabled; + } + + public boolean isUploadEnabled() { + return uploadEnabled; + } + + /** + * Whether to enable file upload via HTTP (not intended for production use). This functionality is for development + * to be able to reload Camel routes and code with source changes (if reload is enabled). If enabled then you can + * upload/delete files via HTTP PUT/DELETE on context-path: /q/upload/{name}. You must also configure the + * uploadSourceDir option. + */ + public void setUploadEnabled(boolean uploadEnabled) { + this.uploadEnabled = uploadEnabled; + } + + public String getUploadSourceDir() { + return uploadSourceDir; + } + + /** + * Source directory when upload is enabled. + */ + public void setUploadSourceDir(String uploadSourceDir) { + this.uploadSourceDir = uploadSourceDir; + } + + /** + * Whether embedded HTTP server is enabled. By default, the server is not enabled. + */ + public HttpServerConfigurationProperties withEnabled(boolean enabled) { + this.enabled = enabled; + return this; + } + + /** + * Hostname to use for binding embedded HTTP server + */ + public HttpServerConfigurationProperties withHost(String host) { + this.host = host; + return this; + } + + /** + * Port to use for binding embedded HTTP server + */ + public HttpServerConfigurationProperties withPort(int port) { + this.port = port; + return this; + } + + /** + * Context-path to use for embedded HTTP server + */ + public HttpServerConfigurationProperties withPath(String path) { + this.path = path; + return this; + } + + /** + * Maximum HTTP body size the embedded HTTP server can accept. + */ + public HttpServerConfigurationProperties withMaxBodySize(long maxBodySize) { + this.maxBodySize = maxBodySize; + return this; + } + + /** + * Whether to use global SSL configuration for securing the embedded HTTP server. + */ + public HttpServerConfigurationProperties withUseGlobalSslContextParameters(boolean useGlobalSslContextParameters) { + this.useGlobalSslContextParameters = useGlobalSslContextParameters; + return this; + } + + /** + * Whether to enable developer console (not intended for production use). Dev console must also be enabled on + * CamelContext. For example by setting camel.context.dev-console=true in application.properties, or via code + * <tt>camelContext.setDevConsole(true);</tt> If enabled then you can access a basic developer console on + * context-path: /q/dev. + */ + public HttpServerConfigurationProperties withDevConsumeEnabled(boolean devConsumeEnabled) { + this.devConsoleEnabled = devConsumeEnabled; + return this; + } + + /** + * Whether to enable health-check console. If enabled then you can access health-check status on context-path: + * /q/health + */ + public HttpServerConfigurationProperties withHealthCheckEnabled(boolean healthCheckEnabled) { + this.healthCheckEnabled = healthCheckEnabled; + return this; + } + + /** + * Whether to enable file upload via HTTP (not intended for production use). This functionality is for development + * to be able to reload Camel routes and code with source changes (if reload is enabled). If enabled then you can + * upload/delete files via HTTP PUT/DELETE on context-path: /q/upload/{name}. You must also configure the + * uploadSourceDir option. + */ + public HttpServerConfigurationProperties withUploadEnabled(boolean uploadEnabled) { + this.uploadEnabled = uploadEnabled; + return this; + } + + /** + * Source directory when upload is enabled. + */ + public HttpServerConfigurationProperties withUploadSourceDir(String uploadSourceDir) { + this.uploadSourceDir = uploadSourceDir; + return this; + } + +} diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java index 42901939812..77e58d187b4 100644 --- a/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java +++ b/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java @@ -58,6 +58,7 @@ public class MainConfigurationProperties extends DefaultConfigurationProperties< private FaultToleranceConfigurationProperties faultToleranceConfigurationProperties; private RestConfigurationProperties restConfigurationProperties; private VaultConfigurationProperties vaultConfigurationProperties; + private HttpServerConfigurationProperties httpServerConfigurationProperties; @Override public void close() { @@ -89,6 +90,10 @@ public class MainConfigurationProperties extends DefaultConfigurationProperties< vaultConfigurationProperties.close(); vaultConfigurationProperties = null; } + if (httpServerConfigurationProperties != null) { + httpServerConfigurationProperties.close(); + httpServerConfigurationProperties = null; + } if (routesBuilders != null) { routesBuilders.clear(); routesBuilders = null; @@ -136,6 +141,23 @@ public class MainConfigurationProperties extends DefaultConfigurationProperties< return lraConfigurationProperties != null; } + /** + * To configure embedded HTTP server (for standalone applications; not Spring Boot or Quarkus) + */ + public HttpServerConfigurationProperties httpServer() { + if (httpServerConfigurationProperties == null) { + httpServerConfigurationProperties = new HttpServerConfigurationProperties(this); + } + return httpServerConfigurationProperties; + } + + /** + * Whether there has been any embedded HTTP server configuration specified + */ + public boolean hasHttpServerConfiguration() { + return httpServerConfigurationProperties != null; + } + /** * To configure thread pools */ diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainConstants.java b/core/camel-main/src/main/java/org/apache/camel/main/MainConstants.java new file mode 100644 index 00000000000..808722a3aa4 --- /dev/null +++ b/core/camel-main/src/main/java/org/apache/camel/main/MainConstants.java @@ -0,0 +1,30 @@ +/* + * 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.main; + +public final class MainConstants { + + public static final String DEFAULT_PROPERTY_PLACEHOLDER_LOCATION = "classpath:application.properties;optional=true"; + public static final String INITIAL_PROPERTIES_LOCATION = "camel.main.initial-properties-location"; + public static final String OVERRIDE_PROPERTIES_LOCATION = "camel.main.override-properties-location"; + public static final String PROPERTY_PLACEHOLDER_LOCATION = "camel.main.property-placeholder-location"; + public static final String PLATFORM_HTTP_SERVER = "platform-http-server"; + + private MainConstants() { + } + +} diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainHttpServerFactory.java b/core/camel-main/src/main/java/org/apache/camel/main/MainHttpServerFactory.java new file mode 100644 index 00000000000..f75a1e1fa36 --- /dev/null +++ b/core/camel-main/src/main/java/org/apache/camel/main/MainHttpServerFactory.java @@ -0,0 +1,33 @@ +/* + * 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.main; + +import org.apache.camel.Service; + +/** + * Factory for creating an embedded HTTP server for standalone (not Spring Boot or Quarkus). + */ +public interface MainHttpServerFactory { + + /** + * Creates the embedded HTTP server + * + * @param configuration server configuration + * @return the server as a {@link Service} to be managed by {@link org.apache.camel.CamelContext}. + */ + Service newHttpServer(HttpServerConfigurationProperties configuration); +} diff --git a/core/camel-main/src/test/java/org/apache/camel/main/MainPropertyPlaceholderWithEnvTest.java b/core/camel-main/src/test/java/org/apache/camel/main/MainPropertyPlaceholderWithEnvTest.java index c2a821149c1..11110460828 100644 --- a/core/camel-main/src/test/java/org/apache/camel/main/MainPropertyPlaceholderWithEnvTest.java +++ b/core/camel-main/src/test/java/org/apache/camel/main/MainPropertyPlaceholderWithEnvTest.java @@ -33,9 +33,11 @@ import static org.junit.jupiter.api.Assertions.assertEquals; @ResourceLock(Resources.SYSTEM_PROPERTIES) public class MainPropertyPlaceholderWithEnvTest { - public static final String ENV_PROPERTY_PLACEHOLDER_LOCATION = MainHelper.toEnvVar(Main.PROPERTY_PLACEHOLDER_LOCATION); - public static final String ENV_INITIAL_PROPERTIES_LOCATION = MainHelper.toEnvVar(Main.INITIAL_PROPERTIES_LOCATION); - public static final String ENV_OVERRIDE_PROPERTIES_LOCATION = MainHelper.toEnvVar(Main.OVERRIDE_PROPERTIES_LOCATION); + public static final String ENV_PROPERTY_PLACEHOLDER_LOCATION + = MainHelper.toEnvVar(MainConstants.PROPERTY_PLACEHOLDER_LOCATION); + public static final String ENV_INITIAL_PROPERTIES_LOCATION = MainHelper.toEnvVar(MainConstants.INITIAL_PROPERTIES_LOCATION); + public static final String ENV_OVERRIDE_PROPERTIES_LOCATION + = MainHelper.toEnvVar(MainConstants.OVERRIDE_PROPERTIES_LOCATION); private static final Map<String, String> THE_CASE_INSENSITIVE_ENVIRONMENT = new HashMap<>(); @@ -58,7 +60,7 @@ public class MainPropertyPlaceholderWithEnvTest { @Test public void testPropertyPlaceholderOrdering() { envVariable(ENV_PROPERTY_PLACEHOLDER_LOCATION, "classpath:default.properties"); - sysVariable(Main.PROPERTY_PLACEHOLDER_LOCATION, "classpath:user.properties"); + sysVariable(MainConstants.PROPERTY_PLACEHOLDER_LOCATION, "classpath:user.properties"); Main main = new Main(); try { @@ -85,7 +87,7 @@ public class MainPropertyPlaceholderWithEnvTest { @Test public void testInitialPropertiesOrdering() { envVariable(ENV_INITIAL_PROPERTIES_LOCATION, "classpath:default.properties"); - sysVariable(Main.INITIAL_PROPERTIES_LOCATION, "classpath:user.properties"); + sysVariable(MainConstants.INITIAL_PROPERTIES_LOCATION, "classpath:user.properties"); Main main = new Main(); try { @@ -146,7 +148,7 @@ public class MainPropertyPlaceholderWithEnvTest { @Test public void testOverridePropertiesOrdering() { envVariable(ENV_OVERRIDE_PROPERTIES_LOCATION, "classpath:default.properties"); - sysVariable(Main.OVERRIDE_PROPERTIES_LOCATION, "classpath:user.properties"); + sysVariable(MainConstants.OVERRIDE_PROPERTIES_LOCATION, "classpath:user.properties"); Main main = new Main(); try { diff --git a/core/camel-main/src/test/java/org/apache/camel/main/MainPropertyPlaceholderWithSystemTest.java b/core/camel-main/src/test/java/org/apache/camel/main/MainPropertyPlaceholderWithSystemTest.java index fb73c0ad677..e83d31f2214 100644 --- a/core/camel-main/src/test/java/org/apache/camel/main/MainPropertyPlaceholderWithSystemTest.java +++ b/core/camel-main/src/test/java/org/apache/camel/main/MainPropertyPlaceholderWithSystemTest.java @@ -32,11 +32,11 @@ public class MainPropertyPlaceholderWithSystemTest { public void testCustomPropertyPlaceholderLocation() { Main main = new Main(); try { - System.setProperty(Main.PROPERTY_PLACEHOLDER_LOCATION, "classpath:default.properties"); + System.setProperty(MainConstants.PROPERTY_PLACEHOLDER_LOCATION, "classpath:default.properties"); main.start(); assertEquals("default", main.getCamelContext().resolvePropertyPlaceholders("{{hello}}")); } finally { - System.clearProperty(Main.PROPERTY_PLACEHOLDER_LOCATION); + System.clearProperty(MainConstants.PROPERTY_PLACEHOLDER_LOCATION); main.stop(); } } @@ -45,11 +45,11 @@ public class MainPropertyPlaceholderWithSystemTest { public void testInitialProperties() { Main main = new Main(); try { - System.setProperty(Main.INITIAL_PROPERTIES_LOCATION, "classpath:initial.properties"); + System.setProperty(MainConstants.INITIAL_PROPERTIES_LOCATION, "classpath:initial.properties"); main.start(); assertEquals("initial", main.getCamelContext().resolvePropertyPlaceholders("{{type}}")); } finally { - System.clearProperty(Main.INITIAL_PROPERTIES_LOCATION); + System.clearProperty(MainConstants.INITIAL_PROPERTIES_LOCATION); main.stop(); } } @@ -61,12 +61,12 @@ public class MainPropertyPlaceholderWithSystemTest { Properties properties = new Properties(); properties.setProperty("type", "custom"); - System.setProperty(Main.INITIAL_PROPERTIES_LOCATION, "classpath:initial.properties"); + System.setProperty(MainConstants.INITIAL_PROPERTIES_LOCATION, "classpath:initial.properties"); main.setInitialProperties(properties); main.start(); assertEquals("custom", main.getCamelContext().resolvePropertyPlaceholders("{{type}}")); } finally { - System.clearProperty(Main.INITIAL_PROPERTIES_LOCATION); + System.clearProperty(MainConstants.INITIAL_PROPERTIES_LOCATION); main.stop(); } } @@ -75,11 +75,11 @@ public class MainPropertyPlaceholderWithSystemTest { public void testOverrideProperties() { Main main = new Main(); try { - System.setProperty(Main.OVERRIDE_PROPERTIES_LOCATION, "classpath:override.properties"); + System.setProperty(MainConstants.OVERRIDE_PROPERTIES_LOCATION, "classpath:override.properties"); main.start(); assertEquals("override", main.getCamelContext().resolvePropertyPlaceholders("{{type}}")); } finally { - System.clearProperty(Main.OVERRIDE_PROPERTIES_LOCATION); + System.clearProperty(MainConstants.OVERRIDE_PROPERTIES_LOCATION); main.stop(); } } @@ -91,12 +91,12 @@ public class MainPropertyPlaceholderWithSystemTest { Properties properties = new Properties(); properties.setProperty("type", "custom"); - System.setProperty(Main.OVERRIDE_PROPERTIES_LOCATION, "classpath:override.properties"); + System.setProperty(MainConstants.OVERRIDE_PROPERTIES_LOCATION, "classpath:override.properties"); main.setOverrideProperties(properties); main.start(); assertEquals("custom", main.getCamelContext().resolvePropertyPlaceholders("{{type}}")); } finally { - System.clearProperty(Main.OVERRIDE_PROPERTIES_LOCATION); + System.clearProperty(MainConstants.OVERRIDE_PROPERTIES_LOCATION); main.stop(); } } @@ -105,9 +105,10 @@ public class MainPropertyPlaceholderWithSystemTest { public void testAll() { Main main = new Main(); try { - System.setProperty(Main.INITIAL_PROPERTIES_LOCATION, "classpath:initial.properties"); - System.setProperty(Main.OVERRIDE_PROPERTIES_LOCATION, "classpath:override.properties"); - System.setProperty(Main.PROPERTY_PLACEHOLDER_LOCATION, "classpath:default.properties,classpath:user.properties"); + System.setProperty(MainConstants.INITIAL_PROPERTIES_LOCATION, "classpath:initial.properties"); + System.setProperty(MainConstants.OVERRIDE_PROPERTIES_LOCATION, "classpath:override.properties"); + System.setProperty(MainConstants.PROPERTY_PLACEHOLDER_LOCATION, + "classpath:default.properties,classpath:user.properties"); main.start(); @@ -116,9 +117,9 @@ public class MainPropertyPlaceholderWithSystemTest { assertEquals("user-value", main.getCamelContext().resolvePropertyPlaceholders("{{user-key}}")); assertEquals("initial-value", main.getCamelContext().resolvePropertyPlaceholders("{{initial-key}}")); } finally { - System.clearProperty(Main.INITIAL_PROPERTIES_LOCATION); - System.clearProperty(Main.OVERRIDE_PROPERTIES_LOCATION); - System.clearProperty(Main.PROPERTY_PLACEHOLDER_LOCATION); + System.clearProperty(MainConstants.INITIAL_PROPERTIES_LOCATION); + System.clearProperty(MainConstants.OVERRIDE_PROPERTIES_LOCATION); + System.clearProperty(MainConstants.PROPERTY_PLACEHOLDER_LOCATION); main.stop(); } } diff --git a/docs/user-manual/modules/ROOT/pages/camel-4-migration-guide.adoc b/docs/user-manual/modules/ROOT/pages/camel-4-migration-guide.adoc index cc676e92136..48f2060bf5c 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-4-migration-guide.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-4-migration-guide.adoc @@ -298,6 +298,19 @@ The `io.fabric8:kubernetes-client` library has been upgraded and some deprecated For example `replaceConfigMap` is now `updateConfigMap`, `replacePod` is now `updatePod` etc. The corresponding constants in class `KubernetesOperations` are also renamed. `REPLACE_CONFIGMAP_OPERATION` is now `UPDATE_CONFIGMAP_OPERATION`, `REPLACE_POD_OPERATION` is now `UPDATE_POD_OPERATION` etc. +=== camel-main + +The following constants has been moved from `BaseMainSupport` / `Main` to `MainConstants`: + +|=== +| Old Name | New Name +| Main.DEFAULT_PROPERTY_PLACEHOLDER_LOCATION | MainConstants.DEFAULT_PROPERTY_PLACEHOLDER_LOCATION +| Main.INITIAL_PROPERTIES_LOCATION | MainConstants.INITIAL_PROPERTIES_LOCATION +| Main.OVERRIDE_PROPERTIES_LOCATION | MainConstants.OVERRIDE_PROPERTIES_LOCATION +| Main.PROPERTY_PLACEHOLDER_LOCATION | MainConstants.PROPERTY_PLACEHOLDER_LOCATION +|=== + + === camel-micrometer The metrics has been renamed to follow Micrometer naming convention https://micrometer.io/docs/concepts#_naming_meters[Naming Meters]. diff --git a/dsl/camel-kamelet-main/pom.xml b/dsl/camel-kamelet-main/pom.xml index 2cba8b8dbf4..a3b8cc56c3f 100644 --- a/dsl/camel-kamelet-main/pom.xml +++ b/dsl/camel-kamelet-main/pom.xml @@ -78,14 +78,7 @@ </dependency> <dependency> <groupId>org.apache.camel</groupId> - <artifactId>camel-platform-http-vertx</artifactId> - <exclusions> - <!-- avoid WARN logs from netty --> - <exclusion> - <groupId>io.netty</groupId> - <artifactId>netty-resolver-dns</artifactId> - </exclusion> - </exclusions> + <artifactId>camel-platform-http-main</artifactId> </dependency> <dependency> <groupId>org.apache.camel</groupId> 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 87af11329e9..c6f1aea0f49 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 @@ -45,9 +45,8 @@ import org.apache.camel.RuntimeCamelException; import org.apache.camel.StartupListener; import org.apache.camel.component.platform.http.HttpEndpointModel; import org.apache.camel.component.platform.http.PlatformHttpComponent; +import org.apache.camel.component.platform.http.main.MainHttpServer; import org.apache.camel.component.platform.http.vertx.VertxPlatformHttpRouter; -import org.apache.camel.component.platform.http.vertx.VertxPlatformHttpServer; -import org.apache.camel.component.platform.http.vertx.VertxPlatformHttpServerConfiguration; import org.apache.camel.console.DevConsole; import org.apache.camel.console.DevConsoleRegistry; import org.apache.camel.health.HealthCheck; @@ -71,7 +70,7 @@ import org.slf4j.LoggerFactory; public final class VertxHttpServer { static VertxPlatformHttpRouter router; - static VertxPlatformHttpServer server; + static MainHttpServer server; static PlatformHttpComponent phc; private static final Logger LOG = LoggerFactory.getLogger(VertxHttpServer.class); @@ -108,12 +107,11 @@ public final class VertxHttpServer { } try { - VertxPlatformHttpServerConfiguration config = new VertxPlatformHttpServerConfiguration(); - config.setPort(port); - server = new VertxPlatformHttpServer(config); - camelContext.addService(server); + server = new MainHttpServer(); + server.setCamelContext(camelContext); + server.setPort(port); server.start(); - router = VertxPlatformHttpRouter.lookup(camelContext); + router = server.getRouter(); if (phc == null) { phc = camelContext.getComponent("platform-http", PlatformHttpComponent.class); } diff --git a/parent/pom.xml b/parent/pom.xml index 9ed27dfd61d..02121b930ab 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -1933,6 +1933,11 @@ <artifactId>camel-platform-http</artifactId> <version>${project.version}</version> </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-platform-http-main</artifactId> + <version>${project.version}</version> + </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-platform-http-vertx</artifactId> diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCamelMainMojo.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCamelMainMojo.java index bfdaa2ca8c2..d1059be2f24 100644 --- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCamelMainMojo.java +++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCamelMainMojo.java @@ -204,6 +204,8 @@ public class PrepareCamelMainMojo extends AbstractGeneratorMojo { prefix = "camel.health."; } else if (file.getName().contains("Lra")) { prefix = "camel.lra."; + } else if (file.getName().contains("HttpServer")) { + prefix = "camel.server."; } else if (file.getName().contains("ThreadPoolProfileConfigurationProperties")) { // skip this file continue; @@ -275,6 +277,9 @@ public class PrepareCamelMainMojo extends AbstractGeneratorMojo { model.getOptions().addAll(data); model.getGroups().add(new MainGroupModel( "camel.main", "Camel Main configurations", "org.apache.camel.main.DefaultConfigurationProperties")); + model.getGroups().add(new MainGroupModel( + "camel.server", "Camel Embedded HTTP Server (only for standalone; not Spring Boot or Quarkus) configurations", + "org.apache.camel.main.HttpServerConfigurationProperties")); model.getGroups() .add(new MainGroupModel( "camel.threadpool", "Camel Thread Pool configurations",
