This is an automated email from the ASF dual-hosted git repository. valdar pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/camel-k-runtime.git
The following commit(s) were added to refs/heads/master by this push: new 72c9d2a add servlet support 72c9d2a is described below commit 72c9d2ae8be188de462ece77493151158da1fd36 Author: lburgazzoli <lburgazz...@gmail.com> AuthorDate: Sat May 18 15:00:39 2019 +0200 add servlet support --- .../main/java/org/apache/camel/k/Constants.java | 10 +- .../src/main/java/org/apache/camel/k/Runtime.java | 31 ++++- .../camel/k/listener/AbstractPhaseListener.java | 7 +- .../apache/camel/k/listener/RoutesConfigurer.java | 7 +- .../apache/camel/k/support/PropertiesSupport.java | 8 +- .../camel-k-runtime-example-health}/pom.xml | 89 ++++++++------- .../services/org/apache/camel/k/customizer/webhook | 3 +- .../src/main/resources/application.properties | 10 ++ .../src/main/resources/routes.groovy | 5 + .../camel-k-runtime-example-servlet}/pom.xml | 89 ++++++++------- .../apache/camel/k/example/WebhookCustomizer.java | 28 ++--- .../services/org/apache/camel/k/customizer/webhook | 3 +- .../src/main/resources/application.properties | 10 ++ .../src/main/resources/routes.groovy | 5 + camel-k-runtime-examples/pom.xml | 37 ++++++ camel-k-runtime-health/pom.xml | 16 ++- .../camel/k/health/HealthContextCustomizer.java} | 43 ++++--- .../org/apache/camel/k/health/HealthEndpoint.java | 125 +++++---------------- .../apache/camel/k/customizer/health} | 3 +- .../camel/k/health/HealthCustomizerTest.java | 53 +++++++++ .../org/apache/camel/k/jvm/ApplicationRuntime.java | 26 ++++- .../pom.xml | 32 +++++- .../camel/k/servlet/ServletContextCustomizer.java | 35 +++--- .../apache/camel/k/servlet/ServletEndpoint.java | 85 ++++++++++++++ .../camel/k/servlet/ServletRegistration.java | 81 +++++++++++++ .../services/org/apache/camel/k/customizer/servlet | 3 +- .../camel/k/servlet/ServletCustomizerTest.java | 55 +++++++++ .../src/test/resources/log4j2-test.xml | 18 +++ pom.xml | 9 ++ 29 files changed, 658 insertions(+), 268 deletions(-) diff --git a/camel-k-runtime-core/src/main/java/org/apache/camel/k/Constants.java b/camel-k-runtime-core/src/main/java/org/apache/camel/k/Constants.java index 7091e4b..b528317 100644 --- a/camel-k-runtime-core/src/main/java/org/apache/camel/k/Constants.java +++ b/camel-k-runtime-core/src/main/java/org/apache/camel/k/Constants.java @@ -18,16 +18,24 @@ package org.apache.camel.k; public final class Constants { public static final String ENV_CAMEL_K_ROUTES = "CAMEL_K_ROUTES"; + public static final String PROPERTY_CAMEL_K_ROUTES = "camel.k.routes"; + public static final String ENV_CAMEL_K_CONF = "CAMEL_K_CONF"; + public static final String PROPERTY_CAMEL_K_CONF = "camel.k.conf"; + public static final String ENV_CAMEL_K_CONF_D = "CAMEL_K_CONF_D"; + public static final String PROPERTY_CAMEL_K_CONF_D = "camel.k.conf.d"; + public static final String ENV_CAMEL_K_CUSTOMIZERS = "CAMEL_K_CUSTOMIZERS"; + public static final String PROPERTY_CAMEL_K_CUSTOMIZER = "camel.k.customizer"; + public static final String SCHEME_CLASSPATH = "classpath:"; public static final String SCHEME_FILE = "file:"; public static final String SCHEME_ENV = "env:"; public static final String LOGGING_LEVEL_PREFIX = "logging.level."; public static final String ROUTES_LOADER_RESOURCE_PATH = "META-INF/services/org/apache/camel/k/loader/"; public static final String CONTEXT_CUSTOMIZER_RESOURCE_PATH = "META-INF/services/org/apache/camel/k/customizer/"; - public static final String PROPERTY_CAMEL_K_CUSTOMIZER = "camel.k.customizer"; + public static final String ENABLE_CUSTOMIZER_PATTERN = "customizer.([\\w][\\w-]*).enabled"; public static final String PROPERTY_PREFIX_REST_COMPONENT_PROPERTY = "camel.rest.componentProperty."; public static final String PROPERTY_PREFIX_REST_ENDPOINT_PROPERTY = "camel.rest.endpointProperty."; diff --git a/camel-k-runtime-core/src/main/java/org/apache/camel/k/Runtime.java b/camel-k-runtime-core/src/main/java/org/apache/camel/k/Runtime.java index f2f1f01..4b1e6f7 100644 --- a/camel-k-runtime-core/src/main/java/org/apache/camel/k/Runtime.java +++ b/camel-k-runtime-core/src/main/java/org/apache/camel/k/Runtime.java @@ -19,6 +19,7 @@ package org.apache.camel.k; import java.util.Properties; import org.apache.camel.CamelContext; +import org.apache.camel.Ordered; import org.apache.camel.component.properties.PropertiesComponent; public interface Runtime { @@ -49,10 +50,36 @@ public interface Runtime { } @FunctionalInterface - interface Listener { - void accept(Phase phase, Runtime runtime); + interface Listener extends Ordered { + boolean accept(Phase phase, Runtime runtime); + + @Override + default int getOrder() { + return Ordered.LOWEST; + } } interface Registry extends org.apache.camel.k.adapter.Registry { } + + /** + * Helper to create a simple runtime from a given Camel Context and Runtime Registry. + * + * @param camelContext the camel context + * @param registry the runtime registry + * @return the runtime + */ + static Runtime of( CamelContext camelContext, Registry registry) { + return new Runtime() { + @Override + public CamelContext getContext() { + return camelContext; + } + + @Override + public Registry getRegistry() { + return registry; + } + }; + } } diff --git a/camel-k-runtime-core/src/main/java/org/apache/camel/k/listener/AbstractPhaseListener.java b/camel-k-runtime-core/src/main/java/org/apache/camel/k/listener/AbstractPhaseListener.java index 7de4991..7678acc 100644 --- a/camel-k-runtime-core/src/main/java/org/apache/camel/k/listener/AbstractPhaseListener.java +++ b/camel-k-runtime-core/src/main/java/org/apache/camel/k/listener/AbstractPhaseListener.java @@ -26,10 +26,13 @@ public abstract class AbstractPhaseListener implements Runtime.Listener { } @Override - public void accept(Runtime.Phase phase, Runtime runtime) { - if (this.phase == phase) { + public boolean accept(Runtime.Phase phase, Runtime runtime) { + boolean run = this.phase == phase; + if (run) { accept(runtime); } + + return run; } protected abstract void accept(Runtime runtime); diff --git a/camel-k-runtime-core/src/main/java/org/apache/camel/k/listener/RoutesConfigurer.java b/camel-k-runtime-core/src/main/java/org/apache/camel/k/listener/RoutesConfigurer.java index 2600c63..3b2c89c 100644 --- a/camel-k-runtime-core/src/main/java/org/apache/camel/k/listener/RoutesConfigurer.java +++ b/camel-k-runtime-core/src/main/java/org/apache/camel/k/listener/RoutesConfigurer.java @@ -36,10 +36,15 @@ public class RoutesConfigurer extends AbstractPhaseListener { @Override protected void accept(Runtime runtime) { - final String routes = System.getenv().getOrDefault(Constants.ENV_CAMEL_K_ROUTES, ""); + String routes = System.getProperty(Constants.PROPERTY_CAMEL_K_ROUTES); + + if (ObjectHelper.isEmpty(routes)) { + routes = System.getenv(Constants.ENV_CAMEL_K_ROUTES); + } if (ObjectHelper.isEmpty(routes)) { LOGGER.warn("No routes found in {} environment variable", Constants.ENV_CAMEL_K_ROUTES); + return; } load(runtime, routes.split(",", -1)); diff --git a/camel-k-runtime-core/src/main/java/org/apache/camel/k/support/PropertiesSupport.java b/camel-k-runtime-core/src/main/java/org/apache/camel/k/support/PropertiesSupport.java index 6ce2360..8c5ee27 100644 --- a/camel-k-runtime-core/src/main/java/org/apache/camel/k/support/PropertiesSupport.java +++ b/camel-k-runtime-core/src/main/java/org/apache/camel/k/support/PropertiesSupport.java @@ -91,10 +91,10 @@ public final class PropertiesSupport { } public static Properties loadProperties() { - final String conf = System.getenv(Constants.ENV_CAMEL_K_CONF); - final String confd = System.getenv(Constants.ENV_CAMEL_K_CONF_D); - - return loadProperties(conf, confd); + return loadProperties( + System.getProperty(Constants.PROPERTY_CAMEL_K_CONF, System.getenv(Constants.ENV_CAMEL_K_CONF)), + System.getProperty(Constants.PROPERTY_CAMEL_K_CONF_D, System.getenv(Constants.ENV_CAMEL_K_CONF_D)) + ); } public static Properties loadProperties(String conf, String confd) { diff --git a/camel-k-runtime-health/pom.xml b/camel-k-runtime-examples/camel-k-runtime-example-health/pom.xml similarity index 62% copy from camel-k-runtime-health/pom.xml copy to camel-k-runtime-examples/camel-k-runtime-example-health/pom.xml index 6846e71..e2d788f 100644 --- a/camel-k-runtime-health/pom.xml +++ b/camel-k-runtime-examples/camel-k-runtime-example-health/pom.xml @@ -20,12 +20,12 @@ <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/xsd/maven-4.0.0.xsd"> <parent> <groupId>org.apache.camel.k</groupId> - <artifactId>camel-k-runtime-parent</artifactId> + <artifactId>camel-k-runtime-examples</artifactId> <version>0.3.3-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> - <artifactId>camel-k-runtime-health</artifactId> + <artifactId>camel-k-runtime-example-health</artifactId> <dependencies> @@ -36,61 +36,72 @@ <!-- ****************************** --> <dependency> - <groupId>org.apache.camel.k</groupId> - <artifactId>camel-k-runtime-core</artifactId> + <groupId>org.apache.camel</groupId> + <artifactId>camel-core</artifactId> </dependency> - <dependency> <groupId>org.apache.camel</groupId> - <artifactId>camel-netty4-http</artifactId> - <scope>provided</scope> + <artifactId>camel-servlet</artifactId> </dependency> - - <!-- ****************************** --> - <!-- --> - <!-- TESTS --> - <!-- --> - <!-- ****************************** --> - <dependency> <groupId>org.apache.camel.k</groupId> <artifactId>camel-k-runtime-jvm</artifactId> - <scope>test</scope> </dependency> - <dependency> - <groupId>org.junit.jupiter</groupId> - <artifactId>junit-jupiter-api</artifactId> - <version>${junit-jupiter.version}</version> - <scope>test</scope> + <groupId>org.apache.camel.k</groupId> + <artifactId>camel-k-runtime-groovy</artifactId> </dependency> <dependency> - <groupId>org.junit.jupiter</groupId> - <artifactId>junit-jupiter-engine</artifactId> - <version>${junit-jupiter.version}</version> - <scope>test</scope> + <groupId>org.apache.camel.k</groupId> + <artifactId>camel-k-runtime-servlet</artifactId> </dependency> <dependency> - <groupId>org.assertj</groupId> - <artifactId>assertj-core</artifactId> - <version>${assertj.version}</version> - <scope>test</scope> + <groupId>org.apache.camel.k</groupId> + <artifactId>camel-k-runtime-health</artifactId> </dependency> - <dependency> <groupId>org.apache.logging.log4j</groupId> - <artifactId>log4j-core</artifactId> + <artifactId>log4j-slf4j-impl</artifactId> <version>${log4j2.version}</version> - <scope>test</scope> </dependency> <dependency> - <groupId>org.apache.logging.log4j</groupId> - <artifactId>log4j-slf4j-impl</artifactId> - <version>${log4j2.version}</version> - <scope>test</scope> + <groupId>org.codehaus.groovy</groupId> + <artifactId>groovy</artifactId> + <version>${groovy.version}</version> </dependency> </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <version>${exec-maven-plugin.version}</version> + <executions> + <execution> + <goals> + <goal>java</goal> + </goals> + </execution> + </executions> + <configuration> + <mainClass>org.apache.camel.k.jvm.Application</mainClass> + <classpathScope>runtime</classpathScope> + <systemProperties> + <systemProperty> + <key>camel.k.conf</key> + <value>${project.basedir}/src/main/resources/application.properties</value> + </systemProperty> + <systemProperty> + <key>camel.k.routes</key> + <value>file:${project.basedir}/src/main/resources/routes.groovy</value> + </systemProperty> + </systemProperties> + </configuration> + </plugin> + </plugins> + </build> + <profiles> <profile> <id>camel3</id> @@ -104,13 +115,6 @@ <dependency> <groupId>org.apache.camel.k</groupId> <artifactId>camel-k-adapter-camel-3</artifactId> - <scope>provided</scope> - </dependency> - <!-- test --> - <dependency> - <groupId>org.apache.camel</groupId> - <artifactId>camel-properties</artifactId> - <scope>test</scope> </dependency> </dependencies> </profile> @@ -126,7 +130,6 @@ <dependency> <groupId>org.apache.camel.k</groupId> <artifactId>camel-k-adapter-camel-2</artifactId> - <scope>provided</scope> </dependency> </dependencies> </profile> diff --git a/camel-k-runtime-health/src/main/resources/META-INF/services/org.apache.camel.k.Runtime$Listener b/camel-k-runtime-examples/camel-k-runtime-example-health/src/main/resources/META-INF/services/org/apache/camel/k/customizer/webhook similarity index 93% copy from camel-k-runtime-health/src/main/resources/META-INF/services/org.apache.camel.k.Runtime$Listener copy to camel-k-runtime-examples/camel-k-runtime-example-health/src/main/resources/META-INF/services/org/apache/camel/k/customizer/webhook index 10ba5ec..6952fcf 100644 --- a/camel-k-runtime-health/src/main/resources/META-INF/services/org.apache.camel.k.Runtime$Listener +++ b/camel-k-runtime-examples/camel-k-runtime-example-health/src/main/resources/META-INF/services/org/apache/camel/k/customizer/webhook @@ -15,5 +15,4 @@ # limitations under the License. # -org.apache.camel.k.health.HealthConfigurer - +class=org.apache.camel.k.example.WebhookCustomizer diff --git a/camel-k-runtime-examples/camel-k-runtime-example-health/src/main/resources/application.properties b/camel-k-runtime-examples/camel-k-runtime-example-health/src/main/resources/application.properties new file mode 100644 index 0000000..b58849b --- /dev/null +++ b/camel-k-runtime-examples/camel-k-runtime-example-health/src/main/resources/application.properties @@ -0,0 +1,10 @@ +# +# Camel +# +camel.context.streamCaching = true + +# +# Camel K +# +customizer.servlet.enabled = true +customizer.health.enabled = true \ No newline at end of file diff --git a/camel-k-runtime-examples/camel-k-runtime-example-health/src/main/resources/routes.groovy b/camel-k-runtime-examples/camel-k-runtime-example-health/src/main/resources/routes.groovy new file mode 100644 index 0000000..439c62d --- /dev/null +++ b/camel-k-runtime-examples/camel-k-runtime-example-health/src/main/resources/routes.groovy @@ -0,0 +1,5 @@ + + +from('servlet:/test') + .convertBodyTo(String.class) + .to('log:info') \ No newline at end of file diff --git a/camel-k-runtime-health/pom.xml b/camel-k-runtime-examples/camel-k-runtime-example-servlet/pom.xml similarity index 63% copy from camel-k-runtime-health/pom.xml copy to camel-k-runtime-examples/camel-k-runtime-example-servlet/pom.xml index 6846e71..2698c00 100644 --- a/camel-k-runtime-health/pom.xml +++ b/camel-k-runtime-examples/camel-k-runtime-example-servlet/pom.xml @@ -20,12 +20,12 @@ <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/xsd/maven-4.0.0.xsd"> <parent> <groupId>org.apache.camel.k</groupId> - <artifactId>camel-k-runtime-parent</artifactId> + <artifactId>camel-k-runtime-examples</artifactId> <version>0.3.3-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> - <artifactId>camel-k-runtime-health</artifactId> + <artifactId>camel-k-runtime-example-servlet</artifactId> <dependencies> @@ -36,61 +36,68 @@ <!-- ****************************** --> <dependency> - <groupId>org.apache.camel.k</groupId> - <artifactId>camel-k-runtime-core</artifactId> + <groupId>org.apache.camel</groupId> + <artifactId>camel-core</artifactId> </dependency> - <dependency> <groupId>org.apache.camel</groupId> - <artifactId>camel-netty4-http</artifactId> - <scope>provided</scope> + <artifactId>camel-servlet</artifactId> </dependency> - - <!-- ****************************** --> - <!-- --> - <!-- TESTS --> - <!-- --> - <!-- ****************************** --> - <dependency> <groupId>org.apache.camel.k</groupId> <artifactId>camel-k-runtime-jvm</artifactId> - <scope>test</scope> - </dependency> - - <dependency> - <groupId>org.junit.jupiter</groupId> - <artifactId>junit-jupiter-api</artifactId> - <version>${junit-jupiter.version}</version> - <scope>test</scope> </dependency> <dependency> - <groupId>org.junit.jupiter</groupId> - <artifactId>junit-jupiter-engine</artifactId> - <version>${junit-jupiter.version}</version> - <scope>test</scope> + <groupId>org.apache.camel.k</groupId> + <artifactId>camel-k-runtime-groovy</artifactId> </dependency> <dependency> - <groupId>org.assertj</groupId> - <artifactId>assertj-core</artifactId> - <version>${assertj.version}</version> - <scope>test</scope> + <groupId>org.apache.camel.k</groupId> + <artifactId>camel-k-runtime-servlet</artifactId> </dependency> - <dependency> <groupId>org.apache.logging.log4j</groupId> - <artifactId>log4j-core</artifactId> + <artifactId>log4j-slf4j-impl</artifactId> <version>${log4j2.version}</version> - <scope>test</scope> </dependency> <dependency> - <groupId>org.apache.logging.log4j</groupId> - <artifactId>log4j-slf4j-impl</artifactId> - <version>${log4j2.version}</version> - <scope>test</scope> + <groupId>org.codehaus.groovy</groupId> + <artifactId>groovy</artifactId> + <version>${groovy.version}</version> </dependency> </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <version>${exec-maven-plugin.version}</version> + <executions> + <execution> + <goals> + <goal>java</goal> + </goals> + </execution> + </executions> + <configuration> + <mainClass>org.apache.camel.k.jvm.Application</mainClass> + <classpathScope>runtime</classpathScope> + <systemProperties> + <systemProperty> + <key>camel.k.conf</key> + <value>${project.basedir}/src/main/resources/application.properties</value> + </systemProperty> + <systemProperty> + <key>camel.k.routes</key> + <value>file:${project.basedir}/src/main/resources/routes.groovy</value> + </systemProperty> + </systemProperties> + </configuration> + </plugin> + </plugins> + </build> + <profiles> <profile> <id>camel3</id> @@ -104,13 +111,6 @@ <dependency> <groupId>org.apache.camel.k</groupId> <artifactId>camel-k-adapter-camel-3</artifactId> - <scope>provided</scope> - </dependency> - <!-- test --> - <dependency> - <groupId>org.apache.camel</groupId> - <artifactId>camel-properties</artifactId> - <scope>test</scope> </dependency> </dependencies> </profile> @@ -126,7 +126,6 @@ <dependency> <groupId>org.apache.camel.k</groupId> <artifactId>camel-k-adapter-camel-2</artifactId> - <scope>provided</scope> </dependency> </dependencies> </profile> diff --git a/camel-k-runtime-health/src/test/java/org/apache/camel/k/health/HealthMain.java b/camel-k-runtime-examples/camel-k-runtime-example-servlet/src/main/java/org/apache/camel/k/example/WebhookCustomizer.java similarity index 56% copy from camel-k-runtime-health/src/test/java/org/apache/camel/k/health/HealthMain.java copy to camel-k-runtime-examples/camel-k-runtime-example-servlet/src/main/java/org/apache/camel/k/example/WebhookCustomizer.java index 3f0062c..b474194 100644 --- a/camel-k-runtime-health/src/test/java/org/apache/camel/k/health/HealthMain.java +++ b/camel-k-runtime-examples/camel-k-runtime-example-servlet/src/main/java/org/apache/camel/k/example/WebhookCustomizer.java @@ -14,24 +14,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.k.health; - -import java.util.Properties; -import java.util.ServiceLoader; +package org.apache.camel.k.example; +import org.apache.camel.CamelContext; +import org.apache.camel.component.servlet.CamelHttpTransportServlet; +import org.apache.camel.k.ContextCustomizer; import org.apache.camel.k.Runtime; -import org.apache.camel.k.jvm.ApplicationRuntime; - -public class HealthMain { - public static void main(String[] args) throws Exception { - Properties p = new Properties(); - p.setProperty("endpoint.health.bindHost", "localhost"); - p.setProperty("endpoint.health.bindPort", "9988"); - p.setProperty("endpoint.health.path", "/ht"); +import org.apache.camel.k.servlet.ServletRegistration; - ApplicationRuntime runtime = new ApplicationRuntime(); - runtime.setProperties(p); - runtime.addListeners(ServiceLoader.load(Runtime.Listener.class)); - runtime.run(); +public class WebhookCustomizer implements ContextCustomizer { + @Override + public void apply(CamelContext camelContext, Runtime.Registry registry) { + registry.bind( + "webhook-servlet", + new ServletRegistration("CamelServlet", new CamelHttpTransportServlet(), "/webhook/*") + ); } } diff --git a/camel-k-runtime-health/src/main/resources/META-INF/services/org.apache.camel.k.Runtime$Listener b/camel-k-runtime-examples/camel-k-runtime-example-servlet/src/main/resources/META-INF/services/org/apache/camel/k/customizer/webhook similarity index 93% copy from camel-k-runtime-health/src/main/resources/META-INF/services/org.apache.camel.k.Runtime$Listener copy to camel-k-runtime-examples/camel-k-runtime-example-servlet/src/main/resources/META-INF/services/org/apache/camel/k/customizer/webhook index 10ba5ec..6952fcf 100644 --- a/camel-k-runtime-health/src/main/resources/META-INF/services/org.apache.camel.k.Runtime$Listener +++ b/camel-k-runtime-examples/camel-k-runtime-example-servlet/src/main/resources/META-INF/services/org/apache/camel/k/customizer/webhook @@ -15,5 +15,4 @@ # limitations under the License. # -org.apache.camel.k.health.HealthConfigurer - +class=org.apache.camel.k.example.WebhookCustomizer diff --git a/camel-k-runtime-examples/camel-k-runtime-example-servlet/src/main/resources/application.properties b/camel-k-runtime-examples/camel-k-runtime-example-servlet/src/main/resources/application.properties new file mode 100644 index 0000000..10c4282 --- /dev/null +++ b/camel-k-runtime-examples/camel-k-runtime-example-servlet/src/main/resources/application.properties @@ -0,0 +1,10 @@ +# +# Camel +# +camel.context.streamCaching = true + +# +# Camel K +# +customizer.webhook.enabled = true +customizer.servlet.enabled = true \ No newline at end of file diff --git a/camel-k-runtime-examples/camel-k-runtime-example-servlet/src/main/resources/routes.groovy b/camel-k-runtime-examples/camel-k-runtime-example-servlet/src/main/resources/routes.groovy new file mode 100644 index 0000000..439c62d --- /dev/null +++ b/camel-k-runtime-examples/camel-k-runtime-example-servlet/src/main/resources/routes.groovy @@ -0,0 +1,5 @@ + + +from('servlet:/test') + .convertBodyTo(String.class) + .to('log:info') \ No newline at end of file diff --git a/camel-k-runtime-examples/pom.xml b/camel-k-runtime-examples/pom.xml new file mode 100644 index 0000000..94e538b --- /dev/null +++ b/camel-k-runtime-examples/pom.xml @@ -0,0 +1,37 @@ +<?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/xsd/maven-4.0.0.xsd"> + <parent> + <groupId>org.apache.camel.k</groupId> + <artifactId>camel-k-runtime-parent</artifactId> + <version>0.3.3-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + + <packaging>pom</packaging> + <artifactId>camel-k-runtime-examples</artifactId> + + + <modules> + <module>camel-k-runtime-example-servlet</module> + <module>camel-k-runtime-example-health</module> + </modules> + +</project> diff --git a/camel-k-runtime-health/pom.xml b/camel-k-runtime-health/pom.xml index 6846e71..f3d7fe3 100644 --- a/camel-k-runtime-health/pom.xml +++ b/camel-k-runtime-health/pom.xml @@ -36,14 +36,17 @@ <!-- ****************************** --> <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-core</artifactId> + <scope>provided</scope> + </dependency> + <dependency> <groupId>org.apache.camel.k</groupId> <artifactId>camel-k-runtime-core</artifactId> </dependency> - <dependency> - <groupId>org.apache.camel</groupId> - <artifactId>camel-netty4-http</artifactId> - <scope>provided</scope> + <groupId>org.apache.camel.k</groupId> + <artifactId>camel-k-runtime-servlet</artifactId> </dependency> <!-- ****************************** --> @@ -53,6 +56,11 @@ <!-- ****************************** --> <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-test</artifactId> + <scope>test</scope> + </dependency> + <dependency> <groupId>org.apache.camel.k</groupId> <artifactId>camel-k-runtime-jvm</artifactId> <scope>test</scope> diff --git a/camel-k-runtime-health/src/test/java/org/apache/camel/k/health/HealthMain.java b/camel-k-runtime-health/src/main/java/org/apache/camel/k/health/HealthContextCustomizer.java similarity index 52% rename from camel-k-runtime-health/src/test/java/org/apache/camel/k/health/HealthMain.java rename to camel-k-runtime-health/src/main/java/org/apache/camel/k/health/HealthContextCustomizer.java index 3f0062c..3217f5a 100644 --- a/camel-k-runtime-health/src/test/java/org/apache/camel/k/health/HealthMain.java +++ b/camel-k-runtime-health/src/main/java/org/apache/camel/k/health/HealthContextCustomizer.java @@ -16,22 +16,37 @@ */ package org.apache.camel.k.health; -import java.util.Properties; -import java.util.ServiceLoader; - +import org.apache.camel.CamelContext; +import org.apache.camel.k.ContextCustomizer; import org.apache.camel.k.Runtime; -import org.apache.camel.k.jvm.ApplicationRuntime; +import org.apache.camel.k.servlet.ServletRegistration; + +public class HealthContextCustomizer implements ContextCustomizer { + public static final String DEFAULT_PATH = "/health"; + + private String path; + + public HealthContextCustomizer() { + this.path = DEFAULT_PATH; + } + + public String getPath() { + return path; + } -public class HealthMain { - public static void main(String[] args) throws Exception { - Properties p = new Properties(); - p.setProperty("endpoint.health.bindHost", "localhost"); - p.setProperty("endpoint.health.bindPort", "9988"); - p.setProperty("endpoint.health.path", "/ht"); + public void setPath(String path) { + this.path = path; + } - ApplicationRuntime runtime = new ApplicationRuntime(); - runtime.setProperties(p); - runtime.addListeners(ServiceLoader.load(Runtime.Listener.class)); - runtime.run(); + @Override + public void apply(CamelContext camelContext, Runtime.Registry registry) { + registry.bind( + "health-servlet", + new ServletRegistration( + "HealthServlet", + new HealthEndpoint(camelContext), + path + ) + ); } } diff --git a/camel-k-runtime-health/src/main/java/org/apache/camel/k/health/HealthEndpoint.java b/camel-k-runtime-health/src/main/java/org/apache/camel/k/health/HealthEndpoint.java index 4f0516e..e42eb44 100644 --- a/camel-k-runtime-health/src/main/java/org/apache/camel/k/health/HealthEndpoint.java +++ b/camel-k-runtime-health/src/main/java/org/apache/camel/k/health/HealthEndpoint.java @@ -16,118 +16,47 @@ */ package org.apache.camel.k.health; -import java.util.Objects; +import java.io.IOException; +import java.io.PrintWriter; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; -import io.netty.bootstrap.ServerBootstrap; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.SocketChannel; -import io.netty.channel.socket.nio.NioServerSocketChannel; -import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpObject; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.HttpResponseStatus; -import io.netty.handler.codec.http.HttpServerCodec; -import io.netty.handler.codec.http.HttpVersion; -import io.netty.handler.logging.LogLevel; -import io.netty.handler.logging.LoggingHandler; -import io.netty.util.AsciiString; import org.apache.camel.CamelContext; import org.apache.camel.ServiceStatus; -import org.apache.camel.k.adapter.ServiceSupport; - -public class HealthEndpoint extends ServiceSupport { - private static final AsciiString CONTENT_TYPE = AsciiString.cached("Content-Type"); - private static final AsciiString CONTENT_LENGTH = AsciiString.cached("Content-Length"); - private static final byte[] OK = {'O', 'K'}; - private static final byte[] KO = {'K', 'O'}; +public class HealthEndpoint extends HttpServlet { private final CamelContext context; - private final String bindHost; - private final int bindPort; - private final String path; - - private EventLoopGroup bossGroup; - private EventLoopGroup workerGroup; - private Channel channel; - public HealthEndpoint(CamelContext context, String bindHost, int bindPort, String path) { + public HealthEndpoint(CamelContext context) { this.context = context; - this.bindHost = bindHost; - this.bindPort = bindPort; - this.path = path; } @Override - protected void doStart() throws Exception { - bossGroup = new NioEventLoopGroup(1); - workerGroup = new NioEventLoopGroup(); - - ServerBootstrap b = new ServerBootstrap(); - b.group(bossGroup, workerGroup) - .channel(NioServerSocketChannel.class) - .handler(new LoggingHandler(LogLevel.DEBUG)) - .childHandler(new ChannelInitializer<SocketChannel>() { - @Override - protected void initChannel(SocketChannel ch) throws Exception { - ch.pipeline() - .addLast(new HttpServerCodec()) - .addLast(new Handler()); - } - }); + protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { + if (context.getStatus() == ServiceStatus.Started) { + resp.setContentType("text/plain"); + resp.setContentLength(2); + resp.setStatus(HttpServletResponse.SC_OK); + + try(PrintWriter writer = resp.getWriter()) { + writer.write("OK"); + } - channel = b.bind(bindHost, bindPort).channel(); - } + } else { + resp.setContentType("text/plain"); + resp.setContentLength(2); + resp.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE); - @Override - protected void doStop() throws Exception { - if (bossGroup != null) { - bossGroup.shutdownGracefully(); - } - if (workerGroup != null) { - workerGroup.shutdownGracefully(); + try(PrintWriter writer = resp.getWriter()) { + writer.write("KO"); + } } } - private class Handler extends SimpleChannelInboundHandler<HttpObject> { - @Override - public void channelReadComplete(ChannelHandlerContext ctx) { - ctx.flush(); - } - - @Override - protected void channelRead0(ChannelHandlerContext ctx, HttpObject object) throws Exception { - if (object instanceof HttpRequest) { - final HttpRequest msg = (HttpRequest)object; - - HttpResponseStatus status; - ByteBuf content; - - if (!Objects.equals(path, msg.uri())) { - status = HttpResponseStatus.NOT_FOUND; - content = Unpooled.wrappedBuffer(KO); - } else if (context.getStatus() == ServiceStatus.Started) { - status = HttpResponseStatus.OK; - content = Unpooled.wrappedBuffer(OK); - } else { - status = HttpResponseStatus.SERVICE_UNAVAILABLE; - content = Unpooled.wrappedBuffer(KO); - } - - FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, content); - response.headers().set(CONTENT_TYPE, "text/plain"); - response.headers().setInt(CONTENT_LENGTH, response.content().readableBytes()); - - ctx.write(response).addListener(ChannelFutureListener.CLOSE); - } - } + @Override + protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { + doGet(req, resp); } } diff --git a/camel-k-runtime-health/src/main/resources/META-INF/services/org.apache.camel.k.Runtime$Listener b/camel-k-runtime-health/src/main/resources/META-INF/services/org/apache/camel/k/customizer/health similarity index 93% copy from camel-k-runtime-health/src/main/resources/META-INF/services/org.apache.camel.k.Runtime$Listener copy to camel-k-runtime-health/src/main/resources/META-INF/services/org/apache/camel/k/customizer/health index 10ba5ec..abe3515 100644 --- a/camel-k-runtime-health/src/main/resources/META-INF/services/org.apache.camel.k.Runtime$Listener +++ b/camel-k-runtime-health/src/main/resources/META-INF/services/org/apache/camel/k/customizer/health @@ -15,5 +15,4 @@ # limitations under the License. # -org.apache.camel.k.health.HealthConfigurer - +class=org.apache.camel.k.health.HealthContextCustomizer diff --git a/camel-k-runtime-health/src/test/java/org/apache/camel/k/health/HealthCustomizerTest.java b/camel-k-runtime-health/src/test/java/org/apache/camel/k/health/HealthCustomizerTest.java new file mode 100644 index 0000000..0713b44 --- /dev/null +++ b/camel-k-runtime-health/src/test/java/org/apache/camel/k/health/HealthCustomizerTest.java @@ -0,0 +1,53 @@ +/** + * 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.k.health; + +import io.undertow.servlet.Servlets; +import io.undertow.servlet.api.DeploymentManager; +import io.undertow.servlet.core.ManagedServlet; +import io.undertow.servlet.core.ManagedServlets; +import org.apache.camel.impl.DefaultCamelContext; +import org.apache.camel.k.InMemoryRegistry; +import org.apache.camel.k.Runtime; +import org.apache.camel.k.servlet.ServletContextCustomizer; +import org.apache.camel.test.AvailablePortFinder; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class HealthCustomizerTest { + + @Test + public void testServletConfigurer() { + Runtime.Registry registry = new InMemoryRegistry(); + Runtime runtime = Runtime.of(new DefaultCamelContext(registry), registry); + + HealthContextCustomizer healthCustomizer = new HealthContextCustomizer(); + healthCustomizer.apply(runtime.getContext(), runtime.getRegistry()); + + ServletContextCustomizer servletCustomizer = new ServletContextCustomizer(); + servletCustomizer.setBindPort(AvailablePortFinder.getNextAvailable()); + servletCustomizer.apply(runtime.getContext(), runtime.getRegistry()); + + DeploymentManager manager = Servlets.defaultContainer().getDeploymentByPath("/"); + ManagedServlets managedServlets = manager.getDeployment().getServlets(); + ManagedServlet servlet = managedServlets.getManagedServlet("HealthServlet"); + + assertThat(servlet).isNotNull(); + assertThat(servlet.getServletInfo().getMappings()).contains("/health"); + } +} diff --git a/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/ApplicationRuntime.java b/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/ApplicationRuntime.java index e02a07e..7852665 100644 --- a/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/ApplicationRuntime.java +++ b/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/ApplicationRuntime.java @@ -16,6 +16,7 @@ */ package org.apache.camel.k.jvm; +import java.util.Comparator; import java.util.LinkedHashSet; import java.util.Set; @@ -94,38 +95,51 @@ public final class ApplicationRuntime implements Runtime { if (p == phase) { try { consumer.accept(runtime); + return true; } catch (Exception e) { throw Exceptions.wrapRuntimeCamelException(e); } } + + return false; }); } private class MainListenerAdapter implements org.apache.camel.main.MainListener { @Override public void beforeStart(MainSupport main) { - listeners.forEach(l -> l.accept(Phase.Starting, ApplicationRuntime.this)); + invokeListeners(Phase.Starting); } @Override public void configure(CamelContext context) { - listeners.forEach(l -> l.accept(Phase.ConfigureContext, ApplicationRuntime.this)); - listeners.forEach(l -> l.accept(Phase.ConfigureRoutes, ApplicationRuntime.this)); + invokeListeners(Phase.ConfigureContext); + invokeListeners(Phase.ConfigureRoutes); } @Override public void afterStart(MainSupport main) { - listeners.forEach(l -> l.accept(Phase.Started, ApplicationRuntime.this)); + invokeListeners(Phase.Started); } @Override public void beforeStop(MainSupport main) { - listeners.forEach(l -> l.accept(Phase.Stopping, ApplicationRuntime.this)); + invokeListeners(Phase.Stopping); } @Override public void afterStop(MainSupport main) { - listeners.forEach(l -> l.accept(Phase.Stopped, ApplicationRuntime.this)); + invokeListeners(Phase.Stopped); + } + + private void invokeListeners(Phase phase) { + listeners.stream() + .sorted(Comparator.comparingInt(Listener::getOrder)) + .forEach(l -> { + if (l.accept(phase, ApplicationRuntime.this)) { + LOGGER.info("Listener {} executed in phase {}", l, phase); + } + }); } } } diff --git a/camel-k-runtime-health/pom.xml b/camel-k-runtime-servlet/pom.xml similarity index 83% copy from camel-k-runtime-health/pom.xml copy to camel-k-runtime-servlet/pom.xml index 6846e71..0317f83 100644 --- a/camel-k-runtime-health/pom.xml +++ b/camel-k-runtime-servlet/pom.xml @@ -25,7 +25,7 @@ </parent> <modelVersion>4.0.0</modelVersion> - <artifactId>camel-k-runtime-health</artifactId> + <artifactId>camel-k-runtime-servlet</artifactId> <dependencies> @@ -36,14 +36,33 @@ <!-- ****************************** --> <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-core</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-servlet</artifactId> + <scope>provided</scope> + </dependency> + <dependency> <groupId>org.apache.camel.k</groupId> <artifactId>camel-k-runtime-core</artifactId> </dependency> + <!-- + the following dependencies should be kept in sync with the version + used by camel + --> <dependency> - <groupId>org.apache.camel</groupId> - <artifactId>camel-netty4-http</artifactId> - <scope>provided</scope> + <groupId>io.undertow</groupId> + <artifactId>undertow-core</artifactId> + <version>${undertow.version}</version> + </dependency> + <dependency> + <groupId>io.undertow</groupId> + <artifactId>undertow-servlet</artifactId> + <version>1.4.26.Final</version> </dependency> <!-- ****************************** --> @@ -57,6 +76,11 @@ <artifactId>camel-k-runtime-jvm</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-test</artifactId> + <scope>test</scope> + </dependency> <dependency> <groupId>org.junit.jupiter</groupId> diff --git a/camel-k-runtime-health/src/main/java/org/apache/camel/k/health/HealthConfigurer.java b/camel-k-runtime-servlet/src/main/java/org/apache/camel/k/servlet/ServletContextCustomizer.java similarity index 67% rename from camel-k-runtime-health/src/main/java/org/apache/camel/k/health/HealthConfigurer.java rename to camel-k-runtime-servlet/src/main/java/org/apache/camel/k/servlet/ServletContextCustomizer.java index cea94fe..5666298 100644 --- a/camel-k-runtime-health/src/main/java/org/apache/camel/k/health/HealthConfigurer.java +++ b/camel-k-runtime-servlet/src/main/java/org/apache/camel/k/servlet/ServletContextCustomizer.java @@ -14,24 +14,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.k.health; +package org.apache.camel.k.servlet; +import org.apache.camel.CamelContext; +import org.apache.camel.Ordered; +import org.apache.camel.k.ContextCustomizer; import org.apache.camel.k.Runtime; -import org.apache.camel.spi.HasId; -public class HealthConfigurer implements Runtime.Listener, HasId { - public static final String ID = "endpoint.health"; +public class ServletContextCustomizer implements ContextCustomizer { public static final String DEFAULT_BIND_HOST = "0.0.0.0"; - public static final int DEFAULT_BIND_PORT = 8081; - public static final String DEFAULT_PATH = "/health"; - - private HealthEndpoint endpoint; + public static final int DEFAULT_BIND_PORT = 8080; + public static final String DEFAULT_PATH = "/"; private String bindHost; private int bindPort; private String path; + private ServletEndpoint endpoint; - public HealthConfigurer() { + public ServletContextCustomizer() { this.bindHost = DEFAULT_BIND_HOST; this.bindPort = DEFAULT_BIND_PORT; this.path = DEFAULT_PATH; @@ -62,23 +62,18 @@ public class HealthConfigurer implements Runtime.Listener, HasId { } @Override - public void accept(Runtime.Phase phase, Runtime runtime) { + public void apply(CamelContext camelContext, Runtime.Registry registry) { + endpoint = new ServletEndpoint(camelContext, bindHost, bindPort, path); + try { - if (phase == Runtime.Phase.Starting) { - endpoint = new HealthEndpoint(runtime.getContext(), bindHost, bindPort, path); - endpoint.start(); - } else if (phase == Runtime.Phase.Stopping) { - if (endpoint != null) { - endpoint.stop(); - } - } + camelContext.addService(endpoint, true, true); } catch (Exception e) { throw new RuntimeException(e); } } @Override - public String getId() { - return ID; + public int getOrder() { + return Ordered.LOWEST; } } diff --git a/camel-k-runtime-servlet/src/main/java/org/apache/camel/k/servlet/ServletEndpoint.java b/camel-k-runtime-servlet/src/main/java/org/apache/camel/k/servlet/ServletEndpoint.java new file mode 100644 index 0000000..26a0968 --- /dev/null +++ b/camel-k-runtime-servlet/src/main/java/org/apache/camel/k/servlet/ServletEndpoint.java @@ -0,0 +1,85 @@ +/** + * 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.k.servlet; + +import javax.servlet.http.HttpServlet; + +import io.undertow.Handlers; +import io.undertow.Undertow; +import io.undertow.server.handlers.PathHandler; +import io.undertow.servlet.Servlets; +import io.undertow.servlet.api.DeploymentInfo; +import io.undertow.servlet.api.DeploymentManager; +import io.undertow.servlet.util.ImmediateInstanceHandle; +import org.apache.camel.CamelContext; +import org.apache.camel.k.adapter.ServiceSupport; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ServletEndpoint extends ServiceSupport { + private static final Logger LOGGER = LoggerFactory.getLogger(ServletEndpoint.class); + + private final CamelContext context; + private final String bindHost; + private final int bindPort; + private final String path; + + private Undertow server; + private DeploymentManager manager; + + public ServletEndpoint(CamelContext context, String bindHost, int bindPort, String path) { + this.context = context; + this.bindHost = bindHost; + this.bindPort = bindPort; + this.path = path; + } + + @Override + protected void doStart() throws Exception { + DeploymentInfo servletBuilder = Servlets.deployment() + .setClassLoader(ServletEndpoint.class.getClassLoader()) + .setContextPath(path) + .setDeploymentName("camel-k.war"); + + context.getRegistry().findByType(ServletRegistration.class).forEach( r -> { + LOGGER.info("Registering servlet: {}", r); + + servletBuilder.addServlet( + Servlets.servlet(r.getName(), HttpServlet.class, () -> new ImmediateInstanceHandle(r.getServlet())).addMappings(r.getMappings()) + ); + } + ); + + this.manager = Servlets.defaultContainer().addDeployment(servletBuilder); + this.manager.deploy(); + + PathHandler path = Handlers.path(Handlers.redirect(this.path)).addPrefixPath(this.path, manager.start()); + + LOGGER.info("Starting servlet engine on {}:{}{}", this.bindHost, this.bindPort, this.path); + + this.server = Undertow.builder().addHttpListener(this.bindPort, this.bindHost).setHandler(path).build(); + this.server.start(); + } + + @Override + protected void doStop() throws Exception { + if (this.server != null) { + LOGGER.info("Stopping servlet engine"); + this.server.stop(); + } + } +} diff --git a/camel-k-runtime-servlet/src/main/java/org/apache/camel/k/servlet/ServletRegistration.java b/camel-k-runtime-servlet/src/main/java/org/apache/camel/k/servlet/ServletRegistration.java new file mode 100644 index 0000000..24ace5a --- /dev/null +++ b/camel-k-runtime-servlet/src/main/java/org/apache/camel/k/servlet/ServletRegistration.java @@ -0,0 +1,81 @@ +/** + * 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.k.servlet; + +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.Set; +import javax.servlet.Servlet; + +/** + * An helper class used to register servlets. + * + * <pre> + * public class WebhookCustomizer implements ContextCustomizer { + * @Override + * public void apply(CamelContext camelContext, Runtime.Registry registry) { + * registry.bind( + * "webhook-servlet", + * new ServletRegistration("CamelServlet", new CamelHttpTransportServlet(), "/webhook/*") + * ); + * } + * } + * <pre> + */ +public final class ServletRegistration { + private final Servlet servlet; + private final String name; + private final Set<String> mappings; + + public ServletRegistration(String name, Servlet servlet, Collection<String> mappings) { + this.name = name; + this.servlet = servlet; + this.mappings = new LinkedHashSet<>(); + this.mappings.addAll(mappings); + } + + public ServletRegistration(String name, Servlet servlet, String... mappings) { + this.name = name; + this.servlet = servlet; + this.mappings = new LinkedHashSet<>(); + + for (String mapping: mappings) { + this.mappings.add(mapping); + } + } + + public String getName() { + return name; + } + + public Servlet getServlet() { + return servlet; + } + + public Collection<String> getMappings() { + return mappings; + } + + @Override + public String toString() { + return "ServletRegistration{" + + "servlet=" + servlet + + ", name='" + name + '\'' + + ", mappings=" + mappings + + '}'; + } +} diff --git a/camel-k-runtime-health/src/main/resources/META-INF/services/org.apache.camel.k.Runtime$Listener b/camel-k-runtime-servlet/src/main/resources/META-INF/services/org/apache/camel/k/customizer/servlet similarity index 93% rename from camel-k-runtime-health/src/main/resources/META-INF/services/org.apache.camel.k.Runtime$Listener rename to camel-k-runtime-servlet/src/main/resources/META-INF/services/org/apache/camel/k/customizer/servlet index 10ba5ec..46bb724 100644 --- a/camel-k-runtime-health/src/main/resources/META-INF/services/org.apache.camel.k.Runtime$Listener +++ b/camel-k-runtime-servlet/src/main/resources/META-INF/services/org/apache/camel/k/customizer/servlet @@ -15,5 +15,4 @@ # limitations under the License. # -org.apache.camel.k.health.HealthConfigurer - +class=org.apache.camel.k.servlet.ServletContextCustomizer diff --git a/camel-k-runtime-servlet/src/test/java/org/apache/camel/k/servlet/ServletCustomizerTest.java b/camel-k-runtime-servlet/src/test/java/org/apache/camel/k/servlet/ServletCustomizerTest.java new file mode 100644 index 0000000..e44bb51 --- /dev/null +++ b/camel-k-runtime-servlet/src/test/java/org/apache/camel/k/servlet/ServletCustomizerTest.java @@ -0,0 +1,55 @@ +/** + * 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.k.servlet; + +import io.undertow.servlet.Servlets; +import io.undertow.servlet.api.DeploymentManager; +import io.undertow.servlet.core.ManagedServlet; +import io.undertow.servlet.core.ManagedServlets; +import org.apache.camel.component.servlet.CamelHttpTransportServlet; +import org.apache.camel.impl.DefaultCamelContext; +import org.apache.camel.k.InMemoryRegistry; +import org.apache.camel.k.Runtime; +import org.apache.camel.test.AvailablePortFinder; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ServletCustomizerTest { + + @Test + public void testServletConfigurer() { + Runtime.Registry registry = new InMemoryRegistry(); + Runtime runtime = Runtime.of(new DefaultCamelContext(registry), registry); + + runtime.getRegistry().bind( + "camel-servlet", + new ServletRegistration("CamelServlet", new CamelHttpTransportServlet(), "/webhook/*") + ); + + ServletContextCustomizer servletCustomizer = new ServletContextCustomizer(); + servletCustomizer.setBindPort(AvailablePortFinder.getNextAvailable()); + servletCustomizer.apply(runtime.getContext(), runtime.getRegistry()); + + DeploymentManager manager = Servlets.defaultContainer().getDeploymentByPath("/"); + ManagedServlets managedServlets = manager.getDeployment().getServlets(); + ManagedServlet servlet = managedServlets.getManagedServlet("CamelServlet"); + + assertThat(servlet).isNotNull(); + assertThat(servlet.getServletInfo().getMappings()).contains("/webhook/*"); + } +} diff --git a/camel-k-runtime-servlet/src/test/resources/log4j2-test.xml b/camel-k-runtime-servlet/src/test/resources/log4j2-test.xml new file mode 100644 index 0000000..6f81163 --- /dev/null +++ b/camel-k-runtime-servlet/src/test/resources/log4j2-test.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Configuration status="INFO"> + <Appenders> + <Console name="STDOUT" target="SYSTEM_OUT"> + <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS}|%-5level|%t|%c - %msg%n"/> + </Console> + <Null name="NONE"/> + </Appenders> + + <Loggers> + <Logger name="io.undertow" level="INFO"/> + <Root level="INFO"> + <!--<AppenderRef ref="STDOUT"/>--> + <AppenderRef ref="NONE"/> + </Root> + </Loggers> + +</Configuration> \ No newline at end of file diff --git a/pom.xml b/pom.xml index 20a48bb..c228d0d 100644 --- a/pom.xml +++ b/pom.xml @@ -55,6 +55,7 @@ <jackson.version>2.9.8</jackson.version> <immutables.version>2.7.5</immutables.version> <semver4j.version>2.2.0</semver4j.version> + <undertow.version>1.4.26.Final</undertow.version> <gmavenplus-plugin.version>1.6.1</gmavenplus-plugin.version> <fabric8-maven-plugin.version>3.5.42</fabric8-maven-plugin.version> <maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version> @@ -62,6 +63,7 @@ <maven-remote-resources-plugin.version>1.5</maven-remote-resources-plugin.version> <versions-maven-plugin.version>2.7</versions-maven-plugin.version> <directory-maven-plugin.version>0.3.1</directory-maven-plugin.version> + <exec-maven-plugin.version>1.6.0</exec-maven-plugin.version> </properties> <developers> @@ -147,6 +149,8 @@ <module>camel-k-runtime-kotlin</module> <module>camel-k-runtime-yaml</module> <module>camel-k-runtime-health</module> + <module>camel-k-runtime-servlet</module> + <module>camel-k-runtime-examples</module> <module>camel-knative-http</module> <module>camel-knative</module> <module>camel-k-runtime-bom</module> @@ -224,6 +228,11 @@ </dependency> <dependency> <groupId>org.apache.camel.k</groupId> + <artifactId>camel-k-runtime-servlet</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.camel.k</groupId> <artifactId>camel-knative</artifactId> <version>${project.version}</version> </dependency>