You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwebbeans.apache.org by rm...@apache.org on 2017/01/02 12:17:56 UTC

svn commit: r1776924 - in /openwebbeans/meecrowave/trunk: meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/ meecrowave-doc/src/main/jbake/content/meecrowave-jolokia/ meecrowave-jolokia/ meecrowave-jolokia/src/main/java/org/apache/meecro...

Author: rmannibucau
Date: Mon Jan  2 12:17:56 2017
New Revision: 1776924

URL: http://svn.apache.org/viewvc?rev=1776924&view=rev
Log:
adding hawt.io integration

Added:
    openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/main/java/org/apache/meecrowave/jolokia/HawtioInitializer.java
      - copied, changed from r1776859, openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/main/java/org/apache/meecrowave/jolokia/JolokiaInitializer.java
    openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/test/java/org/apache/meecrowave/jolokia/HawtioTest.java
      - copied, changed from r1776859, openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/test/java/org/apache/meecrowave/jolokia/JolokiaInitializerTest.java
Modified:
    openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/KnownJarsFilter.java
    openwebbeans/meecrowave/trunk/meecrowave-doc/src/main/jbake/content/meecrowave-jolokia/index.adoc
    openwebbeans/meecrowave/trunk/meecrowave-jolokia/pom.xml
    openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/main/java/org/apache/meecrowave/jolokia/JolokiaInitializer.java
    openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer
    openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/test/java/org/apache/meecrowave/jolokia/JolokiaInitializerTest.java

Modified: openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/KnownJarsFilter.java
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/KnownJarsFilter.java?rev=1776924&r1=1776923&r2=1776924&view=diff
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/KnownJarsFilter.java (original)
+++ openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/KnownJarsFilter.java Mon Jan  2 12:17:56 2017
@@ -90,6 +90,7 @@ public class KnownJarsFilter implements
         add("commons-dbcp-all-1.3-");
         add("commons-digester-");
         add("commons-discovery-");
+        add("commons-fileupload-");
         add("commons-httpclient-");
         add("commons-io-");
         add("commons-jcs-core-");
@@ -122,6 +123,7 @@ public class KnownJarsFilter implements
         add("johnzon-");
         add("jolokia-core-");
         add("jolokia-jvm-");
+        add("jolokia-serv");
         add("json-simple-");
         add("fusemq-leveldb-");
         add("geronimo-");

Modified: openwebbeans/meecrowave/trunk/meecrowave-doc/src/main/jbake/content/meecrowave-jolokia/index.adoc
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-doc/src/main/jbake/content/meecrowave-jolokia/index.adoc?rev=1776924&r1=1776923&r2=1776924&view=diff
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-doc/src/main/jbake/content/meecrowave-jolokia/index.adoc (original)
+++ openwebbeans/meecrowave/trunk/meecrowave-doc/src/main/jbake/content/meecrowave-jolokia/index.adoc Mon Jan  2 12:17:56 2017
@@ -18,6 +18,10 @@ Coordinates:
 </dependency>
 ----
 
+== Jolokia only
+
+If Hawt.io is not setup (not there or inactive) the module will set up jolokia alone.
+
 It will deploy the jolokia servlet on `/jolokia/*` or the property `jolokia.web.mapping` set
 on the `Meecrowave.Builder`.
 
@@ -26,7 +30,46 @@ Meecrowave core configuration for more d
 
 More on https://jolokia.org/reference/html/
 
-== Running HawtIO
+== Hawt.io
+
+By default hawt.io will be deployed and activated on `/hawtio/` endpoint.
+
+To activate it you need to add these dependencies:
+
+[source,xml]
+----
+<dependency>
+  <groupId>io.hawt</groupId>
+  <artifactId>hawtio-springboot</artifactId>
+  <version>1.4.67</version>
+  <optional>true</optional>
+  <exclusions>
+    <exclusion>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-web</artifactId>
+    </exclusion>
+  </exclusions>
+</dependency>
+<dependency>
+  <groupId>org.apache.logging.log4j</groupId>
+  <artifactId>log4j-slf4j-impl</artifactId>
+  <version>${log4j2.version}</version>
+  <optional>true</optional>
+</dependency>
+----
+
+NOTE: we don't need spring boot but we reuse hawt.io spring boot module which packages web resources in a jar.
+
+By default it will setup the security to use the Servlet security which means you can use meecrowave options:
+
+[source]
+----
+./meecrowave-runner --users=admin=admin --roles=admin=admin
+----
+
+And log with admin/admin user.
+
+== Running HawtIO war
 
 To run http://hawt.io, the easiest is to setup jaas and run the hawt.io war:
 

