Merge pull request #14 from dve/patch-1

Update index.adoc to reflect test scope for test dependencies
diff --git a/integration-tests/app-groovy/pom.xml b/integration-tests/app-groovy/pom.xml
index cb26543..a63543d 100644
--- a/integration-tests/app-groovy/pom.xml
+++ b/integration-tests/app-groovy/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <artifactId>integration-tests</artifactId>
     <groupId>org.apache.meecrowave</groupId>
-    <version>1.2.9-SNAPSHOT</version>
+    <version>1.2.10-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
diff --git a/integration-tests/beanvalidation/pom.xml b/integration-tests/beanvalidation/pom.xml
index 1c3323a..3055a9d 100644
--- a/integration-tests/beanvalidation/pom.xml
+++ b/integration-tests/beanvalidation/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <artifactId>integration-tests</artifactId>
     <groupId>org.apache.meecrowave</groupId>
-    <version>1.2.9-SNAPSHOT</version>
+    <version>1.2.10-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
diff --git a/integration-tests/dispatch-jsp/pom.xml b/integration-tests/dispatch-jsp/pom.xml
index c78c456..97eec7f 100644
--- a/integration-tests/dispatch-jsp/pom.xml
+++ b/integration-tests/dispatch-jsp/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <artifactId>integration-tests</artifactId>
     <groupId>org.apache.meecrowave</groupId>
-    <version>1.2.9-SNAPSHOT</version>
+    <version>1.2.10-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
diff --git a/integration-tests/no-cxf/pom.xml b/integration-tests/no-cxf/pom.xml
index 3c2f092..52f2f60 100644
--- a/integration-tests/no-cxf/pom.xml
+++ b/integration-tests/no-cxf/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <artifactId>integration-tests</artifactId>
     <groupId>org.apache.meecrowave</groupId>
-    <version>1.2.9-SNAPSHOT</version>
+    <version>1.2.10-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml
index cf74909..69bdcba 100644
--- a/integration-tests/pom.xml
+++ b/integration-tests/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <artifactId>meecrowave</artifactId>
     <groupId>org.apache.meecrowave</groupId>
-    <version>1.2.9-SNAPSHOT</version>
+    <version>1.2.10-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
diff --git a/integration-tests/sse/pom.xml b/integration-tests/sse/pom.xml
index 3484d9b..e746666 100644
--- a/integration-tests/sse/pom.xml
+++ b/integration-tests/sse/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>integration-tests</artifactId>
         <groupId>org.apache.meecrowave</groupId>
-        <version>1.2.9-SNAPSHOT</version>
+        <version>1.2.10-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/integration-tests/ssl/pom.xml b/integration-tests/ssl/pom.xml
index fd9bf41..88d8514 100644
--- a/integration-tests/ssl/pom.xml
+++ b/integration-tests/ssl/pom.xml
@@ -13,7 +13,7 @@
   <parent>
     <artifactId>integration-tests</artifactId>
     <groupId>org.apache.meecrowave</groupId>
-    <version>1.2.9-SNAPSHOT</version>
+    <version>1.2.10-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
diff --git a/integration-tests/webservices/pom.xml b/integration-tests/webservices/pom.xml
index a194b1b..029108a 100644
--- a/integration-tests/webservices/pom.xml
+++ b/integration-tests/webservices/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <artifactId>integration-tests</artifactId>
     <groupId>org.apache.meecrowave</groupId>
-    <version>1.2.9-SNAPSHOT</version>
+    <version>1.2.10-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
diff --git a/meecrowave-arquillian/pom.xml b/meecrowave-arquillian/pom.xml
index f6b54ee..025adaa 100644
--- a/meecrowave-arquillian/pom.xml
+++ b/meecrowave-arquillian/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <artifactId>meecrowave</artifactId>
     <groupId>org.apache.meecrowave</groupId>
-    <version>1.2.9-SNAPSHOT</version>
+    <version>1.2.10-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
diff --git a/meecrowave-arquillian/src/main/java/org/apache/meecrowave/arquillian/MeecrowaveConfiguration.java b/meecrowave-arquillian/src/main/java/org/apache/meecrowave/arquillian/MeecrowaveConfiguration.java
index 76758a6..2bceac8 100644
--- a/meecrowave-arquillian/src/main/java/org/apache/meecrowave/arquillian/MeecrowaveConfiguration.java
+++ b/meecrowave-arquillian/src/main/java/org/apache/meecrowave/arquillian/MeecrowaveConfiguration.java
@@ -18,12 +18,9 @@
  */
 package org.apache.meecrowave.arquillian;
 
-import org.apache.catalina.Realm;
-import org.apache.meecrowave.Meecrowave;
-import org.apache.xbean.recipe.ObjectRecipe;
-import org.jboss.arquillian.config.descriptor.api.Multiline;
-import org.jboss.arquillian.container.spi.ConfigurationException;
-import org.jboss.arquillian.container.spi.client.container.ContainerConfiguration;
+import static java.util.function.Function.identity;
+import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toMap;
 
 import java.io.ByteArrayInputStream;
 import java.io.File;
@@ -33,9 +30,13 @@
 import java.util.Properties;
 import java.util.stream.Stream;
 
-import static java.util.function.Function.identity;
-import static java.util.stream.Collectors.toList;
-import static java.util.stream.Collectors.toMap;
+import org.apache.catalina.Realm;
+import org.apache.meecrowave.Meecrowave;
+import org.apache.xbean.recipe.ObjectRecipe;
+import org.jboss.arquillian.config.descriptor.api.Multiline;
+import org.jboss.arquillian.container.spi.ConfigurationException;
+import org.jboss.arquillian.container.spi.client.container.ContainerConfiguration;
+import org.jboss.shrinkwrap.api.Configuration;
 
 public class MeecrowaveConfiguration implements ContainerConfiguration {
     private int httpPort = -1;
@@ -119,7 +120,7 @@
         // no-op
     }
 
