You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2020/01/16 06:31:38 UTC

[sling-org-apache-sling-engine] branch master updated: SLING-9002 : Improve service registrations

This is an automated email from the ASF dual-hosted git repository.

cziegeler pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-engine.git


The following commit(s) were added to refs/heads/master by this push:
     new 4ad175f  SLING-9002 : Improve service registrations
4ad175f is described below

commit 4ad175f11d172973fa8e05071c32eaa2a2cfb322
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Thu Jan 16 07:31:24 2020 +0100

    SLING-9002 : Improve service registrations
---
 .../apache/sling/engine/impl/SlingMainServlet.java |  53 +--
 .../engine/impl/SlingRequestProcessorImpl.java     |   2 +-
 .../engine/impl/SlingSettingsServiceImpl.java      |   4 +
 .../impl/console/RequestHistoryConsolePlugin.java  | 346 ++++++++++++++++++++
 .../{ => console}/WebConsoleConfigPrinter.java     |  23 +-
 .../debug/RequestProgressTrackerLogFilter.java     |   7 +-
 .../engine/impl/filter/ServletFilterManager.java   |  20 ++
 .../sling/engine/impl/log/RequestLogger.java       |   5 +-
 .../sling/engine/impl/log/RequestLoggerFilter.java |  21 +-
 .../engine/impl/log/RequestLoggerService.java      |  10 +-
 .../RequestParameterSupportConfigurer.java         |  32 +-
 .../impl/request/RequestHistoryConsolePlugin.java  | 362 ---------------------
 12 files changed, 427 insertions(+), 458 deletions(-)

diff --git a/src/main/java/org/apache/sling/engine/impl/SlingMainServlet.java b/src/main/java/org/apache/sling/engine/impl/SlingMainServlet.java
index 26670b2..5f94c31 100644
--- a/src/main/java/org/apache/sling/engine/impl/SlingMainServlet.java
+++ b/src/main/java/org/apache/sling/engine/impl/SlingMainServlet.java
@@ -21,13 +21,12 @@ package org.apache.sling.engine.impl;
 import java.util.ArrayList;
 import java.util.Dictionary;
 import java.util.Hashtable;
-import java.util.List;
 import java.util.Map;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.regex.Pattern;
 
+import javax.management.NotCompliantMBeanException;
 import javax.servlet.GenericServlet;
 import javax.servlet.Servlet;
 import javax.servlet.ServletException;
@@ -43,12 +42,12 @@ import org.apache.sling.api.servlets.ServletResolver;
 import org.apache.sling.auth.core.AuthenticationSupport;
 import org.apache.sling.commons.mime.MimeTypeService;
 import org.apache.sling.engine.SlingRequestProcessor;
+import org.apache.sling.engine.impl.console.RequestHistoryConsolePlugin;
 import org.apache.sling.engine.impl.filter.ServletFilterManager;
 import org.apache.sling.engine.impl.helper.ClientAbortException;
 import org.apache.sling.engine.impl.helper.RequestListenerManager;
 import org.apache.sling.engine.impl.helper.SlingServletContext;
 import org.apache.sling.engine.impl.request.RequestData;
-import org.apache.sling.engine.impl.request.RequestHistoryConsolePlugin;
 import org.apache.sling.engine.jmx.RequestProcessorMBean;
 import org.apache.sling.engine.servlets.ErrorHandler;
 import org.osgi.framework.BundleContext;
@@ -62,6 +61,8 @@ import org.osgi.service.component.annotations.Modified;
 import org.osgi.service.component.annotations.Reference;
 import org.osgi.service.component.annotations.ReferenceCardinality;
 import org.osgi.service.component.annotations.ReferencePolicy;
+import org.osgi.service.component.propertytypes.ServiceDescription;
+import org.osgi.service.component.propertytypes.ServiceVendor;
 import org.osgi.service.http.context.ServletContextHelper;
 import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
 import org.osgi.service.metatype.annotations.AttributeDefinition;
@@ -74,13 +75,14 @@ import org.slf4j.LoggerFactory;
  * The <code>SlingMainServlet</code>
  */
 @SuppressWarnings("serial")