Modified: openwebbeans/meecrowave/trunk/meecrowave-jolokia/pom.xml
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-jolokia/pom.xml?rev=1776924&r1=1776923&r2=1776924&view=diff
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-jolokia/pom.xml (original)
+++ openwebbeans/meecrowave/trunk/meecrowave-jolokia/pom.xml Mon Jan  2 12:17:56 2017
@@ -49,6 +49,7 @@
       <version>${project.version}</version>
       <scope>provided</scope>
     </dependency>
+    <!-- <jolokia.version>2.0.0-M3</jolokia.version>
     <dependency>
       <groupId>org.jolokia</groupId>
       <artifactId>jolokia-server-core</artifactId>
@@ -64,6 +65,32 @@
       <artifactId>jolokia-service-jmx</artifactId>
       <version>${jolokia.version}</version>
     </dependency>
+    -->
+
+    <dependency> <!-- spring boot module has web resources embedded, reusing that part -->
+      <groupId>io.hawt</groupId>
+      <artifactId>hawtio-springboot</artifactId>
+      <version>1.4.67</version>
+      <optional>true</optional>
+      <exclusions>
+        <exclusion>
+          <groupId>org.springframework.boot</groupId>
+          <artifactId>spring-boot-starter-web</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-slf4j-impl</artifactId>
+      <version>${log4j2.version}</version>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>commons-cli</groupId>
+      <artifactId>commons-cli</artifactId>
+      <version>1.3.1</version>
+      <scope>test</scope>
+    </dependency>
 
     <dependency>
       <groupId>org.apache.meecrowave</groupId>

Copied: openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/main/java/org/apache/meecrowave/jolokia/HawtioInitializer.java (from r1776859, openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/main/java/org/apache/meecrowave/jolokia/JolokiaInitializer.java)
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/main/java/org/apache/meecrowave/jolokia/HawtioInitializer.java?p2=openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/main/java/org/apache/meecrowave/jolokia/HawtioInitializer.java&p1=openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/main/java/org/apache/meecrowave/jolokia/JolokiaInitializer.java&r1=1776859&r2=1776924&rev=1776924&view=diff
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/main/java/org/apache/meecrowave/jolokia/JolokiaInitializer.java (original)
+++ openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/main/java/org/apache/meecrowave/jolokia/HawtioInitializer.java Mon Jan  2 12:17:56 2017
@@ -18,27 +18,322 @@
  */
 package org.apache.meecrowave.jolokia;
 
+import io.hawt.HawtioContextListener;
+import io.hawt.web.AuthenticationFilter;
+import io.hawt.web.CORSFilter;
+import io.hawt.web.CacheHeadersFilter;
+import io.hawt.web.ContextFormatterServlet;
+import io.hawt.web.ExportContextServlet;
+import io.hawt.web.GitServlet;
+import io.hawt.web.JavaDocServlet;
+import io.hawt.web.JolokiaConfiguredAgentServlet;
+import io.hawt.web.LoginServlet;
+import io.hawt.web.LogoutServlet;
+import io.hawt.web.PluginServlet;
+import io.hawt.web.ProxyServlet;
+import io.hawt.web.RedirectFilter;
+import io.hawt.web.SessionExpiryFilter;
+import io.hawt.web.UploadServlet;
+import io.hawt.web.UserServlet;
+import io.hawt.web.XFrameOptionsFilter;
+import io.hawt.web.keycloak.KeycloakServlet;
+import org.apache.catalina.Globals;
+import org.apache.catalina.WebResourceRoot;
+import org.apache.catalina.realm.GenericPrincipal;
+import org.apache.catalina.webresources.JarResourceSet;
+import org.apache.commons.fileupload.servlet.FileCleanerCleanup;
 import org.apache.meecrowave.Meecrowave;
-import org.jolokia.server.core.http.AgentServlet;
+import org.apache.meecrowave.runner.Cli;
+import org.apache.meecrowave.runner.cli.CliOption;
 
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.CDI;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.AppConfigurationEntry;
+import javax.security.auth.login.Configuration;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.spi.LoginModule;
+import javax.servlet.DispatcherType;
+import javax.servlet.FilterRegistration;
 import javax.servlet.ServletContainerInitializer;
 import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
 import javax.servlet.ServletException;
 import javax.servlet.ServletRegistration;
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.security.Principal;
+import java.security.Security;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Set;
 
 import static java.util.Optional.ofNullable;
 