-    Meecrowave.Builder toMeecrowaveConfiguration() {
+    org.apache.meecrowave.configuration.Configuration toMeecrowaveConfiguration() {
         final Meecrowave.Builder builder = new Meecrowave.Builder();
         for (final Field field : MeecrowaveConfiguration.class.getDeclaredFields()) {
             final String name = field.getName();
@@ -130,7 +131,7 @@
             }
 
             try {
-                final Field configField = Meecrowave.Builder.class.getDeclaredField(field.getName());
+                final Field configField = Configuration.class.getDeclaredField(field.getName());
                 if (!configField.getType().equals(field.getType())) {
                     continue;
                 }
diff --git a/meecrowave-arquillian/src/main/java/org/apache/meecrowave/arquillian/MeecrowaveContainer.java b/meecrowave-arquillian/src/main/java/org/apache/meecrowave/arquillian/MeecrowaveContainer.java
index 2c1327c..197c870 100644
--- a/meecrowave-arquillian/src/main/java/org/apache/meecrowave/arquillian/MeecrowaveContainer.java
+++ b/meecrowave-arquillian/src/main/java/org/apache/meecrowave/arquillian/MeecrowaveContainer.java
@@ -18,11 +18,15 @@
  */
 package org.apache.meecrowave.arquillian;
 
+import static java.util.Optional.ofNullable;
+
+import java.io.File;
+
 import org.apache.meecrowave.Meecrowave;
+import org.apache.meecrowave.configuration.Configuration;
 import org.apache.meecrowave.io.IO;
 import org.jboss.arquillian.container.spi.client.container.DeployableContainer;
 import org.jboss.arquillian.container.spi.client.container.DeploymentException;
-import org.jboss.arquillian.container.spi.client.container.LifecycleException;
 import org.jboss.arquillian.container.spi.client.protocol.ProtocolDescription;
 import org.jboss.arquillian.container.spi.client.protocol.metadata.HTTPContext;
 import org.jboss.arquillian.container.spi.client.protocol.metadata.ProtocolMetaData;
@@ -31,12 +35,8 @@
 import org.jboss.shrinkwrap.api.exporter.ZipExporter;
 import org.jboss.shrinkwrap.descriptor.api.Descriptor;
 
-import java.io.File;
-
-import static java.util.Optional.ofNullable;
-
 public class MeecrowaveContainer implements DeployableContainer<MeecrowaveConfiguration> {
-    private Meecrowave.Builder configuration;
+    private Configuration configuration;
     private Meecrowave container;
     private ProtocolDescription defaultProtocol;
 
@@ -52,13 +52,13 @@
     }
 
     @Override
-    public void start() throws LifecycleException {
+    public void start() {
         this.container = new Meecrowave(this.configuration);
         this.container.start();
     }
 
     @Override
-    public void stop() throws LifecycleException {
+    public void stop() {
         ofNullable(this.container).ifPresent(Meecrowave::close);
     }
 
diff --git a/meecrowave-core/pom.xml b/meecrowave-core/pom.xml
index 7c710c5..1ad331a 100644
--- a/meecrowave-core/pom.xml
+++ b/meecrowave-core/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <artifactId>meecrowave</artifactId>
     <groupId>org.apache.meecrowave</groupId>
-    <version>1.2.9-SNAPSHOT</version>
+    <version>1.2.10-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
diff --git a/meecrowave-core/src/main/java/org/apache/meecrowave/Meecrowave.java b/meecrowave-core/src/main/java/org/apache/meecrowave/Meecrowave.java
index 68c70f1..683e44f 100644
--- a/meecrowave-core/src/main/java/org/apache/meecrowave/Meecrowave.java
+++ b/meecrowave-core/src/main/java/org/apache/meecrowave/Meecrowave.java
@@ -19,7 +19,6 @@
 package org.apache.meecrowave;
 
 import static java.util.Collections.emptyList;
-import static java.util.Collections.emptyMap;
 import static java.util.Collections.emptySet;
 import static java.util.Comparator.comparing;
 import static java.util.Locale.ROOT;
@@ -50,9 +49,7 @@
 import java.util.ArrayList;
 import java.util.Base64;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.HashMap;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -68,7 +65,6 @@
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
 
-import javax.annotation.Priority;
 import javax.crypto.Cipher;
 import javax.crypto.spec.SecretKeySpec;
 import javax.enterprise.context.spi.CreationalContext;
@@ -101,6 +97,7 @@
 import org.apache.coyote.http2.Http2Protocol;
 import org.apache.meecrowave.api.StartListening;
 import org.apache.meecrowave.api.StopListening;
+import org.apache.meecrowave.configuration.Configuration;
 import org.apache.meecrowave.cxf.ConfigurableBus;
 import org.apache.meecrowave.cxf.CxfCdiAutoSetup;
 import org.apache.meecrowave.cxf.Cxfs;
@@ -113,7 +110,7 @@
 import org.apache.meecrowave.logging.tomcat.Log4j2Log;
 import org.apache.meecrowave.logging.tomcat.LogFacade;
 import org.apache.meecrowave.openwebbeans.OWBAutoSetup;
-import org.apache.meecrowave.runner.cli.CliOption;
+import org.apache.meecrowave.service.Priotities;
 import org.apache.meecrowave.service.ValueTransformer;
 import org.apache.meecrowave.tomcat.CDIInstanceManager;
 import org.apache.meecrowave.tomcat.LoggingAccessLogPattern;
@@ -127,7 +124,6 @@
 import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
 import org.apache.tomcat.util.modeler.Registry;
 import org.apache.tomcat.util.net.SSLHostConfig;
-import org.apache.webbeans.config.PropertyLoader;
 import org.apache.webbeans.config.WebBeansContext;
 import org.apache.xbean.finder.ResourceFinder;
 import org.apache.xbean.recipe.ObjectRecipe;
@@ -137,7 +133,7 @@
 import org.xml.sax.helpers.DefaultHandler;
 
 public class Meecrowave implements AutoCloseable {
-    private final Builder configuration;
+    private final Configuration configuration;
     protected ConfigurableBus clientBus;
     protected File base;
     protected final File ownedTempDir;
@@ -155,13 +151,15 @@
         this(new Builder());
     }
 
-    public Meecrowave(final Builder builder) {
-        this.configuration = builder;
-        this.ownedTempDir = new File(configuration.tempDir, "meecrowave_" + System.nanoTime());
+    public Meecrowave(final Configuration configuration) {
+        this.configuration = configuration;
+        this.ownedTempDir = new File(this.configuration.getTempDir(), "meecrowave_" + System.nanoTime());
     }
 
     public Builder getConfiguration() {
-        return configuration;
+        return Builder.class.isInstance(configuration) ?
+                Builder.class.cast(configuration) :
+                new Builder(configuration);
     }
 
     public File getBase() {
@@ -266,7 +264,7 @@
                 ctx.setDocBase(meta.docBase.getAbsolutePath());
             }
         });
-        ofNullable(configuration.tomcatFilter).ifPresent(filter -> {
+        ofNullable(configuration.getTomcatFilter()).ifPresent(filter -> {
             try {
                 scanner.setJarScanFilter(JarScanFilter.class.cast(Thread.currentThread().getContextClassLoader().loadClass(filter).newInstance()));
             } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
@@ -276,7 +274,7 @@
 
         final AtomicReference<Runnable> releaseSCI = new AtomicReference<>();
         final ServletContainerInitializer meecrowaveInitializer = (c, ctx1) -> {
-            ctx1.setAttribute("meecrowave.configuration", configuration);
+            ctx1.setAttribute("meecrowave.configuration", getConfiguration());
             ctx1.setAttribute("meecrowave.instance", Meecrowave.this);
 
             new OWBAutoSetup().onStartup(c, ctx1);
@@ -355,17 +353,17 @@
                     }
                     break;
                 case Lifecycle.AFTER_START_EVENT:
-                    ctx.getResources().setCachingAllowed(configuration.webResourceCached);
+                    ctx.getResources().setCachingAllowed(configuration.isWebResourceCached());
                     break;
                 case Lifecycle.BEFORE_INIT_EVENT:
-                    if (configuration.loginConfig != null) {
-                        ctx.setLoginConfig(configuration.loginConfig.build());
+                    if (configuration.getLoginConfig() != null) {
+                        ctx.setLoginConfig(configuration.getLoginConfig().build());
                     }
-                    for (final SecurityConstaintBuilder sc : configuration.securityConstraints) {
+                    for (final SecurityConstaintBuilder sc : configuration.getSecurityConstraints()) {
                         ctx.addConstraint(sc.build());
                     }
-                    if (configuration.webXml != null) {
-                        ctx.getServletContext().setAttribute(Globals.ALT_DD_ATTR, configuration.webXml);
+                    if (configuration.getWebXml() != null) {
+                        ctx.getServletContext().setAttribute(Globals.ALT_DD_ATTR, configuration.getWebXml());
                     }
                     break;
                 default:
@@ -412,7 +410,7 @@
             });
             ctx.setManager(manager);
         }
-        if (configuration.antiResourceLocking && StandardContext.class.isInstance(ctx)) {
+        if (configuration.isAntiResourceLocking() && StandardContext.class.isInstance(ctx)) {
             StandardContext.class.cast(ctx).setAntiResourceLocking(true);
         }
         configuration.getInitializers().forEach(i -> ctx.addServletContainerInitializer(i, emptySet()));
@@ -455,7 +453,7 @@
             System.setProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager");
         }
 
-        if (configuration.loggingGlobalSetup && Log4j2s.IS_PRESENT) {
+        if (configuration.isLoggingGlobalSetup() && Log4j2s.IS_PRESENT) {
 
             setSystemProperty(systemPropsToRestore, "log4j.shutdownHookEnabled", "false");
             setSystemProperty(systemPropsToRestore, "openwebbeans.logging.factory", Log4j2LoggerFactory.class.getName());
@@ -503,19 +501,19 @@
                 workDir = createDirectory(tempDir, "work");
             }
 
-            synchronize(new File(base, "conf"), configuration.conf);
+            synchronize(new File(base, "conf"), configuration.getConf());
         }
 
-        final Properties props = configuration.properties;
+        final Properties props = configuration.getProperties();
         Substitutor substitutor = null;
         for (final String s : props.stringPropertyNames()) {
             final String v = props.getProperty(s);
             if (v != null && v.contains("${")) {
                 if (substitutor == null) {
                     final Map<String, String> placeHolders = new HashMap<>();
-                    placeHolders.put("meecrowave.embedded.http", Integer.toString(configuration.httpPort));
-                    placeHolders.put("meecrowave.embedded.https", Integer.toString(configuration.httpsPort));
-                    placeHolders.put("meecrowave.embedded.stop", Integer.toString(configuration.stopPort));
+                    placeHolders.put("meecrowave.embedded.http", Integer.toString(configuration.getHttpPort()));
+                    placeHolders.put("meecrowave.embedded.https", Integer.toString(configuration.getHttpsPort()));
+                    placeHolders.put("meecrowave.embedded.stop", Integer.toString(configuration.getStopPort()));
                     substitutor = new Substitutor(placeHolders);
                 }
                 props.put(s, substitutor.replace(v));
@@ -525,13 +523,13 @@
         final File conf = new File(base, "conf");
 
         tomcat.setBaseDir(base.getAbsolutePath());
-        tomcat.setHostname(configuration.host);
+        tomcat.setHostname(configuration.getHost());
 
         final boolean initialized;
-        if (configuration.serverXml != null) {
+        if (configuration.getServerXml() != null) {
             final File file = new File(conf, "server.xml");
-            if (!file.equals(configuration.serverXml)) {
-                try (final InputStream is = new FileInputStream(configuration.serverXml);
+            if (!file.equals(configuration.getServerXml())) {
+                try (final InputStream is = new FileInputStream(configuration.getServerXml());
                      final FileOutputStream fos = new FileOutputStream(file)) {
                     IO.copy(is, fos);
                 } catch (final IOException e) {
@@ -541,14 +539,14 @@
 
             // respect config (host/port) of the Configuration
             final QuickServerXmlParser ports = QuickServerXmlParser.parse(file);
-            if (configuration.keepServerXmlAsThis) {
-                configuration.httpPort = Integer.parseInt(ports.http());
-                configuration.stopPort = Integer.parseInt(ports.stop());
+            if (configuration.isKeepServerXmlAsThis()) {
+                configuration.setHttpPort(Integer.parseInt(ports.http()));
+                configuration.setStopPort(Integer.parseInt(ports.stop()));
             } else {
                 final Map<String, String> replacements = new HashMap<>();
-                replacements.put(ports.http(), String.valueOf(configuration.httpPort));
-                replacements.put(ports.https(), String.valueOf(configuration.httpsPort));
-                replacements.put(ports.stop(), String.valueOf(configuration.stopPort));
+                replacements.put(ports.http(), String.valueOf(configuration.getHttpPort()));
+                replacements.put(ports.https(), String.valueOf(configuration.getHttpsPort()));
+                replacements.put(ports.stop(), String.valueOf(configuration.getStopPort()));
 
                 String serverXmlContent;
                 try (final InputStream stream = new FileInputStream(file)) {
@@ -569,7 +567,7 @@
             tomcat.server(createServer(file.getAbsolutePath()));
             initialized = true;
         } else {
-            tomcat.getServer().setPort(configuration.stopPort);
+            tomcat.getServer().setPort(configuration.getStopPort());
             initialized = false;
         }
 
@@ -593,10 +591,10 @@
         });
 
         if (!initialized) {
-            tomcat.setHostname(configuration.host);
-            tomcat.getEngine().setDefaultHost(configuration.host);
+            tomcat.setHostname(configuration.getHost());
+            tomcat.getEngine().setDefaultHost(configuration.getHost());
             final StandardHost host = new StandardHost();
-            host.setName(configuration.host);
+            host.setName(configuration.getHost());
 
             try {
                 final File webapps = createDirectory(base, "webapps");
@@ -623,13 +621,13 @@
             valves.forEach(pipeline::addValve);
         }
 
-        if (configuration.realm != null) {
-            tomcat.getEngine().setRealm(configuration.realm);
+        if (configuration.getRealm() != null) {
+            tomcat.getEngine().setRealm(configuration.getRealm());
         }
 
-        if (tomcat.getRawConnector() == null && !configuration.skipHttp) {
+        if (tomcat.getRawConnector() == null && !configuration.isSkipHttp()) {
             final Connector connector = createConnector();
-            connector.setPort(configuration.httpPort);
+            connector.setPort(configuration.getHttpPort());
             if (connector.getAttribute("connectionTimeout") == null) {
                 connector.setAttribute("connectionTimeout", "3000");
             }
@@ -639,33 +637,33 @@
         }
 
         // create https connector
-        if (configuration.ssl) {
+        if (configuration.isSsl()) {
             final Connector httpsConnector = createConnector();
-            httpsConnector.setPort(configuration.httpsPort);
+            httpsConnector.setPort(configuration.getHttpsPort());
             httpsConnector.setSecure(true);
             httpsConnector.setScheme("https");
             httpsConnector.setProperty("SSLEnabled", "true");
-            if (configuration.sslProtocol != null) {
-                configuration.property("connector.sslhostconfig.sslProtocol", configuration.sslProtocol);
+            if (configuration.getSslProtocol() != null) {
+                configuration.getProperties().setProperty("connector.sslhostconfig.sslProtocol", configuration.getSslProtocol());
             }
-            if (configuration.properties.getProperty("connector.sslhostconfig.hostName") != null) {
-                httpsConnector.setAttribute("defaultSSLHostConfigName", configuration.properties.getProperty("connector.sslhostconfig.hostName"));
+            if (configuration.getProperties().getProperty("connector.sslhostconfig.hostName") != null) {
+                httpsConnector.setAttribute("defaultSSLHostConfigName", configuration.getProperties().getProperty("connector.sslhostconfig.hostName"));
             }
-            if (configuration.keystoreFile != null) {
-                configuration.property("connector.sslhostconfig.certificateKeystoreFile", configuration.keystoreFile);
+            if (configuration.getKeystoreFile() != null) {
+                configuration.getProperties().setProperty("connector.sslhostconfig.certificateKeystoreFile", configuration.getKeystoreFile());
             }
-            if (configuration.keystorePass != null) {
-                configuration.property("connector.sslhostconfig.certificateKeystorePassword", configuration.keystorePass);
+            if (configuration.getKeystorePass() != null) {
+                configuration.getProperties().setProperty("connector.sslhostconfig.certificateKeystorePassword", configuration.getKeystorePass());
             }
-            configuration.property("connector.sslhostconfig.certificateKeystoreType", configuration.keystoreType);
-            if (configuration.clientAuth != null) {
-                httpsConnector.setAttribute("clientAuth", configuration.clientAuth);
+            configuration.getProperties().setProperty("connector.sslhostconfig.certificateKeystoreType", configuration.getKeystoreType());
+            if (configuration.getClientAuth() != null) {
+                httpsConnector.setAttribute("clientAuth", configuration.getClientAuth());
             }
 
-            if (configuration.keyAlias != null) {
-                configuration.property("connector.sslhostconfig.certificateKeyAlias", configuration.keyAlias);
+            if (configuration.getKeyAlias() != null) {
+                configuration.getProperties().setProperty("connector.sslhostconfig.certificateKeyAlias", configuration.getKeyAlias());
             }
-            if (configuration.http2) {
+            if (configuration.isHttp2()) {
                 httpsConnector.addUpgradeProtocol(new Http2Protocol());
             }
             final List<SSLHostConfig> buildSslHostConfig = buildSslHostConfig();
@@ -695,29 +693,29 @@
 
             buildSslHostConfig.forEach(httpsConnector::addSslHostConfig);
 
-            if (configuration.defaultSSLHostConfigName != null) {
-                httpsConnector.setAttribute("defaultSSLHostConfigName", configuration.defaultSSLHostConfigName);
+            if (configuration.getDefaultSSLHostConfigName() != null) {
+                httpsConnector.setAttribute("defaultSSLHostConfigName", configuration.getDefaultSSLHostConfigName());
             }
             tomcat.getService().addConnector(httpsConnector);
-            if (configuration.skipHttp) {
+            if (configuration.isSkipHttp()) {
                 tomcat.setConnector(httpsConnector);
             }
         }
 
-        for (final Connector c : configuration.connectors) {
+        for (final Connector c : configuration.getConnectors()) {
             tomcat.getService().addConnector(c);
         }
-        if (!configuration.skipHttp && !configuration.ssl && !configuration.connectors.isEmpty()) {
-            tomcat.setConnector(configuration.connectors.iterator().next());
+        if (!configuration.isSkipHttp() && !configuration.isSsl() && !configuration.getConnectors().isEmpty()) {
+            tomcat.setConnector(configuration.getConnectors().iterator().next());
         }
 
-        if (configuration.users != null) {
-            for (final Map.Entry<String, String> user : configuration.users.entrySet()) {
+        if (configuration.getUsers() != null) {
+            for (final Map.Entry<String, String> user : configuration.getUsers().entrySet()) {
                 tomcat.addUser(user.getKey(), user.getValue());
             }
         }
-        if (configuration.roles != null) {
-            for (final Map.Entry<String, String> user : configuration.roles.entrySet()) {
+        if (configuration.getRoles() != null) {
+            for (final Map.Entry<String, String> user : configuration.getRoles().entrySet()) {
                 for (final String role : user.getValue().split(" *, *")) {
                     tomcat.addRole(user.getKey(), role);
                 }
@@ -730,9 +728,9 @@
                         MeecrowaveAwareInstanceCustomizer.class.cast(i).setMeecrowave(this);
                     }
                 })
-                .sorted(Meecrowave::sortByPriority)
+                .sorted(Priotities::sortByPriority)
                 .forEach(c -> c.accept(tomcat));
-        configuration.instanceCustomizers.forEach(c -> c.accept(tomcat));
+        configuration.getInstanceCustomizers().forEach(c -> c.accept(tomcat));
 
         StreamSupport.stream(ServiceLoader.load(Meecrowave.ContextCustomizer.class).spliterator(), false)
                 .peek(i -> {
@@ -740,13 +738,13 @@
                         MeecrowaveAwareContextCustomizer.class.cast(i).setMeecrowave(this);
                     }
                 })
-                .sorted(Meecrowave::sortByPriority)
+                .sorted(Priotities::sortByPriority)
                 .forEach(configuration::addGlobalContextCustomizer);
 
         beforeStart();
 
 
-        if (configuration.initializeClientBus && Cxfs.IS_PRESENT && !Cxfs.hasDefaultBus()) {
+        if (configuration.isInitializeClientBus() && Cxfs.IS_PRESENT && !Cxfs.hasDefaultBus()) {
             clientBus = new ConfigurableBus();
             clientBus.initProviders(configuration,
                     ofNullable(Thread.currentThread().getContextClassLoader()).orElseGet(ClassLoader::getSystemClassLoader));
@@ -905,19 +903,19 @@
      */
     private List<Valve> buildValves() {
         final List<Valve> valves = new ArrayList<>();
-        configuration.properties.stringPropertyNames().stream()
+        configuration.getProperties().stringPropertyNames().stream()
                                 .filter(key -> key.startsWith("valves.") && key.endsWith("._className"))
-                                .sorted(comparing(key -> Integer.parseInt(configuration.properties
+                                .sorted(comparing(key -> Integer.parseInt(configuration.getProperties()
                                         .getProperty(key.replaceFirst("\\._className$", "._order"), "0"))))
                                 .map(key -> key.split("\\."))
                                 .filter(parts -> parts.length == 3)
                                 .forEach(key -> {
             final String prefix = key[0] + '.' + key[1] + '.';
-            final ObjectRecipe recipe = newRecipe(configuration.properties.getProperty(prefix + key[2]));
-            configuration.properties.stringPropertyNames().stream()
+            final ObjectRecipe recipe = newRecipe(configuration.getProperties().getProperty(prefix + key[2]));
+            configuration.getProperties().stringPropertyNames().stream()
                     .filter(it -> it.startsWith(prefix) && !it.endsWith("._order") && !it.endsWith("._className"))
                     .forEach(propKey -> {
-                        final String value = configuration.properties.getProperty(propKey);
+                        final String value = configuration.getProperties().getProperty(propKey);
                         recipe.setProperty(propKey.substring(prefix.length()), value);
                     });
             valves.add(Valve.class.cast(recipe.create(Thread.currentThread().getContextClassLoader())));
@@ -929,17 +927,17 @@
         final List<SSLHostConfig> sslHostConfigs = new ArrayList<>();
         // Configures default SSLHostConfig
         final ObjectRecipe defaultSslHostConfig = newRecipe(SSLHostConfig.class.getName());
-        for (final String key : configuration.properties.stringPropertyNames()) {
+        for (final String key : configuration.getProperties().stringPropertyNames()) {
             if (key.startsWith("connector.sslhostconfig.") && key.split("\\.").length == 3) {
                 final String substring = key.substring("connector.sslhostconfig.".length());
-                defaultSslHostConfig.setProperty(substring, configuration.properties.getProperty(key));
+                defaultSslHostConfig.setProperty(substring, configuration.getProperties().getProperty(key));
             }
         }
         if (!defaultSslHostConfig.getProperties().isEmpty()) {
             sslHostConfigs.add(SSLHostConfig.class.cast(defaultSslHostConfig.create()));
         }
         // Allows to add N Multiple SSLHostConfig elements not including the default one.
-        final Collection<Integer> itemNumbers = configuration.properties.stringPropertyNames()
+        final Collection<Integer> itemNumbers = configuration.getProperties().stringPropertyNames()
                                 .stream()
                                 .filter(key -> (key.startsWith("connector.sslhostconfig.") && key.split("\\.").length == 4))
                                 .map(key -> Integer.parseInt(key.split("\\.")[2]))
@@ -947,11 +945,11 @@
         itemNumbers.stream().sorted().forEach(itemNumber -> {
             final ObjectRecipe recipe = newRecipe(SSLHostConfig.class.getName());
             final String prefix = "connector.sslhostconfig." + itemNumber + '.';
-            configuration.properties.stringPropertyNames().stream()
+            configuration.getProperties().stringPropertyNames().stream()
                                     .filter(k -> k.startsWith(prefix))
                                     .forEach(key -> {
                                         final String keyName = key.split("\\.")[3];
-                                        recipe.setProperty(keyName, configuration.properties.getProperty(key));
+                                        recipe.setProperty(keyName, configuration.getProperties().getProperty(key));
                                     });
             if (!recipe.getProperties().isEmpty()) {
                 final SSLHostConfig sslHostConfig = SSLHostConfig.class.cast(recipe.create());
@@ -1039,7 +1037,7 @@
 
     protected Connector createConnector() {
         final Connector connector;
-        final Properties properties = configuration.properties;
+        final Properties properties = configuration.getProperties();
         if (properties != null) {
             final Map<String, String> attributes = new HashMap<>();
             final ObjectRecipe recipe = newRecipe(Connector.class.getName());
@@ -1125,11 +1123,11 @@
 
     private String newBaseDir() {
         deleteBase = false;
-        String dir = configuration.dir;
+        String dir = configuration.getDir();
         if (dir != null) {
             final File dirFile = new File(dir);
             if (dirFile.exists()) {
-                if (base != null && base.exists() && configuration.deleteBaseOnStartup) {
+                if (base != null && base.exists() && configuration.isDeleteBaseOnStartup()) {
                     IO.delete(base);
                 }
                 return dir;
@@ -1167,389 +1165,27 @@
         return recipe;
     }
 
-    private static int priorityOf(final Object i) {
-        return ofNullable(i.getClass().getAnnotation(Priority.class))
-                .map(Priority::value)
-                .orElse(0);
-    }
-
-    private static <T> int sortByPriority(final T a, final T b) {
-        return priorityOf(a) - priorityOf(b);
-    }
-
     // this class holds all the built-in config,
     // extension can use extensions feature (see cli.html) which is basically the same kind of bean
     // accessible through builder.getExtension(type) builder being accessible through the meecrowave.configuration
     // attribute of the ServletContext.
-    public static class Builder {
-        @CliOption(name = "pid-file", description = "A file path to write the process id if the server starts")
-        private File pidFile;
+    public static class Builder extends Configuration /* inheritance for backward compatibility */ {
+        // IMPORTANT: this must stay without any field, use parent class to add config please
+        //            this only holds builder methods
 
-        @CliOption(name = "watcher-bouncing", description = "Activate redeployment on directories update using this bouncing.")
-        private int watcherBouncing = 500;
-
-        @CliOption(name = "http", description = "HTTP port")
-        private int httpPort = 8080;
-
-        @CliOption(name = "https", description = "HTTPS port")
-        private int httpsPort = 8443;
-
-        @CliOption(name = "stop", description = "Shutdown port if used or -1")
-        private int stopPort = -1;
-
-        @CliOption(name = "host", description = "Default host")
-        private String host = "localhost";
-
-        @CliOption(name = "dir", description = "Root folder if provided otherwise a fake one is created in tmp-dir")
-        private String dir;
-
-        @CliOption(name = "server-xml", description = "Provided server.xml")
-        private File serverXml;
-
-        @CliOption(name = "keep-server-xml-as-this", description = "Don't replace ports in server.xml")
-        private boolean keepServerXmlAsThis;
-
-        @CliOption(name = "properties", description = "Passthrough properties")
-        private Properties properties = new Properties();
-
-        @CliOption(name = "quick-session", description = "Should an unsecured but fast session id generator be used")
-        private boolean quickSession = true;
-
-        @CliOption(name = "skip-http", description = "Skip HTTP connector")
-        private boolean skipHttp;
-
-        @CliOption(name = "ssl", description = "Use HTTPS")
-        private boolean ssl;
-
-        @CliOption(name = "keystore-file", description = "HTTPS keystore location")
-        private String keystoreFile;
-
-        @CliOption(name = "keystore-password", description = "HTTPS keystore password")
-        private String keystorePass;
-
-        @CliOption(name = "keystore-type", description = "HTTPS keystore type")
-        private String keystoreType = "JKS";
-
-        @CliOption(name = "client-auth", description = "HTTPS keystore client authentication")
-        private String clientAuth;
-
-        @CliOption(name = "keystore-alias", description = "HTTPS keystore alias")
-        private String keyAlias;
-
-        @CliOption(name = "ssl-protocol", description = "HTTPS protocol")
-        private String sslProtocol;
-
-        @CliOption(name = "web-xml", description = "Global web.xml")
-        private String webXml;
-
-        @CliOption(name = "login-config", description = "web.xml login config")
-        private LoginConfigBuilder loginConfig;
-
-        @CliOption(name = "security-constraint", description = "web.xml security constraint")
-        private Collection<SecurityConstaintBuilder> securityConstraints = new LinkedList<>();
-
-        @CliOption(name = "realm", description = "realm")
-        private Realm realm;
-
-        @CliOption(name = "users", description = "In memory users")
-        private Map<String, String> users;
-
-        @CliOption(name = "roles", description = "In memory roles")
-        private Map<String, String> roles;
-
-        @CliOption(name = "http2", description = "Activate HTTP 2")
-        private boolean http2;
-
-        @CliOption(name = "connector", description = "Custom connectors")
-        private final Collection<Connector> connectors = new ArrayList<>();
-
-        @CliOption(name = "tmp-dir", description = "Temporary directory")
-        private String tempDir = System.getProperty("java.io.tmpdir");
-
-        @CliOption(name = "web-resource-cached", description = "Cache web resources")
-        private boolean webResourceCached = true;
-
-        @CliOption(name = "conf", description = "Conf folder to synchronize")
-        private String conf;
-
-        @CliOption(name = "delete-on-startup", description = "Should the directory be cleaned on startup if existing")
-        private boolean deleteBaseOnStartup = true;
-
-        @CliOption(name = "jaxrs-mapping", description = "Default jaxrs mapping")
-        private String jaxrsMapping = "/*";
-
-        @CliOption(name = "cdi-conversation", description = "Should CDI conversation be activated")
-        private boolean cdiConversation;
-
-        @CliOption(name = "jaxrs-provider-setup", description = "Should default JAX-RS provider be configured")
-        private boolean jaxrsProviderSetup = true;
-
-        @CliOption(name = "jaxrs-default-providers", description = "If jaxrsProviderSetup is true the list of default providers to load (or defaulting to johnson jsonb and jsonp ones)")
-        private String jaxrsDefaultProviders;
-
-        @CliOption(name = "jaxrs-beanvalidation", description = "Should bean validation be activated on JAX-RS endpoint if present in the classpath.")
-        private boolean jaxrsAutoActivateBeanValidation = true;
-
-        @CliOption(name = "jaxrs-log-provider", description = "Should JAX-RS providers be logged")
-        private boolean jaxrsLogProviders = false;
-
-        @CliOption(name = "jsonp-buffer-strategy", description = "JSON-P JAX-RS provider buffer strategy (see johnzon)")
-        private String jsonpBufferStrategy = "QUEUE";
-
-        @CliOption(name = "jsonp-max-string-length", description = "JSON-P JAX-RS provider max string limit size (see johnzon)")
-        private int jsonpMaxStringLen = 64 * 1024;
-
-        @CliOption(name = "jsonp-read-buffer-length", description = "JSON-P JAX-RS provider read buffer limit size (see johnzon)")
-        private int jsonpMaxReadBufferLen = 64 * 1024;
-
-        @CliOption(name = "jsonp-write-buffer-length", description = "JSON-P JAX-RS provider write buffer limit size (see johnzon)")
-        private int jsonpMaxWriteBufferLen = 64 * 1024;
-
-        @CliOption(name = "jsonp-supports-comment", description = "Should JSON-P JAX-RS provider support comments (see johnzon)")
-        private boolean jsonpSupportsComment = false;
-
-        @CliOption(name = "jsonp-supports-comment", description = "Should JSON-P JAX-RS provider prettify the outputs (see johnzon)")
-        private boolean jsonpPrettify = false;
-
-        @CliOption(name = "jsonb-encoding", description = "Which encoding provider JSON-B should use")
-        private String jsonbEncoding = "UTF-8";
-
-        @CliOption(name = "jsonb-nulls", description = "Should JSON-B provider serialize nulls")
-        private boolean jsonbNulls = false;
-
-        @CliOption(name = "jsonb-ijson", description = "Should JSON-B provider comply to I-JSON")
-        private boolean jsonbIJson = false;
-
-        @CliOption(name = "jsonb-prettify", description = "Should JSON-B provider prettify the output")
-        private boolean jsonbPrettify = false;
-
-        @CliOption(name = "jsonb-binary-strategy", description = "Should JSON-B provider prettify the output")
-        private String jsonbBinaryStrategy;
-
-        @CliOption(name = "jsonb-naming-strategy", description = "Should JSON-B provider prettify the output")
-        private String jsonbNamingStrategy;
-
-        @CliOption(name = "jsonb-order-strategy", description = "Should JSON-B provider prettify the output")
-        private String jsonbOrderStrategy;
-
-        @CliOption(name = "logging-global-setup", description = "Should logging be configured to use log4j2 (it is global)")
-        private boolean loggingGlobalSetup = true;
-
-        @CliOption(name = "cxf-servlet-params", description = "Init parameters passed to CXF servlet")
-        private Map<String, String> cxfServletParams;
-
-        @CliOption(name = "tomcat-scanning", description = "Should Tomcat scanning be used (@HandleTypes, @WebXXX)")
-        private boolean tomcatScanning = true;
-
-        @CliOption(name = "tomcat-default-setup", description = "Add default servlet")
-        private boolean tomcatAutoSetup = true;
-
-        @CliOption(name = "tomcat-default-setup-jsp-development", description = "Should JSP support if available be set in development mode")
-        private boolean tomcatJspDevelopment = false;
-
-        @CliOption(name = "use-shutdown-hook", description = "Use shutdown hook to automatically stop the container on Ctrl+C")
-        private boolean useShutdownHook = true;
-
-        @CliOption(name = "tomcat-filter", description = "A Tomcat JarScanFilter")
-        private String tomcatFilter;
-
-        @CliOption(name = "scanning-include", description = "A forced include list of jar names (comma separated values)")
-        private String scanningIncludes;
-
-        @CliOption(name = "scanning-exclude", description = "A forced exclude list of jar names (comma separated values)")
-        private String scanningExcludes;
-
-        @CliOption(name = "scanning-package-include", description = "A forced include list of packages names (comma separated values)")
-        private String scanningPackageIncludes;
-
-        @CliOption(name = "scanning-package-exclude", description = "A forced exclude list of packages names (comma separated values)")
-        private String scanningPackageExcludes;
-
-        @CliOption(name = "web-session-timeout", description = "Force the session timeout for webapps")
-        private Integer webSessionTimeout;
-
-        @CliOption(name = "web-session-cookie-config", description = "Force the cookie-config, it uses a properties syntax with the keys being the web.xml tag names.")
-        private String webSessionCookieConfig;
-
-        @CliOption(name = "tomcat-default", description = "Should Tomcat default be set (session timeout, mime mapping etc...)")
-        private boolean useTomcatDefaults = true;
-
-        @CliOption(name = "tomcat-wrap-loader", description = "(Experimental) When deploying a classpath (current classloader), " +
-                "should meecrowave wrap the loader to define another loader identity but still use the same classes and resources.")
-        private boolean tomcatWrapLoader = false;
-
-        @CliOption(name = "tomcat-skip-jmx", description = "(Experimental) Should Tomcat MBeans be skipped.")
-        private boolean tomcatNoJmx = true;
-
-        @CliOption(name = "shared-libraries", description = "A folder containing shared libraries.", alias = "shared-librairies")
-        private String sharedLibraries;
-
-        @CliOption(name = "log4j2-jul-bridge", description = "Should JUL logs be redirected to Log4j2 - only works before JUL usage.")
-        private boolean useLog4j2JulLogManager = System.getProperty("java.util.logging.manager") == null;
-
-        @CliOption(name = "servlet-container-initializer-injection", description = "Should ServletContainerInitialize support injections.")
-        private boolean injectServletContainerInitializer = true;
-
-        @CliOption(
-                name = "tomcat-access-log-pattern",
-                description = "Activates and configure the access log valve. Value example: '%h %l %u %t \"%r\" %s %b \"%{Referer}i\" \"%{User-Agent}i\"'")
-        private String tomcatAccessLogPattern;
-
-        @CliOption(
-                name = "meecrowave-properties",
-                description = "Loads a meecrowave properties, defaults to meecrowave.properties.")
-        private String meecrowaveProperties = "meecrowave.properties";
-
-        @CliOption(name = "jaxws-support-if-present", description = "Should @WebService CDI beans be deployed if cxf-rt-frontend-jaxws is in the classpath.")
-        private boolean jaxwsSupportIfAvailable = true;
-
-        @CliOption(name = "default-ssl-hostconfig-name", description = "The name of the default SSLHostConfig that will be used for secure https connections.")
-        private String defaultSSLHostConfigName;
-
-        @CliOption(name = "cxf-initialize-client-bus", description = "Should the client bus be set. If false the server one will likely be reused.")
-        private boolean initializeClientBus = true;
-
-        private final Map<Class<?>, Object> extensions = new HashMap<>();
-        private final Collection<Consumer<Tomcat>> instanceCustomizers = new ArrayList<>();
-
-        @CliOption(name = "servlet-container-initializer", description = "ServletContainerInitializer instances.")
-        private Collection<ServletContainerInitializer> initializers = new ArrayList<>();
-
-        @CliOption(name = "tomcat-antiresourcelocking", description = "Should Tomcat anti resource locking feature be activated on StandardContext.")
-        private boolean antiResourceLocking;
-
-        @CliOption(name = "tomcat-context-configurer", description = "Configurers for all webapps. The Consumer<Context> instances will be applied to all deployments.")
-        private Collection<Consumer<Context>> contextConfigurers;
-
-        public Builder() { // load defaults
-            extensions.put(ValueTransformers.class, new ValueTransformers());
-            StreamSupport.stream(ServiceLoader.load(Meecrowave.ConfigurationCustomizer.class).spliterator(), false)
-                    .sorted(Meecrowave::sortByPriority)
-                    .forEach(c -> c.accept(this));
-            loadFrom(meecrowaveProperties);
+        public Builder() {
+            // no-op
         }
 
-        public <T> T getExtension(final Class<T> extension) {
-            // in the cli we read the values from the cli but in other mode from properties
-            // to ensure we can do the same in all modes keeping a nice cli
-            return extension.cast(extensions.computeIfAbsent(extension, k -> {
-                try {
-                    return bind(k.newInstance());
-                } catch (final InstantiationException | IllegalAccessException e) {
-                    throw new IllegalArgumentException(e);
-                }
-            }));
+        // mainly for backward compat
+        public Builder(final Configuration configuration) {
+            super(configuration);
         }
 
-        public boolean isAntiResourceLocking() {
-            return antiResourceLocking;
-        }
-
-        public void setAntiResourceLocking(final boolean antiResourceLocking) {
-            this.antiResourceLocking = antiResourceLocking;
-        }
-
-        public Collection<Consumer<Context>> getGlobalContextConfigurers() {
-            return ofNullable(contextConfigurers).orElseGet(Collections::emptySet);
-        }
-
-        public boolean isTomcatJspDevelopment() {
-            return tomcatJspDevelopment;
-        }
-
-        public void setTomcatJspDevelopment(final boolean tomcatJspDevelopment) {
-            this.tomcatJspDevelopment = tomcatJspDevelopment;
-        }
-
-        public Integer getWebSessionTimeout() {
-            return webSessionTimeout;
-        }
-
-        public void setWebSessionTimeout(final Integer webSessionTimeout) {
-            this.webSessionTimeout = webSessionTimeout;
-        }
-
-        public String getWebSessionCookieConfig() {
-            return webSessionCookieConfig;
-        }
-
-        public void setWebSessionCookieConfig(final String webSessionCookieConfig) {
-            this.webSessionCookieConfig = webSessionCookieConfig;
-        }
-
-        public boolean isInitializeClientBus() {
-            return initializeClientBus;
-        }
-
-        public void setInitializeClientBus(final boolean initializeClientBus) {
-            this.initializeClientBus = initializeClientBus;
-        }
-
-        public boolean isJaxwsSupportIfAvailable() {
-            return jaxwsSupportIfAvailable;
-        }
-
-        public void setJaxwsSupportIfAvailable(final boolean jaxwsSupportIfAvailable) {
-            this.jaxwsSupportIfAvailable = jaxwsSupportIfAvailable;
-        }
-
-        public int getWatcherBouncing() {
-            return watcherBouncing;
-        }
-
-        public void setWatcherBouncing(final int watcherBouncing) {
-            this.watcherBouncing = watcherBouncing;
-        }
-
-        public String getTomcatAccessLogPattern() {
-            return tomcatAccessLogPattern;
-        }
-
-        public void setTomcatAccessLogPattern(final String tomcatAccessLogPattern) {
-            this.tomcatAccessLogPattern = tomcatAccessLogPattern;
-        }
-
-        public boolean isTomcatNoJmx() {
-            return tomcatNoJmx;
-        }
-
-        public void setTomcatNoJmx(final boolean tomcatNoJmx) {
-            this.tomcatNoJmx = tomcatNoJmx;
-        }
-
-        public File getPidFile() {
-            return pidFile;
-        }
-
-        public void setPidFile(final File pidFile) {
-            this.pidFile = pidFile;
-        }
-
-        public String getScanningPackageIncludes() {
-            return scanningPackageIncludes;
-        }
-
-        /**
-         * Define some package names (startsWith) which must get scanned for beans.
-         * This rule get's applied before {@link #setScanningPackageExcludes(String)}
-         */
-        public void setScanningPackageIncludes(final String scanningPackageIncludes) {
-            this.scanningPackageIncludes = scanningPackageIncludes;
-        }
-
-        public String getScanningPackageExcludes() {
-            return scanningPackageExcludes;
-        }
-
-        /**
-         * Define some package names (startsWith) which must <em>NOT</em> get scanned for beans.
-         * This rule get's applied after {@link #setScanningPackageIncludes(String)}.
-         *
-         * Defining just a '*' will be a marker for skipping all not-included packages.
-         * Otherwise we will defer to the standard OpenWebBeans class Filter mechanism.
-         */
-        public void setScanningPackageExcludes(final String scanningPackageExcludes) {
-            this.scanningPackageExcludes = scanningPackageExcludes;
+        @Override
+        public Builder loadFrom(String resource) {
+            super.loadFrom(resource);
+            return this;
         }
 
         public Builder excludePackages(final String packages) {
@@ -1575,475 +1211,22 @@
             return this;
         }
 
-        public void setExtension(final Class<?> type, final Object value) {
-            extensions.put(type, value);
-        }
-
-        public String getScanningIncludes() {
-            return scanningIncludes;
-        }
-
-        public void setScanningIncludes(final String scanningIncludes) {
-            this.scanningIncludes = scanningIncludes;
-        }
-
-        public String getScanningExcludes() {
-            return scanningExcludes;
-        }
-
-        public void setScanningExcludes(final String scanningExcludes) {
-            this.scanningExcludes = scanningExcludes;
-        }
-
-        public String getJsonpBufferStrategy() {
-            return jsonpBufferStrategy;
-        }
-
-        public String getJsonbEncoding() {
-            return jsonbEncoding;
-        }
-
-        public void setJsonbEncoding(final String jsonbEncoding) {
-            this.jsonbEncoding = jsonbEncoding;
-        }
-
-        public boolean isJsonbNulls() {
-            return jsonbNulls;
-        }
-
-        public void setJsonbNulls(final boolean jsonbNulls) {
-            this.jsonbNulls = jsonbNulls;
-        }
-
-        public boolean isJsonbIJson() {
-            return jsonbIJson;
-        }
-
-        public void setJsonbIJson(final boolean jsonbIJson) {
-            this.jsonbIJson = jsonbIJson;
-        }
-
-        public boolean isJsonbPrettify() {
-            return jsonbPrettify;
-        }
-
-        public void setJsonbPrettify(final boolean jsonbPrettify) {
-            this.jsonbPrettify = jsonbPrettify;
-        }
-
-        public String getJsonbBinaryStrategy() {
-            return jsonbBinaryStrategy;
-        }
-
-        public void setJsonbBinaryStrategy(final String jsonbBinaryStrategy) {
-            this.jsonbBinaryStrategy = jsonbBinaryStrategy;
-        }
-
-        public String getJsonbNamingStrategy() {
-            return jsonbNamingStrategy;
-        }
-
-        public void setJsonbNamingStrategy(final String jsonbNamingStrategy) {
-            this.jsonbNamingStrategy = jsonbNamingStrategy;
-        }
-
-        public String getJsonbOrderStrategy() {
-            return jsonbOrderStrategy;
-        }
-
-        public void setJsonbOrderStrategy(final String jsonbOrderStrategy) {
-            this.jsonbOrderStrategy = jsonbOrderStrategy;
-        }
-
-        public Builder withJsonpBufferStrategy(final String jsonpBufferStrategy) {
-            this.jsonpBufferStrategy = jsonpBufferStrategy;
-            return this;
-        }
-
-        public void setJsonpBufferStrategy(final String jsonpBufferStrategy) {
-            this.jsonpBufferStrategy = jsonpBufferStrategy;
-        }
-
-        public int getJsonpMaxStringLen() {
-            return jsonpMaxStringLen;
-        }
-
-        public void setJsonpMaxStringLen(final int jsonpMaxStringLen) {
-            this.jsonpMaxStringLen = jsonpMaxStringLen;
-        }
-
-        public int getJsonpMaxReadBufferLen() {
-            return jsonpMaxReadBufferLen;
-        }
-
-        public void setJsonpMaxReadBufferLen(final int jsonpMaxReadBufferLen) {
-            this.jsonpMaxReadBufferLen = jsonpMaxReadBufferLen;
-        }
-
-        public int getJsonpMaxWriteBufferLen() {
-            return jsonpMaxWriteBufferLen;
-        }
-
-        public void setJsonpMaxWriteBufferLen(final int jsonpMaxWriteBufferLen) {
-            this.jsonpMaxWriteBufferLen = jsonpMaxWriteBufferLen;
-        }
-
-        public boolean isJsonpSupportsComment() {
-            return jsonpSupportsComment;
-        }
-
-        public void setJsonpSupportsComment(final boolean jsonpSupportsComment) {
-            this.jsonpSupportsComment = jsonpSupportsComment;
-        }
-
-        public boolean isJsonpPrettify() {
-            return jsonpPrettify;
-        }
-
-        public void setJsonpPrettify(final boolean jsonpPrettify) {
-            this.jsonpPrettify = jsonpPrettify;
-        }
-
-        public String getSharedLibraries() {
-            return sharedLibraries;
-        }
-
         public Builder sharedLibraries(final String sharedLibraries) {
             setSharedLibraries(sharedLibraries);
             return this;
         }
 
-        public void setSharedLibraries(final String sharedLibraries) {
-            this.sharedLibraries = sharedLibraries;
-        }
-
-        public boolean isJaxrsLogProviders() {
-            return jaxrsLogProviders;
-        }
-
-        public void setJaxrsLogProviders(final boolean jaxrsLogProviders) {
-            this.jaxrsLogProviders = jaxrsLogProviders;
-        }
-
-        public boolean isUseTomcatDefaults() {
-            return useTomcatDefaults;
-        }
-
-        public void setUseTomcatDefaults(final boolean useTomcatDefaults) {
-            this.useTomcatDefaults = useTomcatDefaults;
-        }
-
-        public String getTomcatFilter() {
-            return tomcatFilter;
-        }
-
-        public void setTomcatFilter(final String tomcatFilter) {
-            this.tomcatFilter = tomcatFilter;
-        }
-
-        public boolean isTomcatScanning() {
-            return tomcatScanning;
-        }
-
-        public void setTomcatScanning(final boolean tomcatScanning) {
-            this.tomcatScanning = tomcatScanning;
-        }
-
-        public Map<String, String> getCxfServletParams() {
-            return cxfServletParams;
-        }
-
-        public void setCxfServletParams(final Map<String, String> cxfServletParams) {
-            this.cxfServletParams = cxfServletParams;
-        }
-
-        public boolean isLoggingGlobalSetup() {
-            return loggingGlobalSetup;
-        }
-
-        public void setLoggingGlobalSetup(final boolean loggingGlobalSetup) {
-            this.loggingGlobalSetup = loggingGlobalSetup;
-        }
-
-        public boolean isJaxrsAutoActivateBeanValidation() {
-            return jaxrsAutoActivateBeanValidation;
-        }
-
-        public void setJaxrsAutoActivateBeanValidation(final boolean jaxrsAutoActivateBeanValidation) {
-            this.jaxrsAutoActivateBeanValidation = jaxrsAutoActivateBeanValidation;
-        }
-
-        public boolean isJaxrsProviderSetup() {
-            return jaxrsProviderSetup;
-        }
-
-        public void setJaxrsProviderSetup(final boolean jaxrsProviderSetup) {
-            this.jaxrsProviderSetup = jaxrsProviderSetup;
-        }
-
-        public int getHttpPort() {
-            return httpPort;
-        }
-
-        public void setHttpPort(final int httpPort) {
-            this.httpPort = httpPort;
-        }
-
-        public int getHttpsPort() {
-            return httpsPort;
-        }
-
-        public void setHttpsPort(final int httpsPort) {
-            this.httpsPort = httpsPort;
-        }
-
-        public int getStopPort() {
-            return stopPort;
-        }
-
-        public void setStopPort(final int stopPort) {
-            this.stopPort = stopPort;
-        }
-
-        public String getHost() {
-            return host;
-        }
-
-        public void setHost(final String host) {
-            this.host = host;
-        }
-
-        public String getDir() {
-            return dir;
-        }
-
-        public void setDir(final String dir) {
-            this.dir = dir;
-        }
-
-        public File getServerXml() {
-            return serverXml;
-        }
-
-        public void setServerXml(final File serverXml) {
-            this.serverXml = serverXml;
-        }
-
-        public boolean isKeepServerXmlAsThis() {
-            return keepServerXmlAsThis;
-        }
-
-        public void setKeepServerXmlAsThis(final boolean keepServerXmlAsThis) {
-            this.keepServerXmlAsThis = keepServerXmlAsThis;
-        }
-
-        public Properties getProperties() {
-            return properties;
-        }
-
-        public void setProperties(final Properties properties) {
-            this.properties = properties;
-        }
-
-        public boolean isQuickSession() {
-            return quickSession;
-        }
-
-        public void setQuickSession(final boolean quickSession) {
-            this.quickSession = quickSession;
-        }
-
-        public boolean isSkipHttp() {
-            return skipHttp;
-        }
-
-        public void setSkipHttp(final boolean skipHttp) {
-            this.skipHttp = skipHttp;
-        }
-
-        public boolean isSsl() {
-            return ssl;
-        }
-
-        public void setSsl(final boolean ssl) {
-            this.ssl = ssl;
-        }
-
-        public String getKeystoreFile() {
-            return keystoreFile;
-        }
-
-        public void setKeystoreFile(final String keystoreFile) {
-            this.keystoreFile = keystoreFile;
-        }
-
-        public String getKeystorePass() {
-            return keystorePass;
-        }
-
-        public void setKeystorePass(final String keystorePass) {
-            this.keystorePass = keystorePass;
-        }
-
-        public String getKeystoreType() {
-            return keystoreType;
-        }
-
-        public void setKeystoreType(final String keystoreType) {
-            this.keystoreType = keystoreType;
-        }
-
-        public String getClientAuth() {
-            return clientAuth;
-        }
-
-        public void setClientAuth(final String clientAuth) {
-            this.clientAuth = clientAuth;
-        }
-
-        public String getKeyAlias() {
-            return keyAlias;
-        }
-
-        public void setKeyAlias(final String keyAlias) {
-            this.keyAlias = keyAlias;
-        }
-
-        public String getSslProtocol() {
-            return sslProtocol;
-        }
-
-        public void setSslProtocol(final String sslProtocol) {
-            this.sslProtocol = sslProtocol;
-        }
-
-        public String getWebXml() {
-            return webXml;
-        }
-
-        public void setWebXml(final String webXml) {
-            this.webXml = webXml;
-        }
-
-        public LoginConfigBuilder getLoginConfig() {
-            return loginConfig;
-        }
-
-        public Builder loginConfig(final LoginConfigBuilder loginConfig) {
-            setLoginConfig(loginConfig);
+        public Builder securityConstraints(final Meecrowave.SecurityConstaintBuilder securityConstraint) {
+            if (getSecurityConstraints() == null) {
+                setSecurityConstraints(new ArrayList<>());
+            }
+            getSecurityConstraints().add(securityConstraint);
             return this;
         }
 
-        public void setLoginConfig(final LoginConfigBuilder loginConfig) {
-            this.loginConfig = loginConfig;
-        }
-
-        public Collection<SecurityConstaintBuilder> getSecurityConstraints() {
-            return securityConstraints;
-        }
-
-        public Builder securityConstraints(final SecurityConstaintBuilder securityConstraint) {
-            securityConstraints = securityConstraints == null ? new ArrayList<>() : securityConstraints;
-            securityConstraints.add(securityConstraint);
-            return this;
-        }
-
-        public void setSecurityConstraints(final Collection<SecurityConstaintBuilder> securityConstraints) {
-            this.securityConstraints = securityConstraints;
-        }
-
-        public Realm getRealm() {
-            return realm;
-        }
-
-        public Builder realm(final Realm realm) {
-            setRealm(realm);
-            return this;
-        }
-
-        public void setRealm(final Realm realm) {
-            this.realm = realm;
-        }
-
-        public Map<String, String> getUsers() {
-            return users;
-        }
-
-        public void setUsers(final Map<String, String> users) {
-            this.users = users;
-        }
-
-        public Map<String, String> getRoles() {
-            return roles;
-        }
-
-        public void setRoles(final Map<String, String> roles) {
-            this.roles = roles;
-        }
-
-        public boolean isHttp2() {
-            return http2;
-        }
-
-        public void setHttp2(final boolean http2) {
-            this.http2 = http2;
-        }
-
-        public Collection<Connector> getConnectors() {
-            return connectors;
-        }
-
-        public String getTempDir() {
-            return tempDir;
-        }
-
-        public void setTempDir(final String tempDir) {
-            this.tempDir = tempDir;
-        }
-
-        public boolean isWebResourceCached() {
-            return webResourceCached;
-        }
-
-        public void setWebResourceCached(final boolean webResourceCached) {
-            this.webResourceCached = webResourceCached;
-        }
-
-        public String getConf() {
-            return conf;
-        }
-
-        public void setConf(final String conf) {
-            this.conf = conf;
-        }
-
-        public boolean isDeleteBaseOnStartup() {
-            return deleteBaseOnStartup;
-        }
-
-        public void setDeleteBaseOnStartup(final boolean deleteBaseOnStartup) {
-            this.deleteBaseOnStartup = deleteBaseOnStartup;
-        }
-
-        public String getJaxrsMapping() {
-            return jaxrsMapping;
-        }
-
-        public void setJaxrsMapping(final String jaxrsMapping) {
-            this.jaxrsMapping = jaxrsMapping;
-        }
-
-        public boolean isCdiConversation() {
-            return cdiConversation;
-        }
-
-        public void setCdiConversation(final boolean cdiConversation) {
-            this.cdiConversation = cdiConversation;
-        }
-
         public Builder randomHttpPort() {
             try (final ServerSocket serverSocket = new ServerSocket(0)) {
-                this.httpPort = serverSocket.getLocalPort();
+                setHttpPort(serverSocket.getLocalPort());
             } catch (final IOException e) {
                 throw new IllegalStateException(e);
             }
@@ -2052,99 +1235,47 @@
 
         public Builder randomHttpsPort() {
             try (final ServerSocket serverSocket = new ServerSocket(0)) {
-                this.httpsPort = serverSocket.getLocalPort();
+                setHttpsPort(serverSocket.getLocalPort());
             } catch (final IOException e) {
                 throw new IllegalStateException(e);
             }
             return this;
         }
 
-        public Builder loadFrom(final String resource) {
-            // load all of those files on the classpath, sorted by ordinal
-            Properties config = PropertyLoader.getProperties(resource,
-                    sortedProperties -> mergeProperties(resource, sortedProperties),
-                    () -> {});
-            if (config == null || config.isEmpty()) {
-                final File file = new File(resource);
-                if (file.exists()) {
-                    config = new Properties();
-                    try (InputStream is = new FileInputStream(file)) {
-                        config.load(is);
-                    }
-                    catch (IOException e) {
-                        throw new IllegalStateException(e);
-                    }
-                }
-            }
-            if (config != null) {
-                loadFromProperties(config);
-            }
-            return this;
-        }
-
-        public void setServerXml(final String file) {
-            if (file == null) {
-                serverXml = null;
-            } else {
-                final File sXml = new File(file);
-                if (sXml.exists()) {
-                    serverXml = sXml;
-                }
-            }
-        }
-
         public Builder property(final String key, final String value) {
-            properties.setProperty(key, value);
+            getProperties().setProperty(key, value);
             return this;
         }
 
 
         public Builder user(final String name, final String pwd) {
-            if (users == null) {
-                users = new HashMap<>();
+            if (getUsers() == null) {
+                setUsers(new HashMap<>());
             }
-            this.users.put(name, pwd);
+            getUsers().put(name, pwd);
             return this;
         }
 
         public Builder role(final String user, final String roles) {
-            if (this.roles == null) {
-                this.roles = new HashMap<>();
+            if (getRoles() == null) {
+                setRoles(new HashMap<>());
             }
-            this.roles.put(user, roles);
+            getRoles().put(user, roles);
             return this;
         }
 
         public Builder cxfServletParam(final String key, final String value) {
-            if (this.cxfServletParams == null) {
-                this.cxfServletParams = new HashMap<>();
+            if (getCxfServletParams() == null) {
+                setCxfServletParams(new HashMap<>());
             }
-            this.cxfServletParams.put(key, value);
+            getCxfServletParams().put(key, value);
             return this;
         }
 
-        public String getActiveProtocol() {
-            return isSkipHttp() ? "https" : "http";
-        }
-
-        public int getActivePort() {
-            return isSkipHttp() ? getHttpsPort() : getHttpPort();
-        }
-
-        public boolean isTomcatAutoSetup() {
-            return tomcatAutoSetup;
-        }
-
-        public void setTomcatAutoSetup(final boolean tomcatAutoSetup) {
-            this.tomcatAutoSetup = tomcatAutoSetup;
-        }
-
-        public boolean isUseShutdownHook() {
-            return useShutdownHook;
-        }
-
-        public void setUseShutdownHook(final boolean useShutdownHook) {
-            this.useShutdownHook = useShutdownHook;
+        @Deprecated // withers are deprecated, we prefer the no fluent API
+        public Builder withJsonpBufferStrategy(final String jsonpBufferStrategy) {
+            setJsonpBufferStrategy(jsonpBufferStrategy);
+            return this;
         }
 
         public Builder noShutdownHook() {
@@ -2152,255 +1283,416 @@
             return this;
         }
 
-        public boolean isTomcatWrapLoader() {
-            return tomcatWrapLoader;
-        }
-
-        public void setTomcatWrapLoader(final boolean tomcatWrapLoader) {
-            this.tomcatWrapLoader = tomcatWrapLoader;
-        }
-
-        public void addInstanceCustomizer(final Consumer<Tomcat> customizer) {
-            instanceCustomizers.add(customizer);
-        }
-
         public Builder instanceCustomizer(final Consumer<Tomcat> customizer) {
             addInstanceCustomizer(customizer);
             return this;
         }
 
-        public void addCustomizer(final Consumer<Builder> configurationCustomizer) {
-            configurationCustomizer.accept(this);
+        public Builder pidFile(final Path pidFile) {
+            setPidFile(pidFile.toFile());
+            return this;
         }
 
-        public void addGlobalContextCustomizer(final Consumer<Context> contextConfigurer) {
-            if (contextConfigurers == null) {
-                contextConfigurers = new ArrayList<>();
+        public Builder watcherBouncing(final int watcherBouncing) {
+            setWatcherBouncing(watcherBouncing);
+            return this;
+        }
+
+        public Builder httpPort(final int httpPort) {
+            if (httpPort <= 0) {
+                randomHttpPort();
+            } else {
+                setHttpPort(httpPort);
             }
-            contextConfigurers.add(contextConfigurer);
+            return this;
         }
 
-        public void addServletContextInitializer(final ServletContainerInitializer initializer) {
-            initializers.add(initializer);
-        }
-
-        public Collection<ServletContainerInitializer> getInitializers() {
-            return initializers;
-        }
-
-        public String getJaxrsDefaultProviders() {
-            return jaxrsDefaultProviders;
-        }
-
-        public void setJaxrsDefaultProviders(final String jaxrsDefaultProviders) {
-            this.jaxrsDefaultProviders = jaxrsDefaultProviders;
-        }
-
-        public boolean isUseLog4j2JulLogManager() {
-            return useLog4j2JulLogManager;
-        }
-
-        public void setUseLog4j2JulLogManager(final boolean useLog4j2JulLogManager) {
-            this.useLog4j2JulLogManager = useLog4j2JulLogManager;
-        }
-
-        public String getDefaultSSLHostConfigName() {
-            return defaultSSLHostConfigName;
-        }
-
-        public void setDefaultSSLHostConfigName(final String defaultSSLHostConfigName) {
-            this.defaultSSLHostConfigName = defaultSSLHostConfigName;
-        }
-
-        public void loadFromProperties(final Properties config) {
-            // filtering properties with system properties or themself
-            final Substitutor strSubstitutor = new Substitutor(emptyMap()) {
-                @Override
-                public String getOrDefault(final String key, final String or) {
-                    final String property = System.getProperty(key);
-                    return property == null ? config.getProperty(key, or) : or;
-                }
-            };
-
-            final ValueTransformers transformers = getExtension(ValueTransformers.class);
-            for (final String key : config.stringPropertyNames()) {
-                final String val = config.getProperty(key);
-                if (val == null || val.trim().isEmpty()) {
-                    continue;
-                }
-                final String newVal = transformers.apply(strSubstitutor.replace(config.getProperty(key)));
-                if (!val.equals(newVal)) {
-                    config.setProperty(key, newVal);
-                }
+        public Builder httpsPort(final int httpsPort) {
+            if (httpsPort <= 0) {
+                randomHttpsPort();
+            } else {
+                setHttpsPort(httpsPort);
             }
+            return this;
+        }
 
-            for (final Field field : Builder.class.getDeclaredFields()) {
-                final CliOption annotation = field.getAnnotation(CliOption.class);
-                if (annotation == null) {
-                    continue;
-                }
-                final String name = field.getName();
-                Stream.of(Stream.of(annotation.name()), Stream.of(annotation.alias()))
-                        .flatMap(a -> a)
-                        .map(config::getProperty)
-                        .filter(Objects::nonNull)
-                        .findAny().ifPresent(val -> {
-                    final Object toSet;
-                    if (field.getType() == String.class) {
-                        toSet = val;
-                    } else if (field.getType() == int.class) {
-                        if ("httpPort".equals(name) && "-1".equals(val)) { // special case in case of random port
-                            randomHttpPort();
-                            toSet = null;
-                        } else {
-                            toSet = Integer.parseInt(val);
-                        }
-                    } else if (field.getType() == boolean.class) {
-                        toSet = Boolean.parseBoolean(val);
-                    } else if (field.getType() == File.class) {
-                        toSet = new File(val);
-                    } else {
-                        toSet = null;
-                    }
-                    if (toSet == null) { // handled elsewhere
-                        return;
-                    }
+        public Builder stopPort(final int stopPort) {
+            setStopPort(stopPort);
+            return this;
+        }
 
-                    if (!field.isAccessible()) {
-                        field.setAccessible(true);
-                    }
-                    try {
-                        field.set(this, toSet);
-                    } catch (final IllegalAccessException e) {
-                        throw new IllegalStateException(e);
-                    }
-                });
+        public Builder host(final String host) {
+            setHost(host);
+            return this;
+        }
+
+        public Builder dir(final String dir) {
+            setDir(dir);
+            return this;
+        }
+
+        public Builder serverXml(final Path serverXml) {
+            setServerXml(serverXml.toFile());
+            return this;
+        }
+
+        public Builder keepServerXmlAsThis(final boolean keepServerXmlAsThis) {
+            setKeepServerXmlAsThis(keepServerXmlAsThis);
+            return this;
+        }
+
+        public Builder properties(final Properties properties) {
+            getProperties().putAll(properties);
+            return this;
+        }
+
+        public Builder quickSession(final boolean quickSession) {
+            setQuickSession(quickSession);
+            return this;
+        }
+
+        public Builder skipHttp(final boolean skipHttp) {
+            setSkipHttp(skipHttp);
+            return this;
+        }
+
+        public Builder ssl(final boolean ssl) {
+            setSsl(ssl);
+            return this;
+        }
+
+        public Builder keystoreFile(final String keystoreFile) {
+            setKeystoreFile(keystoreFile);
+            return this;
+        }
+
+        public Builder keystorePass(final String keystorePass) {
+            setKeystorePass(keystorePass);
+            return this;
+        }
+
+        public Builder keystoreType(final String keystoreType) {
+            setKeystoreType(keystoreType);
+            return this;
+        }
+
+        public Builder clientAuth(final String clientAuth) {
+            setClientAuth(clientAuth);
+            return this;
+        }
+
+        public Builder keyAlias(final String keyAlias) {
+            setKeyAlias(keyAlias);
+            return this;
+        }
+
+        public Builder sslProtocol(final String sslProtocol) {
+            setSslProtocol(sslProtocol);
+            return this;
+        }
+
+        public Builder webXml(final String webXml) {
+            setWebXml(webXml);
+            return this;
+        }
+
+        public Builder loginConfig(final LoginConfigBuilder loginConfig) {
+            setLoginConfig(loginConfig);
+            return this;
+        }
+
+        public Builder securityConstraint(final SecurityConstaintBuilder securityConstraint) {
+            if (getSecurityConstraints() == null) {
+                setSecurityConstraints(new ArrayList<>());
             }
+            getSecurityConstraints().add(securityConstraint);
+            return this;
+        }
 
-            // not trivial types
-            for (final String prop : config.stringPropertyNames()) {
-                if (prop.startsWith("properties.")) {
-                    property(prop.substring("properties.".length()), config.getProperty(prop));
-                } else if (prop.startsWith("users.")) {
-                    user(prop.substring("users.".length()), config.getProperty(prop));
-                } else if (prop.startsWith("roles.")) {
-                    role(prop.substring("roles.".length()), config.getProperty(prop));
-                } else if (prop.startsWith("cxf.servlet.params.")) {
-                    cxfServletParam(prop.substring("cxf.servlet.params.".length()), config.getProperty(prop));
-                } else if (prop.startsWith("connector.")) { // created in container
-                    property(prop, config.getProperty(prop));
-                } else if (prop.equals("realm")) {
-                    final ObjectRecipe recipe = newRecipe(config.getProperty(prop));
-                    for (final String realmConfig : config.stringPropertyNames()) {
-                        if (realmConfig.startsWith("realm.")) {
-                            recipe.setProperty(realmConfig.substring("realm.".length()), config.getProperty(realmConfig));
-                        }
-                    }
-                    this.realm = Realm.class.cast(recipe.create());
-                } else if (prop.equals("login")) {
-                    final ObjectRecipe recipe = newRecipe(LoginConfigBuilder.class.getName());
-                    for (final String nestedConfig : config.stringPropertyNames()) {
-                        if (nestedConfig.startsWith("login.")) {
-                            recipe.setProperty(nestedConfig.substring("login.".length()), config.getProperty(nestedConfig));
-                        }
-                    }
-                    loginConfig = LoginConfigBuilder.class.cast(recipe.create());
-                } else if (prop.equals("securityConstraint")) {
-                    final ObjectRecipe recipe = newRecipe(SecurityConstaintBuilder.class.getName());
-                    for (final String nestedConfig : config.stringPropertyNames()) {
-                        if (nestedConfig.startsWith("securityConstraint.")) {
-                            recipe.setProperty(nestedConfig.substring("securityConstraint.".length()), config.getProperty(nestedConfig));
-                        }
-                    }
-                    securityConstraints.add(SecurityConstaintBuilder.class.cast(recipe.create()));
-                } else if (prop.equals("configurationCustomizer")) {
-                    final ObjectRecipe recipe = newRecipe(prop);
-                    for (final String nestedConfig : config.stringPropertyNames()) {
-                        if (nestedConfig.startsWith(prop + '.')) {
-                            recipe.setProperty(nestedConfig.substring(prop.length() + 2 /*dot*/), config.getProperty(nestedConfig));
-                        }
-                    }
-                    addCustomizer(Consumer.class.cast(recipe.create()));
-                }
+        public Builder realm(final Realm realm) {
+            setRealm(realm);
+            return this;
+        }
+
+        public Builder users(final Map<String, String> users) {
+            if (getUsers() == null) {
+                setUsers(new HashMap<>());
             }
+            getUsers().putAll(users);
+            return this;
         }
 
-        public <T> T bind(final T instance) {
-            final ValueTransformers transformers = getExtension(ValueTransformers.class);
-            Class<? extends Object> type = instance.getClass();
-            do {
-                Stream.of(type.getDeclaredFields())
-                        .filter(f -> f.isAnnotationPresent(CliOption.class))
-                        .forEach(f -> {
-                            final CliOption annotation = f.getAnnotation(CliOption.class);
-                            String value = properties.getProperty(annotation.name());
-                            if (value == null) {
-                                value = Stream.of(annotation.alias()).map(properties::getProperty).findFirst().orElse(null);
-                                if (value == null) {
-                                    return;
-                                }
-                            }
-
-                            value = transformers.apply(value);
-
-                            if (!f.isAccessible()) {
-                                f.setAccessible(true);
-                            }
-                            final Class<?> t = f.getType();
-                            try {
-                                if (t == String.class) {
-                                    f.set(instance, value);
-                                } else if (t == int.class) {
-                                    f.set(instance, Integer.parseInt(value));
-                                } else if (t == boolean.class) {
-                                    f.set(instance, Boolean.parseBoolean(value));
-                                } else {
-                                    throw new IllegalArgumentException("Unsupported type " + t);
-                                }
-                            } catch (final IllegalAccessException iae) {
-                                throw new IllegalStateException(iae);
-                            }
-                        });
-                type = type.getSuperclass();
-            } while (type != Object.class);
-            return instance;
-        }
-
-        public boolean isInjectServletContainerInitializer() {
-            return injectServletContainerInitializer;
-        }
-
-        public void setInjectServletContainerInitializer(final boolean injectServletContainerInitializer) {
-            this.injectServletContainerInitializer = injectServletContainerInitializer;
-        }
-
-        public String getMeecrowaveProperties() {
-            return meecrowaveProperties;
-        }
-
-        public void setMeecrowaveProperties(final String meecrowaveProperties) {
-            this.meecrowaveProperties = meecrowaveProperties;
-        }
-
-        private Properties mergeProperties(final String resource, final List<Properties> sortedProperties) {
-            Properties mergedProperties = new Properties();
-            Properties master = null;
-            for (final Properties p : sortedProperties)
-            {
-                if (Boolean.parseBoolean(p.getProperty("configuration.complete", "false"))) {
-                    if (master != null) {
-                        throw new IllegalArgumentException("Ambiguous '" + resource + "', " +
-                                "multiple " + resource + " with configuration.complete=true");
-                    }
-                    master = p;
-                }
-                mergedProperties.putAll(p);
+        public Builder roles(final Map<String, String> roles) {
+            if (getRoles() == null) {
+                setRoles(new HashMap<>());
             }
+            getRoles().putAll(roles);
+            return this;
+        }
 
-            if (master != null) {
-                return master;
-            }
-            return mergedProperties;
+        public Builder http2(final boolean http2) {
+            setHttp2(http2);
+            return this;
+        }
+
+        public Builder connector(final Connector connector) {
+            getConnectors().add(connector);
+            return this;
+        }
+
+        public Builder tempDir(final String tempDir) {
+            setTempDir(tempDir);
+            return this;
+        }
+
+        public Builder webResourceCached(final boolean webResourceCached) {
+            setWebResourceCached(webResourceCached);
+            return this;
+        }
+
+        public Builder conf(final String conf) {
+            setConf(conf);
+            return this;
+        }
+
+        public Builder deleteBaseOnStartup(final boolean deleteBaseOnStartup) {
+            setDeleteBaseOnStartup(deleteBaseOnStartup);
+            return this;
+        }
+
+        public Builder jaxrsMapping(final String jaxrsMapping) {
+            setJaxrsMapping(jaxrsMapping);
+            return this;
+        }
+
+        public Builder cdiConversation(final boolean cdiConversation) {
+            setCdiConversation(cdiConversation);
+            return this;
+        }
+
+        public Builder jaxrsProviderSetup(final boolean jaxrsProviderSetup) {
+            setJaxrsProviderSetup(jaxrsProviderSetup);
+            return this;
+        }
+
+        public Builder jaxrsDefaultProviders(final String jaxrsDefaultProviders) {
+            setJaxrsDefaultProviders(jaxrsDefaultProviders);
+            return this;
+        }
+
+        public Builder jaxrsAutoActivateBeanValidation(final boolean jaxrsAutoActivateBeanValidation) {
+            setJaxrsAutoActivateBeanValidation(jaxrsAutoActivateBeanValidation);
+            return this;
+        }
+
+        public Builder jaxrsLogProviders(final boolean jaxrsLogProviders) {
+            setJaxrsLogProviders(jaxrsLogProviders);
+            return this;
+        }
+
+        public Builder jsonpBufferStrategy(final String jsonpBufferStrategy) {
+            setJsonpBufferStrategy(jsonpBufferStrategy);
+            return this;
+        }
+
+        public Builder jsonpMaxStringLen(final int jsonpMaxStringLen) {
+            setJsonpMaxStringLen(jsonpMaxStringLen);
+            return this;
+        }
+
+        public Builder jsonpMaxReadBufferLen(final int jsonpMaxReadBufferLen) {
+            setJsonpMaxReadBufferLen(jsonpMaxReadBufferLen);
+            return this;
+        }
+
+        public Builder jsonpMaxWriteBufferLen(final int jsonpMaxWriteBufferLen) {
+            setJsonpMaxWriteBufferLen(jsonpMaxWriteBufferLen);
+            return this;
+        }
+
+        public Builder jsonpSupportsComment(final boolean jsonpSupportsComment) {
+            setJsonpSupportsComment(jsonpSupportsComment);
+            return this;
+        }
+
+        public Builder jsonpPrettify(final boolean jsonpPrettify) {
+            setJsonpPrettify(jsonpPrettify);
+            return this;
+        }
+
+        public Builder jsonbEncoding(final String jsonbEncoding) {
+            setJsonbEncoding(jsonbEncoding);
+            return this;
+        }
+
+        public Builder jsonbNulls(final boolean jsonbNulls) {
+            setJsonbNulls(jsonbNulls);
+            return this;
+        }
+
+        public Builder jsonbIJson(final boolean jsonbIJson) {
+            setJsonbIJson(jsonbIJson);
+            return this;
+        }
+
+        public Builder jsonbPrettify(final boolean jsonbPrettify) {
+            setJsonbPrettify(jsonbPrettify);
+            return this;
+        }
+
+        public Builder jsonbBinaryStrategy(final String jsonbBinaryStrategy) {
+            setJsonbBinaryStrategy(jsonbBinaryStrategy);
+            return this;
+        }
+
+        public Builder jsonbNamingStrategy(final String jsonbNamingStrategy) {
+            setJsonbNamingStrategy(jsonbNamingStrategy);
+            return this;
+        }
+
+        public Builder jsonbOrderStrategy(final String jsonbOrderStrategy) {
+            setJsonbOrderStrategy(jsonbOrderStrategy);
+            return this;
+        }
+
+        public Builder loggingGlobalSetup(final boolean loggingGlobalSetup) {
+            setLoggingGlobalSetup(loggingGlobalSetup);
+            return this;
+        }
+
+        public Builder tomcatScanning(final boolean tomcatScanning) {
+            setTomcatScanning(tomcatScanning);
+            return this;
+        }
+
+        public Builder tomcatAutoSetup(final boolean tomcatAutoSetup) {
+            setTomcatAutoSetup(tomcatAutoSetup);
+            return this;
+        }
+
+        public Builder tomcatJspDevelopment(final boolean tomcatJspDevelopment) {
+            setTomcatJspDevelopment(tomcatJspDevelopment);
+            return this;
+        }
+
+        public Builder useShutdownHook(final boolean useShutdownHook) {
+            setUseShutdownHook(useShutdownHook);
+            return this;
+        }
+
+        public Builder tomcatFilter(final String tomcatFilter) {
+            setTomcatFilter(tomcatFilter);
+            return this;
+        }
+
+        public Builder scanningIncludes(final String scanningIncludes) {
+            setScanningIncludes(scanningIncludes);
+            return this;
+        }
+
+        public Builder scanningExcludes(final String scanningExcludes) {
+            setScanningExcludes(scanningExcludes);
+            return this;
+        }
+
+        public Builder scanningPackageIncludes(final String scanningPackageIncludes) {
+            setScanningPackageIncludes(scanningPackageIncludes);
+            return this;
+        }
+
+        public Builder scanningPackageIncludes(final Collection<String> scanningPackageIncludes) {
+            setScanningPackageIncludes(String.join(",", scanningPackageIncludes));
+            return this;
+        }
+
+        public Builder scanningPackageExcludes(final String scanningPackageExcludes) {
+            setScanningPackageExcludes(scanningPackageExcludes);
+            return this;
+        }
+
+        public Builder scanningPackageExcludes(final Collection<String> scanningPackageExcludes) {
+            setScanningPackageExcludes(String.join(",", scanningPackageExcludes));
+            return this;
+        }
+
+        public Builder webSessionTimeout(final int webSessionTimeout) {
+            setWebSessionTimeout(webSessionTimeout);
+            return this;
+        }
+
+        public Builder webSessionCookieConfig(final String webSessionCookieConfig) {
+            setWebSessionCookieConfig(webSessionCookieConfig);
+            return this;
+        }
+
+        public Builder useTomcatDefaults(final boolean useTomcatDefaults) {
+            setUseTomcatDefaults(useTomcatDefaults);
+            return this;
+        }
+
+        public Builder tomcatWrapLoader(final boolean tomcatWrapLoader) {
+            setTomcatWrapLoader(tomcatWrapLoader);
+            return this;
+        }
+
+        public Builder tomcatNoJmx(final boolean tomcatNoJmx) {
+            setTomcatNoJmx(tomcatNoJmx);
+            return this;
+        }
+
+        public Builder useLog4j2JulLogManager(final boolean useLog4j2JulLogManager) {
+            setUseLog4j2JulLogManager(useLog4j2JulLogManager);
+            return this;
+        }
+
+        public Builder injectServletContainerInitializer(final boolean injectServletContainerInitializer) {
+            setInjectServletContainerInitializer(injectServletContainerInitializer);
+            return this;
+        }
+
+        public Builder tomcatAccessLogPattern(final String tomcatAccessLogPattern) {
+            setTomcatAccessLogPattern(tomcatAccessLogPattern);
+            return this;
+        }
+
+        public Builder meecrowaveProperties(final String meecrowaveProperties) {
+            setMeecrowaveProperties(meecrowaveProperties);
+            return this;
+        }
+
+        public Builder jaxwsSupportIfAvailable(final boolean jaxwsSupportIfAvailable) {
+            setJaxwsSupportIfAvailable(jaxwsSupportIfAvailable);
+            return this;
+        }
+
+        public Builder defaultSSLHostConfigName(final String defaultSSLHostConfigName) {
+            setDefaultSSLHostConfigName(defaultSSLHostConfigName);
+            return this;
+        }
+
+        public Builder initializeClientBus(final boolean initializeClientBus) {
+            setInitializeClientBus(initializeClientBus);
+            return this;
+        }
+
+        public Builder instanceCustomizers(final Consumer<Tomcat> instanceCustomizer) {
+            addInstanceCustomizer(instanceCustomizer);
+            return this;
+        }
+
+        public Builder initializer(final ServletContainerInitializer initializer) {
+            addServletContextInitializer(initializer);
+            return this;
+        }
+
+        public Builder antiResourceLocking(final boolean antiResourceLocking) {
+            setAntiResourceLocking(antiResourceLocking);
+            return this;
+        }
+
+        public Builder contextConfigurer(final Consumer<Context> contextConfigurers) {
+            addGlobalContextCustomizer(contextConfigurers);
+            return this;
         }
     }
 
@@ -2708,7 +2000,7 @@
     }
 
     // just to type it and allow some extensions to use a ServiceLoader
-    public interface ConfigurationCustomizer extends Consumer<Meecrowave.Builder> {
+    public interface ConfigurationCustomizer extends Consumer<Configuration> {
     }
 
     /**
diff --git a/meecrowave-core/src/main/java/org/apache/meecrowave/cdi/MeecrowaveSeContainerInitializer.java b/meecrowave-core/src/main/java/org/apache/meecrowave/cdi/MeecrowaveSeContainerInitializer.java
index 04c2392..dda9bcb 100644
--- a/meecrowave-core/src/main/java/org/apache/meecrowave/cdi/MeecrowaveSeContainerInitializer.java
+++ b/meecrowave-core/src/main/java/org/apache/meecrowave/cdi/MeecrowaveSeContainerInitializer.java
@@ -19,6 +19,7 @@
 package org.apache.meecrowave.cdi;
 
 import org.apache.meecrowave.Meecrowave;
+import org.apache.meecrowave.configuration.Configuration;
 import org.apache.meecrowave.logging.jul.Log4j2Logger;
 import org.apache.meecrowave.logging.openwebbeans.Log4j2LoggerFactory;
 import org.apache.meecrowave.logging.tomcat.Log4j2Log;
@@ -55,18 +56,18 @@
                 System.getProperty("org.apache.tomcat.Logger", Log4j2Log.class.getName()));
     }
 
-    private Meecrowave.Builder builder = new Meecrowave.Builder();
+    private Configuration builder = new Meecrowave.Builder();
 
     @Override
     public SeContainerInitializer addProperty(final String s, final Object o) {
-        if (Meecrowave.Builder.class.isInstance(o)) {
-            builder = Meecrowave.Builder.class.cast(o);
+        if (Configuration.class.isInstance(o)) {
+            builder = Configuration.class.cast(o);
             return this;
         }
 
         final String setter = "set" + Character.toUpperCase(s.charAt(0)) + s.substring(1);
-        final Class<? extends Meecrowave.Builder> builderClass = builder.getClass();
-        final Optional<Method> setterOpt = Stream.of(builderClass.getMethods())
+        final Class<? extends Configuration> builderClass = builder.getClass();
+        final Optional<Method> setterOpt = Stream.of(Configuration.class.getMethods())
                 .filter(m -> m.getName().equals(setter) && m.getParameterCount() == 1)
                 .findFirst();
         if (!setterOpt.isPresent()) {
diff --git a/meecrowave-core/src/main/java/org/apache/meecrowave/configuration/Configuration.java b/meecrowave-core/src/main/java/org/apache/meecrowave/configuration/Configuration.java
new file mode 100644
index 0000000..669c9f0
--- /dev/null
+++ b/meecrowave-core/src/main/java/org/apache/meecrowave/configuration/Configuration.java
@@ -0,0 +1,1373 @@
+/*
+ * 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.meecrowave.configuration;
+
+import static java.util.Collections.emptyMap;
+import static java.util.Optional.ofNullable;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.net.ServerSocket;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Properties;
+import java.util.ServiceLoader;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
+import javax.servlet.ServletContainerInitializer;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.Realm;
+import org.apache.catalina.connector.Connector;
+import org.apache.catalina.startup.Tomcat;
+import org.apache.meecrowave.Meecrowave;
+import org.apache.meecrowave.lang.Substitutor;
+import org.apache.meecrowave.runner.cli.CliOption;
+import org.apache.meecrowave.service.Priotities;
+import org.apache.webbeans.config.PropertyLoader;
+import org.apache.xbean.recipe.ObjectRecipe;
+import org.apache.xbean.recipe.Option;
+
+public class Configuration {
+    @CliOption(name = "pid-file", description = "A file path to write the process id if the server starts")
+    private File pidFile;
+
+    @CliOption(name = "watcher-bouncing", description = "Activate redeployment on directories update using this bouncing.")
+    private int watcherBouncing = 500;
+
+    @CliOption(name = "http", description = "HTTP port")
+    private int httpPort = 8080;
+
+    @CliOption(name = "https", description = "HTTPS port")
+    private int httpsPort = 8443;
+
+    @CliOption(name = "stop", description = "Shutdown port if used or -1")
+    private int stopPort = -1;
+
+    @CliOption(name = "host", description = "Default host")
+    private String host = "localhost";
+
+    @CliOption(name = "dir", description = "Root folder if provided otherwise a fake one is created in tmp-dir")
+    private String dir;
+
+    @CliOption(name = "server-xml", description = "Provided server.xml")
+    private File serverXml;
+
+    @CliOption(name = "keep-server-xml-as-this", description = "Don't replace ports in server.xml")
+    private boolean keepServerXmlAsThis;
+
+    @CliOption(name = "properties", description = "Passthrough properties")
+    private Properties properties = new Properties();
+
+    @CliOption(name = "quick-session", description = "Should an unsecured but fast session id generator be used")
+    private boolean quickSession = true;
+
+    @CliOption(name = "skip-http", description = "Skip HTTP connector")
+    private boolean skipHttp;
+
+    @CliOption(name = "ssl", description = "Use HTTPS")
+    private boolean ssl;
+
+    @CliOption(name = "keystore-file", description = "HTTPS keystore location")
+    private String keystoreFile;
+
+    @CliOption(name = "keystore-password", description = "HTTPS keystore password")
+    private String keystorePass;
+
+    @CliOption(name = "keystore-type", description = "HTTPS keystore type")
+    private String keystoreType = "JKS";
+
+    @CliOption(name = "client-auth", description = "HTTPS keystore client authentication")
+    private String clientAuth;
+
+    @CliOption(name = "keystore-alias", description = "HTTPS keystore alias")
+    private String keyAlias;
+
+    @CliOption(name = "ssl-protocol", description = "HTTPS protocol")
+    private String sslProtocol;
+
+    @CliOption(name = "web-xml", description = "Global web.xml")
+    private String webXml;
+
+    @CliOption(name = "login-config", description = "web.xml login config")
+    private Meecrowave.LoginConfigBuilder loginConfig;
+
+    @CliOption(name = "security-constraint", description = "web.xml security constraint")
+    private Collection<Meecrowave.SecurityConstaintBuilder> securityConstraints = new LinkedList<>();
+
+    @CliOption(name = "realm", description = "realm")
+    private Realm realm;
+
+    @CliOption(name = "users", description = "In memory users")
+    private Map<String, String> users;
+
+    @CliOption(name = "roles", description = "In memory roles")
+    private Map<String, String> roles;
+
+    @CliOption(name = "http2", description = "Activate HTTP 2")
+    private boolean http2;
+
+    @CliOption(name = "connector", description = "Custom connectors")
+    private final Collection<Connector> connectors = new ArrayList<>();
+
+    @CliOption(name = "tmp-dir", description = "Temporary directory")
+    private String tempDir = System.getProperty("java.io.tmpdir");
+
+    @CliOption(name = "web-resource-cached", description = "Cache web resources")
+    private boolean webResourceCached = true;
+
+    @CliOption(name = "conf", description = "Conf folder to synchronize")
+    private String conf;
+
+    @CliOption(name = "delete-on-startup", description = "Should the directory be cleaned on startup if existing")
+    private boolean deleteBaseOnStartup = true;
+
+    @CliOption(name = "jaxrs-mapping", description = "Default jaxrs mapping")
+    private String jaxrsMapping = "/*";
+
+    @CliOption(name = "cdi-conversation", description = "Should CDI conversation be activated")
+    private boolean cdiConversation;
+
+    @CliOption(name = "jaxrs-provider-setup", description = "Should default JAX-RS provider be configured")
+    private boolean jaxrsProviderSetup = true;
+
+    @CliOption(name = "jaxrs-default-providers", description = "If jaxrsProviderSetup is true the list of default providers to load (or defaulting to johnson jsonb and jsonp ones)")
+    private String jaxrsDefaultProviders;
+
+    @CliOption(name = "jaxrs-beanvalidation", description = "Should bean validation be activated on JAX-RS endpoint if present in the classpath.")
+    private boolean jaxrsAutoActivateBeanValidation = true;
+
+    @CliOption(name = "jaxrs-log-provider", description = "Should JAX-RS providers be logged")
+    private boolean jaxrsLogProviders = false;
+
+    @CliOption(name = "jsonp-buffer-strategy", description = "JSON-P JAX-RS provider buffer strategy (see johnzon)")
+    private String jsonpBufferStrategy = "QUEUE";
+
+    @CliOption(name = "jsonp-max-string-length", description = "JSON-P JAX-RS provider max string limit size (see johnzon)")
+    private int jsonpMaxStringLen = 64 * 1024;
+
+    @CliOption(name = "jsonp-read-buffer-length", description = "JSON-P JAX-RS provider read buffer limit size (see johnzon)")
+    private int jsonpMaxReadBufferLen = 64 * 1024;
+
+    @CliOption(name = "jsonp-write-buffer-length", description = "JSON-P JAX-RS provider write buffer limit size (see johnzon)")
+    private int jsonpMaxWriteBufferLen = 64 * 1024;
+
+    @CliOption(name = "jsonp-supports-comment", description = "Should JSON-P JAX-RS provider support comments (see johnzon)")
+    private boolean jsonpSupportsComment = false;
+
+    @CliOption(name = "jsonp-supports-comment", description = "Should JSON-P JAX-RS provider prettify the outputs (see johnzon)")
+    private boolean jsonpPrettify = false;
+
+    @CliOption(name = "jsonb-encoding", description = "Which encoding provider JSON-B should use")
+    private String jsonbEncoding = "UTF-8";
+
+    @CliOption(name = "jsonb-nulls", description = "Should JSON-B provider serialize nulls")
+    private boolean jsonbNulls = false;
+
+    @CliOption(name = "jsonb-ijson", description = "Should JSON-B provider comply to I-JSON")
+    private boolean jsonbIJson = false;
+
+    @CliOption(name = "jsonb-prettify", description = "Should JSON-B provider prettify the output")
+    private boolean jsonbPrettify = false;
+
+    @CliOption(name = "jsonb-binary-strategy", description = "Should JSON-B provider prettify the output")
+    private String jsonbBinaryStrategy;
+
+    @CliOption(name = "jsonb-naming-strategy", description = "Should JSON-B provider prettify the output")
+    private String jsonbNamingStrategy;
+
+    @CliOption(name = "jsonb-order-strategy", description = "Should JSON-B provider prettify the output")
+    private String jsonbOrderStrategy;
+
+    @CliOption(name = "logging-global-setup", description = "Should logging be configured to use log4j2 (it is global)")
+    private boolean loggingGlobalSetup = true;
+
+    @CliOption(name = "cxf-servlet-params", description = "Init parameters passed to CXF servlet")
+    private Map<String, String> cxfServletParams;
+
+    @CliOption(name = "tomcat-scanning", description = "Should Tomcat scanning be used (@HandleTypes, @WebXXX)")
+    private boolean tomcatScanning = true;
+
+    @CliOption(name = "tomcat-default-setup", description = "Add default servlet")
+    private boolean tomcatAutoSetup = true;
+
+    @CliOption(name = "tomcat-default-setup-jsp-development", description = "Should JSP support if available be set in development mode")
+    private boolean tomcatJspDevelopment = false;
+
+    @CliOption(name = "use-shutdown-hook", description = "Use shutdown hook to automatically stop the container on Ctrl+C")
+    private boolean useShutdownHook = true;
+
+    @CliOption(name = "tomcat-filter", description = "A Tomcat JarScanFilter")
+    private String tomcatFilter;
+
+    @CliOption(name = "scanning-include", description = "A forced include list of jar names (comma separated values)")
+    private String scanningIncludes;
+
+    @CliOption(name = "scanning-exclude", description = "A forced exclude list of jar names (comma separated values)")
+    private String scanningExcludes;
+
+    @CliOption(name = "scanning-package-include", description = "A forced include list of packages names (comma separated values)")
+    private String scanningPackageIncludes;
+
+    @CliOption(name = "scanning-package-exclude", description = "A forced exclude list of packages names (comma separated values)")
+    private String scanningPackageExcludes;
+
+    @CliOption(name = "web-session-timeout", description = "Force the session timeout for webapps")
+    private Integer webSessionTimeout;
+
+    @CliOption(name = "web-session-cookie-config", description = "Force the cookie-config, it uses a properties syntax with the keys being the web.xml tag names.")
+    private String webSessionCookieConfig;
+
+    @CliOption(name = "tomcat-default", description = "Should Tomcat default be set (session timeout, mime mapping etc...)")
+    private boolean useTomcatDefaults = true;
+
+    @CliOption(name = "tomcat-wrap-loader", description = "(Experimental) When deploying a classpath (current classloader), " +
+            "should meecrowave wrap the loader to define another loader identity but still use the same classes and resources.")
+    private boolean tomcatWrapLoader = false;
+
+    @CliOption(name = "tomcat-skip-jmx", description = "(Experimental) Should Tomcat MBeans be skipped.")
+    private boolean tomcatNoJmx = true;
+
+    @CliOption(name = "shared-libraries", description = "A folder containing shared libraries.", alias = "shared-librairies")
+    private String sharedLibraries;
+
+    @CliOption(name = "log4j2-jul-bridge", description = "Should JUL logs be redirected to Log4j2 - only works before JUL usage.")
+    private boolean useLog4j2JulLogManager = System.getProperty("java.util.logging.manager") == null;
+
+    @CliOption(name = "servlet-container-initializer-injection", description = "Should ServletContainerInitialize support injections.")
+    private boolean injectServletContainerInitializer = true;
+
+    @CliOption(
+            name = "tomcat-access-log-pattern",
+            description = "Activates and configure the access log valve. Value example: '%h %l %u %t \"%r\" %s %b \"%{Referer}i\" \"%{User-Agent}i\"'")
+    private String tomcatAccessLogPattern;
+
+    @CliOption(
+            name = "meecrowave-properties",
+            description = "Loads a meecrowave properties, defaults to meecrowave.properties.")
+    private String meecrowaveProperties = "meecrowave.properties";
+
+    @CliOption(name = "jaxws-support-if-present", description = "Should @WebService CDI beans be deployed if cxf-rt-frontend-jaxws is in the classpath.")
+    private boolean jaxwsSupportIfAvailable = true;
+
+    @CliOption(name = "default-ssl-hostconfig-name", description = "The name of the default SSLHostConfig that will be used for secure https connections.")
+    private String defaultSSLHostConfigName;
+
+    @CliOption(name = "cxf-initialize-client-bus", description = "Should the client bus be set. If false the server one will likely be reused.")
+    private boolean initializeClientBus = true;
+
+    private final Map<Class<?>, Object> extensions = new HashMap<>();
+    private final Collection<Consumer<Tomcat>> instanceCustomizers = new ArrayList<>();
+
+    @CliOption(name = "servlet-container-initializer", description = "ServletContainerInitializer instances.")
+    private Collection<ServletContainerInitializer> initializers = new ArrayList<>();
+
+    @CliOption(name = "tomcat-antiresourcelocking", description = "Should Tomcat anti resource locking feature be activated on StandardContext.")
+    private boolean antiResourceLocking;
+
+    @CliOption(name = "tomcat-context-configurer", description = "Configurers for all webapps. The Consumer<Context> instances will be applied to all deployments.")
+    private Collection<Consumer<Context>> contextConfigurers;
+
+    public Configuration(final Configuration toCopy) {
+        pidFile = toCopy.pidFile;
+        watcherBouncing = toCopy.watcherBouncing;
+        httpPort = toCopy.httpPort;
+        httpsPort = toCopy.httpsPort;
+        stopPort = toCopy.stopPort;
+        host = toCopy.host;
+        dir = toCopy.dir;
+        serverXml = toCopy.serverXml;
+        keepServerXmlAsThis = toCopy.keepServerXmlAsThis;
+        properties = toCopy.properties;
+        quickSession = toCopy.quickSession;
+        skipHttp = toCopy.skipHttp;
+        ssl = toCopy.ssl;
+        keystoreFile = toCopy.keystoreFile;
+        keystorePass = toCopy.keystorePass;
+        keystoreType = toCopy.keystoreType;
+        clientAuth = toCopy.clientAuth;
+        keyAlias = toCopy.keyAlias;
+        sslProtocol = toCopy.sslProtocol;
+        webXml = toCopy.webXml;
+        loginConfig = toCopy.loginConfig;
+        securityConstraints = toCopy.securityConstraints;
+        realm = toCopy.realm;
+        users = toCopy.users;
+        roles = toCopy.roles;
+        http2 = toCopy.http2;
+        connectors.addAll(toCopy.connectors);
+        tempDir = toCopy.tempDir;
+        webResourceCached = toCopy.webResourceCached;
+        conf = toCopy.conf;
+        deleteBaseOnStartup = toCopy.deleteBaseOnStartup;
+        jaxrsMapping = toCopy.jaxrsMapping;
+        cdiConversation = toCopy.cdiConversation;
+        jaxrsProviderSetup = toCopy.jaxrsProviderSetup;
+        jaxrsDefaultProviders = toCopy.jaxrsDefaultProviders;
+        jaxrsAutoActivateBeanValidation = toCopy.jaxrsAutoActivateBeanValidation;
+        jaxrsLogProviders = toCopy.jaxrsLogProviders;
+        jsonpBufferStrategy = toCopy.jsonpBufferStrategy;
+        jsonpMaxStringLen = toCopy.jsonpMaxStringLen;
+        jsonpMaxReadBufferLen = toCopy.jsonpMaxReadBufferLen;
+        jsonpMaxWriteBufferLen = toCopy.jsonpMaxWriteBufferLen;
+        jsonpSupportsComment = toCopy.jsonpSupportsComment;
+        jsonpPrettify = toCopy.jsonpPrettify;
+        jsonbEncoding = toCopy.jsonbEncoding;
+        jsonbNulls = toCopy.jsonbNulls;
+        jsonbIJson = toCopy.jsonbIJson;
+        jsonbPrettify = toCopy.jsonbPrettify;
+        jsonbBinaryStrategy = toCopy.jsonbBinaryStrategy;
+        jsonbNamingStrategy = toCopy.jsonbNamingStrategy;
+        jsonbOrderStrategy = toCopy.jsonbOrderStrategy;
+        loggingGlobalSetup = toCopy.loggingGlobalSetup;
+        cxfServletParams = toCopy.cxfServletParams;
+        tomcatScanning = toCopy.tomcatScanning;
+        tomcatAutoSetup = toCopy.tomcatAutoSetup;
+        tomcatJspDevelopment = toCopy.tomcatJspDevelopment;
+        useShutdownHook = toCopy.useShutdownHook;
+        tomcatFilter = toCopy.tomcatFilter;
+        scanningIncludes = toCopy.scanningIncludes;
+        scanningExcludes = toCopy.scanningExcludes;
+        scanningPackageIncludes = toCopy.scanningPackageIncludes;
+        scanningPackageExcludes = toCopy.scanningPackageExcludes;
+        webSessionTimeout = toCopy.webSessionTimeout;
+        webSessionCookieConfig = toCopy.webSessionCookieConfig;
+        useTomcatDefaults = toCopy.useTomcatDefaults;
+        tomcatWrapLoader = toCopy.tomcatWrapLoader;
+        tomcatNoJmx = toCopy.tomcatNoJmx;
+        sharedLibraries = toCopy.sharedLibraries;
+        useLog4j2JulLogManager = toCopy.useLog4j2JulLogManager;
+        injectServletContainerInitializer = toCopy.injectServletContainerInitializer;
+        tomcatAccessLogPattern = toCopy.tomcatAccessLogPattern;
+        meecrowaveProperties = toCopy.meecrowaveProperties;
+        jaxwsSupportIfAvailable = toCopy.jaxwsSupportIfAvailable;
+        defaultSSLHostConfigName = toCopy.defaultSSLHostConfigName;
+        initializeClientBus = toCopy.initializeClientBus;
+        extensions.putAll(toCopy.extensions);
+        instanceCustomizers.addAll(toCopy.instanceCustomizers);
+        initializers = toCopy.initializers;
+        antiResourceLocking = toCopy.antiResourceLocking;
+        contextConfigurers = toCopy.contextConfigurers;
+    }
+
+    public Configuration() { // load defaults
+        extensions.put(Meecrowave.ValueTransformers.class, new Meecrowave.ValueTransformers());
+        StreamSupport.stream(ServiceLoader.load(Meecrowave.ConfigurationCustomizer.class).spliterator(), false)
+                .sorted(Priotities::sortByPriority)
+                .forEach(c -> c.accept(this));
+        loadFrom(meecrowaveProperties);
+    }
+
+    public Collection<Consumer<Tomcat>> getInstanceCustomizers() {
+        return instanceCustomizers;
+    }
+
+    public <T> T getExtension(final Class<T> extension) {
+        // in the cli we read the values from the cli but in other mode from properties
+        // to ensure we can do the same in all modes keeping a nice cli
+        return extension.cast(extensions.computeIfAbsent(extension, k -> {
+            try {
+                return bind(k.newInstance());
+            } catch (final InstantiationException | IllegalAccessException e) {
+                throw new IllegalArgumentException(e);
+            }
+        }));
+    }
+
+    public boolean isAntiResourceLocking() {
+        return antiResourceLocking;
+    }
+
+    public void setAntiResourceLocking(final boolean antiResourceLocking) {
+        this.antiResourceLocking = antiResourceLocking;
+    }
+
+    public Collection<Consumer<Context>> getGlobalContextConfigurers() {
+        return ofNullable(contextConfigurers).orElseGet(Collections::emptySet);
+    }
+
+    public boolean isTomcatJspDevelopment() {
+        return tomcatJspDevelopment;
+    }
+
+    public void setTomcatJspDevelopment(final boolean tomcatJspDevelopment) {
+        this.tomcatJspDevelopment = tomcatJspDevelopment;
+    }
+
+    public Integer getWebSessionTimeout() {
+        return webSessionTimeout;
+    }
+
+    public void setWebSessionTimeout(final Integer webSessionTimeout) {
+        this.webSessionTimeout = webSessionTimeout;
+    }
+
+    public String getWebSessionCookieConfig() {
+        return webSessionCookieConfig;
+    }
+
+    public void setWebSessionCookieConfig(final String webSessionCookieConfig) {
+        this.webSessionCookieConfig = webSessionCookieConfig;
+    }
+
+    public boolean isInitializeClientBus() {
+        return initializeClientBus;
+    }
+
+    public void setInitializeClientBus(final boolean initializeClientBus) {
+        this.initializeClientBus = initializeClientBus;
+    }
+
+    public boolean isJaxwsSupportIfAvailable() {
+        return jaxwsSupportIfAvailable;
+    }
+
+    public void setJaxwsSupportIfAvailable(final boolean jaxwsSupportIfAvailable) {
+        this.jaxwsSupportIfAvailable = jaxwsSupportIfAvailable;
+    }
+
+    public int getWatcherBouncing() {
+        return watcherBouncing;
+    }
+
+    public void setWatcherBouncing(final int watcherBouncing) {
+        this.watcherBouncing = watcherBouncing;
+    }
+
+    public String getTomcatAccessLogPattern() {
+        return tomcatAccessLogPattern;
+    }
+
+    public void setTomcatAccessLogPattern(final String tomcatAccessLogPattern) {
+        this.tomcatAccessLogPattern = tomcatAccessLogPattern;
+    }
+
+    public boolean isTomcatNoJmx() {
+        return tomcatNoJmx;
+    }
+
+    public void setTomcatNoJmx(final boolean tomcatNoJmx) {
+        this.tomcatNoJmx = tomcatNoJmx;
+    }
+
+    public File getPidFile() {
+        return pidFile;
+    }
+
+    public void setPidFile(final File pidFile) {
+        this.pidFile = pidFile;
+    }
+
+    public String getScanningPackageIncludes() {
+        return scanningPackageIncludes;
+    }
+
+    /**
+     * Define some package names (startsWith) which must get scanned for beans.
+     * This rule get's applied before {@link #setScanningPackageExcludes(String)}
+     */
+    public void setScanningPackageIncludes(final String scanningPackageIncludes) {
+        this.scanningPackageIncludes = scanningPackageIncludes;
+    }
+
+    public String getScanningPackageExcludes() {
+        return scanningPackageExcludes;
+    }
+
+    /**
+     * Define some package names (startsWith) which must <em>NOT</em> get scanned for beans.
+     * This rule get's applied after {@link #setScanningPackageIncludes(String)}.
+     *
+     * Defining just a '*' will be a marker for skipping all not-included packages.
+     * Otherwise we will defer to the standard OpenWebBeans class Filter mechanism.
+     */
+    public void setScanningPackageExcludes(final String scanningPackageExcludes) {
+        this.scanningPackageExcludes = scanningPackageExcludes;
+    }
+
+    public void setExtension(final Class<?> type, final Object value) {
+        extensions.put(type, value);
+    }
+
+    public String getScanningIncludes() {
+        return scanningIncludes;
+    }
+
+    public void setScanningIncludes(final String scanningIncludes) {
+        this.scanningIncludes = scanningIncludes;
+    }
+
+    public String getScanningExcludes() {
+        return scanningExcludes;
+    }
+
+    public void setScanningExcludes(final String scanningExcludes) {
+        this.scanningExcludes = scanningExcludes;
+    }
+
+    public String getJsonpBufferStrategy() {
+        return jsonpBufferStrategy;
+    }
+
+    public String getJsonbEncoding() {
+        return jsonbEncoding;
+    }
+
+    public void setJsonbEncoding(final String jsonbEncoding) {
+        this.jsonbEncoding = jsonbEncoding;
+    }
+
+    public boolean isJsonbNulls() {
+        return jsonbNulls;
+    }
+
+    public void setJsonbNulls(final boolean jsonbNulls) {
+        this.jsonbNulls = jsonbNulls;
+    }
+
+    public boolean isJsonbIJson() {
+        return jsonbIJson;
+    }
+
+    public void setJsonbIJson(final boolean jsonbIJson) {
+        this.jsonbIJson = jsonbIJson;
+    }
+
+    public boolean isJsonbPrettify() {
+        return jsonbPrettify;
+    }
+
+    public void setJsonbPrettify(final boolean jsonbPrettify) {
+        this.jsonbPrettify = jsonbPrettify;
+    }
+
+    public String getJsonbBinaryStrategy() {
+        return jsonbBinaryStrategy;
+    }
+
+    public void setJsonbBinaryStrategy(final String jsonbBinaryStrategy) {
+        this.jsonbBinaryStrategy = jsonbBinaryStrategy;
+    }
+
+    public String getJsonbNamingStrategy() {
+        return jsonbNamingStrategy;
+    }
+
+    public void setJsonbNamingStrategy(final String jsonbNamingStrategy) {
+        this.jsonbNamingStrategy = jsonbNamingStrategy;
+    }
+
+    public String getJsonbOrderStrategy() {
+        return jsonbOrderStrategy;
+    }
+
+    public void setJsonbOrderStrategy(final String jsonbOrderStrategy) {
+        this.jsonbOrderStrategy = jsonbOrderStrategy;
+    }
+
+    public void setJsonpBufferStrategy(final String jsonpBufferStrategy) {
+        this.jsonpBufferStrategy = jsonpBufferStrategy;
+    }
+
+    public int getJsonpMaxStringLen() {
+        return jsonpMaxStringLen;
+    }
+
+    public void setJsonpMaxStringLen(final int jsonpMaxStringLen) {
+        this.jsonpMaxStringLen = jsonpMaxStringLen;
+    }
+
+    public int getJsonpMaxReadBufferLen() {
+        return jsonpMaxReadBufferLen;
+    }
+
+    public void setJsonpMaxReadBufferLen(final int jsonpMaxReadBufferLen) {
+        this.jsonpMaxReadBufferLen = jsonpMaxReadBufferLen;
+    }
+
+    public int getJsonpMaxWriteBufferLen() {
+        return jsonpMaxWriteBufferLen;
+    }
+
+    public void setJsonpMaxWriteBufferLen(final int jsonpMaxWriteBufferLen) {
+        this.jsonpMaxWriteBufferLen = jsonpMaxWriteBufferLen;
+    }
+
+    public boolean isJsonpSupportsComment() {
+        return jsonpSupportsComment;
+    }
+
+    public void setJsonpSupportsComment(final boolean jsonpSupportsComment) {
+        this.jsonpSupportsComment = jsonpSupportsComment;
+    }
+
+    public boolean isJsonpPrettify() {
+        return jsonpPrettify;
+    }
+
+    public void setJsonpPrettify(final boolean jsonpPrettify) {
+        this.jsonpPrettify = jsonpPrettify;
+    }
+
+    public String getSharedLibraries() {
+        return sharedLibraries;
+    }
+
+    public void setSharedLibraries(final String sharedLibraries) {
+        this.sharedLibraries = sharedLibraries;
+    }
+
+    public boolean isJaxrsLogProviders() {
+        return jaxrsLogProviders;
+    }
+
+    public void setJaxrsLogProviders(final boolean jaxrsLogProviders) {
+        this.jaxrsLogProviders = jaxrsLogProviders;
+    }
+
+    public boolean isUseTomcatDefaults() {
+        return useTomcatDefaults;
+    }
+
+    public void setUseTomcatDefaults(final boolean useTomcatDefaults) {
+        this.useTomcatDefaults = useTomcatDefaults;
+    }
+
+    public String getTomcatFilter() {
+        return tomcatFilter;
+    }
+
+    public void setTomcatFilter(final String tomcatFilter) {
+        this.tomcatFilter = tomcatFilter;
+    }
+
+    public boolean isTomcatScanning() {
+        return tomcatScanning;
+    }
+
+    public void setTomcatScanning(final boolean tomcatScanning) {
+        this.tomcatScanning = tomcatScanning;
+    }
+
+    public Map<String, String> getCxfServletParams() {
+        return cxfServletParams;
+    }
+
+    public void setCxfServletParams(final Map<String, String> cxfServletParams) {
+        this.cxfServletParams = cxfServletParams;
+    }
+
+    public boolean isLoggingGlobalSetup() {
+        return loggingGlobalSetup;
+    }
+
+    public void setLoggingGlobalSetup(final boolean loggingGlobalSetup) {
+        this.loggingGlobalSetup = loggingGlobalSetup;
+    }
+
+    public boolean isJaxrsAutoActivateBeanValidation() {
+        return jaxrsAutoActivateBeanValidation;
+    }
+
+    public void setJaxrsAutoActivateBeanValidation(final boolean jaxrsAutoActivateBeanValidation) {
+        this.jaxrsAutoActivateBeanValidation = jaxrsAutoActivateBeanValidation;
+    }
+
+    public boolean isJaxrsProviderSetup() {
+        return jaxrsProviderSetup;
+    }
+
+    public void setJaxrsProviderSetup(final boolean jaxrsProviderSetup) {
+        this.jaxrsProviderSetup = jaxrsProviderSetup;
+    }
+
+    public int getHttpPort() {
+        return httpPort;
+    }
+
+    public void setHttpPort(final int httpPort) {
+        this.httpPort = httpPort;
+    }
+
+    public int getHttpsPort() {
+        return httpsPort;
+    }
+
+    public void setHttpsPort(final int httpsPort) {
+        this.httpsPort = httpsPort;
+    }
+
+    public int getStopPort() {
+        return stopPort;
+    }
+
+    public void setStopPort(final int stopPort) {
+        this.stopPort = stopPort;
+    }
+
+    public String getHost() {
+        return host;
+    }
+
+    public void setHost(final String host) {
+        this.host = host;
+    }
+
+    public String getDir() {
+        return dir;
+    }
+
+    public void setDir(final String dir) {
+        this.dir = dir;
+    }
+
+    public File getServerXml() {
+        return serverXml;
+    }
+
+    public void setServerXml(final File serverXml) {
+        this.serverXml = serverXml;
+    }
+
+    public boolean isKeepServerXmlAsThis() {
+        return keepServerXmlAsThis;
+    }
+
+    public void setKeepServerXmlAsThis(final boolean keepServerXmlAsThis) {
+        this.keepServerXmlAsThis = keepServerXmlAsThis;
+    }
+
+    public Properties getProperties() {
+        return properties;
+    }
+
+    public void setProperties(final Properties properties) {
+        this.properties = properties;
+    }
+
+    public boolean isQuickSession() {
+        return quickSession;
+    }
+
+    public void setQuickSession(final boolean quickSession) {
+        this.quickSession = quickSession;
+    }
+
+    public boolean isSkipHttp() {
+        return skipHttp;
+    }
+
+    public void setSkipHttp(final boolean skipHttp) {
+        this.skipHttp = skipHttp;
+    }
+
+    public boolean isSsl() {
+        return ssl;
+    }
+
+    public void setSsl(final boolean ssl) {
+        this.ssl = ssl;
+    }
+
+    public String getKeystoreFile() {
+        return keystoreFile;
+    }
+
+    public void setKeystoreFile(final String keystoreFile) {
+        this.keystoreFile = keystoreFile;
+    }
+
+    public String getKeystorePass() {
+        return keystorePass;
+    }
+
+    public void setKeystorePass(final String keystorePass) {
+        this.keystorePass = keystorePass;
+    }
+
+    public String getKeystoreType() {
+        return keystoreType;
+    }
+
+    public void setKeystoreType(final String keystoreType) {
+        this.keystoreType = keystoreType;
+    }
+
+    public String getClientAuth() {
+        return clientAuth;
+    }
+
+    public void setClientAuth(final String clientAuth) {
+        this.clientAuth = clientAuth;
+    }
+
+    public String getKeyAlias() {
+        return keyAlias;
+    }
+
+    public void setKeyAlias(final String keyAlias) {
+        this.keyAlias = keyAlias;
+    }
+
+    public String getSslProtocol() {
+        return sslProtocol;
+    }
+
+    public void setSslProtocol(final String sslProtocol) {
+        this.sslProtocol = sslProtocol;
+    }
+
+    public String getWebXml() {
+        return webXml;
+    }
+
+    public void setWebXml(final String webXml) {
+        this.webXml = webXml;
+    }
+
+    public Meecrowave.LoginConfigBuilder getLoginConfig() {
+        return loginConfig;
+    }
+
+    public void setLoginConfig(final Meecrowave.LoginConfigBuilder loginConfig) {
+        this.loginConfig = loginConfig;
+    }
+
+    public Collection<Meecrowave.SecurityConstaintBuilder> getSecurityConstraints() {
+        return securityConstraints;
+    }
+
+    public void setSecurityConstraints(final Collection<Meecrowave.SecurityConstaintBuilder> securityConstraints) {
+        this.securityConstraints = securityConstraints;
+    }
+
+    public Realm getRealm() {
+        return realm;
+    }
+
+    public void setRealm(final Realm realm) {
+        this.realm = realm;
+    }
+
+    public Map<String, String> getUsers() {
+        return users;
+    }
+
+    public void setUsers(final Map<String, String> users) {
+        this.users = users;
+    }
+
+    public Map<String, String> getRoles() {
+        return roles;
+    }
+
+    public void setRoles(final Map<String, String> roles) {
+        this.roles = roles;
+    }
+
+    public boolean isHttp2() {
+        return http2;
+    }
+
+    public void setHttp2(final boolean http2) {
+        this.http2 = http2;
+    }
+
+    public Collection<Connector> getConnectors() {
+        return connectors;
+    }
+
+    public String getTempDir() {
+        return tempDir;
+    }
+
+    public void setTempDir(final String tempDir) {
+        this.tempDir = tempDir;
+    }
+
+    public boolean isWebResourceCached() {
+        return webResourceCached;
+    }
+
+    public void setWebResourceCached(final boolean webResourceCached) {
+        this.webResourceCached = webResourceCached;
+    }
+
+    public String getConf() {
+        return conf;
+    }
+
+    public void setConf(final String conf) {
+        this.conf = conf;
+    }
+
+    public boolean isDeleteBaseOnStartup() {
+        return deleteBaseOnStartup;
+    }
+
+    public void setDeleteBaseOnStartup(final boolean deleteBaseOnStartup) {
+        this.deleteBaseOnStartup = deleteBaseOnStartup;
+    }
+
+    public String getJaxrsMapping() {
+        return jaxrsMapping;
+    }
+
+    public void setJaxrsMapping(final String jaxrsMapping) {
+        this.jaxrsMapping = jaxrsMapping;
+    }
+
+    public boolean isCdiConversation() {
+        return cdiConversation;
+    }
+
+    public void setCdiConversation(final boolean cdiConversation) {
+        this.cdiConversation = cdiConversation;
+    }
+
+    public void setServerXml(final String file) {
+        if (file == null) {
+            serverXml = null;
+        } else {
+            final File sXml = new File(file);
+            if (sXml.exists()) {
+                serverXml = sXml;
+            }
+        }
+    }
+
+    public String getActiveProtocol() {
+        return isSkipHttp() ? "https" : "http";
+    }
+
+    public int getActivePort() {
+        return isSkipHttp() ? getHttpsPort() : getHttpPort();
+    }
+
+    public boolean isTomcatAutoSetup() {
+        return tomcatAutoSetup;
+    }
+
+    public void setTomcatAutoSetup(final boolean tomcatAutoSetup) {
+        this.tomcatAutoSetup = tomcatAutoSetup;
+    }
+
+    public boolean isUseShutdownHook() {
+        return useShutdownHook;
+    }
+
+    public void setUseShutdownHook(final boolean useShutdownHook) {
+        this.useShutdownHook = useShutdownHook;
+    }
+
+    public boolean isTomcatWrapLoader() {
+        return tomcatWrapLoader;
+    }
+
+    public void setTomcatWrapLoader(final boolean tomcatWrapLoader) {
+        this.tomcatWrapLoader = tomcatWrapLoader;
+    }
+
+    public void addInstanceCustomizer(final Consumer<Tomcat> customizer) {
+        instanceCustomizers.add(customizer);
+    }
+
+    public void addCustomizer(final Consumer<Configuration> configurationCustomizer) {
+        configurationCustomizer.accept(this);
+    }
+
+    public void addGlobalContextCustomizer(final Consumer<Context> contextConfigurer) {
+        if (contextConfigurers == null) {
+            contextConfigurers = new ArrayList<>();
+        }
+        contextConfigurers.add(contextConfigurer);
+    }
+
+    public void addServletContextInitializer(final ServletContainerInitializer initializer) {
+        initializers.add(initializer);
+    }
+
+    public Collection<ServletContainerInitializer> getInitializers() {
+        return initializers;
+    }
+
+    public String getJaxrsDefaultProviders() {
+        return jaxrsDefaultProviders;
+    }
+
+    public void setJaxrsDefaultProviders(final String jaxrsDefaultProviders) {
+        this.jaxrsDefaultProviders = jaxrsDefaultProviders;
+    }
+
+    public boolean isUseLog4j2JulLogManager() {
+        return useLog4j2JulLogManager;
+    }
+
+    public void setUseLog4j2JulLogManager(final boolean useLog4j2JulLogManager) {
+        this.useLog4j2JulLogManager = useLog4j2JulLogManager;
+    }
+
+    public String getDefaultSSLHostConfigName() {
+        return defaultSSLHostConfigName;
+    }
+
+    public void setDefaultSSLHostConfigName(final String defaultSSLHostConfigName) {
+        this.defaultSSLHostConfigName = defaultSSLHostConfigName;
+    }
+
+    public void loadFromProperties(final Properties config) {
+        // filtering properties with system properties or themself
+        final Substitutor strSubstitutor = new Substitutor(emptyMap()) {
+            @Override
+            public String getOrDefault(final String key, final String or) {
+                final String property = System.getProperty(key);
+                return property == null ? config.getProperty(key, or) : or;
+            }
+        };
+
+        final Meecrowave.ValueTransformers transformers = getExtension(Meecrowave.ValueTransformers.class);
+        for (final String key : config.stringPropertyNames()) {
+            final String val = config.getProperty(key);
+            if (val == null || val.trim().isEmpty()) {
+                continue;
+            }
+            final String newVal = transformers.apply(strSubstitutor.replace(config.getProperty(key)));
+            if (!val.equals(newVal)) {
+                config.setProperty(key, newVal);
+            }
+        }
+
+        for (final Field field : Configuration.class.getDeclaredFields()) {
+            final CliOption annotation = field.getAnnotation(CliOption.class);
+            if (annotation == null) {
+                continue;
+            }
+            final String name = field.getName();
+            Stream.of(Stream.of(annotation.name()), Stream.of(annotation.alias()))
+                    .flatMap(a -> a)
+                    .map(config::getProperty)
+                    .filter(Objects::nonNull)
+                    .findAny().ifPresent(val -> {
+                final Object toSet;
+                if (field.getType() == String.class) {
+                    toSet = val;
+                } else if (field.getType() == int.class) {
+                    if ("httpPort".equals(name) && "-1".equals(val)) { // special case in case of random port
+                        try (final ServerSocket serverSocket = new ServerSocket(0)) {
+                            setHttpPort(serverSocket.getLocalPort());
+                        } catch (final IOException e) {
+                            throw new IllegalStateException(e);
+                        }
+                        toSet = null;
+                    } else {
+                        toSet = Integer.parseInt(val);
+                    }
+                } else if (field.getType() == boolean.class) {
+                    toSet = Boolean.parseBoolean(val);
+                } else if (field.getType() == File.class) {
+                    toSet = new File(val);
+                } else {
+                    toSet = null;
+                }
+                if (toSet == null) { // handled elsewhere
+                    return;
+                }
+
+                if (!field.isAccessible()) {
+                    field.setAccessible(true);
+                }
+                try {
+                    field.set(this, toSet);
+                } catch (final IllegalAccessException e) {
+                    throw new IllegalStateException(e);
+                }
+            });
+        }
+
+        // not trivial types
+        for (final String prop : config.stringPropertyNames()) {
+            if (prop.startsWith("properties.")) {
+                getProperties().setProperty(prop.substring("properties.".length()), config.getProperty(prop));
+            } else if (prop.startsWith("users.")) {
+                if (users == null) {
+                    users = new HashMap<>();
+                }
+                users.put(prop.substring("users.".length()), config.getProperty(prop));
+            } else if (prop.startsWith("roles.")) {
+                if (roles == null) {
+                    roles = new HashMap<>();
+                }
+                roles.put(prop.substring("roles.".length()), config.getProperty(prop));
+            } else if (prop.startsWith("cxf.servlet.params.")) {
+                if (cxfServletParams == null) {
+                    cxfServletParams = new HashMap<>();
+                }
+                cxfServletParams.put(prop.substring("cxf.servlet.params.".length()), config.getProperty(prop));
+            } else if (prop.startsWith("connector.")) { // created in container
+                getProperties().setProperty(prop, config.getProperty(prop));
+            } else if (prop.equals("realm")) {
+                final ObjectRecipe recipe = newRecipe(config.getProperty(prop));
+                for (final String realmConfig : config.stringPropertyNames()) {
+                    if (realmConfig.startsWith("realm.")) {
+                        recipe.setProperty(realmConfig.substring("realm.".length()), config.getProperty(realmConfig));
+                    }
+                }
+                this.realm = Realm.class.cast(recipe.create());
+            } else if (prop.equals("login")) {
+                final ObjectRecipe recipe = newRecipe(Meecrowave.LoginConfigBuilder.class.getName());
+                for (final String nestedConfig : config.stringPropertyNames()) {
+                    if (nestedConfig.startsWith("login.")) {
+                        recipe.setProperty(nestedConfig.substring("login.".length()), config.getProperty(nestedConfig));
+                    }
+                }
+                loginConfig = Meecrowave.LoginConfigBuilder.class.cast(recipe.create());
+            } else if (prop.equals("securityConstraint")) {
+                final ObjectRecipe recipe = newRecipe(Meecrowave.SecurityConstaintBuilder.class.getName());
+                for (final String nestedConfig : config.stringPropertyNames()) {
+                    if (nestedConfig.startsWith("securityConstraint.")) {
+                        recipe.setProperty(nestedConfig.substring("securityConstraint.".length()), config.getProperty(nestedConfig));
+                    }
+                }
+                securityConstraints.add(Meecrowave.SecurityConstaintBuilder.class.cast(recipe.create()));
+            } else if (prop.equals("configurationCustomizer")) {
+                final ObjectRecipe recipe = newRecipe(prop);
+                for (final String nestedConfig : config.stringPropertyNames()) {
+                    if (nestedConfig.startsWith(prop + '.')) {
+                        recipe.setProperty(nestedConfig.substring(prop.length() + 2 /*dot*/), config.getProperty(nestedConfig));
+                    }
+                }
+                addCustomizer(Consumer.class.cast(recipe.create()));
+            }
+        }
+    }
+
+    public <T> T bind(final T instance) {
+        final Meecrowave.ValueTransformers transformers = getExtension(Meecrowave.ValueTransformers.class);
+        Class<?> type = instance.getClass();
+        do {
+            Stream.of(type.getDeclaredFields())
+                    .filter(f -> f.isAnnotationPresent(CliOption.class))
+                    .forEach(f -> {
+                        final CliOption annotation = f.getAnnotation(CliOption.class);
+                        String value = properties.getProperty(annotation.name());
+                        if (value == null) {
+                            value = Stream.of(annotation.alias()).map(properties::getProperty).findFirst().orElse(null);
+                            if (value == null) {
+                                return;
+                            }
+                        }
+
+                        value = transformers.apply(value);
+
+                        if (!f.isAccessible()) {
+                            f.setAccessible(true);
+                        }
+                        final Class<?> t = f.getType();
+                        try {
+                            if (t == String.class) {
+                                f.set(instance, value);
+                            } else if (t == int.class) {
+                                f.set(instance, Integer.parseInt(value));
+                            } else if (t == boolean.class) {
+                                f.set(instance, Boolean.parseBoolean(value));
+                            } else {
+                                throw new IllegalArgumentException("Unsupported type " + t);
+                            }
+                        } catch (final IllegalAccessException iae) {
+                            throw new IllegalStateException(iae);
+                        }
+                    });
+            type = type.getSuperclass();
+        } while (type != Object.class);
+        return instance;
+    }
+
+    public boolean isInjectServletContainerInitializer() {
+        return injectServletContainerInitializer;
+    }
+
+    public void setInjectServletContainerInitializer(final boolean injectServletContainerInitializer) {
+        this.injectServletContainerInitializer = injectServletContainerInitializer;
+    }
+
+    public String getMeecrowaveProperties() {
+        return meecrowaveProperties;
+    }
+
+    public void setMeecrowaveProperties(final String meecrowaveProperties) {
+        this.meecrowaveProperties = meecrowaveProperties;
+    }
+
+    private Properties mergeProperties(final String resource, final List<Properties> sortedProperties) {
+        Properties mergedProperties = new Properties();
+        Properties master = null;
+        for (final Properties p : sortedProperties)
+        {
+            if (Boolean.parseBoolean(p.getProperty("configuration.complete", "false"))) {
+                if (master != null) {
+                    throw new IllegalArgumentException("Ambiguous '" + resource + "', " +
+                            "multiple " + resource + " with configuration.complete=true");
+                }
+                master = p;
+            }
+            mergedProperties.putAll(p);
+        }
+
+        if (master != null) {
+            return master;
+        }
+        return mergedProperties;
+    }
+
+    public Configuration loadFrom(final String resource) {
+        // load all of those files on the classpath, sorted by ordinal
+        Properties config = PropertyLoader.getProperties(resource,
+                sortedProperties -> mergeProperties(resource, sortedProperties),
+                () -> {});
+        if (config == null || config.isEmpty()) {
+            final File file = new File(resource);
+            if (file.exists()) {
+                config = new Properties();
+                try (InputStream is = new FileInputStream(file)) {
+                    config.load(is);
+                }
+                catch (IOException e) {
+                    throw new IllegalStateException(e);
+                }
+            }
+        }
+        if (config != null) {
+            loadFromProperties(config);
+        }
+        return this;
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!Configuration.class.isInstance(o) /*tolerate builder*/) {
+            return false;
+        }
+        final Configuration that = Configuration.class.cast(o);
+        return watcherBouncing == that.watcherBouncing &&
+                httpPort == that.httpPort &&
+                httpsPort == that.httpsPort &&
+                stopPort == that.stopPort &&
+                keepServerXmlAsThis == that.keepServerXmlAsThis &&
+                quickSession == that.quickSession &&
+                skipHttp == that.skipHttp &&
+                ssl == that.ssl &&
+                http2 == that.http2 &&
+                webResourceCached == that.webResourceCached &&
+                deleteBaseOnStartup == that.deleteBaseOnStartup &&
+                cdiConversation == that.cdiConversation &&
+                jaxrsProviderSetup == that.jaxrsProviderSetup &&
+                jaxrsAutoActivateBeanValidation == that.jaxrsAutoActivateBeanValidation &&
+                jaxrsLogProviders == that.jaxrsLogProviders &&
+                jsonpMaxStringLen == that.jsonpMaxStringLen &&
+                jsonpMaxReadBufferLen == that.jsonpMaxReadBufferLen &&
+                jsonpMaxWriteBufferLen == that.jsonpMaxWriteBufferLen &&
+                jsonpSupportsComment == that.jsonpSupportsComment &&
+                jsonpPrettify == that.jsonpPrettify &&
+                jsonbNulls == that.jsonbNulls &&
+                jsonbIJson == that.jsonbIJson &&
+                jsonbPrettify == that.jsonbPrettify &&
+                loggingGlobalSetup == that.loggingGlobalSetup &&
+                tomcatScanning == that.tomcatScanning &&
+                tomcatAutoSetup == that.tomcatAutoSetup &&
+                tomcatJspDevelopment == that.tomcatJspDevelopment &&
+                useShutdownHook == that.useShutdownHook &&
+                useTomcatDefaults == that.useTomcatDefaults &&
+                tomcatWrapLoader == that.tomcatWrapLoader &&
+                tomcatNoJmx == that.tomcatNoJmx &&
+                useLog4j2JulLogManager == that.useLog4j2JulLogManager &&
+                injectServletContainerInitializer == that.injectServletContainerInitializer &&
+                jaxwsSupportIfAvailable == that.jaxwsSupportIfAvailable &&
+                initializeClientBus == that.initializeClientBus &&
+                antiResourceLocking == that.antiResourceLocking &&
+                Objects.equals(pidFile, that.pidFile) &&
+                Objects.equals(host, that.host) &&
+                Objects.equals(dir, that.dir) &&
+                Objects.equals(serverXml, that.serverXml) &&
+                Objects.equals(properties, that.properties) &&
+                Objects.equals(keystoreFile, that.keystoreFile) &&
+                Objects.equals(keystorePass, that.keystorePass) &&
+                Objects.equals(keystoreType, that.keystoreType) &&
+                Objects.equals(clientAuth, that.clientAuth) &&
+                Objects.equals(keyAlias, that.keyAlias) &&
+                Objects.equals(sslProtocol, that.sslProtocol) &&
+                Objects.equals(webXml, that.webXml) &&
+                Objects.equals(loginConfig, that.loginConfig) &&
+                Objects.equals(securityConstraints, that.securityConstraints) &&
+                Objects.equals(realm, that.realm) &&
+                Objects.equals(users, that.users) &&
+                Objects.equals(roles, that.roles) &&
+                Objects.equals(connectors, that.connectors) &&
+                Objects.equals(tempDir, that.tempDir) &&
+                Objects.equals(conf, that.conf) &&
+                Objects.equals(jaxrsMapping, that.jaxrsMapping) &&
+                Objects.equals(jaxrsDefaultProviders, that.jaxrsDefaultProviders) &&
+                Objects.equals(jsonpBufferStrategy, that.jsonpBufferStrategy) &&
+                Objects.equals(jsonbEncoding, that.jsonbEncoding) &&
+                Objects.equals(jsonbBinaryStrategy, that.jsonbBinaryStrategy) &&
+                Objects.equals(jsonbNamingStrategy, that.jsonbNamingStrategy) &&
+                Objects.equals(jsonbOrderStrategy, that.jsonbOrderStrategy) &&
+                Objects.equals(cxfServletParams, that.cxfServletParams) &&
+                Objects.equals(tomcatFilter, that.tomcatFilter) &&
+                Objects.equals(scanningIncludes, that.scanningIncludes) &&
+                Objects.equals(scanningExcludes, that.scanningExcludes) &&
+                Objects.equals(scanningPackageIncludes, that.scanningPackageIncludes) &&
+                Objects.equals(scanningPackageExcludes, that.scanningPackageExcludes) &&
+                Objects.equals(webSessionTimeout, that.webSessionTimeout) &&
+                Objects.equals(webSessionCookieConfig, that.webSessionCookieConfig) &&
+                Objects.equals(sharedLibraries, that.sharedLibraries) &&
+                Objects.equals(tomcatAccessLogPattern, that.tomcatAccessLogPattern) &&
+                Objects.equals(meecrowaveProperties, that.meecrowaveProperties) &&
+                Objects.equals(defaultSSLHostConfigName, that.defaultSSLHostConfigName) &&
+                Objects.equals(extensions, that.extensions) &&
+                Objects.equals(instanceCustomizers, that.instanceCustomizers) &&
+                Objects.equals(initializers, that.initializers) &&
+                Objects.equals(contextConfigurers, that.contextConfigurers);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(pidFile, watcherBouncing, httpPort, httpsPort, stopPort, host, dir, serverXml, keepServerXmlAsThis, properties, quickSession, skipHttp, ssl, keystoreFile, keystorePass, keystoreType, clientAuth, keyAlias, sslProtocol, webXml, loginConfig, securityConstraints, realm, users, roles, http2, connectors, tempDir, webResourceCached, conf, deleteBaseOnStartup, jaxrsMapping, cdiConversation, jaxrsProviderSetup, jaxrsDefaultProviders, jaxrsAutoActivateBeanValidation, jaxrsLogProviders, jsonpBufferStrategy, jsonpMaxStringLen, jsonpMaxReadBufferLen, jsonpMaxWriteBufferLen, jsonpSupportsComment, jsonpPrettify, jsonbEncoding, jsonbNulls, jsonbIJson, jsonbPrettify, jsonbBinaryStrategy, jsonbNamingStrategy, jsonbOrderStrategy, loggingGlobalSetup, cxfServletParams, tomcatScanning, tomcatAutoSetup, tomcatJspDevelopment, useShutdownHook, tomcatFilter, scanningIncludes, scanningExcludes, scanningPackageIncludes, scanningPackageExcludes, webSessionTimeout, webSessionCookieConfig, useTomcatDefaults, tomcatWrapLoader, tomcatNoJmx, sharedLibraries, useLog4j2JulLogManager, injectServletContainerInitializer, tomcatAccessLogPattern, meecrowaveProperties, jaxwsSupportIfAvailable, defaultSSLHostConfigName, initializeClientBus, extensions, instanceCustomizers, initializers, antiResourceLocking, contextConfigurers);
+    }
+
+    private static ObjectRecipe newRecipe(final String clazz) {
+        final ObjectRecipe recipe = new ObjectRecipe(clazz);
+        recipe.allow(Option.FIELD_INJECTION);
+        recipe.allow(Option.PRIVATE_PROPERTIES);
+        return recipe;
+    }
+}
diff --git a/meecrowave-core/src/main/java/org/apache/meecrowave/cxf/ConfigurableBus.java b/meecrowave-core/src/main/java/org/apache/meecrowave/cxf/ConfigurableBus.java
index 6b2a3ff..11dc8c2 100644
--- a/meecrowave-core/src/main/java/org/apache/meecrowave/cxf/ConfigurableBus.java
+++ b/meecrowave-core/src/main/java/org/apache/meecrowave/cxf/ConfigurableBus.java
@@ -75,10 +75,10 @@
 import org.apache.johnzon.jaxrs.JsrMessageBodyReader;
 import org.apache.johnzon.jaxrs.JsrMessageBodyWriter;
 import org.apache.johnzon.jaxrs.jsonb.jaxrs.JsonbJaxrsProvider;
-import org.apache.meecrowave.Meecrowave;
+import org.apache.meecrowave.configuration.Configuration;
 
 public class ConfigurableBus extends ExtensionManagerBus {
-    public void initProviders(final Meecrowave.Builder builder,
+    public void initProviders(final Configuration builder,
                               final ClassLoader loader) {
         final List<Object> providers =
                 ofNullable(builder.getJaxrsDefaultProviders())
diff --git a/meecrowave-core/src/main/java/org/apache/meecrowave/cxf/CxfCdiAutoSetup.java b/meecrowave-core/src/main/java/org/apache/meecrowave/cxf/CxfCdiAutoSetup.java
index f1477d5..dc7555e 100644
--- a/meecrowave-core/src/main/java/org/apache/meecrowave/cxf/CxfCdiAutoSetup.java
+++ b/meecrowave-core/src/main/java/org/apache/meecrowave/cxf/CxfCdiAutoSetup.java
@@ -34,6 +34,7 @@
 import org.apache.cxf.transport.http.DestinationRegistry;
 import org.apache.cxf.transport.servlet.ServletDestination;
 import org.apache.meecrowave.Meecrowave;
+import org.apache.meecrowave.configuration.Configuration;
 import org.apache.meecrowave.logging.tomcat.LogFacade;
 
 import javax.servlet.DispatcherType;
@@ -76,8 +77,8 @@
     private static final String NAME = "cxf-cdi";
 
     @Override
-    public void onStartup(final Set<Class<?>> c, final ServletContext ctx) throws ServletException {
-        final Meecrowave.Builder builder = Meecrowave.Builder.class.cast(ctx.getAttribute("meecrowave.configuration"));
+    public void onStartup(final Set<Class<?>> c, final ServletContext ctx) {
+        final Configuration builder = Configuration.class.cast(ctx.getAttribute("meecrowave.configuration"));
         final MeecrowaveCXFCdiServlet delegate = new MeecrowaveCXFCdiServlet();
         final FilterRegistration.Dynamic jaxrs = ctx.addFilter(NAME, new Filter() {
             private final String servletPath = builder.getJaxrsMapping().endsWith("/*") ?
@@ -403,7 +404,7 @@
                     resourcesToLog.clear();
 
                     // log @Providers
-                    if (Meecrowave.Builder.class.cast(sc.getServletContext().getAttribute("meecrowave.configuration")).isJaxrsLogProviders()) {
+                    if (Configuration.class.cast(sc.getServletContext().getAttribute("meecrowave.configuration")).isJaxrsLogProviders()) {
                         final ServerProviderFactory spf = ServerProviderFactory.class.cast(endpoint.get(ServerProviderFactory.class.getName()));
                         dump(log, spf, "MessageBodyReaders", "messageReaders");
                         dump(log, spf, "MessageBodyWriters", "messageWriters");
diff --git a/meecrowave-core/src/main/java/org/apache/meecrowave/cxf/JAXWSCdiExtension.java b/meecrowave-core/src/main/java/org/apache/meecrowave/cxf/JAXWSCdiExtension.java
index 9b345c3..2065122 100644
--- a/meecrowave-core/src/main/java/org/apache/meecrowave/cxf/JAXWSCdiExtension.java
+++ b/meecrowave-core/src/main/java/org/apache/meecrowave/cxf/JAXWSCdiExtension.java
@@ -18,7 +18,7 @@
  */
 package org.apache.meecrowave.cxf;
 
-import org.apache.meecrowave.Meecrowave;
+import org.apache.meecrowave.configuration.Configuration;
 import org.apache.meecrowave.logging.tomcat.LogFacade;
 import org.apache.webbeans.component.OwbBean;
 
@@ -82,7 +82,7 @@
 
         public void load(@Observes final AfterDeploymentValidation afterDeploymentValidation, final BeanManager beanManager) {
             if (!active || serviceBeans.isEmpty() ||
-                    !Meecrowave.Builder.class.cast(beanManager.getReference(beanManager.resolve(beanManager.getBeans(Meecrowave.Builder.class)), Meecrowave.Builder.class, null))
+                    !Configuration.class.cast(beanManager.getReference(beanManager.resolve(beanManager.getBeans(Configuration.class)), Configuration.class, null))
                                              .isJaxwsSupportIfAvailable()) {
                 return;
             }
diff --git a/meecrowave-core/src/main/java/org/apache/meecrowave/cxf/MeecrowaveBus.java b/meecrowave-core/src/main/java/org/apache/meecrowave/cxf/MeecrowaveBus.java
index cf73320..284e73c 100644
--- a/meecrowave-core/src/main/java/org/apache/meecrowave/cxf/MeecrowaveBus.java
+++ b/meecrowave-core/src/main/java/org/apache/meecrowave/cxf/MeecrowaveBus.java
@@ -34,6 +34,7 @@
 import org.apache.cxf.interceptor.Interceptor;
 import org.apache.cxf.message.Message;
 import org.apache.meecrowave.Meecrowave;
+import org.apache.meecrowave.configuration.Configuration;
 
 @Named("cxf")
 @Typed({MeecrowaveBus.class, Bus.class})
@@ -50,7 +51,7 @@
         final ClassLoader appLoader = context.getClassLoader();
 
         final Meecrowave meecrowave = Meecrowave.class.cast(context.getAttribute("meecrowave.instance"));
-        final Meecrowave.Builder builder = Meecrowave.Builder.class.cast(context.getAttribute("meecrowave.configuration"));
+        final Configuration builder = Configuration.class.cast(context.getAttribute("meecrowave.configuration"));
         if (meecrowave.getClientBus() == null) {
             delegate = new ConfigurableBus();
             if (builder != null && builder.isJaxrsProviderSetup()) {
diff --git a/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/KnownClassesFilter.java b/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/KnownClassesFilter.java
index 5b24649..0cf0498 100644
--- a/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/KnownClassesFilter.java
+++ b/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/KnownClassesFilter.java
@@ -18,7 +18,7 @@
  */
 package org.apache.meecrowave.openwebbeans;
 
-import org.apache.meecrowave.Meecrowave;
+import org.apache.meecrowave.configuration.Configuration;
 import org.apache.xbean.finder.filter.Filter;
 
 import java.util.HashSet;
@@ -171,7 +171,7 @@
         delegateAccept = new OptimizedExclusionFilter(included);
     }
 
-    public void init(final Meecrowave.Builder config) {
+    public void init(final Configuration config) {
         forced = buildArray(config.getScanningPackageIncludes()).orElse(forced);
         skipped = buildArray(config.getScanningPackageExcludes()).orElse(skipped);
 
diff --git a/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/KnownJarsFilter.java b/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/KnownJarsFilter.java
index 3d7d15d..9153d90 100644
--- a/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/KnownJarsFilter.java
+++ b/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/KnownJarsFilter.java
@@ -25,7 +25,7 @@
 import java.util.HashSet;
 import java.util.stream.Stream;
 
-import org.apache.meecrowave.Meecrowave;
+import org.apache.meecrowave.configuration.Configuration;
 import org.apache.tomcat.JarScanFilter;
 import org.apache.tomcat.JarScanType;
 
@@ -362,7 +362,7 @@
         // no-op
     }
 
-    KnownJarsFilter(final Meecrowave.Builder config) {
+    KnownJarsFilter(final Configuration config) {
         ofNullable(config.getScanningIncludes()).ifPresent(i -> {
             forceIncludes.clear();
             forceIncludes.addAll(Stream.of(i.split(",")).map(String::trim).filter(j -> !j.isEmpty()).collect(toSet()));
diff --git a/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/MeecrowaveExtension.java b/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/MeecrowaveExtension.java
index a944bd5..2acc0eb 100644
--- a/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/MeecrowaveExtension.java
+++ b/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/MeecrowaveExtension.java
@@ -41,20 +41,46 @@
 
     void addBeansFromJava(@Observes final BeforeBeanDiscovery bbd, final BeanManager bm) {
         if (Cxfs.IS_PRESENT) {
-            // stream not really needed but here for the pattern in case we need other beans
-            Stream.of(MeecrowaveBus.class)
+            bbd.addInterceptorBinding(JAXRSFieldInjectionInterceptor.Binding.class);
+
+            Stream.of(MeecrowaveBus.class, JAXRSFieldInjectionInterceptor.class)
                   .forEach(type -> bbd.addAnnotatedType(bm.createAnnotatedType(type)));
         }
     }
 
-    void enableContextFieldInjectionWorks(@Observes final ProcessAnnotatedType<?> pat, final BeanManager bm) {
+    void onPat(@Observes final ProcessAnnotatedType<?> pat, final BeanManager bm) {
         final AnnotatedType<?> at = pat.getAnnotatedType();
-        if (Cxfs.IS_PRESENT
+        if (isJaxRsEndpoint(bm, at)) {
+            pat.setAnnotatedType(new JAXRSFIeldInjectionAT(this, at));
+        } else if (isVetoedMeecrowaveCore(at.getJavaClass().getName())) {
+            pat.veto();
+        }
+    }
+
+    private boolean isJaxRsEndpoint(final BeanManager bm, final AnnotatedType<?> at) {
+        return Cxfs.IS_PRESENT
                 && at.isAnnotationPresent(Path.class)
                 && !at.isAnnotationPresent(JAXRSFieldInjectionInterceptor.Binding.class)
-                && at.getAnnotations().stream().anyMatch(a -> bm.isNormalScope(a.annotationType()))) {
-            pat.setAnnotatedType(new JAXRSFIeldInjectionAT(this, at));
-        }
+                && at.getAnnotations().stream().anyMatch(a -> bm.isNormalScope(a.annotationType()));
+    }
+
+    // for fatjars
+    private boolean isVetoedMeecrowaveCore(final String name) {
+        return !"org.apache.meecrowave.cxf.MeecrowaveBus".equals(name)
+                && !"org.apache.meecrowave.cxf.JAXRSFieldInjectionInterceptor".equals(name)
+                && (name.startsWith("org.apache.meecrowave.api.")
+                    || name.startsWith("org.apache.meecrowave.cdi.")
+                    || name.startsWith("org.apache.meecrowave.configuration.")
+                    || name.startsWith("org.apache.meecrowave.cxf.")
+                    || name.startsWith("org.apache.meecrowave.io.")
+                    || name.startsWith("org.apache.meecrowave.lang.")
+                    || name.startsWith("org.apache.meecrowave.logging.")
+                    || name.startsWith("org.apache.meecrowave.openwebbeans.")
+                    || name.startsWith("org.apache.meecrowave.runner.")
+                    || name.startsWith("org.apache.meecrowave.service.")
+                    || name.startsWith("org.apache.meecrowave.tomcat.")
+                    || name.startsWith("org.apache.meecrowave.watching.")
+                    || name.equals("org.apache.meecrowave.Meecrowave"));
     }
 
     private static class JAXRSFIeldInjectionAT<T> extends AnnotatedTypeWrapper<T> {
diff --git a/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/OWBAutoSetup.java b/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/OWBAutoSetup.java
index f862b39..6e419bb 100644
--- a/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/OWBAutoSetup.java
+++ b/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/OWBAutoSetup.java
@@ -19,13 +19,11 @@
 package org.apache.meecrowave.openwebbeans;
 
 import org.apache.meecrowave.Meecrowave;
-import org.apache.meecrowave.cxf.Cxfs;
-import org.apache.meecrowave.cxf.JAXRSFieldInjectionInterceptor;
+import org.apache.meecrowave.configuration.Configuration;
 import org.apache.webbeans.annotation.DefaultLiteral;
 import org.apache.webbeans.config.WebBeansContext;
 import org.apache.webbeans.configurator.BeanConfiguratorImpl;
 import org.apache.webbeans.container.BeanManagerImpl;
-import org.apache.webbeans.intercept.InterceptorsManager;
 import org.apache.webbeans.servlet.WebBeansConfigurationListener;
 
 import javax.enterprise.context.ApplicationScoped;
@@ -38,15 +36,14 @@
 import javax.servlet.ServletContainerInitializer;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletContextEvent;
-import javax.servlet.ServletException;
 import java.util.EnumSet;
 import java.util.Set;
 import java.util.function.Consumer;
 
 public class OWBAutoSetup implements ServletContainerInitializer {
     @Override
-    public void onStartup(final Set<Class<?>> c, final ServletContext ctx) throws ServletException {
-        final Meecrowave.Builder builder = Meecrowave.Builder.class.cast(ctx.getAttribute("meecrowave.configuration"));
+    public void onStartup(final Set<Class<?>> c, final ServletContext ctx) {
+        final Configuration builder = Configuration.class.cast(ctx.getAttribute("meecrowave.configuration"));
         final Meecrowave instance = Meecrowave.class.cast(ctx.getAttribute("meecrowave.instance"));
         if (builder.isCdiConversation()) {
             try {
@@ -89,13 +86,12 @@
 
         private void customizeContext(final WebBeansContext instance) {
             final BeanManagerImpl beanManager = instance.getBeanManagerImpl();
-            final InterceptorsManager interceptorsManager = instance.getInterceptorsManager();
 
             beanManager.addInternalBean(newBean(instance, configurator ->
                     configurator.beanClass(Meecrowave.Builder.class)
                             .scope(ApplicationScoped.class)
                             .qualifiers(DefaultLiteral.INSTANCE)
-                            .types(Meecrowave.Builder.class, Object.class)
+                            .types(Configuration.class, Meecrowave.Builder.class, Object.class)
                             .createWith(cc -> meecrowave.getConfiguration())));
             beanManager.addInternalBean(newBean(instance, configurator ->
                     configurator.beanClass(Meecrowave.class)
@@ -103,11 +99,6 @@
                             .qualifiers(DefaultLiteral.INSTANCE)
                             .types(Meecrowave.class, AutoCloseable.class, Object.class)
                             .createWith(cc -> meecrowave)));
-
-            if (Cxfs.IS_PRESENT) {
-                interceptorsManager.addInterceptorBindingType(JAXRSFieldInjectionInterceptor.Binding.class);
-                beanManager.addAdditionalAnnotatedType(this, beanManager.createAnnotatedType(JAXRSFieldInjectionInterceptor.class));
-            }
         }
 
         private <T> Bean<?> newBean(final WebBeansContext instance, final Consumer<BeanConfigurator<T>> configurer) {
diff --git a/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/OWBTomcatWebScannerService.java b/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/OWBTomcatWebScannerService.java
index ca1a9b9..b3789b3 100644
--- a/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/OWBTomcatWebScannerService.java
+++ b/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/OWBTomcatWebScannerService.java
@@ -19,6 +19,7 @@
 package org.apache.meecrowave.openwebbeans;
 
 import org.apache.meecrowave.Meecrowave;
+import org.apache.meecrowave.configuration.Configuration;
 import org.apache.meecrowave.logging.tomcat.LogFacade;
 import org.apache.tomcat.JarScanFilter;
 import org.apache.webbeans.config.WebBeansContext;
@@ -299,7 +300,7 @@
         this.filter = filter;
 
         super.init(ctx);
-        final Meecrowave.Builder config = Meecrowave.Builder.class.cast(ServletContext.class.cast(ctx).getAttribute("meecrowave.configuration"));
+        final Configuration config = Configuration.class.cast(ServletContext.class.cast(ctx).getAttribute("meecrowave.configuration"));
         if (this.filter == null) {
             this.filter = new KnownJarsFilter(config);
         }
diff --git a/meecrowave-core/src/main/java/org/apache/meecrowave/runner/Cli.java b/meecrowave-core/src/main/java/org/apache/meecrowave/runner/Cli.java
index fbb7ab5..526fe5f 100644
--- a/meecrowave-core/src/main/java/org/apache/meecrowave/runner/Cli.java
+++ b/meecrowave-core/src/main/java/org/apache/meecrowave/runner/Cli.java
@@ -27,6 +27,7 @@
 import org.apache.commons.cli.HelpFormatter;
 import org.apache.commons.cli.ParseException;
 import org.apache.meecrowave.Meecrowave;
+import org.apache.meecrowave.configuration.Configuration;
 import org.apache.meecrowave.runner.cli.CliOption;
 import org.apache.xbean.recipe.ObjectRecipe;
 
@@ -291,7 +292,7 @@
             options.addOption(null, "context", true, "The context to use to deploy the webapp");
             options.addOption(null, "webapp", true, "Location of the webapp, if not set the classpath will be deployed");
             options.addOption(null, "docbase", true, "Location of the docbase for a classpath deployment");
-            final List<Field> fields = Stream.of(Meecrowave.Builder.class.getDeclaredFields())
+            final List<Field> fields = Stream.of(Configuration.class.getDeclaredFields())
                     .filter(f -> f.isAnnotationPresent(CliOption.class))
                     .collect(toList());
             final Map<Object, List<Field>> propertiesOptions = StreamSupport.stream(ServiceLoader.load(Options.class).spliterator(), false)
diff --git a/meecrowave-core/src/main/java/org/apache/meecrowave/MeecrowaveExplosion.java b/meecrowave-core/src/main/java/org/apache/meecrowave/service/Priotities.java
similarity index 61%
rename from meecrowave-core/src/main/java/org/apache/meecrowave/MeecrowaveExplosion.java
rename to meecrowave-core/src/main/java/org/apache/meecrowave/service/Priotities.java
index 0ae9210..33a7548 100644
--- a/meecrowave-core/src/main/java/org/apache/meecrowave/MeecrowaveExplosion.java
+++ b/meecrowave-core/src/main/java/org/apache/meecrowave/service/Priotities.java
@@ -16,10 +16,24 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.meecrowave;
+package org.apache.meecrowave.service;
 
-public class MeecrowaveExplosion extends RuntimeException {
-    public MeecrowaveExplosion(final String msg, final Exception e) {
-        super(msg, e);
+import static java.util.Optional.ofNullable;
+
+import javax.annotation.Priority;
+
+public final class Priotities {
+    private Priotities() {
+        // no-op
+    }
+
+    private static int priorityOf(final Object i) {
+        return ofNullable(i.getClass().getAnnotation(Priority.class))
+                .map(Priority::value)
+                .orElse(0);
+    }
+
+    public static <T> int sortByPriority(final T a, final T b) {
+        return priorityOf(a) - priorityOf(b);
     }
 }
diff --git a/meecrowave-core/src/main/java/org/apache/meecrowave/tomcat/MeecrowaveContextConfig.java b/meecrowave-core/src/main/java/org/apache/meecrowave/tomcat/MeecrowaveContextConfig.java
index 8427fb3..466f09f 100644
--- a/meecrowave-core/src/main/java/org/apache/meecrowave/tomcat/MeecrowaveContextConfig.java
+++ b/meecrowave-core/src/main/java/org/apache/meecrowave/tomcat/MeecrowaveContextConfig.java
@@ -26,8 +26,6 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.annotation.Annotation;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.net.URL;
 import java.nio.charset.StandardCharsets;
@@ -49,9 +47,8 @@
 import org.apache.catalina.LifecycleEvent;
 import org.apache.catalina.startup.ContextConfig;
 import org.apache.catalina.startup.WebappServiceLoader;
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
 import org.apache.meecrowave.Meecrowave;
+import org.apache.meecrowave.configuration.Configuration;
 import org.apache.meecrowave.logging.tomcat.LogFacade;
 import org.apache.meecrowave.openwebbeans.OWBTomcatWebScannerService;
 import org.apache.meecrowave.watching.ReloadOnChangeController;
@@ -64,18 +61,16 @@
 import org.xml.sax.InputSource;
 
 public class MeecrowaveContextConfig extends ContextConfig {
-    private static final Log LOG = LogFactory.getLog(ContextConfig.class);
-
     private static final byte[] DEFAULT_WEB_XML = "<web-app version=\"3.1\" />".getBytes(StandardCharsets.UTF_8);
 
-    private final Meecrowave.Builder configuration;
+    private final Configuration configuration;
     private final Map<String, Collection<Class<?>>> webClasses = new HashMap<>();
     private final boolean fixDocBase;
     private final ServletContainerInitializer intializer;
     private OwbAnnotationFinder finder;
     private ReloadOnChangeController watcher;
 
-    public MeecrowaveContextConfig(final Meecrowave.Builder configuration, final boolean fixDocBase, final ServletContainerInitializer intializer) {
+    public MeecrowaveContextConfig(final Configuration configuration, final boolean fixDocBase, final ServletContainerInitializer intializer) {
         this.configuration = configuration;
         this.fixDocBase = fixDocBase;
         this.intializer= intializer;
@@ -92,7 +87,8 @@
     @Override
     protected void webConfig() {
         if (context.getServletContext().getAttribute("meecrowave.configuration") == null) { // redeploy
-            context.getServletContext().setAttribute("meecrowave.configuration", configuration);
+            context.getServletContext().setAttribute("meecrowave.configuration",
+                    Meecrowave.Builder.class.isInstance(configuration) ? configuration : new Meecrowave.Builder(configuration));
             context.addServletContainerInitializer(intializer, emptySet());
         }
 
@@ -212,28 +208,4 @@
             ok = false;
         }
     }
-
-    private Object invokePrivate(final String mtdName, final Class<?> paramType, final Object param) {
-        try {
-            final Method declaredMethod = ContextConfig.class.getDeclaredMethod(mtdName, paramType);
-            if (!declaredMethod.isAccessible()) {
-                declaredMethod.setAccessible(true);
-            }
-            return declaredMethod.invoke(this, param);
-        } catch (final InvocationTargetException ite) {
-            return rethrow(ite.getTargetException());
-        } catch (final Exception ex) {
-            return rethrow(ex);
-        }
-    }
-
-    private Object rethrow(final Throwable ex) {
-        if (RuntimeException.class.isInstance(ex)) {
-            throw RuntimeException.class.cast(ex);
-        }
-        if (Error.class.isInstance(ex)) {
-            throw Error.class.cast(ex);
-        }
-        throw new IllegalStateException(ex);
-    }
 }
diff --git a/meecrowave-core/src/main/java/org/apache/meecrowave/tomcat/TomcatAutoInitializer.java b/meecrowave-core/src/main/java/org/apache/meecrowave/tomcat/TomcatAutoInitializer.java
index ebdf825..d56859b 100644
--- a/meecrowave-core/src/main/java/org/apache/meecrowave/tomcat/TomcatAutoInitializer.java
+++ b/meecrowave-core/src/main/java/org/apache/meecrowave/tomcat/TomcatAutoInitializer.java
@@ -25,12 +25,12 @@
 import javax.servlet.ServletRegistration;
 
 import org.apache.catalina.servlets.DefaultServlet;
-import org.apache.meecrowave.Meecrowave;
+import org.apache.meecrowave.configuration.Configuration;
 
 public class TomcatAutoInitializer implements ServletContainerInitializer {
     @Override
     public void onStartup(final Set<Class<?>> c, final ServletContext ctx) {
-        final Meecrowave.Builder builder = Meecrowave.Builder.class.cast(ctx.getAttribute("meecrowave.configuration"));
+        final Configuration builder = Configuration.class.cast(ctx.getAttribute("meecrowave.configuration"));
         if (!builder.isTomcatAutoSetup()) {
             return;
         }
diff --git a/meecrowave-core/src/main/resources/META-INF/beans.xml b/meecrowave-core/src/main/resources/META-INF/beans.xml
index 22807d9..3bb9076 100644
--- a/meecrowave-core/src/main/resources/META-INF/beans.xml
+++ b/meecrowave-core/src/main/resources/META-INF/beans.xml
@@ -1,3 +1,4 @@
+<?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
@@ -16,6 +17,9 @@
     specific language governing permissions and limitations
     under the License.
 -->
-<beans>
-    <trim/>
-</beans>
+<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+        http://xmlns.jcp.org/xml/ns/javaee
+        http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd"
+       version="2.0" bean-discovery-mode="none"/>
diff --git a/meecrowave-core/src/test/java/org/apache/meecrowave/ConfigInjection.java b/meecrowave-core/src/test/java/org/apache/meecrowave/ConfigInjection.java
index 6fc5153..57d2d99 100644
--- a/meecrowave-core/src/test/java/org/apache/meecrowave/ConfigInjection.java
+++ b/meecrowave-core/src/test/java/org/apache/meecrowave/ConfigInjection.java
@@ -18,18 +18,19 @@
  */
 package org.apache.meecrowave;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import javax.inject.Inject;
+
+import org.apache.meecrowave.configuration.Configuration;
 import org.apache.webbeans.config.WebBeansContext;
 import org.apache.webbeans.inject.OWBInjector;
 import org.junit.Test;
 
-import javax.inject.Inject;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
 public class ConfigInjection {
     @Inject
-    private Meecrowave.Builder builder;
+    private Configuration configuration;
 
     @Test
     public void inject() {
@@ -38,8 +39,8 @@
                         .randomHttpPort()
                         .includePackages(ConfigInjection.class.getName())).bake()) {
             OWBInjector.inject(WebBeansContext.currentInstance().getBeanManagerImpl(), this, null);
-            assertNotNull(builder);
-            assertEquals(ConfigInjection.class.getName(), builder.getScanningPackageIncludes());
+            assertNotNull(configuration);
+            assertEquals(ConfigInjection.class.getName(), configuration.getScanningPackageIncludes());
         }
     }
 }
diff --git a/meecrowave-core/src/test/java/org/apache/meecrowave/JsonStructureEndpointTest.java b/meecrowave-core/src/test/java/org/apache/meecrowave/JsonStructureEndpointTest.java
new file mode 100644
index 0000000..1393307
--- /dev/null
+++ b/meecrowave-core/src/test/java/org/apache/meecrowave/JsonStructureEndpointTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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.meecrowave;
+
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON_TYPE;
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.json.Json;
+import javax.json.JsonArray;
+import javax.json.JsonObject;
+import javax.json.JsonValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.core.MediaType;
+
+import org.junit.Test;
+
+// mainly here to ensure JsrProvider is not needed thanks to default JsonbJaxrsProvider
+public class JsonStructureEndpointTest {
+    @Test
+    public void run() throws IOException {
+        try (final Meecrowave container = new Meecrowave(new Meecrowave.Builder()
+                .randomHttpPort()
+                .includePackages(Endpoint.class.getName()))
+                .bake()) {
+            final String base = "http://localhost:" + container.getConfiguration().getHttpPort() + "/JsonStructureEndpointTest/";
+            assertEquals("{\"test\":\"yes\"}", slurp(base + "object"));
+            assertEquals("[\"test\",\"yes\"]", slurp(base + "array"));
+            assertEquals("true", slurp(base + "value"));
+        }
+    }
+
+    private String slurp(final String url) {
+        final Client client = ClientBuilder.newClient();
+        try {
+            return client.target(url).request(APPLICATION_JSON_TYPE).get(String.class);
+        } finally {
+            client.close();
+        }
+    }
+
+    @ApplicationScoped
+    @Path("JsonStructureEndpointTest")
+    @Produces(MediaType.APPLICATION_JSON)
+    public static class Endpoint {
+        @GET
+        @Path("object")
+        public JsonObject object() {
+            return Json.createObjectBuilder().add("test", "yes").build();
+        }
+
+        @GET
+        @Path("array")
+        public JsonArray array() {
+            return Json.createArrayBuilder().add("test").add("yes").build();
+        }
+
+        @GET
+        @Path("value")
+        public JsonValue value() {
+            return JsonValue.TRUE;
+        }
+    }
+}
diff --git a/meecrowave-core/src/test/java/org/apache/meecrowave/MeecrowaveTest.java b/meecrowave-core/src/test/java/org/apache/meecrowave/MeecrowaveTest.java
index 3355519..391887b 100644
--- a/meecrowave-core/src/test/java/org/apache/meecrowave/MeecrowaveTest.java
+++ b/meecrowave-core/src/test/java/org/apache/meecrowave/MeecrowaveTest.java
@@ -20,6 +20,7 @@
 
 import org.apache.catalina.Context;
 import org.apache.cxf.helpers.FileUtils;
+import org.apache.meecrowave.configuration.Configuration;
 import org.apache.meecrowave.io.IO;
 import org.apache.meecrowave.runner.cli.CliOption;
 import org.junit.Test;
@@ -53,6 +54,8 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import javax.enterprise.inject.spi.CDI;
+
 public class MeecrowaveTest {
     @Test
     public void fastStartupSessionId() {
@@ -168,11 +171,20 @@
     @Test
     public void classpath() {
         try (final Meecrowave meecrowave = new Meecrowave(new Meecrowave.Builder().randomHttpPort().includePackages("org.superbiz.app")).bake()) {
-            assertEquals("simplefalse", slurp(new URL("http://localhost:" + meecrowave.getConfiguration().getHttpPort() + "/api/test")));
-            assertEquals("simplefiltertrue", slurp(new URL("http://localhost:" + meecrowave.getConfiguration().getHttpPort() + "/filter")));
-            assertEquals(
-                    "sci:" + Bounced.class.getName() + Endpoint.class.getName() + InterfaceApi.class.getName() + RsApp.class.getName() + TestJsonEndpoint.class.getName(),
-                    slurp(new URL("http://localhost:" + meecrowave.getConfiguration().getHttpPort() + "/sci")));
+            assertClasspath(meecrowave);
+        } catch (final IOException e) {
+            fail(e.getMessage());
+        }
+    }
+
+    @Test
+    public void classpathUsingConfigurationAndNotBuilder() {
+        final Meecrowave.Builder randomPortHolder = new Meecrowave.Builder().randomHttpPort();
+        final Configuration configuration = new Configuration();
+        configuration.setHttpPort(randomPortHolder.getHttpPort());
+        configuration.setScanningPackageIncludes("org.superbiz.app");
+        try (final Meecrowave meecrowave = new Meecrowave(new Configuration()).bake()) {
+            assertClasspath(meecrowave);
         } catch (final IOException e) {
             fail(e.getMessage());
         }
@@ -187,6 +199,15 @@
         }
     }
 
+    private void assertClasspath(final Meecrowave meecrowave) throws MalformedURLException {
+        assertEquals(CDI.current().select(Configuration.class).get(), meecrowave.getConfiguration()); // not symmetric cause of proxy!
+        assertEquals("simplefalse", slurp(new URL("http://localhost:" + meecrowave.getConfiguration().getHttpPort() + "/api/test")));
+        assertEquals("simplefiltertrue", slurp(new URL("http://localhost:" + meecrowave.getConfiguration().getHttpPort() + "/filter")));
+        assertEquals(
+                "sci:" + Bounced.class.getName() + Endpoint.class.getName() + InterfaceApi.class.getName() + RsApp.class.getName() + TestJsonEndpoint.class.getName(),
+                slurp(new URL("http://localhost:" + meecrowave.getConfiguration().getHttpPort() + "/sci")));
+    }
+
     private String slurp(final URL url) {
         try (final InputStream is = url.openStream()) {
             return IO.toString(is);
diff --git a/meecrowave-core/src/test/java/org/apache/meecrowave/runner/CliTest.java b/meecrowave-core/src/test/java/org/apache/meecrowave/runner/CliTest.java
index 2b33ccc..7df0193 100644
--- a/meecrowave-core/src/test/java/org/apache/meecrowave/runner/CliTest.java
+++ b/meecrowave-core/src/test/java/org/apache/meecrowave/runner/CliTest.java
@@ -123,7 +123,8 @@
         @Override
         public void onStartup(final Set<Class<?>> set, final ServletContext servletContext) throws ServletException {
             OPTS_SET.set("val".equals(
-                    Meecrowave.Builder.class.cast(servletContext.getAttribute("meecrowave.configuration")).getExtension(MyOpts.class).opt));
+                    Meecrowave.Builder.class.cast(servletContext.getAttribute("meecrowave.configuration"))
+                            .getExtension(MyOpts.class).opt));
         }
     }
 }
diff --git a/meecrowave-core/src/test/java/org/apache/meecrowave/api/ListeningTest.java b/meecrowave-core/src/test/java/org/apache/meecrowave/test/api/ListeningTest.java
similarity index 93%
rename from meecrowave-core/src/test/java/org/apache/meecrowave/api/ListeningTest.java
rename to meecrowave-core/src/test/java/org/apache/meecrowave/test/api/ListeningTest.java
index 7aa57e6..613eaeb 100644
--- a/meecrowave-core/src/test/java/org/apache/meecrowave/api/ListeningTest.java
+++ b/meecrowave-core/src/test/java/org/apache/meecrowave/test/api/ListeningTest.java
@@ -16,11 +16,12 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.meecrowave.api;
+package org.apache.meecrowave.test.api;
 
-import org.apache.catalina.LifecycleException;
-import org.apache.meecrowave.Meecrowave;
-import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+import java.util.ArrayList;
+import java.util.List;
 
 import javax.enterprise.context.ApplicationScoped;
 import javax.enterprise.event.Observes;
@@ -31,14 +32,16 @@
 import javax.ws.rs.client.Client;
 import javax.ws.rs.client.ClientBuilder;
 import javax.ws.rs.core.MediaType;
-import java.util.ArrayList;
-import java.util.List;
 
-import static org.junit.Assert.assertEquals;
+import org.apache.meecrowave.Meecrowave;
+import org.apache.meecrowave.api.ListeningBase;
+import org.apache.meecrowave.api.StartListening;
+import org.apache.meecrowave.api.StopListening;
+import org.junit.Test;
 
 public class ListeningTest {
     @Test
-    public void events() throws LifecycleException {
+    public void events() {
         final Listener listener;
         final String base;
         int count = 0;
diff --git a/meecrowave-doc/pom.xml b/meecrowave-doc/pom.xml
index 348b665..a9c4d0f 100644
--- a/meecrowave-doc/pom.xml
+++ b/meecrowave-doc/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <artifactId>meecrowave</artifactId>
     <groupId>org.apache.meecrowave</groupId>
-    <version>1.2.9-SNAPSHOT</version>
+    <version>1.2.10-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
diff --git a/meecrowave-doc/src/main/java/org/apache/meecrowave/doc/generator/CliConfiguration.java b/meecrowave-doc/src/main/java/org/apache/meecrowave/doc/generator/CliConfiguration.java
index 3906890..f7d16a1 100644
--- a/meecrowave-doc/src/main/java/org/apache/meecrowave/doc/generator/CliConfiguration.java
+++ b/meecrowave-doc/src/main/java/org/apache/meecrowave/doc/generator/CliConfiguration.java
@@ -18,22 +18,22 @@
  */
 package org.apache.meecrowave.doc.generator;
 
-import org.apache.meecrowave.Meecrowave;
-import org.apache.meecrowave.runner.cli.CliOption;
+import static java.util.stream.Collectors.joining;
 
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Field;
 import java.util.Comparator;
 import java.util.stream.Stream;
 
-import static java.util.stream.Collectors.joining;
+import org.apache.meecrowave.configuration.Configuration;
+import org.apache.meecrowave.runner.cli.CliOption;
 
 public class CliConfiguration extends BaseGenerator {
     @Override
     protected String generate() {
         return super.tableConfig() + "|===\n|Name|Description\n" +
                 Stream.of(
-                        Stream.of(Meecrowave.Builder.class.getDeclaredFields())
+                        Stream.of(Configuration.class.getDeclaredFields())
                                 .filter(f -> f.isAnnotationPresent(CliOption.class))
                                 .sorted(Comparator.comparing(Field::getName))
                                 .map(f -> f.getAnnotation(CliOption.class)),
diff --git a/meecrowave-doc/src/main/java/org/apache/meecrowave/doc/generator/Configuration.java b/meecrowave-doc/src/main/java/org/apache/meecrowave/doc/generator/Configuration.java
index 8806ef8..990e79e 100644
--- a/meecrowave-doc/src/main/java/org/apache/meecrowave/doc/generator/Configuration.java
+++ b/meecrowave-doc/src/main/java/org/apache/meecrowave/doc/generator/Configuration.java
@@ -18,20 +18,19 @@
  */
 package org.apache.meecrowave.doc.generator;
 
-import org.apache.meecrowave.Meecrowave;
-import org.apache.meecrowave.runner.cli.CliOption;
+import static java.util.stream.Collectors.joining;
 
 import java.lang.reflect.Field;
 import java.util.Comparator;
 import java.util.stream.Stream;
 
-import static java.util.stream.Collectors.joining;
+import org.apache.meecrowave.runner.cli.CliOption;
 
 public class Configuration extends BaseGenerator {
     @Override
     protected String generate() {
         return super.tableConfig() + "|===\n|Name|Description\n" +
-                Stream.of(Meecrowave.Builder.class.getDeclaredFields())
+                Stream.of(org.apache.meecrowave.configuration.Configuration.class.getDeclaredFields())
                         .filter(f -> f.isAnnotationPresent(CliOption.class))
                         .sorted(Comparator.comparing(Field::getName))
                         .map(f -> "|" + f.getName() + "|" + f.getAnnotation(CliOption.class).description())
diff --git a/meecrowave-doc/src/main/java/org/apache/meecrowave/doc/generator/GradleConfiguration.java b/meecrowave-doc/src/main/java/org/apache/meecrowave/doc/generator/GradleConfiguration.java
index 2ff58a4..a7a617d 100644
--- a/meecrowave-doc/src/main/java/org/apache/meecrowave/doc/generator/GradleConfiguration.java
+++ b/meecrowave-doc/src/main/java/org/apache/meecrowave/doc/generator/GradleConfiguration.java
@@ -25,7 +25,7 @@
 import java.lang.reflect.Field;
 import java.util.stream.Stream;
 
-import org.apache.meecrowave.Meecrowave;
+import org.apache.meecrowave.configuration.Configuration;
 import org.apache.meecrowave.gradle.MeecrowaveExtension;
 import org.apache.meecrowave.runner.cli.CliOption;
 
@@ -62,7 +62,7 @@
                 return "Should the extension be skipped completely";
             default:
                 try {
-                    return Meecrowave.Builder.class.getDeclaredField(opt).getAnnotation(CliOption.class).description();
+                    return Configuration.class.getDeclaredField(opt).getAnnotation(CliOption.class).description();
                 } catch (final NoSuchFieldException e) {
                     throw new IllegalArgumentException("option " + opt + " not found");
                 }
diff --git a/meecrowave-doc/src/main/jbake/content/components.adoc b/meecrowave-doc/src/main/jbake/content/components.adoc
index 87811f2..b453bf5 100755
--- a/meecrowave-doc/src/main/jbake/content/components.adoc
+++ b/meecrowave-doc/src/main/jbake/content/components.adoc
@@ -46,9 +46,8 @@
 
 == Meecrowave and Monitoring
 
-Meecrowave provides few integration for the monitoring:
-
-link:{context_rootpath}/meecrowave-jolokia/index.html[Jolokia (JMX)]
+For monitoring, link:https://microprofile.io/[Microprofile] can be a neat companion of Apache Meecrowave.
+You can have a look to link:http://geronimo.apache.org/microprofile/[Geronimo] implementation.
 
 == Meecrowave and JTA
 
diff --git a/meecrowave-doc/src/main/jbake/content/download.adoc b/meecrowave-doc/src/main/jbake/content/download.adoc
index ae1f342..5ce8926 100755
--- a/meecrowave-doc/src/main/jbake/content/download.adoc
+++ b/meecrowave-doc/src/main/jbake/content/download.adoc
@@ -12,7 +12,10 @@
 [.table.table-bordered,options="header"]
 |===
 |Name|Version|Date|Size|Type|Links
-|Meecrowave Source Release|1.2.8|2019-05-26 08:49:48|1 MB 512 kB|zip| http://www.apache.org/dyn/closer.lua/openwebbeans/meecrowave/1.2.8/meecrowave-1.2.8-source-release.zip[icon:download[] zip] https://dist.apache.org/repos/dist/release/openwebbeans/meecrowave/1.2.8/meecrowave-1.2.8-source-release.zip.sha512[icon:download[] sha512] https://dist.apache.org/repos/dist/release/openwebbeans/meecrowave/1.2.8/meecrowave-1.2.8-source-release.zip.asc[icon:download[] asc]
+|Meecrowave Source Release|1.2.9|2019-09-30 08:19:59|1 MB 552 kB|zip| http://www.apache.org/dyn/closer.lua/openwebbeans/meecrowave/1.2.9/meecrowave-1.2.9-source-release.zip[icon:download[] zip] https://dist.apache.org/repos/dist/release/openwebbeans/meecrowave/1.2.9/meecrowave-1.2.9-source-release.zip.sha512[icon:download[] sha512] https://dist.apache.org/repos/dist/release/openwebbeans/meecrowave/1.2.9/meecrowave-1.2.9-source-release.zip.asc[icon:download[] asc]
+|Meecrowave Core runner|1.2.9|2019-09-30 08:21:17|9 MB 972 kB|jar| https://repo.maven.apache.org/maven2/org/apache/meecrowave/meecrowave-core/1.2.9/meecrowave-core-1.2.9-runner.jar[icon:download[] jar] https://repo.maven.apache.org/maven2/org/apache/meecrowave/meecrowave-core/1.2.9/meecrowave-core-1.2.9-runner.jar.sha1[icon:download[] sha1] https://repo.maven.apache.org/maven2/org/apache/meecrowave/meecrowave-core/1.2.9/meecrowave-core-1.2.9-runner.jar.asc[icon:download[] asc]
+|Meecrowave Core|1.2.9|2019-09-30 08:21:05|220 kB|jar| https://repo.maven.apache.org/maven2/org/apache/meecrowave/meecrowave-core/1.2.9/meecrowave-core-1.2.9.jar[icon:download[] jar] https://repo.maven.apache.org/maven2/org/apache/meecrowave/meecrowave-core/1.2.9/meecrowave-core-1.2.9.jar.sha1[icon:download[] sha1] https://repo.maven.apache.org/maven2/org/apache/meecrowave/meecrowave-core/1.2.9/meecrowave-core-1.2.9.jar.asc[icon:download[] asc]
+|Meecrowave Source Release|1.2.8|2019-05-26 08:49:48|1 MB 512 kB|zip| https://archive.apache.org/dist/openwebbeans/meecrowave/1.2.8/meecrowave-1.2.8-source-release.zip[icon:download[] zip] https://archive.apache.org/dist/openwebbeans/meecrowave/1.2.8/meecrowave-1.2.8-source-release.zip.sha512[icon:download[] sha512] https://archive.apache.org/dist/openwebbeans/meecrowave/1.2.8/meecrowave-1.2.8-source-release.zip.asc[icon:download[] asc]
 |Meecrowave Core runner|1.2.8|2019-05-26 08:51:12|9 MB 796 kB|jar| https://repo.maven.apache.org/maven2/org/apache/meecrowave/meecrowave-core/1.2.8/meecrowave-core-1.2.8-runner.jar[icon:download[] jar] https://repo.maven.apache.org/maven2/org/apache/meecrowave/meecrowave-core/1.2.8/meecrowave-core-1.2.8-runner.jar.sha1[icon:download[] sha1] https://repo.maven.apache.org/maven2/org/apache/meecrowave/meecrowave-core/1.2.8/meecrowave-core-1.2.8-runner.jar.asc[icon:download[] asc]
 |Meecrowave Core|1.2.8|2019-05-26 08:51:00|214 kB|jar| https://repo.maven.apache.org/maven2/org/apache/meecrowave/meecrowave-core/1.2.8/meecrowave-core-1.2.8.jar[icon:download[] jar] https://repo.maven.apache.org/maven2/org/apache/meecrowave/meecrowave-core/1.2.8/meecrowave-core-1.2.8.jar.sha1[icon:download[] sha1] https://repo.maven.apache.org/maven2/org/apache/meecrowave/meecrowave-core/1.2.8/meecrowave-core-1.2.8.jar.asc[icon:download[] asc]
 |Meecrowave Source Release|1.2.7|2019-02-25 08:33:35|1 MB 507 kB|zip| https://archive.apache.org/dist/openwebbeans/meecrowave/1.2.7/meecrowave-1.2.7-source-release.zip[icon:download[] zip] https://archive.apache.org/dist/openwebbeans/meecrowave/1.2.7/meecrowave-1.2.7-source-release.zip.sha512[icon:download[] sha512] https://archive.apache.org/dist/openwebbeans/meecrowave/1.2.7/meecrowave-1.2.7-source-release.zip.asc[icon:download[] asc]
diff --git a/meecrowave-doc/src/main/jbake/content/meecrowave-core/configuration.adoc b/meecrowave-doc/src/main/jbake/content/meecrowave-core/configuration.adoc
index 06e60e7..3269ae1 100755
--- a/meecrowave-doc/src/main/jbake/content/meecrowave-core/configuration.adoc
+++ b/meecrowave-doc/src/main/jbake/content/meecrowave-core/configuration.adoc
@@ -60,7 +60,9 @@
         .initialize()) {
 
     // use the configuration to access extensions, custom config or even server port
-    Meecrowave.Builder config = container.select(Meecrowave.Builder.class).get();
+    Configuration config = container.select(Configuration.class).get();
+    // or
+    Meecrowave.Builder config2 = container.select(Meecrowave.Builder.class).get();
     int port = config.getHttpPort();
 
     // default wait implementation relying on tomcat one
diff --git a/meecrowave-doc/src/main/jbake/content/meecrowave-jolokia/index.adoc b/meecrowave-doc/src/main/jbake/content/meecrowave-jolokia/index.adoc
deleted file mode 100644
index 5bb908c..0000000
--- a/meecrowave-doc/src/main/jbake/content/meecrowave-jolokia/index.adoc
+++ /dev/null
@@ -1,107 +0,0 @@
-= Meecrowave Jolokia
-:jbake-date: 2016-12-04
-:jbake-type: page
-:jbake-status: published
-:jbake-meecrowavepdf:
-:jbake-meecrowavetitleicon: icon icon_puzzle_alt
-:jbake-meecrowavecolor: body-red
-:icons: font
-
-Coordinates:
-
-[source,xml]
-----
-<dependency>
-  <groupId>org.apache.meecrowave</groupId>
-  <artifactId>meecrowave-jolokia</artifactId>
-  <version>${meecrowave.version}</version>
-</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`.
-
-IMPORTANT: don't forget to secure this endpoint cause it let you access all the JMX MBeans. See
-Meecrowave core configuration for more details.
-
-More on https://jolokia.org/reference/html/
-
-== 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:
-
-[source]
-----
-java -Djava.security.auth.login.config=login.config \
-    -jar meecrowave-runner.jar \
-    -webapp hawtio-default-offline-1.4.67.war
-----
-
-This assumes you created a `login.config`:
-
-[source]
-----
-karaf {
-  org.apache.catalina.realm.JAASMemoryLoginModule required
-	pathname="/path/to/tomcat-users.xml";
-};
-----
-
-NOTE: the JAAS login module is named `karaf` because it is the default of hawt.io (check `io.hawt.web.AuthenticationFilter.init()`).
-
-And if you use - as in previous snippet - tomcat-users.xml you need to create an admin (role) user:
-
-[source,xml]
-----
-<tomcat-users>
-  <user username="admin" password="admin" role="hawtio" roles="admin" />
-</tomcat-users>
-----
-
-NOTE: don't try to use `io.hawt.web.tomcat.TomcatUserDatabaseLoginContext` of hawt.io which does the same as `JAASMemoryLoginModule`
-excepted it doesn't handle absolute paths which enforce you to use a `catalina.base`.
-
-Using hawt.io war you don't need to run jolokia servlet by yourself, it is already done.
diff --git a/meecrowave-gradle-plugin/pom.xml b/meecrowave-gradle-plugin/pom.xml
index a73b795..a97cb67 100644
--- a/meecrowave-gradle-plugin/pom.xml
+++ b/meecrowave-gradle-plugin/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <artifactId>meecrowave</artifactId>
     <groupId>org.apache.meecrowave</groupId>
-    <version>1.2.9-SNAPSHOT</version>
+    <version>1.2.10-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
diff --git a/meecrowave-jolokia/pom.xml b/meecrowave-jolokia/pom.xml
deleted file mode 100644
index e91be7f..0000000
--- a/meecrowave-jolokia/pom.xml
+++ /dev/null
@@ -1,111 +0,0 @@
-<?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>
-    <artifactId>meecrowave</artifactId>
-    <groupId>org.apache.meecrowave</groupId>
-    <version>1.2.9-SNAPSHOT</version>
-  </parent>
-  <modelVersion>4.0.0</modelVersion>
-
-  <artifactId>meecrowave-jolokia</artifactId>
-  <name>Meecrowave :: Jolokia</name>
-
-  <properties>
-    <jolokia.version>2.0.0-M3</jolokia.version>
-    <meecrowave.build.name>${project.groupId}.jolokia</meecrowave.build.name>
-  </properties>
-
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.tomcat</groupId>
-      <artifactId>tomcat-servlet-api</artifactId>
-      <version>${tomcat.version}</version>
-      <scope>provided</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.meecrowave</groupId>
-      <artifactId>meecrowave-core</artifactId>
-      <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>
-      <version>${jolokia.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.jolokia</groupId>
-      <artifactId>jolokia-service-serializer</artifactId>
-      <version>${jolokia.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.jolokia</groupId>
-      <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.68</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>${commons-cli.version}</version>
-      <scope>test</scope>
-    </dependency>
-
-    <dependency>
-      <groupId>org.apache.meecrowave</groupId>
-      <artifactId>meecrowave-junit</artifactId>
-      <version>${project.version}</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <version>${junit.version}</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>commons-io</groupId>
-      <artifactId>commons-io</artifactId>
-      <version>2.6</version>
-      <scope>test</scope>
-    </dependency>
-  </dependencies>
-</project>
diff --git a/meecrowave-jolokia/src/main/java/org/apache/meecrowave/jolokia/HawtioInitializer.java b/meecrowave-jolokia/src/main/java/org/apache/meecrowave/jolokia/HawtioInitializer.java
deleted file mode 100644
index 862f676..0000000
--- a/meecrowave-jolokia/src/main/java/org/apache/meecrowave/jolokia/HawtioInitializer.java
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * 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.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.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 HawtioInitializer implements ServletContainerInitializer {
-    @Override
-    public void onStartup(final Set<Class<?>> set, final ServletContext servletContext) throws ServletException {
-        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;
-        }
-    }
-}
diff --git a/meecrowave-jolokia/src/main/java/org/apache/meecrowave/jolokia/JolokiaInitializer.java b/meecrowave-jolokia/src/main/java/org/apache/meecrowave/jolokia/JolokiaInitializer.java
deleted file mode 100644
index ae12e44..0000000
--- a/meecrowave-jolokia/src/main/java/org/apache/meecrowave/jolokia/JolokiaInitializer.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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.meecrowave.jolokia;
-
-import org.apache.meecrowave.Meecrowave;
-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;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRegistration;
-import java.util.Set;
-
-import static java.util.Optional.ofNullable;
-
-public class JolokiaInitializer implements ServletContainerInitializer {
-    @Override
-    public void onStartup(final Set<Class<?>> set, final ServletContext servletContext) throws ServletException {
-        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(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;
-        }
-    }
-}
diff --git a/meecrowave-jolokia/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer b/meecrowave-jolokia/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer
deleted file mode 100644
index fb09a91..0000000
--- a/meecrowave-jolokia/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer
+++ /dev/null
@@ -1,2 +0,0 @@
-org.apache.meecrowave.jolokia.JolokiaInitializer
-org.apache.meecrowave.jolokia.HawtioInitializer
diff --git a/meecrowave-jolokia/src/main/resources/META-INF/services/org.apache.meecrowave.runner.Cli$Options b/meecrowave-jolokia/src/main/resources/META-INF/services/org.apache.meecrowave.runner.Cli$Options
deleted file mode 100644
index 4ff54c5..0000000
--- a/meecrowave-jolokia/src/main/resources/META-INF/services/org.apache.meecrowave.runner.Cli$Options
+++ /dev/null
@@ -1,2 +0,0 @@
-org.apache.meecrowave.jolokia.HawtioInitializer$HawtioConfiguration
-org.apache.meecrowave.jolokia.JolokiaInitializer$JolokiaConfiguration
\ No newline at end of file
diff --git a/meecrowave-jolokia/src/test/java/org/apache/meecrowave/jolokia/HawtioTest.java b/meecrowave-jolokia/src/test/java/org/apache/meecrowave/jolokia/HawtioTest.java
deleted file mode 100644
index 9b003a2..0000000
--- a/meecrowave-jolokia/src/test/java/org/apache/meecrowave/jolokia/HawtioTest.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.meecrowave.jolokia;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.meecrowave.junit.MeecrowaveRule;
-import org.junit.ClassRule;
-import org.junit.Test;
-
-import java.io.IOException;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
-
-import static org.junit.Assert.assertTrue;
-
-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() + "/hawtio/"),
-                StandardCharsets.UTF_8);
-        assertTrue(actual, actual.contains("<title>hawtio</title>"));
-    }
-}
diff --git a/meecrowave-jolokia/src/test/java/org/apache/meecrowave/jolokia/JolokiaInitializerTest.java b/meecrowave-jolokia/src/test/java/org/apache/meecrowave/jolokia/JolokiaInitializerTest.java
deleted file mode 100644
index ea0e4bf..0000000
--- a/meecrowave-jolokia/src/test/java/org/apache/meecrowave/jolokia/JolokiaInitializerTest.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.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;
-
-import java.io.IOException;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
-
-import static org.junit.Assert.assertTrue;
-
-public class JolokiaInitializerTest {
-    @ClassRule
-    public static final MeecrowaveRule RULE = new MeecrowaveRule(new Meecrowave.Builder() {{
-        randomHttpPort();
-        this.setExtension(HawtioInitializer.HawtioConfiguration.class, new HawtioInitializer.HawtioConfiguration() {{
-            setActive(false);
-        }});
-    }}, "");
-
-    @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"),
-                StandardCharsets.UTF_8);
-        assertTrue(actual, actual.contains("\"status\":200"));
-        assertTrue(actual, actual.contains("\"mbean\":\"java.lang:type=Memory\""));
-    }
-}
diff --git a/meecrowave-jpa/pom.xml b/meecrowave-jpa/pom.xml
index 87c3d06..abf9bbf 100644
--- a/meecrowave-jpa/pom.xml
+++ b/meecrowave-jpa/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <artifactId>meecrowave</artifactId>
     <groupId>org.apache.meecrowave</groupId>
-    <version>1.2.9-SNAPSHOT</version>
+    <version>1.2.10-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
diff --git a/meecrowave-jta/pom.xml b/meecrowave-jta/pom.xml
index 6a073f7..4bf7b61 100644
--- a/meecrowave-jta/pom.xml
+++ b/meecrowave-jta/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <artifactId>meecrowave</artifactId>
     <groupId>org.apache.meecrowave</groupId>
-    <version>1.2.9-SNAPSHOT</version>
+    <version>1.2.10-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
diff --git a/meecrowave-junit/pom.xml b/meecrowave-junit/pom.xml
index 088133e..9cebb27 100644
--- a/meecrowave-junit/pom.xml
+++ b/meecrowave-junit/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <artifactId>meecrowave</artifactId>
     <groupId>org.apache.meecrowave</groupId>
-    <version>1.2.9-SNAPSHOT</version>
+    <version>1.2.10-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
diff --git a/meecrowave-junit/src/main/java/org/apache/meecrowave/junit5/MeecrowaveExtension.java b/meecrowave-junit/src/main/java/org/apache/meecrowave/junit5/MeecrowaveExtension.java
index 83727f2..e09792a 100644
--- a/meecrowave-junit/src/main/java/org/apache/meecrowave/junit5/MeecrowaveExtension.java
+++ b/meecrowave-junit/src/main/java/org/apache/meecrowave/junit5/MeecrowaveExtension.java
@@ -29,6 +29,7 @@
 import javax.enterprise.context.spi.CreationalContext;
 
 import org.apache.meecrowave.Meecrowave;
+import org.apache.meecrowave.configuration.Configuration;
 import org.apache.meecrowave.testing.Injector;
 import org.junit.jupiter.api.extension.AfterAllCallback;
 import org.junit.jupiter.api.extension.AfterEachCallback;
@@ -71,7 +72,7 @@
                 try {
                     final Object value = method.invoke(config);
 
-                    final Field configField = Meecrowave.Builder.class.getDeclaredField(method.getName());
+                    final Field configField = Configuration.class.getDeclaredField(method.getName());
                     if (!configField.isAccessible()) {
                         configField.setAccessible(true);
                     }
diff --git a/meecrowave-letsencrypt/pom.xml b/meecrowave-letsencrypt/pom.xml
index 71f5492..4072f75 100644
--- a/meecrowave-letsencrypt/pom.xml
+++ b/meecrowave-letsencrypt/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <artifactId>meecrowave</artifactId>
     <groupId>org.apache.meecrowave</groupId>
-    <version>1.2.9-SNAPSHOT</version>
+    <version>1.2.10-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
diff --git a/meecrowave-maven-plugin/pom.xml b/meecrowave-maven-plugin/pom.xml
index afc7dc8..d30d912 100644
--- a/meecrowave-maven-plugin/pom.xml
+++ b/meecrowave-maven-plugin/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <groupId>org.apache.meecrowave</groupId>
     <artifactId>meecrowave</artifactId>
-    <version>1.2.9-SNAPSHOT</version>
+    <version>1.2.10-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
@@ -86,6 +86,12 @@
       <scope>test</scope>
     </dependency>
     <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-archiver</artifactId>
+      <version>4.1.0</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
       <groupId>org.apache.maven</groupId>
       <artifactId>maven-compat</artifactId>
       <version>${maven.version}</version>
diff --git a/meecrowave-maven-plugin/src/main/java/org/apache/meecrowave/maven/MeecrowaveRunMojo.java b/meecrowave-maven-plugin/src/main/java/org/apache/meecrowave/maven/MeecrowaveRunMojo.java
index 0de0a53..6bf16e2 100644
--- a/meecrowave-maven-plugin/src/main/java/org/apache/meecrowave/maven/MeecrowaveRunMojo.java
+++ b/meecrowave-maven-plugin/src/main/java/org/apache/meecrowave/maven/MeecrowaveRunMojo.java
@@ -59,6 +59,7 @@
 import org.apache.maven.plugins.annotations.Parameter;
 import org.apache.maven.project.MavenProject;
 import org.apache.meecrowave.Meecrowave;
+import org.apache.meecrowave.configuration.Configuration;
 import org.apache.meecrowave.tomcat.ProvidedLoader;
 
 @Mojo(name = "run", requiresDependencyResolution = RUNTIME_PLUS_SYSTEM)
@@ -345,7 +346,7 @@
         final Supplier<ClassLoader> appLoaderSupplier = createClassLoader(loader);
         thread.setContextClassLoader(appLoaderSupplier.get());
         try {
-            final Meecrowave.Builder builder = getConfig();
+            final Configuration builder = getConfig();
             try (final Meecrowave meecrowave = new Meecrowave(builder) {
                 @Override
                 protected void beforeStart() {
@@ -495,14 +496,14 @@
         };
     }
 
-    private Meecrowave.Builder getConfig() {
-        final Meecrowave.Builder config = new Meecrowave.Builder();
+    private Configuration getConfig() {
+        final Configuration config = new Configuration();
         for (final Field field : MeecrowaveRunMojo.class.getDeclaredFields()) {
             if ("properties".equals(field.getName())) {
                 continue;
             }
             try {
-                final Field configField = Meecrowave.Builder.class.getDeclaredField(field.getName());
+                final Field configField = Configuration.class.getDeclaredField(field.getName());
                 field.setAccessible(true);
                 configField.setAccessible(true);
 
diff --git a/meecrowave-oauth2/pom.xml b/meecrowave-oauth2/pom.xml
index 46639a4..55d089a 100644
--- a/meecrowave-oauth2/pom.xml
+++ b/meecrowave-oauth2/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <artifactId>meecrowave</artifactId>
     <groupId>org.apache.meecrowave</groupId>
-    <version>1.2.9-SNAPSHOT</version>
+    <version>1.2.10-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
diff --git a/meecrowave-proxy/pom.xml b/meecrowave-proxy/pom.xml
index 75dc8a2..0de91ae 100644
--- a/meecrowave-proxy/pom.xml
+++ b/meecrowave-proxy/pom.xml
@@ -17,13 +17,11 @@
     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">
+<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>
     <artifactId>meecrowave</artifactId>
     <groupId>org.apache.meecrowave</groupId>
-    <version>1.2.9-SNAPSHOT</version>
+    <version>1.2.10-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
diff --git a/meecrowave-specs-api/pom.xml b/meecrowave-specs-api/pom.xml
index 7d06ed5..78f30a6 100644
--- a/meecrowave-specs-api/pom.xml
+++ b/meecrowave-specs-api/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <artifactId>meecrowave</artifactId>
     <groupId>org.apache.meecrowave</groupId>
-    <version>1.2.9-SNAPSHOT</version>
+    <version>1.2.10-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
diff --git a/pom.xml b/pom.xml
index 348fb8b..dfebba1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,7 +28,7 @@
 
   <groupId>org.apache.meecrowave</groupId>
   <artifactId>meecrowave</artifactId>
-  <version>1.2.9-SNAPSHOT</version>
+  <version>1.2.10-SNAPSHOT</version>
   <packaging>pom</packaging>
 
   <name>Meecrowave</name>
@@ -38,6 +38,7 @@
     <connection>scm:git:https://gitbox.apache.org/repos/asf/openwebbeans-meecrowave.git</connection>
     <developerConnection>scm:git:https://gitbox.apache.org/repos/asf/openwebbeans-meecrowave.git</developerConnection>
     <url>https://github.com/apache/openwebbeans-meecrowave</url>
+    <tag>HEAD</tag>
   </scm>
 
   <issueManagement>
@@ -50,17 +51,17 @@
     <meecrowave.build.name>${project.groupId}.${project.artifactId}</meecrowave.build.name>
 
     <junit.version>4.13-beta-3</junit.version>
-    <tomcat.version>9.0.22</tomcat.version>
-    <openwebbeans.version>2.0.12-SNAPSHOT</openwebbeans.version>
-    <cxf.version>3.3.2</cxf.version>
-    <johnzon.version>1.1.13</johnzon.version>
-    <log4j2.version>2.11.2</log4j2.version>
+    <tomcat.version>9.0.27</tomcat.version>
+    <openwebbeans.version>2.0.12</openwebbeans.version>
+    <cxf.version>3.3.3</cxf.version>
+    <johnzon.version>1.2.1</johnzon.version>
+    <log4j2.version>2.12.1</log4j2.version>
     <deltaspike.version>1.8.2</deltaspike.version>
     <jaxb.version>2.2.11</jaxb.version>
     <openjpa.version>3.0.0</openjpa.version>
     <jpa-spec.version>1.0-alpha-1</jpa-spec.version>
     <h2.version>1.4.196</h2.version>
-    <dbcp2.version>2.5.0</dbcp2.version>
+    <dbcp2.version>2.7.0</dbcp2.version>
     <commons-cli.version>1.4</commons-cli.version>
     <xbean.version>4.14</xbean.version>
 
@@ -75,7 +76,6 @@
     <module>meecrowave-junit</module>
     <module>meecrowave-arquillian</module>
     <module>meecrowave-jpa</module>
-    <module>meecrowave-jolokia</module>
     <module>meecrowave-doc</module>
     <module>meecrowave-jta</module>
     <module>integration-tests</module>
@@ -109,12 +109,12 @@
       <dependency>
         <groupId>org.apache.geronimo.specs</groupId>
         <artifactId>geronimo-json_1.1_spec</artifactId>
-        <version>1.1</version>
+        <version>1.3</version>
       </dependency>
       <dependency>
         <groupId>org.apache.geronimo.specs</groupId>
         <artifactId>geronimo-jsonb_1.0_spec</artifactId>
-        <version>1.1</version>
+        <version>1.2</version>
       </dependency>
       <dependency>
         <groupId>org.apache.geronimo.specs</groupId>