-@Component(property = {
-        Constants.SERVICE_VENDOR + "=The Apache Software Foundation",
-        Constants.SERVICE_DESCRIPTION + "=Sling Servlet"
-})
+@Component(configurationPid = SlingMainServlet.PID, service = {})
+@ServiceDescription("Sling Servlet")
+@ServiceVendor("The Apache Software Foundation")
 @Designate(ocd=SlingMainServlet.Config.class)
 public class SlingMainServlet extends GenericServlet {
 
+    public static final String PID = "org.apache.sling.engine.impl.SlingMainServlet";
+
     @ObjectClassDefinition(name ="Apache Sling Main Servlet",
             description="Main processor of the Sling framework controlling all " +
                     "aspects of processing requests inside of Sling, namely authentication, " +
@@ -185,8 +187,6 @@ public class SlingMainServlet extends GenericServlet {
 
     private volatile boolean allowTrace;
 
-    private volatile Object printerRegistration;
-
     // new properties
 
     private final SlingHttpContext slingHttpContext = new SlingHttpContext();
@@ -451,23 +451,6 @@ public class SlingMainServlet extends GenericServlet {
                 this.servletRegistration.setProperties(getServletContextRegistrationProps(servletName));
             }
         }
-
-        // setup the request info recorder
-        try {
-            int maxRequests = config.sling_max_record_requests();
-            String[] patterns = config.sling_store_pattern_requests();
-            if ( patterns == null ) patterns = new String[0];
-            List<Pattern> compiledPatterns = new ArrayList<>(patterns.length);
-            for (String pattern : patterns) {
-                if(pattern != null && pattern.trim().length() > 0) {
-                    compiledPatterns.add(Pattern.compile(pattern));
-                }
-            }
-            RequestHistoryConsolePlugin.initPlugin(bundleContext, maxRequests, compiledPatterns);
-        } catch (Throwable t) {
-            log.debug(
-                    "Unable to register web console request recorder plugin.", t);
-        }
     }
 
     @Activate
@@ -517,9 +500,6 @@ public class SlingMainServlet extends GenericServlet {
                     // initialize requestListenerManager
                     requestListenerManager = new RequestListenerManager(bundleContext, slingServletContext);
 
-                    // Setup configuration printer
-                    printerRegistration = WebConsoleConfigPrinter.register(bundleContext, filterManager);
-
                     try {
                         Dictionary<String, String> mbeanProps = new Hashtable<>();
                         mbeanProps.put("jmx.objectname", "org.apache.sling:type=engine,service=RequestProcessor");
@@ -527,7 +507,7 @@ public class SlingMainServlet extends GenericServlet {
                         RequestProcessorMBeanImpl mbean = new RequestProcessorMBeanImpl();
                         requestProcessorMBeanRegistration = bundleContext.registerService(RequestProcessorMBean.class, mbean, mbeanProps);
                         requestProcessor.setMBean(mbean);
-                    } catch (Throwable t) {
+                    } catch (NotCompliantMBeanException t) {
                         log.debug("Unable to register mbean");
                     }
 
@@ -553,14 +533,6 @@ public class SlingMainServlet extends GenericServlet {
                      "being called. There is a risk that objects are not properly destroyed.");
         }
 
-        // unregister request recorder plugin
-        try {
-            RequestHistoryConsolePlugin.destroyPlugin();
-        } catch (Throwable t) {
-            log.debug(
-                    "Problem unregistering web console request recorder plugin.", t);
-        }
-
         // second unregister the servlet context *before* unregistering
         // and destroying the the sling main servlet
         if (this.contextRegistration != null) {
@@ -602,11 +574,6 @@ public class SlingMainServlet extends GenericServlet {
             requestProcessorMBeanRegistration = null;
         }
 
-        // this reverses the activation setup
-        if ( this.printerRegistration != null ) {
-            WebConsoleConfigPrinter.unregister(this.printerRegistration);
-            this.printerRegistration = null;
-        }
         // destroy servlet filters before destroying the sling servlet
         // context because the filters depend on that context
         if (filterManager != null) {
diff --git a/src/main/java/org/apache/sling/engine/impl/SlingRequestProcessorImpl.java b/src/main/java/org/apache/sling/engine/impl/SlingRequestProcessorImpl.java
index 90af1ee..d70283b 100644
--- a/src/main/java/org/apache/sling/engine/impl/SlingRequestProcessorImpl.java
+++ b/src/main/java/org/apache/sling/engine/impl/SlingRequestProcessorImpl.java
@@ -47,6 +47,7 @@ import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.api.servlets.ServletResolver;
 import org.apache.sling.api.wrappers.SlingHttpServletResponseWrapper;
 import org.apache.sling.engine.SlingRequestProcessor;
+import org.apache.sling.engine.impl.console.RequestHistoryConsolePlugin;
 import org.apache.sling.engine.impl.filter.AbstractSlingFilterChain;
 import org.apache.sling.engine.impl.filter.FilterHandle;
 import org.apache.sling.engine.impl.filter.RequestSlingFilterChain;
@@ -56,7 +57,6 @@ import org.apache.sling.engine.impl.filter.SlingComponentFilterChain;
 import org.apache.sling.engine.impl.parameters.ParameterSupport;
 import org.apache.sling.engine.impl.request.ContentData;
 import org.apache.sling.engine.impl.request.RequestData;
-import org.apache.sling.engine.impl.request.RequestHistoryConsolePlugin;
 import org.apache.sling.engine.servlets.ErrorHandler;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
diff --git a/src/main/java/org/apache/sling/engine/impl/SlingSettingsServiceImpl.java b/src/main/java/org/apache/sling/engine/impl/SlingSettingsServiceImpl.java
index 646b014..dd6ddec 100644
--- a/src/main/java/org/apache/sling/engine/impl/SlingSettingsServiceImpl.java
+++ b/src/main/java/org/apache/sling/engine/impl/SlingSettingsServiceImpl.java
@@ -21,6 +21,8 @@ package org.apache.sling.engine.impl;
 import org.apache.sling.engine.SlingSettingsService;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.propertytypes.ServiceDescription;
+import org.osgi.service.component.propertytypes.ServiceVendor;
 
 /**
  * The implementation of the settings service has moved to the
@@ -29,6 +31,8 @@ import org.osgi.service.component.annotations.Reference;
  * @deprecated
  */
 @Component(service = SlingSettingsService.class)
+@ServiceDescription("deprecated")
+@ServiceVendor("The Apache Software Foundation")
 @Deprecated
 public class SlingSettingsServiceImpl
     implements SlingSettingsService {
diff --git a/src/main/java/org/apache/sling/engine/impl/console/RequestHistoryConsolePlugin.java b/src/main/java/org/apache/sling/engine/impl/console/RequestHistoryConsolePlugin.java
new file mode 100644
index 0000000..dd0dafd
--- /dev/null
+++ b/src/main/java/org/apache/sling/engine/impl/console/RequestHistoryConsolePlugin.java
@@ -0,0 +1,346 @@
+/*
+ * 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.sling.engine.impl.console;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.regex.Pattern;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.request.RequestProgressTracker;
+import org.apache.sling.api.request.ResponseUtil;
+import org.apache.sling.api.resource.ResourceUtil;
+import org.apache.sling.engine.impl.SlingMainServlet;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Modified;
+import org.osgi.service.component.propertytypes.ServiceDescription;
+import org.osgi.service.component.propertytypes.ServiceVendor;
+
+/**
+ * Felix OSGi console plugin that displays info about recent requests processed
+ * by Sling. Info about all requests can be found in the logs, but this is
+ * useful when testing or explaining things.
+ */
+@Component(service = Servlet.class,
+    configurationPid = SlingMainServlet.PID,
+    property = {
+            "felix.webconsole.label=" + RequestHistoryConsolePlugin.LABEL,
+            "felix.webconsole.title=Recent requests",
+            "felix.webconsole.category=Sling"
+    })
+@ServiceDescription("Web Console Plugin to display information about recent Sling requests")
+@ServiceVendor("The Apache Software Foundation")
+public class RequestHistoryConsolePlugin extends HttpServlet {
+
+    private static final long serialVersionUID = -5738101314957623511L;
+
+    public static final String LABEL = "requests";
+
+    public static final String INDEX = "index";
+
+    public static final String CLEAR = "clear";
+
+    private static volatile RequestHistoryConsolePlugin instance;
+
+    public static final int STORED_REQUESTS_COUNT = 20;
+
+    private volatile RequestInfoMap requests;
+
+    private volatile List<Pattern> storePatterns;
+
+    @Activate
+    public RequestHistoryConsolePlugin(final SlingMainServlet.Config config) {
+        update(config);
+        instance = this;
+    }
+
+
+    @Modified
+    protected void update(final SlingMainServlet.Config config) {
+        this.requests = (config.sling_max_record_requests() > 0)
+                ? new RequestInfoMap(config.sling_max_record_requests())
+                : null;
+        final List<Pattern> compiledPatterns = new ArrayList<>();
+        if (config.sling_store_pattern_requests() != null) {
+            for (String pattern : config.sling_store_pattern_requests()) {
+                if (pattern != null && pattern.trim().length() > 0) {
+                    compiledPatterns.add(Pattern.compile(pattern));
+                }
+            }
+        }
+        this.storePatterns = compiledPatterns;
+
+    }
+
+    @Deactivate
+    protected void deactivate() {
+        instance = null;
+        clear();
+    }
+
+    public static void recordRequest(final SlingHttpServletRequest r) {
+        final RequestHistoryConsolePlugin local = instance;
+        if (local != null) {
+            local.addRequest(r);
+        }
+    }
+
+    private void addRequest(SlingHttpServletRequest r) {
+        if (requests != null) {
+            String requestPath = r.getPathInfo();
+            boolean accept = true;
+            if (storePatterns != null && storePatterns.size() > 0) {
+                accept = false;
+                for (Pattern pattern : storePatterns) {
+                    if (pattern.matcher(requestPath).matches()) {
+                        accept = true;
+                        break;
+                    }
+                }
+            }
+
+            if (accept) {
+                synchronized (requests) {
+                    RequestInfo info = new RequestInfo(r);
+                    requests.put(info.getKey(), info);
+                }
+            }
+        }
+    }
+
+    private void clear() {
+        if (requests != null) {
+            synchronized (requests) {
+                requests.clear();
+            }
+        }
+    }
+
+    private String getLinksTable(String currentRequestIndex) {
+        final List<String> links = new ArrayList<String>();
+        if (requests != null) {
+            synchronized (requests) {
+                for (RequestInfo info : requests.values()) {
+                    final String key = ResponseUtil.escapeXml(info.getKey());
+                    final boolean isCurrent = info.getKey().equals(
+                        currentRequestIndex);
+                    final StringBuilder sb = new StringBuilder();
+                    sb.append("<span style='white-space: pre; text-align:right; font-size:80%'>");
+                    sb.append(String.format("%1$8s", key));
+                    sb.append("</span> ");
+                    sb.append("<a href='" + LABEL + "?index=" + key + "'>");
+                    if (isCurrent) {
+                        sb.append("<b>");
+                    }
+                    sb.append(ResponseUtil.escapeXml(info.getLabel()));
+                    if (isCurrent) {
+                        sb.append("</b>");
+                    }
+                    sb.append("</a> ");
+                    links.add(sb.toString());
+                }
+            }
+        }
+
+        final int nCols = 5;
+        while ((links.size() % nCols) != 0) {
+            links.add("&nbsp;");
+        }
+
+        final StringBuilder tbl = new StringBuilder();
+
+        tbl.append("<table class='nicetable ui-widget'>\n<tr>\n");
+        if (links.isEmpty()) {
+            tbl.append("No Requests recorded");
+        } else {
+            int i = 0;
+            for (String str : links) {
+                if ((i++ % nCols) == 0) {
+                    tbl.append("</tr>\n<tr>\n");
+                }
+                tbl.append("<td>");
+                tbl.append(str);
+                tbl.append("</td>\n");
+            }
+        }
+        tbl.append("</tr>\n");
+
+        tbl.append("</table>\n");
+        return tbl.toString();
+    }
+
+    @Override
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
+            throws ServletException, IOException {
+
+        // Select request to display
+        RequestInfo info = null;
+        String key = req.getParameter(INDEX);
+        if (key != null && requests != null) {
+            synchronized (requests) {
+                info = requests.get(key);
+            }
+        }
+
+        final PrintWriter pw = resp.getWriter();
+
+        if (requests != null) {
+            pw.println("<p class='statline ui-state-highlight'>Recorded "
+                + requests.size() + " requests (max: "
+                + requests.getMaxSize() + ")</p>");
+        } else {
+            pw.println("<p class='statline ui-state-highlight'>Request Recording disabled</p>");
+        }
+
+        pw.println("<div class='ui-widget-header ui-corner-top buttonGroup'>");
+        pw.println("<span style='float: left; margin-left: 1em'>Recent Requests</span>");
+        pw.println("<form method='POST'><input type='hidden' name='clear' value='clear'><input type='submit' value='Clear' class='ui-state-default ui-corner-all'></form>");
+        pw.println("</div>");
+
+        pw.println(getLinksTable(key));
+        pw.println("<br/>");
+
+        if (info != null) {
+
+            pw.println("<table class='nicetable ui-widget'>");
+
+            // Links to other requests
+            pw.println("<thead>");
+            pw.println("<tr>");
+            pw.printf(
+                "<th class='ui-widget-header'>Request %s (%s %s) by %s - RequestProgressTracker Info</th>%n",
+                key, ResponseUtil.escapeXml(info.getMethod()),
+                ResponseUtil.escapeXml(info.getPathInfo()), ResponseUtil.escapeXml(info.getUser()));
+            pw.println("</tr>");
+            pw.println("</thead>");
+
+            pw.println("<tbody>");
+
+            // Request Progress Tracker Info
+            pw.println("<tr><td>");
+            final Iterator<String> it = info.getTracker().getMessages();
+            pw.print("<pre>");
+            while (it.hasNext()) {
+                pw.print(ResponseUtil.escapeXml(it.next()));
+            }
+            pw.println("</pre></td></tr>");
+            pw.println("</tbody></table>");
+        }
+    }
+
+    @Override
+    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
+            throws IOException {
+        if (req.getParameter(CLEAR) != null) {
+            clear();
+            resp.sendRedirect(req.getRequestURI());
+        }
+    }
+
+    private static class RequestInfo {
+
+        private static AtomicLong requestCounter = new AtomicLong(0);
+
+        private final String key;
+
+        private final String method;
+
+        private final String pathInfo;
+
+        private final String user;
+
+        private final RequestProgressTracker tracker;
+
+        RequestInfo(SlingHttpServletRequest request) {
+            this.key = String.valueOf(requestCounter.incrementAndGet());
+            this.method = request.getMethod();
+            this.pathInfo = request.getPathInfo();
+            this.user = request.getRemoteUser();
+            this.tracker = request.getRequestProgressTracker();
+        }
+
+        public String getKey() {
+            return key;
+        }
+
+        public String getMethod() {
+            return method;
+        }
+
+        public String getPathInfo() {
+            return pathInfo;
+        }
+
+        public String getUser() {
+            return user;
+        }
+
+        public String getLabel() {
+            final StringBuilder sb = new StringBuilder();
+
+            sb.append(getMethod());
+            sb.append(' ');
+
+            final String path = getPathInfo();
+            if (path != null && path.length() > 0) {
+                sb.append(ResourceUtil.getName(getPathInfo()));
+            } else {
+                sb.append('/');
+            }
+
+            return sb.toString();
+        }
+
+        public RequestProgressTracker getTracker() {
+            return tracker;
+        }
+    }
+
+    private static class RequestInfoMap extends LinkedHashMap<String, RequestInfo> {
+
+        private static final long serialVersionUID = 4120391774146501524L;
+        private int maxSize;
+
+        RequestInfoMap(int maxSize) {
+            this.maxSize = maxSize;
+        }
+
+        @Override
+        protected boolean removeEldestEntry(java.util.Map.Entry<String, RequestInfo> eldest) {
+            return size() > maxSize;
+        }
+
+        public int getMaxSize() {
+            return maxSize;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/engine/impl/WebConsoleConfigPrinter.java b/src/main/java/org/apache/sling/engine/impl/console/WebConsoleConfigPrinter.java
similarity index 83%
rename from src/main/java/org/apache/sling/engine/impl/WebConsoleConfigPrinter.java
rename to src/main/java/org/apache/sling/engine/impl/console/WebConsoleConfigPrinter.java
index 1b83ba3..e36dd74 100644
--- a/src/main/java/org/apache/sling/engine/impl/WebConsoleConfigPrinter.java
+++ b/src/main/java/org/apache/sling/engine/impl/console/WebConsoleConfigPrinter.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.sling.engine.impl;
+package org.apache.sling.engine.impl.console;
 
 import java.io.PrintWriter;
 import java.util.Dictionary;
@@ -42,14 +42,8 @@ public class WebConsoleConfigPrinter {
         this.filterManager = filterManager;
     }
 
-    private static final class Registration {
-        public ServiceRegistration filterPlugin;
-    }
-
-    public static Object register(final BundleContext bundleContext,
+    public static ServiceRegistration register(final BundleContext bundleContext,
             final ServletFilterManager filterManager) {
-        final Registration reg = new Registration();
-
         // first we register the plugin for the filters
         final WebConsoleConfigPrinter filterPrinter = new WebConsoleConfigPrinter(filterManager);
         final Dictionary<String, String> serviceProps = new Hashtable<String, String>();
@@ -60,19 +54,14 @@ public class WebConsoleConfigPrinter {
         serviceProps.put("felix.webconsole.title", "Sling Servlet Filter");
         serviceProps.put("felix.webconsole.configprinter.modes", "always");
 
-        reg.filterPlugin = bundleContext.registerService(WebConsoleConfigPrinter.class.getName(),
+        return bundleContext.registerService(WebConsoleConfigPrinter.class.getName(),
                 filterPrinter,
                 serviceProps);
-        return reg;
     }
 
-    public static void unregister(final Object reg) {
-        if ( reg instanceof Registration ) {
-            final Registration registration = (Registration)reg;
-            if ( registration.filterPlugin != null) {
-                registration.filterPlugin.unregister();
-                registration.filterPlugin = null;
-            }
+    public static void unregister(final ServiceRegistration reg) {
+        if (reg != null) {
+            reg.unregister();
         }
     }
 
diff --git a/src/main/java/org/apache/sling/engine/impl/debug/RequestProgressTrackerLogFilter.java b/src/main/java/org/apache/sling/engine/impl/debug/RequestProgressTrackerLogFilter.java
index 7ff83ac..6798beb 100644
--- a/src/main/java/org/apache/sling/engine/impl/debug/RequestProgressTrackerLogFilter.java
+++ b/src/main/java/org/apache/sling/engine/impl/debug/RequestProgressTrackerLogFilter.java
@@ -34,9 +34,10 @@ import org.apache.sling.api.request.RequestPathInfo;
 import org.apache.sling.api.request.RequestProgressTracker;
 import org.apache.sling.engine.EngineConstants;
 import org.apache.sling.engine.impl.request.SlingRequestProgressTracker;
-import org.osgi.framework.Constants;
 import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.propertytypes.ServiceDescription;
+import org.osgi.service.component.propertytypes.ServiceVendor;
 import org.osgi.service.metatype.annotations.AttributeDefinition;
 import org.osgi.service.metatype.annotations.Designate;
 import org.osgi.service.metatype.annotations.ObjectClassDefinition;
@@ -51,10 +52,10 @@ import org.slf4j.LoggerFactory;
 @Designate(ocd=RequestProgressTrackerLogFilter.Config.class)
 @Component(service=Filter.class,
            property={
-                   Constants.SERVICE_DESCRIPTION + "=RequestProgressTracker dump filter",
-                   Constants.SERVICE_VENDOR + "=The Apache Software Foundation",
                    EngineConstants.SLING_FILTER_SCOPE + "=" + EngineConstants.FILTER_SCOPE_REQUEST
            })
+@ServiceDescription("RequestProgressTracker dump filte")
+@ServiceVendor("The Apache Software Foundation")
 public class RequestProgressTrackerLogFilter implements Filter {
 
     @ObjectClassDefinition(name="Apache Sling Request Progress Tracker Log Filter",
diff --git a/src/main/java/org/apache/sling/engine/impl/filter/ServletFilterManager.java b/src/main/java/org/apache/sling/engine/impl/filter/ServletFilterManager.java
index 53ef9f2..d22676a 100644
--- a/src/main/java/org/apache/sling/engine/impl/filter/ServletFilterManager.java
+++ b/src/main/java/org/apache/sling/engine/impl/filter/ServletFilterManager.java
@@ -29,6 +29,7 @@ import javax.servlet.ServletException;
 
 import org.apache.sling.commons.osgi.OsgiUtil;
 import org.apache.sling.engine.EngineConstants;
+import org.apache.sling.engine.impl.console.WebConsoleConfigPrinter;
 import org.apache.sling.engine.impl.helper.SlingFilterConfig;
 import org.apache.sling.engine.impl.helper.SlingServletContext;
 import org.apache.sling.engine.jmx.FilterProcessorMBean;
@@ -103,6 +104,8 @@ public class ServletFilterManager extends ServiceTracker<Filter, Filter> {
 
     private final Map<Long, MBeanReg> mbeanMap = new ConcurrentHashMap<>();
 
+    private volatile ServiceRegistration printerRegistration;
+
     private static final org.osgi.framework.Filter SERVICE_FILTER;
     static {
         org.osgi.framework.Filter f = null;
@@ -125,6 +128,23 @@ public class ServletFilterManager extends ServiceTracker<Filter, Filter> {
         }
     }
 
+    @Override
+    public void open() {
+        super.open();
+        // Setup configuration printer
+        printerRegistration = WebConsoleConfigPrinter.register(context, this);
+
+    }
+
+    @Override
+    public void close() {
+        if (this.printerRegistration != null) {
+            WebConsoleConfigPrinter.unregister(this.printerRegistration);
+            this.printerRegistration = null;
+        }
+        super.close();
+    }
+
     public SlingFilterChainHelper getFilterChain(final FilterChainType chain) {
         return filterChains[chain.ordinal()];
     }
diff --git a/src/main/java/org/apache/sling/engine/impl/log/RequestLogger.java b/src/main/java/org/apache/sling/engine/impl/log/RequestLogger.java
index 3fff3bf..edd2178 100644
--- a/src/main/java/org/apache/sling/engine/impl/log/RequestLogger.java
+++ b/src/main/java/org/apache/sling/engine/impl/log/RequestLogger.java
@@ -37,10 +37,7 @@ import org.osgi.service.metatype.annotations.Option;
  * The <code>RequestLogger</code> just registers {@link RequestLoggerService}
  * instance on behalf of the provided configuration.
  */
-@Component(property = {
-        "service.description=Request Logger",
-        "service.vendor=The Apache Software Foundation"
-})
+@Component
 @Designate(ocd = RequestLogger.Config.class)
 public class RequestLogger {
 
diff --git a/src/main/java/org/apache/sling/engine/impl/log/RequestLoggerFilter.java b/src/main/java/org/apache/sling/engine/impl/log/RequestLoggerFilter.java
index 4a0479e..ed58511 100644
--- a/src/main/java/org/apache/sling/engine/impl/log/RequestLoggerFilter.java
+++ b/src/main/java/org/apache/sling/engine/impl/log/RequestLoggerFilter.java
@@ -30,24 +30,27 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.sling.engine.impl.SlingMainServlet;
-import org.osgi.framework.Constants;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.ConfigurationPolicy;
 import org.osgi.service.component.annotations.Reference;
 import org.osgi.service.component.annotations.ReferenceCardinality;
 import org.osgi.service.component.annotations.ReferencePolicy;
+import org.osgi.service.component.propertytypes.ServiceDescription;
+import org.osgi.service.component.propertytypes.ServiceRanking;
+import org.osgi.service.component.propertytypes.ServiceVendor;
 import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
+import org.osgi.service.http.whiteboard.propertytypes.HttpWhiteboardContextSelect;
+import org.osgi.service.http.whiteboard.propertytypes.HttpWhiteboardFilterPattern;
 import org.slf4j.LoggerFactory;
 
 @Component(configurationPolicy = ConfigurationPolicy.IGNORE,
-           service = Filter.class,
-           property = {
-                   HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT+ "=(" + HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME + "=" + SlingMainServlet.SERVLET_CONTEXT_NAME + ")",
-                   HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN + "=/",
-                   Constants.SERVICE_RANKING + ":Integer=32768",
-                   Constants.SERVICE_DESCRIPTION + "=Request Logger Filter",
-                   Constants.SERVICE_VENDOR + "=The Apache Software Foundation"
-           })
+        service = Filter.class)
+@HttpWhiteboardContextSelect("(" + HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME + "="
+        + SlingMainServlet.SERVLET_CONTEXT_NAME + ")")
+@HttpWhiteboardFilterPattern("/")
+@ServiceRanking(32768)
+@ServiceDescription("Request Logger Filter")
+@ServiceVendor("The Apache Software Foundation")
 public final class RequestLoggerFilter implements Filter {
 
     private static final RequestLoggerService[] NONE = new RequestLoggerService[0];
diff --git a/src/main/java/org/apache/sling/engine/impl/log/RequestLoggerService.java b/src/main/java/org/apache/sling/engine/impl/log/RequestLoggerService.java
index b3b7f04..ac1c00e 100644
--- a/src/main/java/org/apache/sling/engine/impl/log/RequestLoggerService.java
+++ b/src/main/java/org/apache/sling/engine/impl/log/RequestLoggerService.java
@@ -27,6 +27,8 @@ import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.ConfigurationPolicy;
 import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.propertytypes.ServiceDescription;
+import org.osgi.service.component.propertytypes.ServiceVendor;
 import org.osgi.service.metatype.annotations.AttributeDefinition;
 import org.osgi.service.metatype.annotations.Designate;
 import org.osgi.service.metatype.annotations.ObjectClassDefinition;
@@ -36,11 +38,9 @@ import org.osgi.service.metatype.annotations.Option;
  * The <code>RequestLoggerService</code> is a factory component which gets
  * configuration to register loggers for the {@link RequestLogger}.
  */
-@Component(service = RequestLoggerService.class, configurationPolicy = ConfigurationPolicy.REQUIRE,
-     property = {
-             "service.description=Factory for configuration based request/access loggers",
-             "service.vendor=The Apache Software Foundation"
-     })
+@Component(service = RequestLoggerService.class, configurationPolicy = ConfigurationPolicy.REQUIRE)
+@ServiceDescription("Factory for configuration based request/access loggers")
+@ServiceVendor("The Apache Software Foundation")
 @Designate(ocd = RequestLoggerService.Config.class, factory = true)
 public class RequestLoggerService {
 
diff --git a/src/main/java/org/apache/sling/engine/impl/parameters/RequestParameterSupportConfigurer.java b/src/main/java/org/apache/sling/engine/impl/parameters/RequestParameterSupportConfigurer.java
index a915342..7e64f9b 100644
--- a/src/main/java/org/apache/sling/engine/impl/parameters/RequestParameterSupportConfigurer.java
+++ b/src/main/java/org/apache/sling/engine/impl/parameters/RequestParameterSupportConfigurer.java
@@ -21,34 +21,38 @@ package org.apache.sling.engine.impl.parameters;
 import java.io.File;
 import java.io.IOException;
 
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.settings.SlingSettingsService;
-import org.osgi.framework.Constants;
 import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.propertytypes.ServiceDescription;
+import org.osgi.service.component.propertytypes.ServiceRanking;
+import org.osgi.service.component.propertytypes.ServiceVendor;
+import org.osgi.service.http.whiteboard.propertytypes.HttpWhiteboardContextSelect;
+import org.osgi.service.http.whiteboard.propertytypes.HttpWhiteboardFilterPattern;
 import org.osgi.service.metatype.annotations.AttributeDefinition;
 import org.osgi.service.metatype.annotations.Designate;
 import org.osgi.service.metatype.annotations.ObjectClassDefinition;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-
 @Component(
         name = RequestParameterSupportConfigurer.PID,
-        property = {
-            Constants.SERVICE_RANKING + ":Integer=" + Integer.MAX_VALUE,
-            "osgi.http.whiteboard.context.select=(osgi.http.whiteboard.context.name=org.apache.sling)",
-            "osgi.http.whiteboard.filter.pattern=/"
-        },
         service = Filter.class)
+@HttpWhiteboardContextSelect("(osgi.http.whiteboard.context.name=org.apache.sling)")
+@HttpWhiteboardFilterPattern("/")
+@ServiceDescription("Filter for request parameter support")
+@ServiceVendor("The Apache Software Foundation")
+@ServiceRanking(Integer.MAX_VALUE)
 @Designate(ocd=RequestParameterSupportConfigurer.Config.class)
 public class RequestParameterSupportConfigurer implements Filter {
 
diff --git a/src/main/java/org/apache/sling/engine/impl/request/RequestHistoryConsolePlugin.java b/src/main/java/org/apache/sling/engine/impl/request/RequestHistoryConsolePlugin.java
deleted file mode 100644
index c15f5ea..0000000
--- a/src/main/java/org/apache/sling/engine/impl/request/RequestHistoryConsolePlugin.java
+++ /dev/null
@@ -1,362 +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.sling.engine.impl.request;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Dictionary;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.regex.Pattern;
-
-import javax.servlet.Servlet;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.sling.api.SlingHttpServletRequest;
-import org.apache.sling.api.request.RequestProgressTracker;
-import org.apache.sling.api.request.ResponseUtil;
-import org.apache.sling.api.resource.ResourceUtil;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceRegistration;
-
-/**
- * Felix OSGi console plugin that displays info about recent requests processed
- * by Sling. Info about all requests can be found in the logs, but this is
- * useful when testing or explaining things.
- */
-@SuppressWarnings("serial")
-public class RequestHistoryConsolePlugin {
-
-    public static final String LABEL = "requests";
-
-    public static final String INDEX = "index";
-
-    public static final String CLEAR = "clear";
-
-    private static Plugin instance;
-
-    private static ServiceRegistration<Servlet> serviceRegistration;
-
-    public static final int STORED_REQUESTS_COUNT = 20;
-
-    private RequestHistoryConsolePlugin() {
-    }
-
-    public static void recordRequest(SlingHttpServletRequest r) {
-        if (instance != null) {
-            instance.addRequest(r);
-        }
-    }
-
-    public static void initPlugin(BundleContext context, int maxRequests, List<Pattern> storePatterns) {
-        if (instance == null) {
-            final Plugin tmp = new Plugin();
-            instance.update(maxRequests, storePatterns);
-            final Dictionary<String, Object> props = new Hashtable<String, Object>();
-            props.put(Constants.SERVICE_DESCRIPTION,
-                "Web Console Plugin to display information about recent Sling requests");
-            props.put(Constants.SERVICE_VENDOR,
-                "The Apache Software Foundation");
-            props.put(Constants.SERVICE_PID, tmp.getClass().getName());
-            props.put("felix.webconsole.label", LABEL);
-            props.put("felix.webconsole.title", "Recent requests");
-            props.put("felix.webconsole.category", "Sling");
-
-            serviceRegistration = context.registerService(Servlet.class, tmp, props);
-            instance = tmp;
-        } else {
-            instance.update(maxRequests, storePatterns);
-        }
-    }
-
-    public static void destroyPlugin() {
-        if (instance != null) {
-            try {
-                if (serviceRegistration != null) {
-                    serviceRegistration.unregister();
-                    serviceRegistration = null;
-                }
-            } finally {
-                instance = null;
-            }
-        }
-    }
-
-    public static final class Plugin extends HttpServlet {
-
-        private volatile RequestInfoMap requests;
-
-        private volatile List<Pattern> storePatterns;
-
-        public void update(int maxRequests, List<Pattern> storePatterns) {
-            this.requests = (maxRequests > 0)
-                    ? new RequestInfoMap(maxRequests)
-                    : null;
-            this.storePatterns = storePatterns;
-        }
-
-        public void deactivate() {
-            if (serviceRegistration != null) {
-                serviceRegistration.unregister();
-                serviceRegistration = null;
-            }
-
-            clear();
-        }
-
-        private void addRequest(SlingHttpServletRequest r) {
-            if (requests != null) {
-                String requestPath = r.getPathInfo();
-                boolean accept = true;
-                if (storePatterns != null && storePatterns.size() > 0) {
-                    accept = false;
-                    for (Pattern pattern : storePatterns) {
-                        if (pattern.matcher(requestPath).matches()) {
-                            accept = true;
-                            break;
-                        }
-                    }
-                }
-
-                if (accept) {
-                    synchronized (requests) {
-                        RequestInfo info = new RequestInfo(r);
-                        requests.put(info.getKey(), info);
-                    }
-                }
-            }
-        }
-
-        private void clear() {
-            if (requests != null) {
-                synchronized (requests) {
-                    requests.clear();
-                }
-            }
-        }
-
-        private String getLinksTable(String currentRequestIndex) {
-            final List<String> links = new ArrayList<String>();
-            if (requests != null) {
-                synchronized (requests) {
-                    for (RequestInfo info : requests.values()) {
-                        final String key = ResponseUtil.escapeXml(info.getKey());
-                        final boolean isCurrent = info.getKey().equals(
-                            currentRequestIndex);
-                        final StringBuilder sb = new StringBuilder();
-                        sb.append("<span style='white-space: pre; text-align:right; font-size:80%'>");
-                        sb.append(String.format("%1$8s", key));
-                        sb.append("</span> ");
-                        sb.append("<a href='" + LABEL + "?index=" + key + "'>");
-                        if (isCurrent) {
-                            sb.append("<b>");
-                        }
-                        sb.append(ResponseUtil.escapeXml(info.getLabel()));
-                        if (isCurrent) {
-                            sb.append("</b>");
-                        }
-                        sb.append("</a> ");
-                        links.add(sb.toString());
-                    }
-                }
-            }
-
-            final int nCols = 5;
-            while ((links.size() % nCols) != 0) {
-                links.add("&nbsp;");
-            }
-
-            final StringBuilder tbl = new StringBuilder();
-
-            tbl.append("<table class='nicetable ui-widget'>\n<tr>\n");
-            if (links.isEmpty()) {
-                tbl.append("No Requests recorded");
-            } else {
-                int i = 0;
-                for (String str : links) {
-                    if ((i++ % nCols) == 0) {
-                        tbl.append("</tr>\n<tr>\n");
-                    }
-                    tbl.append("<td>");
-                    tbl.append(str);
-                    tbl.append("</td>\n");
-                }
-            }
-            tbl.append("</tr>\n");
-
-            tbl.append("</table>\n");
-            return tbl.toString();
-        }
-
-        @Override
-        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
-                throws ServletException, IOException {
-
-            // Select request to display
-            RequestInfo info = null;
-            String key = req.getParameter(INDEX);
-            if (key != null && requests != null) {
-                synchronized (requests) {
-                    info = requests.get(key);
-                }
-            }
-
-            final PrintWriter pw = resp.getWriter();
-
-            if (requests != null) {
-                pw.println("<p class='statline ui-state-highlight'>Recorded "
-                    + requests.size() + " requests (max: "
-                    + requests.getMaxSize() + ")</p>");
-            } else {
-                pw.println("<p class='statline ui-state-highlight'>Request Recording disabled</p>");
-            }
-
-            pw.println("<div class='ui-widget-header ui-corner-top buttonGroup'>");
-            pw.println("<span style='float: left; margin-left: 1em'>Recent Requests</span>");
-            pw.println("<form method='POST'><input type='hidden' name='clear' value='clear'><input type='submit' value='Clear' class='ui-state-default ui-corner-all'></form>");
-            pw.println("</div>");
-
-            pw.println(getLinksTable(key));
-            pw.println("<br/>");
-
-            if (info != null) {
-
-                pw.println("<table class='nicetable ui-widget'>");
-
-                // Links to other requests
-                pw.println("<thead>");
-                pw.println("<tr>");
-                pw.printf(
-                    "<th class='ui-widget-header'>Request %s (%s %s) by %s - RequestProgressTracker Info</th>%n",
-                    key, ResponseUtil.escapeXml(info.getMethod()),
-                    ResponseUtil.escapeXml(info.getPathInfo()), ResponseUtil.escapeXml(info.getUser()));
-                pw.println("</tr>");
-                pw.println("</thead>");
-
-                pw.println("<tbody>");
-
-                // Request Progress Tracker Info
-                pw.println("<tr><td>");
-                final Iterator<String> it = info.getTracker().getMessages();
-                pw.print("<pre>");
-                while (it.hasNext()) {
-                    pw.print(ResponseUtil.escapeXml(it.next()));
-                }
-                pw.println("</pre></td></tr>");
-                pw.println("</tbody></table>");
-            }
-        }
-
-        @Override
-        protected void doPost(HttpServletRequest req, HttpServletResponse resp)
-                throws IOException {
-            if (req.getParameter(CLEAR) != null) {
-                clear();
-                resp.sendRedirect(req.getRequestURI());
-            }
-        }
-    }
-
-    private static class RequestInfo {
-
-        private static AtomicLong requestCounter = new AtomicLong(0);
-
-        private final String key;
-
-        private final String method;
-
-        private final String pathInfo;
-
-        private final String user;
-
-        private final RequestProgressTracker tracker;
-
-        RequestInfo(SlingHttpServletRequest request) {
-            this.key = String.valueOf(requestCounter.incrementAndGet());
-            this.method = request.getMethod();
-            this.pathInfo = request.getPathInfo();
-            this.user = request.getRemoteUser();
-            this.tracker = request.getRequestProgressTracker();
-        }
-
-        public String getKey() {
-            return key;
-        }
-
-        public String getMethod() {
-            return method;
-        }
-
-        public String getPathInfo() {
-            return pathInfo;
-        }
-
-        public String getUser() {
-            return user;
-        }
-
-        public String getLabel() {
-            final StringBuilder sb = new StringBuilder();
-
-            sb.append(getMethod());
-            sb.append(' ');
-
-            final String path = getPathInfo();
-            if (path != null && path.length() > 0) {
-                sb.append(ResourceUtil.getName(getPathInfo()));
-            } else {
-                sb.append('/');
-            }
-
-            return sb.toString();
-        }
-
-        public RequestProgressTracker getTracker() {
-            return tracker;
-        }
-    }
-
-    private static class RequestInfoMap extends
-            LinkedHashMap<String, RequestInfo> {
-
-        private int maxSize;
-
-        RequestInfoMap(int maxSize) {
-            this.maxSize = maxSize;
-        }
-
-        @Override
-        protected boolean removeEldestEntry(
-                java.util.Map.Entry<String, RequestInfo> eldest) {
-            return size() > maxSize;
-        }
-
-        public int getMaxSize() {
-            return maxSize;
-        }
-    }
-}
\ No newline at end of file