-public class JolokiaInitializer implements ServletContainerInitializer {
+public class HawtioInitializer implements ServletContainerInitializer {
     @Override
     public void onStartup(final Set<Class<?>> set, final ServletContext servletContext) throws ServletException {
-        final Meecrowave.Builder builder = Meecrowave.Builder.class.cast(servletContext.getAttribute("meecrowave.configuration"));
-        final ServletRegistration.Dynamic jolokia = servletContext.addServlet("jolokia", AgentServlet.class);
-        jolokia.setLoadOnStartup(1);
-        final String mapping = ofNullable(builder.getProperties())
-                .map(p -> p.getProperty("jolokia.web.mapping"))
-                .orElse("/jolokia/*");
-        jolokia.addMapping(mapping);
-        servletContext.log("Installed Jolokia on " + mapping);
+        try {
+            servletContext.getClassLoader().loadClass("io.hawt.web.UserServlet");
+        } catch (final ClassNotFoundException e) {
+            servletContext.log("Hawt.io not available, skipping");
+            return;
+        }
+        Delegate.doSetup(servletContext);
+    }
+
+    private static class Delegate {
+        private Delegate() {
+            // no-op
+        }
+
+        private static void doSetup(final ServletContext servletContext) {
+            final Meecrowave.Builder config = Meecrowave.Builder.class.cast(servletContext.getAttribute("meecrowave.configuration"));
+            final HawtioConfiguration configuration = config.getExtension(HawtioConfiguration.class);
+            final JolokiaInitializer.JolokiaConfiguration jolokia = config.getExtension(JolokiaInitializer.JolokiaConfiguration.class);
+            if (!configuration.isActive()) {
+                return;
+            }
+
+            doSetupJaas(configuration, servletContext);
+
+            final String mapping = ofNullable(configuration.getMapping()).orElse("/hawtio/");
+
+            {
+                final ServletRegistration.Dynamic servlet = servletContext.addServlet("hawtio-user", UserServlet.class);
+                servlet.addMapping(mapping + "user/*");
+            }
+            {
+                final ServletRegistration.Dynamic servlet = servletContext.addServlet("hawtio-proxy", ProxyServlet.class);
+                servlet.addMapping(mapping + "proxy/*");
+            }
+            {
+                final ServletRegistration.Dynamic servlet = servletContext.addServlet("hawtio-file-upload", UploadServlet.class);
+                servlet.addMapping(mapping + "file-upload/*");
+            }
+            {
+                final ServletRegistration.Dynamic servlet = servletContext.addServlet("hawtio-login", LoginServlet.class);
+                servlet.addMapping(mapping + "auth/login/*");
+            }
+            {
+                final ServletRegistration.Dynamic servlet = servletContext.addServlet("hawtio-logout", LogoutServlet.class);
+                servlet.addMapping(mapping + "auth/logout/*");
+            }
+            {
+                final ServletRegistration.Dynamic servlet = servletContext.addServlet("hawtio-keycloak", KeycloakServlet.class);
+                servlet.addMapping(mapping + "keycloak/*");
+            }
+            {
+                final ServletRegistration.Dynamic servlet = servletContext.addServlet("hawtio-exportContext", ExportContextServlet.class);
+                servlet.addMapping(mapping + "exportContext/*");
+            }
+            {
+                final ServletRegistration.Dynamic servlet = servletContext.addServlet("hawtio-javadoc", JavaDocServlet.class);
+                servlet.addMapping(mapping + "javadoc/*");
+            }
+            {
+                final ServletRegistration.Dynamic servlet = servletContext.addServlet("hawtio-plugin", PluginServlet.class);
+                servlet.addMapping(mapping + "plugin/*");
+            }
+            {
+                final ServletRegistration.Dynamic servlet = servletContext.addServlet("hawtio-contextFormatter", ContextFormatterServlet.class);
+                servlet.addMapping(mapping + "contextFormatter/*");
+            }
+            {
+                final ServletRegistration.Dynamic servlet = servletContext.addServlet("hawtio-git", GitServlet.class);
+                servlet.addMapping(mapping + "git/*");
+            }
+            {
+                final ServletRegistration.Dynamic servlet = servletContext.addServlet("hawtio-jolokia", JolokiaConfiguredAgentServlet.class);
+                servlet.setInitParameter("mbeanQualifier", "qualifier=hawtio");
+                servlet.setInitParameter("includeStackTrace", "false");
+                servlet.setInitParameter("restrictorClass", "io.hawt.web.RBACRestrictor");
+                servlet.addMapping(mapping + "jolokia/*");
+            }
+            {
+                final WebResourceRoot root = WebResourceRoot.class.cast(servletContext.getAttribute(Globals.RESOURCES_ATTR));
+                final String url = servletContext.getClassLoader().getResource("static/hawtio").toExternalForm();
+                final int sep = url.lastIndexOf("!/");
+                String jar = url;
+                if (jar.startsWith("jar:")) {
+                    jar = url.substring("jar:".length(), sep);
+                }
+                if (jar.startsWith("file:")) {
+                    jar = jar.substring("file:".length());
+                }
+                root.addPostResources(new JarResourceSet(root, mapping, jar, "/static/hawtio/"));
+            }
+
+            servletContext.addListener(HawtioContextListener.class);
+            servletContext.addListener(FileCleanerCleanup.class);
+
+            {
+                final FilterRegistration.Dynamic filter = servletContext.addFilter("hawtio-redirect", RedirectFilter.class);
+                filter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), false, mapping + "*");
+            }
+            {
+                final FilterRegistration.Dynamic filter = servletContext.addFilter("hawtio-cacheheaders", CacheHeadersFilter.class);
+                filter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), false, mapping + "*");
+            }
+            {
+                final FilterRegistration.Dynamic filter = servletContext.addFilter("hawtio-cors", CORSFilter.class);
+                filter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), false, mapping + "*");
+            }
+            {
+                final FilterRegistration.Dynamic filter = servletContext.addFilter("hawtio-xframe", XFrameOptionsFilter.class);
+                filter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), false, mapping + "*");
+            }
+            {
+                final FilterRegistration.Dynamic filter = servletContext.addFilter("hawtio-sessionexpiry", SessionExpiryFilter.class);
+                filter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), false, mapping + "*");
+            }
+            {
+                final FilterRegistration.Dynamic filter = servletContext.addFilter("hawtio-authentication", AuthenticationFilter.class);
+                filter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), false,
+                        mapping + "auth/*", mapping + "upload/*", mapping + "javadoc/*", mapping + "jolokia/*",
+                        ofNullable(jolokia.getMapping()).orElse("/jolokia/*"));
+            }
+
+            servletContext.log("Installed Hawt.io on " + mapping);
+        }
+
+        private static void doSetupJaas(final HawtioConfiguration configuration, final ServletContext servletContext) {
+            if (!configuration.isJaas()) {
+                return;
+            }
+            final String key = "login.configuration.provider";
+            final String val = Security.getProperty(key);
+            Security.setProperty(key, EmbeddedConfiguration.class.getName());
+            servletContext.addListener(new ServletContextListener() {
+                @Override
+                public void contextDestroyed(final ServletContextEvent sce) {
+                    Security.setProperty(key, val == null ? "sun.security.provider.ConfigFile" : val);
+                }
+            });
+        }
+    }
+
+    public static class EmbeddedConfiguration extends Configuration {
+        private final AppConfigurationEntry[] entries = new AppConfigurationEntry[]{
+                new AppConfigurationEntry(EmbeddedLoginModule.class.getName(), AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, new HashMap<>())
+        };
+
+        @Override
+        public AppConfigurationEntry[] getAppConfigurationEntry(final String name) {
+            return "karaf".equals(name) ? entries : null;
+        }
+    }
+
+    public static class EmbeddedLoginModule implements LoginModule {
+        private Subject subject;
+        private CallbackHandler callbackHandler;
+
+        private Principal principal;
+
+        @Override
+        public void initialize(final Subject subject, final CallbackHandler callbackHandler,
+                               final Map<String, ?> sharedState, final Map<String, ?> options) {
+            this.subject = subject;
+            this.callbackHandler = callbackHandler;
+        }
+
+        @Override
+        public boolean login() throws LoginException {
+            final Callback[] callbacks = new Callback[2];
+            callbacks[0] = new NameCallback("Username: ");
+            callbacks[1] = new PasswordCallback("Password: ", false);
+            try {
+                callbackHandler.handle(callbacks);
+            } catch (IOException | UnsupportedCallbackException e) {
+                throw new LoginException(e.toString());
+            }
+
+            final BeanManager beanManager = CDI.current().getBeanManager();
+            final HttpServletRequest request =
+                    HttpServletRequest.class.cast(
+                            beanManager.getReference(
+                                    beanManager.resolve(beanManager.getBeans(HttpServletRequest.class)),
+                                    HttpServletRequest.class,
+                                    beanManager.createCreationalContext(null)));
+
+            try {
+                request.login(NameCallback.class.cast(callbacks[0]).getName(), new String(PasswordCallback.class.cast(callbacks[1]).getPassword()));
+            } catch (final ServletException e) {
+                throw new LoginException(e.getMessage());
+            }
+
+            principal = request.getUserPrincipal();
+
+            return principal != null;
+        }
+
+        @Override
+        public boolean commit() throws LoginException {
+            if (!subject.getPrincipals().contains(principal)) {
+                subject.getPrincipals().add(principal);
+                if (GenericPrincipal.class.isInstance(principal)) {
+                    final String roles[] = GenericPrincipal.class.cast(principal).getRoles();
+                    for (final String role : roles) {
+                        subject.getPrincipals().add(new GenericPrincipal(role, null, null));
+                    }
+
+                }
+            }
+            return true;
+        }
+
+        @Override
+        public boolean abort() throws LoginException {
+            principal = null;
+            return true;
+        }
+
+        @Override
+        public boolean logout() throws LoginException {
+            subject.getPrincipals().remove(principal);
+            return true;
+        }
+    }
+
+    public static class HawtioConfiguration implements Cli.Options {
+        @CliOption(name = "hawtio-mapping", description = "Hawt.io base endpoint")
+        private String mapping;
+
+        @CliOption(name = "hawtio-active", description = "Should Hawt.io be deployed if present")
+        private boolean active = true;
+
+        @CliOption(name = "hawtio-meecrowave-jaas", description = "Should meecrowave setup jaas")
+        private boolean jaas = true;
+
+        public boolean isJaas() {
+            return jaas;
+        }
+
+        public void setJaas(final boolean jaas) {
+            this.jaas = jaas;
+        }
+
+        public boolean isActive() {
+            return active;
+        }
+
+        public void setActive(final boolean active) {
+            this.active = active;
+        }
+
+        public String getMapping() {
+            return mapping;
+        }
+
+        public void setMapping(final String mapping) {
+            this.mapping = mapping;
+        }
     }
 }

