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>

Reply via email to