Modified: openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/main/java/org/apache/meecrowave/jolokia/JolokiaInitializer.java
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/main/java/org/apache/meecrowave/jolokia/JolokiaInitializer.java?rev=1776924&r1=1776923&r2=1776924&view=diff
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/main/java/org/apache/meecrowave/jolokia/JolokiaInitializer.java (original)
+++ openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/main/java/org/apache/meecrowave/jolokia/JolokiaInitializer.java Mon Jan  2 12:17:56 2017
@@ -19,7 +19,9 @@
 package org.apache.meecrowave.jolokia;
 
 import org.apache.meecrowave.Meecrowave;
-import org.jolokia.server.core.http.AgentServlet;
+import org.apache.meecrowave.runner.Cli;
+import org.apache.meecrowave.runner.cli.CliOption;
+import org.jolokia.http.AgentServlet;
 
 import javax.servlet.ServletContainerInitializer;
 import javax.servlet.ServletContext;
@@ -32,13 +34,48 @@ import static java.util.Optional.ofNulla
 public class JolokiaInitializer implements ServletContainerInitializer {
     @Override
     public void onStartup(final Set<Class<?>> set, final ServletContext servletContext) throws ServletException {
-        final Meecrowave.Builder builder = Meecrowave.Builder.class.cast(servletContext.getAttribute("meecrowave.configuration"));
+        final Meecrowave.Builder config = Meecrowave.Builder.class.cast(servletContext.getAttribute("meecrowave.configuration"));
+        final JolokiaConfiguration configuration = config.getExtension(JolokiaConfiguration.class);
+        if (!configuration.isActive()) {
+            return;
+        }
+        try { // if hawtio is setup skip it
+            servletContext.getClassLoader().loadClass("io.hawt.web.UserServlet");
+            if (config.getExtension(HawtioInitializer.HawtioConfiguration.class).isActive()) {
+                return;
+            }
+        } catch (final ClassNotFoundException e) {
+            // that's what we want
+        }
+
         final ServletRegistration.Dynamic jolokia = servletContext.addServlet("jolokia", AgentServlet.class);
         jolokia.setLoadOnStartup(1);
-        final String mapping = ofNullable(builder.getProperties())
-                .map(p -> p.getProperty("jolokia.web.mapping"))
-                .orElse("/jolokia/*");
+        final String mapping = ofNullable(configuration.getMapping()).orElse("/jolokia/*");
         jolokia.addMapping(mapping);
         servletContext.log("Installed Jolokia on " + mapping);
     }
+
+    public static class JolokiaConfiguration implements Cli.Options {
+        @CliOption(name = "jolokia-mapping", description = "Jolokia endpoint")
+        private String mapping;
+
+        @CliOption(name = "jolokia-active", description = "Should Jolokia be deployed (only if hawt.io is not)")
+        private boolean active = true;
+
+        public boolean isActive() {
+            return active;
+        }
+
+        public void setActive(final boolean active) {
+            this.active = active;
+        }
+
+        public String getMapping() {
+            return mapping;
+        }
+
+        public void setMapping(final String mapping) {
+            this.mapping = mapping;
+        }
+    }
 }

Modified: openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer?rev=1776924&r1=1776923&r2=1776924&view=diff
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer (original)
+++ openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer Mon Jan  2 12:17:56 2017
@@ -1 +1,2 @@
 org.apache.meecrowave.jolokia.JolokiaInitializer
+org.apache.meecrowave.jolokia.HawtioInitializer

Copied: openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/test/java/org/apache/meecrowave/jolokia/HawtioTest.java (from r1776859, openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/test/java/org/apache/meecrowave/jolokia/JolokiaInitializerTest.java)
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/test/java/org/apache/meecrowave/jolokia/HawtioTest.java?p2=openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/test/java/org/apache/meecrowave/jolokia/HawtioTest.java&p1=openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/test/java/org/apache/meecrowave/jolokia/JolokiaInitializerTest.java&r1=1776859&r2=1776924&rev=1776924&view=diff
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/test/java/org/apache/meecrowave/jolokia/JolokiaInitializerTest.java (original)
+++ openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/test/java/org/apache/meecrowave/jolokia/HawtioTest.java Mon Jan  2 12:17:56 2017
@@ -29,16 +29,15 @@ import java.nio.charset.StandardCharsets
 
 import static org.junit.Assert.assertTrue;
 
-public class JolokiaInitializerTest {
+public class HawtioTest {
     @ClassRule
     public static final MeecrowaveRule RULE = new MeecrowaveRule();
 
     @Test
     public void run() throws IOException {
         final String actual = IOUtils.toString(
-                new URL("http://localhost:" + RULE.getConfiguration().getHttpPort() + "/jolokia/read/java.lang:type=Memory/HeapMemoryUsage"),
+                new URL("http://localhost:" + RULE.getConfiguration().getHttpPort() + "/hawtio/"),
                 StandardCharsets.UTF_8);
-        assertTrue(actual, actual.contains("\"status\":200"));
-        assertTrue(actual, actual.contains("\"mbean\":\"java.lang:type=Memory\""));
+        assertTrue(actual, actual.contains("<title>hawtio</title>"));
     }
 }

Modified: openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/test/java/org/apache/meecrowave/jolokia/JolokiaInitializerTest.java
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/test/java/org/apache/meecrowave/jolokia/JolokiaInitializerTest.java?rev=1776924&r1=1776923&r2=1776924&view=diff
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/test/java/org/apache/meecrowave/jolokia/JolokiaInitializerTest.java (original)
+++ openwebbeans/meecrowave/trunk/meecrowave-jolokia/src/test/java/org/apache/meecrowave/jolokia/JolokiaInitializerTest.java Mon Jan  2 12:17:56 2017
@@ -19,6 +19,7 @@
 package org.apache.meecrowave.jolokia;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.meecrowave.Meecrowave;
 import org.apache.meecrowave.junit.MeecrowaveRule;
 import org.junit.ClassRule;
 import org.junit.Test;
@@ -31,7 +32,11 @@ import static org.junit.Assert.assertTru
 
 public class JolokiaInitializerTest {
     @ClassRule
-    public static final MeecrowaveRule RULE = new MeecrowaveRule();
+    public static final MeecrowaveRule RULE = new MeecrowaveRule(new Meecrowave.Builder() {{
+        this.setExtension(HawtioInitializer.HawtioConfiguration.class, new HawtioInitializer.HawtioConfiguration() {{
+            setActive(false);
+        }});
+    }}, "");
 
     @Test
     public void run() throws IOException {