You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by gg...@apache.org on 2022/03/30 10:56:24 UTC

[karaf] branch KARAF-7392 created (now 122d1bb)

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

ggrzybek pushed a change to branch KARAF-7392
in repository https://gitbox.apache.org/repos/asf/karaf.git.


      at 122d1bb  [KARAF-7406] Update Karaf 4.4 manual to show new features of Pax Web 8

This branch includes the following new commits:

     new 5cc4c25  [KARAF-7392] Upgrade to Pax Web 8.0.1 - all integration tests work fine
     new bd5a583  [KARAF-7392] Fix some minor details in Webconsole plugin after Pax Web 8 upgrade
     new 122d1bb  [KARAF-7406] Update Karaf 4.4 manual to show new features of Pax Web 8

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


[karaf] 02/03: [KARAF-7392] Fix some minor details in Webconsole plugin after Pax Web 8 upgrade

Posted by gg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ggrzybek pushed a commit to branch KARAF-7392
in repository https://gitbox.apache.org/repos/asf/karaf.git

commit bd5a5838b8790605cbc9fe66e2d2fa2ec79fd8cf
Author: Grzegorz Grzybek <gr...@gmail.com>
AuthorDate: Fri Feb 11 12:31:29 2022 +0100

    [KARAF-7392] Fix some minor details in Webconsole plugin after Pax Web 8 upgrade
---
 .../java/org/apache/karaf/webconsole/http/HttpPlugin.java    | 12 +++++++-----
 webconsole/http/src/main/resources/res/ui/http-contexts.js   |  6 +++---
 2 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/webconsole/http/src/main/java/org/apache/karaf/webconsole/http/HttpPlugin.java b/webconsole/http/src/main/java/org/apache/karaf/webconsole/http/HttpPlugin.java
index 7373447..7156302 100644
--- a/webconsole/http/src/main/java/org/apache/karaf/webconsole/http/HttpPlugin.java
+++ b/webconsole/http/src/main/java/org/apache/karaf/webconsole/http/HttpPlugin.java
@@ -165,7 +165,7 @@ public class HttpPlugin extends AbstractWebConsolePlugin {
             jw.value(servlet.getServlet());
             jw.key("servletName");
             jw.value(servlet.getServletName());
-            jw.key("state");
+            jw.key("type");
             jw.value(servlet.getType());
             jw.key("urls");
             jw.array();
@@ -189,7 +189,7 @@ public class HttpPlugin extends AbstractWebConsolePlugin {
             jw.object();
             jw.key("id");
             jw.value(webDetail.getBundleId());
-            jw.key("bundlestate");
+            jw.key("bundleState");
             jw.value(webDetail.getState());
             jw.key("contextpath");
             jw.value(webDetail.getContextPath());
@@ -249,7 +249,9 @@ public class HttpPlugin extends AbstractWebConsolePlugin {
         ReportWebContainerView view = webContainer.adapt(ReportWebContainerView.class);
 
         for (WebApplicationInfo info : view.listWebApplications()) {
-
+            if (!info.isWab()) {
+                continue;
+            }
             WebDetail webDetail = new WebDetail();
             webDetail.setBundleId(info.getBundle().getBundleId());
             webDetail.setContextPath(info.getContextPath().trim());
@@ -289,10 +291,10 @@ public class HttpPlugin extends AbstractWebConsolePlugin {
                 stateSummary.append(", ");
             }
             first = false;
-            stateSummary.append(state.getValue()).append(" ").append(state.getKey());
+            stateSummary.append(state.getValue()).append(" from ").append(state.getKey());
         }
 
-        return "Http contexts: " + stateSummary;
+        return "Servlets: " + stateSummary;
     }
 
     public void setWebContainer(WebContainer webContainer) {
diff --git a/webconsole/http/src/main/resources/res/ui/http-contexts.js b/webconsole/http/src/main/resources/res/ui/http-contexts.js
index 47307f9..71d505c 100644
--- a/webconsole/http/src/main/resources/res/ui/http-contexts.js
+++ b/webconsole/http/src/main/resources/res/ui/http-contexts.js
@@ -112,13 +112,13 @@ function renderContextData( /* Element */ parent, /* Object */ context ) {
     for ( var idx in context.urls ) {
       urlBox.appendChild( link( trimUrl(context.urls[idx]), context.urls[idx] ) );
     }
+    parent.appendChild( urlBox );
 
     var contextBox = td( null, null );
     for ( var idx in context.contexts ) {
-      urlBox.appendChild( text( context.contexts[idx]  ) );
+        contextBox.appendChild( text( context.contexts[idx]  ) );
     }
-
-    parent.appendChild( urlBox );
+    parent.appendChild( contextBox );
 }
 
 function renderWebCtxtData( /* Element */ parent, /* Object */ webCtxt ) {

[karaf] 01/03: [KARAF-7392] Upgrade to Pax Web 8.0.1 - all integration tests work fine

Posted by gg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ggrzybek pushed a commit to branch KARAF-7392
in repository https://gitbox.apache.org/repos/asf/karaf.git

commit 5cc4c256fa591908e6b06e4d934589bf443bb36d
Author: Grzegorz Grzybek <gr...@gmail.com>
AuthorDate: Fri Feb 11 12:11:48 2022 +0100

    [KARAF-7392] Upgrade to Pax Web 8.0.1 - all integration tests work fine
---
 .../features/specs/src/main/feature/feature.xml    |   2 +
 .../spring-legacy/src/main/feature/feature.xml     |   9 +-
 .../features/spring/src/main/feature/feature.xml   |   2 +-
 .../features/standard/src/main/feature/feature.xml |  15 +-
 .../karaf-servlet-example-annotation/pom.xml       |   2 +-
 .../karaf/http/command/ServletListCommand.java     |  62 ------
 .../org/apache/karaf/http/core/ServletInfo.java    |  84 --------
 .../org/apache/karaf/http/core/ServletService.java |   2 +
 .../karaf/http/core/internal/HttpMBeanImpl.java    |  15 +-
 .../http/core/internal/ServletEventHandler.java    |  47 -----
 .../http/core/internal/ServletServiceImpl.java     |  77 ++-----
 .../karaf/http/core/internal/osgi/Activator.java   |  41 +---
 .../http/core/internal/HttpMBeanImplTest.java      |   2 +-
 .../java/org/apache/karaf/itests/HttpTest.java     |   3 +-
 .../test/java/org/apache/karaf/itests/WebTest.java |  13 +-
 .../itests/examples/HttpResourceExampleTest.java   |  11 +-
 .../karaf/itests/examples/RestExampleTest.java     |   9 +-
 .../karaf/itests/examples/ServletExampleTest.java  |  15 +-
 .../karaf/itests/examples/WarExampleTest.java      |   3 +-
 .../itests/examples/WebSocketExampleTest.java      |   8 +-
 ...venResolverRegisteredBeforeConfigAdminTest.java |   6 +-
 pom.xml                                            |   3 +-
 .../org/apache/karaf/web/WebContainerService.java  |   6 +-
 .../java/org/apache/karaf/web/commands/List.java   |  70 -------
 .../web/internal/WebContainerServiceImpl.java      | 231 +++++++--------------
 .../apache/karaf/web/internal/WebEventHandler.java |  40 ----
 .../apache/karaf/web/internal/osgi/Activator.java  |  18 +-
 .../web/management/internal/WebMBeanImpl.java      |  61 +++++-
 .../apache/karaf/webconsole/http/Activator.java    |  35 +---
 .../apache/karaf/webconsole/http/HttpPlugin.java   | 105 ++++------
 .../karaf/webconsole/http/ServletDetails.java      |  27 ++-
 .../karaf/webconsole/http/ServletEventHandler.java |  72 -------
 .../karaf/webconsole/http/WebEventHandler.java     |  68 ------
 .../src/main/resources/res/ui/http-contexts.js     |  14 +-
 34 files changed, 308 insertions(+), 870 deletions(-)

diff --git a/assemblies/features/specs/src/main/feature/feature.xml b/assemblies/features/specs/src/main/feature/feature.xml
index 25cc1fe..1106d73 100644
--- a/assemblies/features/specs/src/main/feature/feature.xml
+++ b/assemblies/features/specs/src/main/feature/feature.xml
@@ -124,6 +124,8 @@
 
     <!-- converter -->
     <feature name="converter" version="${felix.converter.version}">
+        <bundle start-level="9">mvn:org.osgi/org.osgi.util.function/${org.osgi.util.function.version}</bundle>
+        <bundle start-level="9">mvn:org.osgi/org.osgi.util.promise/${org.osgi.util.promise.version}</bundle>
         <bundle>mvn:org.apache.felix/org.apache.felix.converter/${felix.converter.version}</bundle>
     </feature>
 
diff --git a/assemblies/features/spring-legacy/src/main/feature/feature.xml b/assemblies/features/spring-legacy/src/main/feature/feature.xml
index eb18156..0a8b56f 100644
--- a/assemblies/features/spring-legacy/src/main/feature/feature.xml
+++ b/assemblies/features/spring-legacy/src/main/feature/feature.xml
@@ -44,7 +44,6 @@
         <feature>spring-dm</feature>
         <feature version="[2.5.6,4)">spring-web</feature>
         <bundle start-level="30">mvn:org.springframework.osgi/spring-osgi-web/${spring.osgi.version}</bundle>
-        <requirement>osgi.implementation;osgi.implementation="osgi.http";version:Version="1.1"</requirement>
     </feature>
 
     <!-- Spring 3.1.x support (required for spring-dm) -->
@@ -116,7 +115,6 @@
         <bundle dependency="true">mvn:javax.servlet/javax.servlet-api/3.1.0</bundle>
     	<bundle start-level="30">mvn:org.springframework/spring-web/${spring31.version}</bundle>
 		<bundle start-level="30">mvn:org.springframework/spring-webmvc/${spring31.version}</bundle>
-        <requirement>osgi.implementation;osgi.implementation="osgi.http";version:Version="1.1"</requirement>
     </feature>
 
     <feature name="spring-web-portlet" description="Spring 3.1.x Web Portlet support" version="${spring31.version}">
@@ -193,7 +191,6 @@
         <bundle dependency="true">mvn:javax.servlet/javax.servlet-api/3.1.0</bundle>
         <bundle start-level="30">mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.spring-web/${spring43.version}</bundle>
         <bundle start-level="30">mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.spring-webmvc/${spring43.version}</bundle>
-        <requirement>osgi.implementation;osgi.implementation="osgi.http";version:Version="1.1"</requirement>
     </feature>
 
     <feature name="spring-web-portlet" description="Spring 4.3.x Web Portlet support" version="${spring43.version}">
@@ -276,7 +273,6 @@
         <bundle dependency="true">mvn:javax.servlet/javax.servlet-api/3.1.0</bundle>
         <bundle start-level="30">mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.spring-web/${spring52.version}</bundle>
         <bundle start-level="30">mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.spring-webmvc/${spring52.version}</bundle>
-        <requirement>osgi.implementation;osgi.implementation="osgi.http";version:Version="1.1"</requirement>
     </feature>
 
     <feature name="spring-websocket" description="Spring 5.2.x WebSocket support" version="${spring52.version}">
@@ -288,6 +284,7 @@
     <!-- Spring Security support -->
 
     <feature name="spring-security" description="Spring Security 3.1.x support" version="${spring.security31.version}">
+        <feature>pax-web-jsp</feature>
         <feature>pax-web-war</feature>
 	    <feature version="[3,4)">spring-web</feature>
         <bundle dependency="true">mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aspectj/${aspectj.bundle.version}</bundle>
@@ -299,6 +296,7 @@
     </feature>
 
     <feature name="spring-security" description="Spring Security 4.2.x support" version="${spring.security42.version}">
+        <feature>pax-web-jsp</feature>
         <feature>pax-web-war</feature>
         <feature version="[4,5)">spring-web</feature>
         <bundle dependency="true">mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aspectj/${aspectj.bundle.version}</bundle>
@@ -310,6 +308,7 @@
     </feature>
 
     <feature name="spring-security" description="Spring Security 5.3.x support" version="${spring.security53.version}">
+        <feature>pax-web-jsp</feature>
         <feature>pax-web-war</feature>
         <feature version="[5.1,6)">spring-jdbc</feature>
         <feature version="[5.1,6)">spring-tx</feature>
@@ -327,6 +326,7 @@
     </feature>
 
     <feature name="spring-security" description="Spring Security 5.4.x support" version="${spring.security54.version}">
+        <feature>pax-web-jsp</feature>
         <feature>pax-web-war</feature>
         <feature version="[5.2,6)">spring-jdbc</feature>
         <feature version="[5.2,6)">spring-tx</feature>
@@ -344,6 +344,7 @@
     </feature>
 
     <feature name="spring-security" description="Spring Security 5.5.x support" version="${spring.security55.version}">
+        <feature>pax-web-jsp</feature>
         <feature>pax-web-war</feature>
         <feature version="[5.2,6)">spring-jdbc</feature>
         <feature version="[5.2,6)">spring-tx</feature>
diff --git a/assemblies/features/spring/src/main/feature/feature.xml b/assemblies/features/spring/src/main/feature/feature.xml
index a79e1f8..88a5890 100644
--- a/assemblies/features/spring/src/main/feature/feature.xml
+++ b/assemblies/features/spring/src/main/feature/feature.xml
@@ -89,7 +89,6 @@
         <bundle dependency="true">mvn:javax.servlet/javax.servlet-api/3.1.0</bundle>
         <bundle start-level="30">mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.spring-web/${spring53.version}</bundle>
         <bundle start-level="30">mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.spring-webmvc/${spring53.version}</bundle>
-        <requirement>osgi.implementation;osgi.implementation="osgi.http";version:Version="1.1"</requirement>
     </feature>
 
     <feature name="spring-websocket" description="Spring 5.3.x WebSocket support" version="${spring53.version}">
@@ -101,6 +100,7 @@
     <!-- Spring Security -->
 
     <feature name="spring-security" description="Spring Security 5.6.x support" version="${spring.security56.version}">
+        <feature>pax-web-jsp</feature>
         <feature>pax-web-war</feature>
         <feature version="[5.2,6)">spring-jdbc</feature>
         <feature version="[5.2,6)">spring-tx</feature>
diff --git a/assemblies/features/standard/src/main/feature/feature.xml b/assemblies/features/standard/src/main/feature/feature.xml
index 0836fa3..68bc166 100644
--- a/assemblies/features/standard/src/main/feature/feature.xml
+++ b/assemblies/features/standard/src/main/feature/feature.xml
@@ -867,7 +867,7 @@ org.osgi.service.http.port=8181
     </feature>
 
     <feature name="pax-web-http" description="Pax Web OSGi HTTP Service" version="${pax.web.version}">
-        <feature>pax-http</feature>
+        <feature>pax-web-http-jetty</feature>
         <bundle start-level="30">mvn:org.apache.karaf.http/org.apache.karaf.http.core/${project.version}</bundle>
         <capability>http-service;provider:=pax-http</capability>
         <conditional>
@@ -881,23 +881,26 @@ org.osgi.service.http.port=8181
 
     <feature name="pax-web-http-whiteboard" description="Pax Web OSGi HTTP Whiteboard support" version="${pax.web.version}">
         <feature>pax-web-http</feature>
-        <feature>pax-http-whiteboard</feature>
+        <feature>pax-web-whiteboard</feature>
+        <feature>pax-web-websockets</feature>
     </feature>
     <feature name="http-whiteboard" description="Transition feature for backward compatibility" version="${pax.web.version}">
         <feature>pax-web-http-whiteboard</feature>
     </feature>
 
-    <feature name="pax-web-war" description="Turn Karaf as a full WebContainer" version="${project.version}">
+    <feature name="pax-web-http-war" description="Turn Karaf as a full WebContainer" version="${project.version}">
         <feature>pax-web-http</feature>
-        <feature>pax-war</feature>
+        <feature>pax-web-war</feature>
+        <feature>pax-web-jsp</feature>
+        <feature>pax-web-websockets</feature>
         <bundle start-level="30">mvn:org.apache.karaf.web/org.apache.karaf.web.core/${project.version}</bundle>
     </feature>
     <feature name="war" description="Transition feature for backward compatibility" version="${project.version}">
-        <feature>pax-web-war</feature>
+        <feature>pax-web-http-war</feature>
     </feature>
 
     <feature name="jetty" description="Transition feature for backward compatibility" version="9.4.43.v20210629">
-        <feature>pax-jetty</feature>
+        <feature>pax-web-jetty</feature>
     </feature>
 
     <feature name="kar" description="Provide KAR (KARaf archive) support" version="${project.version}">
diff --git a/examples/karaf-servlet-example/karaf-servlet-example-annotation/pom.xml b/examples/karaf-servlet-example/karaf-servlet-example-annotation/pom.xml
index 32dc06b..1bc23a0 100644
--- a/examples/karaf-servlet-example/karaf-servlet-example-annotation/pom.xml
+++ b/examples/karaf-servlet-example/karaf-servlet-example-annotation/pom.xml
@@ -49,7 +49,7 @@
                 <configuration>
                     <instructions>
                         <_wab>src/main/webapp/</_wab>
-                        <Web-ContextPath>servlet-example</Web-ContextPath>
+                        <Web-ContextPath>/servlet-example</Web-ContextPath>
                         <Export-Package>!*</Export-Package>
                         <Import-Package>
                             *
diff --git a/http/src/main/java/org/apache/karaf/http/command/ServletListCommand.java b/http/src/main/java/org/apache/karaf/http/command/ServletListCommand.java
deleted file mode 100644
index afbe003..0000000
--- a/http/src/main/java/org/apache/karaf/http/command/ServletListCommand.java
+++ /dev/null
@@ -1,62 +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.karaf.http.command;
-
-import java.util.Arrays;
-
-import org.apache.karaf.http.core.ServletInfo;
-import org.apache.karaf.http.core.ServletService;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.table.Col;
-import org.apache.karaf.shell.support.table.ShellTable;
-
-@Command(scope = "http", name = "list", description = "Lists details for servlets.")
-@Service
-public class ServletListCommand implements Action {
-
-    @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
-    boolean noFormat;
-
-    @Reference
-    private ServletService servletService;
-    
-    @Override
-    public Object execute() throws Exception {
-        ShellTable table = new ShellTable();
-        table.column(new Col("ID"));
-        table.column(new Col("Servlet"));
-        table.column(new Col("Servlet-Name"));
-        table.column(new Col("State"));
-        table.column(new Col("Alias"));
-        table.column(new Col("Url"));
-
-        for (ServletInfo info : servletService.getServlets()) {
-            table.addRow().addContent(info.getBundleId(), info.getClassName(), info.getName(),
-                                      info.getStateString(), info.getAlias(), Arrays.toString(info.getUrls()));
-        }
-        table.print(System.out, !noFormat);
-        return null;
-    }
-
-    public void setServletService(ServletService servletService) {
-        this.servletService = servletService;
-    }
-}
diff --git a/http/src/main/java/org/apache/karaf/http/core/ServletInfo.java b/http/src/main/java/org/apache/karaf/http/core/ServletInfo.java
deleted file mode 100644
index 515eb36..0000000
--- a/http/src/main/java/org/apache/karaf/http/core/ServletInfo.java
+++ /dev/null
@@ -1,84 +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.karaf.http.core;
-
-import org.ops4j.pax.web.service.spi.WebEvent;
-
-public class ServletInfo {
-    private String name;
-    private long bundleId;
-    private String className;
-    private String alias;
-    private int state;
-    private String[] urls;
-
-    public String getName() {
-        return name;
-    }
-    public void setName(String name) {
-        this.name = name;
-    }
-    public long getBundleId() {
-        return bundleId;
-    }
-    public void setBundleId(long bundleId) {
-        this.bundleId = bundleId;
-    }
-    public String getClassName() {
-        return className;
-    }
-    public void setClassName(String className) {
-        this.className = className;
-    }
-    public int getState() {
-        return state;
-    }
-    public void setState(int state) {
-        this.state = state;
-    }
-    public String getAlias() {
-        return alias;
-    }
-    public void setAlias(String alias) {
-        this.alias = alias;
-    }
-    public String[] getUrls() {
-        return urls;
-    }
-    public void setUrls(String[] urls) {
-        this.urls = urls;
-    }
-    
-    public String getStateString() {
-        switch (state) {
-            case WebEvent.DEPLOYING:
-                return "Deploying  ";
-            case WebEvent.DEPLOYED:
-                return "Deployed   ";
-            case WebEvent.UNDEPLOYING:
-                return "Undeploying";
-            case WebEvent.UNDEPLOYED:
-                return "Undeployed ";
-            case WebEvent.FAILED:
-                return "Failed     ";
-            case WebEvent.WAITING:
-                return "Waiting    ";
-            default:
-                return "Failed     ";
-        }
-    }
-}
diff --git a/http/src/main/java/org/apache/karaf/http/core/ServletService.java b/http/src/main/java/org/apache/karaf/http/core/ServletService.java
index fd9b24a..a6296bd 100644
--- a/http/src/main/java/org/apache/karaf/http/core/ServletService.java
+++ b/http/src/main/java/org/apache/karaf/http/core/ServletService.java
@@ -18,6 +18,8 @@ package org.apache.karaf.http.core;
 
 import java.util.List;
 
+import org.ops4j.pax.web.service.spi.model.info.ServletInfo;
+
 public interface ServletService {
 
     List<ServletInfo> getServlets();
diff --git a/http/src/main/java/org/apache/karaf/http/core/internal/HttpMBeanImpl.java b/http/src/main/java/org/apache/karaf/http/core/internal/HttpMBeanImpl.java
index 3d359c8..c5c7582 100644
--- a/http/src/main/java/org/apache/karaf/http/core/internal/HttpMBeanImpl.java
+++ b/http/src/main/java/org/apache/karaf/http/core/internal/HttpMBeanImpl.java
@@ -34,14 +34,15 @@ import javax.management.openmbean.TabularDataSupport;
 import javax.management.openmbean.TabularType;
 
 import org.apache.karaf.http.core.*;
+import org.ops4j.pax.web.service.spi.model.info.ServletInfo;
 
 /**
  * Implementation of the HTTP MBean.
  */
 public class HttpMBeanImpl extends StandardMBean implements HttpMBean {
 
-    private ServletService servletService;
-    private ProxyService proxyService;
+    private final ServletService servletService;
+    private final ProxyService proxyService;
 
     public HttpMBeanImpl(ServletService servletService, ProxyService proxyService) throws NotCompliantMBeanException {
         super(HttpMBean.class);
@@ -53,16 +54,16 @@ public class HttpMBeanImpl extends StandardMBean implements HttpMBean {
     public TabularData getServlets() throws MBeanException {
         try {
             CompositeType servletType = new CompositeType("Servlet", "HTTP Servlet",
-                new String[]{"Bundle-ID", "Servlet", "Servlet Name", "State", "Alias", "URL"},
-                new String[]{"ID of the bundle that registered the servlet", "Class name of the servlet", "Servlet Name", "Current state of the servlet", "Aliases of the servlet", "URL of the servlet"},
+                new String[]{"Bundle-ID", "Servlet", "Servlet Name", "Context Path", "Type", "URL"},
+                new String[]{"ID of the bundle that registered the servlet", "Class name of the servlet", "Servlet Name", "Contexts of the servlet", "Type of the servlet", "URLs of the servlet"},
                 new OpenType[]{SimpleType.LONG, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING});
-            TabularType tableType = new TabularType("Servlets", "Table of all HTTP servlets", servletType, new String[]{"Bundle-ID", "Servlet Name", "State"});
+            TabularType tableType = new TabularType("Servlets", "Table of all HTTP servlets", servletType, new String[]{"Bundle-ID", "Servlet Name", "Type"});
             TabularData table = new TabularDataSupport(tableType);
             List<ServletInfo> servletInfos = servletService.getServlets();
             for (ServletInfo info : servletInfos) {
                 CompositeData data = new CompositeDataSupport(servletType,
-                        new String[]{"Bundle-ID", "Servlet", "Servlet Name", "State", "Alias", "URL"},
-                        new Object[]{info.getBundleId(), info.getClassName(), info.getName(), info.getStateString(), info.getAlias(), Arrays.toString(info.getUrls())});
+                        new String[]{"Bundle-ID", "Servlet", "Servlet Name", "Context Path", "Type", "URL"},
+                        new Object[]{info.getBundle().getBundleId(), info.getServletClass(), info.getServletName(), Arrays.toString(info.getContexts()), info.getType(), Arrays.toString(info.getMapping())});
                 table.put(data);
             }
             return table;
diff --git a/http/src/main/java/org/apache/karaf/http/core/internal/ServletEventHandler.java b/http/src/main/java/org/apache/karaf/http/core/internal/ServletEventHandler.java
deleted file mode 100644
index de3bafb..0000000
--- a/http/src/main/java/org/apache/karaf/http/core/internal/ServletEventHandler.java
+++ /dev/null
@@ -1,47 +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.karaf.http.core.internal;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.ops4j.pax.web.service.spi.ServletEvent;
-import org.ops4j.pax.web.service.spi.ServletListener;
-import org.osgi.framework.Bundle;
-
-public class ServletEventHandler implements ServletListener {
-
-	Map<String, ServletEvent> servletEvents = new HashMap<>();
-	
-	public synchronized void servletEvent(ServletEvent event) {
-		servletEvents.put(event.getServletName(), event);
-	}
-
-	/**
-	 * @return the servletEvents
-	 */
-	public synchronized List<ServletEvent> getServletEvents() {
-		return new ArrayList<>(servletEvents.values());
-	}
-
-	public synchronized void removeEventsForBundle(Bundle bundle) {
-        servletEvents.entrySet().removeIf(entry -> entry.getValue().getBundle() == bundle);
-	}
-
-}
diff --git a/http/src/main/java/org/apache/karaf/http/core/internal/ServletServiceImpl.java b/http/src/main/java/org/apache/karaf/http/core/internal/ServletServiceImpl.java
index 6b85f33..1a218a2 100644
--- a/http/src/main/java/org/apache/karaf/http/core/internal/ServletServiceImpl.java
+++ b/http/src/main/java/org/apache/karaf/http/core/internal/ServletServiceImpl.java
@@ -17,77 +17,34 @@
 package org.apache.karaf.http.core.internal;
 
 import java.util.ArrayList;
-import java.util.Comparator;
+import java.util.Collections;
 import java.util.List;
+import java.util.Set;
 
-import javax.servlet.Servlet;
-
-import org.apache.karaf.http.core.ServletInfo;
 import org.apache.karaf.http.core.ServletService;
-import org.ops4j.pax.web.service.spi.ServletEvent;
+import org.ops4j.pax.web.service.WebContainer;
+import org.ops4j.pax.web.service.spi.model.info.ServletInfo;
+import org.ops4j.pax.web.service.spi.model.views.ReportWebContainerView;
 
 public class ServletServiceImpl implements ServletService {
-    private ServletEventHandler servletEventHandler;
+    private final WebContainer webContainer;
 
-    public ServletServiceImpl(ServletEventHandler servletEventHandler) {
-        this.servletEventHandler = servletEventHandler;
+    public ServletServiceImpl(WebContainer webContainer) {
+        this.webContainer = webContainer;
     }
 
     @Override
     public List<ServletInfo> getServlets() {
-        List<ServletInfo> servletInfos = new ArrayList<>();
-        List<ServletEvent> events = servletEventHandler.getServletEvents();
-        events.sort(Comparator.<ServletEvent>comparingLong(s -> s.getBundle().getBundleId())
-                .thenComparing(ServletEvent::getServletName));
-        for (ServletEvent event : events) {
-            Servlet servlet = event.getServlet();
-            String servletClassName = " ";
-            if (servlet != null) {
-                    servletClassName = servlet.getClass().getName();
-                    servletClassName = servletClassName.substring(servletClassName.lastIndexOf(".") + 1);
-            }
-            String servletName = event.getServletName() != null ? event.getServletName() : " ";
-            if (servletName.contains(".")) {
-                servletName = servletName.substring(servletName.lastIndexOf(".") + 1);
-            }
-
-            String alias = event.getAlias();
-            String[] urls = event.getUrlParameter();
-
-            String contextPath = event.getBundle().getHeaders().get("Web-ContextPath");
-            if (contextPath == null) {
-                contextPath = event.getBundle().getHeaders().get("Webapp-Context"); // this one used by pax-web but is deprecated
-            }
-            if (contextPath != null) {
-                contextPath = contextPath.trim();
-                if (!contextPath.startsWith("/")) {
-                    contextPath = "/" + contextPath;
-                }
-                if (alias != null) {
-                    alias = contextPath + alias;
-                }
-                if (urls != null) {
-                    urls = urls.clone();
-                    for (int i = 0; i < urls.length; i++) {
-                        if (urls[i].startsWith("/")) {
-                            urls[i] = contextPath + urls[i];
-                        } else {
-                            urls[i] = contextPath + "/" + urls[i];
-                        }
-                    }
-                }
-            }
-
-            ServletInfo info = new ServletInfo();
-            info.setBundleId(event.getBundle().getBundleId());
-            info.setName(servletName);
-            info.setClassName(servletClassName);
-            info.setState(event.getType());
-            info.setAlias(alias != null ? alias : " ");
-            info.setUrls(urls != null ? urls : new String[] {""});
-            servletInfos.add(info);
+        if (webContainer == null) {
+            return Collections.emptyList();
+        }
+        ReportWebContainerView view = webContainer.adapt(ReportWebContainerView.class);
+        if (view == null) {
+            return Collections.emptyList();
         }
-        return servletInfos;
+
+        Set<ServletInfo> servletInfos = view.listServlets();
+        return new ArrayList<>(servletInfos);
     }
 
 }
diff --git a/http/src/main/java/org/apache/karaf/http/core/internal/osgi/Activator.java b/http/src/main/java/org/apache/karaf/http/core/internal/osgi/Activator.java
index e1a2b37..cfbc874 100644
--- a/http/src/main/java/org/apache/karaf/http/core/internal/osgi/Activator.java
+++ b/http/src/main/java/org/apache/karaf/http/core/internal/osgi/Activator.java
@@ -21,7 +21,6 @@ import org.apache.karaf.http.core.ProxyService;
 import org.apache.karaf.http.core.ServletService;
 import org.apache.karaf.http.core.internal.HttpMBeanImpl;
 import org.apache.karaf.http.core.internal.ProxyServiceImpl;
-import org.apache.karaf.http.core.internal.ServletEventHandler;
 import org.apache.karaf.http.core.internal.ServletServiceImpl;
 import org.apache.karaf.http.core.internal.proxy.RandomBalancingPolicy;
 import org.apache.karaf.http.core.internal.proxy.RoundRobinBalancingPolicy;
@@ -30,9 +29,7 @@ import org.apache.karaf.util.tracker.annotation.Managed;
 import org.apache.karaf.util.tracker.annotation.ProvideService;
 import org.apache.karaf.util.tracker.annotation.RequireService;
 import org.apache.karaf.util.tracker.annotation.Services;
-import org.ops4j.pax.web.service.spi.ServletListener;
-import org.osgi.framework.BundleEvent;
-import org.osgi.framework.BundleListener;
+import org.ops4j.pax.web.service.WebContainer;
 import org.osgi.service.cm.ConfigurationAdmin;
 import org.osgi.service.cm.ManagedService;
 import org.osgi.service.http.HttpService;
@@ -43,6 +40,7 @@ import java.util.Hashtable;
 @Services(
         requires = {
                 @RequireService(HttpService.class),
+                @RequireService(WebContainer.class),
                 @RequireService(ConfigurationAdmin.class)
         },
         provides = {
@@ -53,8 +51,6 @@ import java.util.Hashtable;
 @Managed("org.apache.karaf.http")
 public class Activator extends BaseActivator implements ManagedService {
 
-    private BundleListener listener;
-
     private ProxyService proxyService;
 
     @Override
@@ -69,20 +65,12 @@ public class Activator extends BaseActivator implements ManagedService {
             return;
         }
 
-        final ServletEventHandler servletEventHandler = new ServletEventHandler();
-        register(ServletListener.class, servletEventHandler);
-
-        ServletServiceImpl servletService = new ServletServiceImpl(servletEventHandler);
-        register(ServletService.class, servletService);
-
-        listener = event -> {
-            if (event.getType() == BundleEvent.UNINSTALLED
-                    || event.getType() == BundleEvent.UNRESOLVED
-                    || event.getType() == BundleEvent.STOPPED) {
-                servletEventHandler.removeEventsForBundle(event.getBundle());
-            }
-        };
-        bundleContext.addBundleListener(listener);
+        WebContainer webContainer = getTrackedService(WebContainer.class);
+        ServletServiceImpl servletService = null;
+        if (webContainer != null) {
+            servletService = new ServletServiceImpl(webContainer);
+            register(ServletService.class, servletService);
+        }
 
         RandomBalancingPolicy randomBalancingPolicy = new RandomBalancingPolicy();
         Hashtable<String, String> randomBalancingPolicyProperties = new Hashtable<>();
@@ -97,17 +85,10 @@ public class Activator extends BaseActivator implements ManagedService {
         proxyService = new ProxyServiceImpl(httpService, configurationAdmin, bundleContext);
         register(ProxyService.class, proxyService);
 
-        HttpMBeanImpl httpMBean = new HttpMBeanImpl(servletService, proxyService);
-        registerMBean(httpMBean, "type=http");
-    }
-
-    @Override
-    protected void doStop() {
-        if (listener != null) {
-            bundleContext.removeBundleListener(listener);
-            listener = null;
+        if (servletService != null) {
+            HttpMBeanImpl httpMBean = new HttpMBeanImpl(servletService, proxyService);
+            registerMBean(httpMBean, "type=http");
         }
-        super.doStop();
     }
 
     @Override
diff --git a/http/src/test/java/org/apache/karaf/http/core/internal/HttpMBeanImplTest.java b/http/src/test/java/org/apache/karaf/http/core/internal/HttpMBeanImplTest.java
index 994eb70..960db02 100644
--- a/http/src/test/java/org/apache/karaf/http/core/internal/HttpMBeanImplTest.java
+++ b/http/src/test/java/org/apache/karaf/http/core/internal/HttpMBeanImplTest.java
@@ -28,7 +28,7 @@ public class HttpMBeanImplTest {
 
     @Test
     public void testRegisterMBean() throws Exception {
-        HttpMBeanImpl httpMBean = new HttpMBeanImpl(new ServletServiceImpl(new ServletEventHandler()), new ProxyServiceImpl(null, null, null));
+        HttpMBeanImpl httpMBean = new HttpMBeanImpl(new ServletServiceImpl(null), new ProxyServiceImpl(null, null, null));
         MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
         mbeanServer.registerMBean(httpMBean, new ObjectName("org.apache.karaf:type=http,name=root"));
         
diff --git a/itests/test/src/test/java/org/apache/karaf/itests/HttpTest.java b/itests/test/src/test/java/org/apache/karaf/itests/HttpTest.java
index 02e1a47..3374b68 100644
--- a/itests/test/src/test/java/org/apache/karaf/itests/HttpTest.java
+++ b/itests/test/src/test/java/org/apache/karaf/itests/HttpTest.java
@@ -38,13 +38,14 @@ public class HttpTest extends BaseTest {
     @Before
     public void installHttpFeature() throws Exception {
         installAndAssertFeature("http");
+        installAndAssertFeature("pax-web-karaf");
         installAndAssertFeature("webconsole");
     }
     
     @Test
     public void list() throws Exception {
         waitForService("(objectClass=javax.servlet.ServletContext)", 5000);
-        assertContains("/system/console", executeCommand("http:list"));
+        assertContains("/system/console", executeCommand("web:servlet-list"));
     }
 
     @Test
diff --git a/itests/test/src/test/java/org/apache/karaf/itests/WebTest.java b/itests/test/src/test/java/org/apache/karaf/itests/WebTest.java
index 3d1d09b..6fb77c7 100644
--- a/itests/test/src/test/java/org/apache/karaf/itests/WebTest.java
+++ b/itests/test/src/test/java/org/apache/karaf/itests/WebTest.java
@@ -40,11 +40,12 @@ public class WebTest extends BaseTest {
     @Before
     public void installWarFeature() throws Exception {
         installAndAssertFeature("war");
+        installAndAssertFeature("pax-web-karaf");
     }
 
     @Test
     public void listCommand() throws Exception {
-        String listOutput = executeCommand("web:list");
+        String listOutput = executeCommand("web:wab-list");
         System.out.println(listOutput);
         assertFalse(listOutput.isEmpty());
     }
@@ -60,12 +61,12 @@ public class WebTest extends BaseTest {
     @Test
     public void installUninstallCommands() throws Exception {
         System.out.println(executeCommand("web:install mvn:org.apache.karaf.examples/karaf-war-example-webapp/" + System.getProperty("karaf.version") + "/war test"));
-        String listOutput = executeCommand("web:list");
+        String listOutput = executeCommand("web:wab-list");
         System.out.println(listOutput);
         assertContains("/test", listOutput);
         while (!listOutput.contains("Deployed")) {
             Thread.sleep(500);
-            listOutput = executeCommand("web:list");
+            listOutput = executeCommand("web:wab-list");
         }
         URL url = new URL("http://localhost:" + getHttpPort() + "/test");
         HttpURLConnection connection = (HttpURLConnection) url.openConnection();
@@ -84,11 +85,11 @@ public class WebTest extends BaseTest {
         String name = "mvn_org.apache.karaf.examples_karaf-war-example-webapp_" + System.getProperty("karaf.version") + "_war";
         String bundleId = executeCommand("bundle:id " + name);
         System.out.println(executeCommand("web:uninstall " + bundleId));
-        listOutput = executeCommand("web:list");
+        listOutput = executeCommand("web:wab-list");
         System.out.println(listOutput);
         while (listOutput.contains("/test")) {
             Thread.sleep(500);
-            listOutput = executeCommand("web:list");
+            listOutput = executeCommand("web:wab-list");
         }
         assertContainsNot("/test", listOutput);
     }
@@ -98,10 +99,10 @@ public class WebTest extends BaseTest {
         MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
         ObjectName name = new ObjectName("org.apache.karaf:type=web,name=root");
         mbeanServer.invoke(name, "install", new Object[]{ "mvn:org.apache.karaf.examples/karaf-war-example-webapp/" + System.getProperty("karaf.version") + "/war", "test" }, new String[]{ String.class.getName(), String.class.getName() });
+        Thread.sleep(2000);
         TabularData webBundles = (TabularData) mbeanServer.getAttribute(name, "WebBundles");
         assertEquals(1, webBundles.size());
 
-        Thread.sleep(2000);
 
         URL url = new URL("http://localhost:" + getHttpPort() + "/test");
         HttpURLConnection connection = (HttpURLConnection) url.openConnection();
diff --git a/itests/test/src/test/java/org/apache/karaf/itests/examples/HttpResourceExampleTest.java b/itests/test/src/test/java/org/apache/karaf/itests/examples/HttpResourceExampleTest.java
index 3ed7a11..5cc2b00 100644
--- a/itests/test/src/test/java/org/apache/karaf/itests/examples/HttpResourceExampleTest.java
+++ b/itests/test/src/test/java/org/apache/karaf/itests/examples/HttpResourceExampleTest.java
@@ -32,19 +32,20 @@ import java.net.URL;
 @ExamReactorStrategy(PerClass.class)
 public class HttpResourceExampleTest extends BaseTest {
 
-    @Test(timeout = 60000L)
+    @Test(timeout = 600000L)
     public void test() throws Exception {
         addFeaturesRepository("mvn:org.apache.karaf.examples/karaf-http-resource-example-features/" + System.getProperty("karaf.version") + "/xml");
 
+        installAndAssertFeature("pax-web-karaf");
         installAndAssertFeature("karaf-http-resource-example-whiteboard");
 
-        String command = executeCommand("http:list");
-        while (!command.contains("Deployed")) {
+        String command = executeCommand("web:servlet-list");
+        while (!command.contains("/example/*")) {
             Thread.sleep(200);
-            command = executeCommand("http:list");
+            command = executeCommand("web:servlet-list");
         }
         assertContains("ResourceServlet", command);
-        assertContains("Deployed", command);
+        assertContains("Whiteboard", command);
 
         URL url = new URL("http://localhost:" + getHttpPort() + "/example/index.html");
         HttpURLConnection connection = (HttpURLConnection) url.openConnection();
diff --git a/itests/test/src/test/java/org/apache/karaf/itests/examples/RestExampleTest.java b/itests/test/src/test/java/org/apache/karaf/itests/examples/RestExampleTest.java
index 9d1e94c..fbe4d25 100644
--- a/itests/test/src/test/java/org/apache/karaf/itests/examples/RestExampleTest.java
+++ b/itests/test/src/test/java/org/apache/karaf/itests/examples/RestExampleTest.java
@@ -38,6 +38,7 @@ public class RestExampleTest extends BaseTest {
         addFeaturesRepository("mvn:org.apache.karaf.examples/karaf-rest-example-features/" + System.getProperty("karaf.version") + "/xml");
         installAndAssertFeature("http");
         installAndAssertFeature("http-whiteboard");
+        installAndAssertFeature("pax-web-karaf");
     }
 
     private void verify() throws Exception {
@@ -118,12 +119,14 @@ public class RestExampleTest extends BaseTest {
     public void testWhiteboard() throws Exception {
         setup();
 
+        installAndAssertFeature("activation");
+        installAndAssertFeature("scr");
         installAndAssertFeature("karaf-rest-example-whiteboard");
 
-        String output = executeCommand("http:list");
-        while (!output.contains("Deployed")) {
+        String output = executeCommand("web:servlet-list");
+        while (!output.contains("cxf-servlet")) {
             Thread.sleep(500);
-            output = executeCommand("http:list");
+            output = executeCommand("web:servlet-list");
         }
         System.out.println(output);
 
diff --git a/itests/test/src/test/java/org/apache/karaf/itests/examples/ServletExampleTest.java b/itests/test/src/test/java/org/apache/karaf/itests/examples/ServletExampleTest.java
index 0a91655..2631394 100644
--- a/itests/test/src/test/java/org/apache/karaf/itests/examples/ServletExampleTest.java
+++ b/itests/test/src/test/java/org/apache/karaf/itests/examples/ServletExampleTest.java
@@ -43,13 +43,14 @@ public class ServletExampleTest extends BaseTest {
         addFeaturesRepository("mvn:org.apache.karaf.examples/karaf-servlet-example-features/" + System.getProperty("karaf.version") + "/xml");
         installAndAssertFeature("http");
         installAndAssertFeature("http-whiteboard");
+        installAndAssertFeature("pax-web-karaf");
     }
 
     private void verify() throws Exception {
-        String command = executeCommand("http:list");
+        String command = executeCommand("web:servlet-list");
         while (!command.contains("servlet-example")) {
             Thread.sleep(200);
-            command = executeCommand("http:list");
+            command = executeCommand("web:servlet-list");
         }
         System.out.println(command);
 
@@ -85,10 +86,10 @@ public class ServletExampleTest extends BaseTest {
 
         installAndAssertFeature("karaf-servlet-example-annotation");
 
-        String command = executeCommand("http:list");
-        while (!command.contains("servlet-example/multipart")) {
+        String command = executeCommand("web:servlet-list");
+        while (!command.contains("/multipart")) {
             Thread.sleep(200);
-            command = executeCommand("http:list");
+            command = executeCommand("web:servlet-list");
         }
 
         verify();
@@ -118,10 +119,10 @@ public class ServletExampleTest extends BaseTest {
 
         installAndAssertFeature("karaf-servlet-example-upload");
 
-        String command = executeCommand("http:list");
+        String command = executeCommand("web:servlet-list");
         while (!command.contains("upload-example")) {
             Thread.sleep(200);
-            command = executeCommand("http:list");
+            command = executeCommand("web:servlet-list");
         }
         System.out.println(command);
 
diff --git a/itests/test/src/test/java/org/apache/karaf/itests/examples/WarExampleTest.java b/itests/test/src/test/java/org/apache/karaf/itests/examples/WarExampleTest.java
index 967d270..fa13328 100644
--- a/itests/test/src/test/java/org/apache/karaf/itests/examples/WarExampleTest.java
+++ b/itests/test/src/test/java/org/apache/karaf/itests/examples/WarExampleTest.java
@@ -35,12 +35,13 @@ public class WarExampleTest extends BaseTest {
     @Test
     public void test() throws Exception {
         addFeaturesRepository("mvn:org.apache.karaf.examples/karaf-war-example-features/" + System.getProperty("karaf.version") + "/xml");
+        installAndAssertFeature("pax-web-karaf");
         installAndAssertFeature("karaf-war-example");
 
         // give time to the webapp to deploy
         Thread.sleep(2000);
 
-        String output = executeCommand("web:list");
+        String output = executeCommand("web:wab-list");
         System.out.println(output);
         assertContains("example", output);
 
diff --git a/itests/test/src/test/java/org/apache/karaf/itests/examples/WebSocketExampleTest.java b/itests/test/src/test/java/org/apache/karaf/itests/examples/WebSocketExampleTest.java
index 7ddacd1..8f36ca0 100644
--- a/itests/test/src/test/java/org/apache/karaf/itests/examples/WebSocketExampleTest.java
+++ b/itests/test/src/test/java/org/apache/karaf/itests/examples/WebSocketExampleTest.java
@@ -49,14 +49,16 @@ public class WebSocketExampleTest extends BaseTest {
     public void test() throws Exception {
         featureService.installFeature("scr");
         featureService.installFeature("http");
+        featureService.installFeature("pax-web-karaf");
+        featureService.installFeature("pax-web-jetty-websockets");
 
         Bundle bundle = bundleContext.installBundle("mvn:org.apache.karaf.examples/karaf-websocket-example/" + System.getProperty("karaf.version"));
         bundle.start();
 
-        String httpList = executeCommand("http:list");
-        while (!httpList.contains("Deployed")) {
+        String httpList = executeCommand("web:servlet-list");
+        while (!httpList.contains("/example-websocket/*")) {
             Thread.sleep(1000);
-            httpList = executeCommand("http:list");
+            httpList = executeCommand("web:servlet-list");
         }
         System.out.println(httpList);
 
diff --git a/itests/test/src/test/java/org/apache/karaf/itests/mavenresolver/MavenResolverRegisteredBeforeConfigAdminTest.java b/itests/test/src/test/java/org/apache/karaf/itests/mavenresolver/MavenResolverRegisteredBeforeConfigAdminTest.java
index 67fe43d..7de267e 100644
--- a/itests/test/src/test/java/org/apache/karaf/itests/mavenresolver/MavenResolverRegisteredBeforeConfigAdminTest.java
+++ b/itests/test/src/test/java/org/apache/karaf/itests/mavenresolver/MavenResolverRegisteredBeforeConfigAdminTest.java
@@ -18,6 +18,7 @@ package org.apache.karaf.itests.mavenresolver;
 
 import static org.junit.Assert.assertEquals;
 import static org.ops4j.pax.exam.CoreOptions.composite;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.debugConfiguration;
 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.replaceConfigurationFile;
 
@@ -49,7 +50,10 @@ public class MavenResolverRegisteredBeforeConfigAdminTest extends KarafMinimalMo
         composite(super.baseConfig()),
         composite(editConfigurationFilePut("etc/org.apache.karaf.features.cfg", new File("target/test-classes/etc/org.apache.karaf.features.cfg"))),
         // etc/config.properties which doesn't have org.ops4j.pax.url.mvn.requireConfigAdminConfig=true
-        replaceConfigurationFile("etc/config.properties", new File("target/test-classes/etc/config.properties"))
+        replaceConfigurationFile("etc/config.properties", new File("target/test-classes/etc/config.properties")),
+        // threaded=false, so we don't get:
+        // java.io.IOException: Cannot bind to URL [rmi://:1099/karaf-root]: javax.naming.ServiceUnavailableException
+        editConfigurationFilePut("etc/org.apache.karaf.management.cfg", "threaded", "false")
         };
     }
 
diff --git a/pom.xml b/pom.xml
index cc78be7..d2adda3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -300,6 +300,7 @@
         <org.osgi.service.metatype.version>1.4.1</org.osgi.service.metatype.version>
         <org.osgi.service.namespace.version>1.0.0</org.osgi.service.namespace.version>
         <org.osgi.service.repository.version>1.1.0</org.osgi.service.repository.version>
+        <org.osgi.util.function.version>1.2.0</org.osgi.util.function.version>
         <org.osgi.util.promise.version>1.2.0</org.osgi.util.promise.version>
 
         <pax.cdi.version>1.1.4</pax.cdi.version>
@@ -308,7 +309,7 @@
         <pax.base.version>1.5.1</pax.base.version>
         <pax.swissbox.version>1.8.5</pax.swissbox.version>
         <pax.url.version>2.6.10</pax.url.version>
-        <pax.web.version>7.3.23</pax.web.version>
+        <pax.web.version>8.0.1</pax.web.version>
         <pax.tinybundle.version>3.0.0</pax.tinybundle.version>
         <pax.jdbc.version>1.5.0</pax.jdbc.version>
         <pax.jms.version>1.1.0</pax.jms.version>
diff --git a/web/src/main/java/org/apache/karaf/web/WebContainerService.java b/web/src/main/java/org/apache/karaf/web/WebContainerService.java
index 3a59926..04db023 100644
--- a/web/src/main/java/org/apache/karaf/web/WebContainerService.java
+++ b/web/src/main/java/org/apache/karaf/web/WebContainerService.java
@@ -18,6 +18,8 @@ package org.apache.karaf.web;
 
 import java.util.List;
 
+import org.ops4j.pax.web.service.spi.model.info.WebApplicationInfo;
+
 /**
  * Describe the WebContainer service.
  */
@@ -29,7 +31,7 @@ public interface WebContainerService {
      * @return the list of web bundles.
      * @throws Exception in case of listing failure.
      */
-    List<WebBundle> list() throws Exception;
+    List<WebApplicationInfo> list() throws Exception;
 
     /**
      * Helper method to create a webbundle location and install the bundle.
@@ -80,6 +82,6 @@ public interface WebContainerService {
      * @param id The ID of the bundle.
      * @return The web context associated with the given bundle.
      */
-	String getWebContextPath(Long id);
+	String getWebContextPath(Long id) throws Exception;
 
 }
diff --git a/web/src/main/java/org/apache/karaf/web/commands/List.java b/web/src/main/java/org/apache/karaf/web/commands/List.java
deleted file mode 100644
index a862a45..0000000
--- a/web/src/main/java/org/apache/karaf/web/commands/List.java
+++ /dev/null
@@ -1,70 +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.karaf.web.commands;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.table.Col;
-import org.apache.karaf.shell.support.table.ShellTable;
-import org.apache.karaf.web.WebBundle;
-import org.apache.karaf.web.WebContainerService;
-
-@Command(scope = "web", name = "list", description = "Lists details for war bundles.")
-@Service
-public class List implements Action {
-
-    @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
-    boolean noFormat;
-
-    @Reference
-    private WebContainerService webContainerService;
-    
-    public void setWebContainerService(WebContainerService webContainerService) {
-        this.webContainerService = webContainerService;
-    }
-
-    @Override
-    public Object execute() throws Exception {
-    	ShellTable table = new ShellTable();
-        table.column(new Col("ID"));
-        table.column(new Col("State"));
-        table.column(new Col("Web-State"));
-        table.column(new Col("Level"));
-        table.column(new Col("Web-ContextPath"));
-        table.column(new Col("Name"));
-        
-        java.util.List<WebBundle> webBundles = webContainerService.list();
-        if (webBundles != null && !webBundles.isEmpty()) {
-            for (WebBundle webBundle : webBundles) {
-            	table.addRow().addContent(
-                        webBundle.getBundleId(),
-                        webBundle.getState(),
-                        webBundle.getWebState(),
-                        webBundle.getLevel(),
-                        webBundle.getContextPath(),
-                        webBundle.getName());
-            }
-            
-        }
-        table.print(System.out, !noFormat);
-        return null;
-    }
-    
-}
diff --git a/web/src/main/java/org/apache/karaf/web/internal/WebContainerServiceImpl.java b/web/src/main/java/org/apache/karaf/web/internal/WebContainerServiceImpl.java
index b0d06b5..1fe16ed 100644
--- a/web/src/main/java/org/apache/karaf/web/internal/WebContainerServiceImpl.java
+++ b/web/src/main/java/org/apache/karaf/web/internal/WebContainerServiceImpl.java
@@ -16,102 +16,52 @@
  */
 package org.apache.karaf.web.internal;
 
-import org.apache.karaf.web.WebBundle;
 import org.apache.karaf.web.WebContainerService;
-import org.ops4j.pax.web.service.spi.WarManager;
-import org.ops4j.pax.web.service.spi.WebEvent;
+import org.ops4j.pax.web.service.WebContainer;
+import org.ops4j.pax.web.service.spi.model.info.WebApplicationInfo;
+import org.ops4j.pax.web.service.spi.model.views.ReportWebContainerView;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleEvent;
-import org.osgi.framework.BundleListener;
-import org.osgi.framework.Constants;
-import org.osgi.framework.startlevel.BundleStartLevel;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * Implementation of the WebContainer service.
  */
-public class WebContainerServiceImpl implements WebContainerService, BundleListener {
+public class WebContainerServiceImpl implements WebContainerService {
     
     private BundleContext bundleContext;
-    private WebEventHandler webEventHandler;
-    private WarManager warManager;
-    
+    private WebContainer webContainer;
+
     private static final Logger LOGGER = LoggerFactory.getLogger(WebContainerServiceImpl.class);
     
     public void setBundleContext(BundleContext bundleContext) {
         this.bundleContext = bundleContext;
     }
-    
-    public void setWebEventHandler(WebEventHandler webEventHandler) {
-        this.webEventHandler = webEventHandler;
-    }
 
-    public void setWarManager(WarManager warManager) {
-        this.warManager = warManager;
+    public void setWebContainer(WebContainer webContainer) {
+        this.webContainer = webContainer;
     }
 
     @Override
-    public void bundleChanged(BundleEvent bundleEvent) {
-        if (bundleEvent.getType() == BundleEvent.UNINSTALLED
-                || bundleEvent.getType() == BundleEvent.UNRESOLVED
-                || bundleEvent.getType() == BundleEvent.STOPPED) {
-            webEventHandler.getBundleEvents().remove(bundleEvent.getBundle().getBundleId());
+    public List<WebApplicationInfo> list() throws Exception {
+        if (webContainer == null) {
+            return Collections.emptyList();
         }
-    }
-
-    @Override
-    public List<WebBundle> list() throws Exception {
-        Bundle[] bundles = bundleContext.getBundles();
-        Map<Long, WebEvent> bundleEvents = webEventHandler.getBundleEvents();
-        List<WebBundle> webBundles = new ArrayList<>();
-        if (bundles != null) {
-            for (Bundle bundle : bundles) {
-                // first check if the bundle is a web bundle
-                String contextPath = bundle.getHeaders().get("Web-ContextPath");
-                if (contextPath == null) {
-                    contextPath = bundle.getHeaders().get("Webapp-Context"); // this one used by pax-web but is deprecated
-                }
-                if (contextPath == null) {
-                    // the bundle is not a web bundle
-                    continue;
-                }
-                
-                WebBundle webBundle = new WebBundle();
-                contextPath = contextPath.trim();
-                
-                // get the bundle name
-                String name = bundle.getHeaders().get(Constants.BUNDLE_NAME);
-                // if there is no name, then default to symbolic name
-                name = (name == null) ? bundle.getSymbolicName() : name;
-                // if there is no symbolic name, resort to location
-                name = (name == null) ? bundle.getLocation() : name;
-                // get the bundle version
-                String version = bundle.getHeaders().get(Constants.BUNDLE_VERSION);
-                name = ((version != null)) ? name + " (" + version + ")" : name;
-                long bundleId = bundle.getBundleId();
-                int level = bundle.adapt(BundleStartLevel.class).getStartLevel();
-                if (!contextPath.startsWith("/")) {
-                    contextPath = "/" + contextPath;
-                }
-                
-                webBundle.setBundleId(bundleId);
-                webBundle.setName(name);
-                webBundle.setContextPath(contextPath);
-                webBundle.setLevel(level);
-                webBundle.setState(getStateString(bundle));
-                webBundle.setWebState(state(bundle.getBundleId()));
-                
-                webBundles.add(webBundle);
-            }
+        ReportWebContainerView view = webContainer.adapt(ReportWebContainerView.class);
+        if (view == null) {
+            return Collections.emptyList();
         }
-        
-        return webBundles;
+
+        Set<WebApplicationInfo> webBundles = view.listWebApplications();
+        return new ArrayList<>(webBundles);
     }
 
     @Override
@@ -123,17 +73,20 @@ public class WebContainerServiceImpl implements WebContainerService, BundleListe
 
     @Override
     public void uninstall(List<Long> bundleIds) throws Exception {
+        List<WebApplicationInfo> apps = list();
+        Map<Long, Bundle> mapping = new HashMap<>();
+        for (WebApplicationInfo app : apps) {
+            mapping.put(app.getBundle().getBundleId(), app.getBundle());
+        }
+
         if (bundleIds != null && !bundleIds.isEmpty()) {
             for (long bundleId : bundleIds) {
-                if (webEventHandler.getBundleEvents().containsKey(bundleId)) {
-                    WebEvent webEvent = webEventHandler.getBundleEvents().get(bundleId);
-                    Bundle bundle = webEvent.getBundle();
-                    if (bundle != null) {
-                        bundle.uninstall();
-                    } else {
-                        System.out.println("Bundle ID " + bundleId + " is invalid");
-                        LOGGER.warn("Bundle ID {} is invalid", bundleId);
-                    }
+                Bundle bundle = mapping.get(bundleId);
+                if (bundle != null) {
+                    bundle.uninstall();
+                } else {
+                    System.out.println("Bundle ID " + bundleId + " is invalid");
+                    LOGGER.warn("Bundle ID {} is invalid", bundleId);
                 }
             }
         }
@@ -142,17 +95,21 @@ public class WebContainerServiceImpl implements WebContainerService, BundleListe
     @Override
     public void start(List<Long> bundleIds) throws Exception {
         if (bundleIds != null && !bundleIds.isEmpty()) {
+            List<WebApplicationInfo> apps = list();
+            Map<Long, Bundle> mapping = new HashMap<>();
+            for (WebApplicationInfo app : apps) {
+                mapping.put(app.getBundle().getBundleId(), app.getBundle());
+            }
             for (long bundleId : bundleIds) {
-                if (webEventHandler.getBundleEvents().containsKey(bundleId)) {
-                    WebEvent webEvent = webEventHandler.getBundleEvents().get(bundleId);
-                    Bundle bundle = webEvent.getBundle();
-                    if (bundle != null) {
-                        // deploy
-                        warManager.start(bundleId, null);
-                    } else {
-                        System.out.println("Bundle ID " + bundleId + " is invalid");
-                        LOGGER.warn("Bundle ID {} is invalid", bundleId);
-                    }
+                Bundle bundle = mapping.get(bundleId);
+                if (bundle != null) {
+                    // deploy
+                    // TOCHECK: Pax Web has no "War Manager", so WAB == Bundle and we can't have started Bundle without
+                    //  started WAB
+                    bundle.start();
+                } else {
+                    System.out.println("Bundle ID " + bundleId + " is invalid");
+                    LOGGER.warn("Bundle ID {} is invalid", bundleId);
                 }
             }
         }
@@ -161,52 +118,34 @@ public class WebContainerServiceImpl implements WebContainerService, BundleListe
     @Override
     public void stop(List<Long> bundleIds) throws Exception {
         if (bundleIds != null && !bundleIds.isEmpty()) {
+            List<WebApplicationInfo> apps = list();
+            Map<Long, Bundle> mapping = new HashMap<>();
+            for (WebApplicationInfo app : apps) {
+                mapping.put(app.getBundle().getBundleId(), app.getBundle());
+            }
             for (long bundleId : bundleIds) {
-                if (webEventHandler.getBundleEvents().containsKey(bundleId)) {
-                    WebEvent webEvent = webEventHandler.getBundleEvents().get(bundleId);
-                    Bundle bundle = webEvent.getBundle();
-                    if (bundle != null) {
-                        // deploy
-                        warManager.stop(bundleId);
-                    } else {
-                        System.out.println("Bundle ID " + bundleId + " is invalid");
-                        LOGGER.warn("Bundle ID {} is invalid", bundleId);
-                    }
+                Bundle bundle = mapping.get(bundleId);
+                if (bundle != null) {
+                    // undeploy
+                    // TOCHECK: Pax Web has no "War Manager", so WAB == Bundle and we can't have started Bundle without
+                    //  started WAB
+                    bundle.stop();
+                } else {
+                    System.out.println("Bundle ID " + bundleId + " is invalid");
+                    LOGGER.warn("Bundle ID {} is invalid", bundleId);
                 }
             }
         }
     }
 
     @Override
-    public String state(long bundleId) {
-
-        Map<Long, WebEvent> bundleEvents = webEventHandler.getBundleEvents();
+    public String state(long bundleId) throws Exception {
+        List<WebApplicationInfo> apps = list();
+        Map<Long, Bundle> mapping = new HashMap<>();
         StringBuilder topic = new StringBuilder("Unknown    ");
-
-        if (bundleEvents.containsKey(bundleId)) {
-            WebEvent webEvent = bundleEvents.get(bundleId);
-
-            switch(webEvent.getType()) {
-                case WebEvent.DEPLOYING:
-                    topic = new StringBuilder("Deploying  ");
-                    break;
-                case WebEvent.DEPLOYED:
-                    topic = new StringBuilder("Deployed   ");
-                    break;
-                case WebEvent.UNDEPLOYING:
-                    topic = new StringBuilder("Undeploying");
-                    break;
-                case WebEvent.UNDEPLOYED:
-                    topic = new StringBuilder("Undeployed ");
-                    break;
-                case WebEvent.FAILED:
-                    topic = new StringBuilder("Failed     ");
-                    break;
-                case WebEvent.WAITING:
-                    topic = new StringBuilder("Waiting    ");
-                    break;
-                default:
-                    topic = new StringBuilder("Failed     ");
+        for (WebApplicationInfo app : apps) {
+            if (bundleId == app.getBundle().getBundleId()) {
+                topic = new StringBuilder(app.getDeploymentState());
             }
         }
 
@@ -217,36 +156,16 @@ public class WebContainerServiceImpl implements WebContainerService, BundleListe
         return topic.toString();
     }
 
-    /**
-     * Return a string representation of the bundle state.
-     * 
-     * TODO use an util method provided by bundle core
-     * 
-     * @param bundle the target bundle.
-     * @return the string representation of the state
-     */
-    private String getStateString(Bundle bundle) {
-        int state = bundle.getState();
-        if (state == Bundle.ACTIVE) {
-            return "Active     ";
-        } else if (state == Bundle.INSTALLED) {
-            return "Installed  ";
-        } else if (state == Bundle.RESOLVED) {
-            return "Resolved   ";
-        } else if (state == Bundle.STARTING) {
-            return "Starting   ";
-        } else if (state == Bundle.STOPPING) {
-            return "Stopping   ";
-        } else {
-            return "Unknown    ";
-        }
-    }
-
 	@Override
-	public String getWebContextPath(Long id) {
-		Map<Long, WebEvent> bundleEvents = webEventHandler.getBundleEvents();
-		WebEvent webEvent = bundleEvents.get(id);
-		return webEvent.getContextPath();
+	public String getWebContextPath(Long id) throws Exception {
+        List<WebApplicationInfo> apps = list();
+        Map<Long, Bundle> mapping = new HashMap<>();
+        for (WebApplicationInfo app : apps) {
+            if (id == app.getBundle().getBundleId()) {
+                return app.getContextPath();
+            }
+        }
+        return "";
 	}
 
 }
diff --git a/web/src/main/java/org/apache/karaf/web/internal/WebEventHandler.java b/web/src/main/java/org/apache/karaf/web/internal/WebEventHandler.java
deleted file mode 100644
index e91395c..0000000
--- a/web/src/main/java/org/apache/karaf/web/internal/WebEventHandler.java
+++ /dev/null
@@ -1,40 +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.karaf.web.internal;
-
-import org.ops4j.pax.web.service.spi.WebEvent;
-import org.ops4j.pax.web.service.spi.WebListener;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Class implementing {@link WebListener} service to retrieve {@link WebEvent}.
- */
-public class WebEventHandler implements WebListener {
-
-    private final Map<Long, WebEvent> bundleEvents = new HashMap<>();
-
-    public Map<Long, WebEvent> getBundleEvents() {
-        return bundleEvents;
-    }
-
-    public void webEvent(WebEvent event) {
-        getBundleEvents().put(event.getBundle().getBundleId(), event);
-    }
-
-}
diff --git a/web/src/main/java/org/apache/karaf/web/internal/osgi/Activator.java b/web/src/main/java/org/apache/karaf/web/internal/osgi/Activator.java
index db1ee64..c31dc59 100644
--- a/web/src/main/java/org/apache/karaf/web/internal/osgi/Activator.java
+++ b/web/src/main/java/org/apache/karaf/web/internal/osgi/Activator.java
@@ -22,13 +22,11 @@ import org.apache.karaf.util.tracker.annotation.RequireService;
 import org.apache.karaf.util.tracker.annotation.Services;
 import org.apache.karaf.web.WebContainerService;
 import org.apache.karaf.web.internal.WebContainerServiceImpl;
-import org.apache.karaf.web.internal.WebEventHandler;
 import org.apache.karaf.web.management.internal.WebMBeanImpl;
-import org.ops4j.pax.web.service.spi.WarManager;
-import org.ops4j.pax.web.service.spi.WebListener;
+import org.ops4j.pax.web.service.WebContainer;
 
 @Services(
-        requires = @RequireService(WarManager.class),
+        requires = @RequireService(WebContainer.class),
         provides = @ProvideService(WebContainerService.class)
 )
 public class Activator extends BaseActivator {
@@ -37,19 +35,14 @@ public class Activator extends BaseActivator {
 
     @Override
     protected void doStart() throws Exception {
-        WarManager warManager = getTrackedService(WarManager.class);
-        if (warManager == null) {
+        WebContainer webContainer = getTrackedService(WebContainer.class);
+        if (webContainer == null) {
             return;
         }
 
-        WebEventHandler webEventHandler = new WebEventHandler();
-        register(WebListener.class, webEventHandler);
-
         webContainerService = new WebContainerServiceImpl();
-        bundleContext.addBundleListener(webContainerService);
         webContainerService.setBundleContext(bundleContext);
-        webContainerService.setWarManager(warManager);
-        webContainerService.setWebEventHandler(webEventHandler);
+        webContainerService.setWebContainer(webContainer);
         register(WebContainerService.class, webContainerService);
 
         WebMBeanImpl webMBean = new WebMBeanImpl();
@@ -60,7 +53,6 @@ public class Activator extends BaseActivator {
     @Override
     protected void doStop() {
         if (webContainerService != null) {
-            bundleContext.removeBundleListener(webContainerService);
             webContainerService = null;
         }
         super.doStop();
diff --git a/web/src/main/java/org/apache/karaf/web/management/internal/WebMBeanImpl.java b/web/src/main/java/org/apache/karaf/web/management/internal/WebMBeanImpl.java
index 239e39b..a601d25 100644
--- a/web/src/main/java/org/apache/karaf/web/management/internal/WebMBeanImpl.java
+++ b/web/src/main/java/org/apache/karaf/web/management/internal/WebMBeanImpl.java
@@ -16,9 +16,12 @@
  */
 package org.apache.karaf.web.management.internal;
 
-import org.apache.karaf.web.WebBundle;
 import org.apache.karaf.web.WebContainerService;
 import org.apache.karaf.web.management.WebMBean;
+import org.ops4j.pax.web.service.spi.model.info.WebApplicationInfo;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.startlevel.BundleStartLevel;
 
 import javax.management.MBeanException;
 import javax.management.NotCompliantMBeanException;
@@ -57,16 +60,33 @@ public class WebMBeanImpl extends StandardMBean implements WebMBean {
             TabularType tableType = new TabularType("Web Bundles", "Table of web bundles", webType,
                     new String[]{"ID"});
             TabularData table = new TabularDataSupport(tableType);
-            for (WebBundle webBundle : webContainerService.list()) {
+            for (WebApplicationInfo webBundle : webContainerService.list()) {
+                String contextPath = webBundle.getContextPath();
+
+                // get the bundle name
+                String name = webBundle.getBundle().getHeaders().get(Constants.BUNDLE_NAME);
+                // if there is no name, then default to symbolic name
+                name = (name == null) ? webBundle.getBundle().getSymbolicName() : name;
+                // if there is no symbolic name, resort to location
+                name = (name == null) ? webBundle.getBundle().getLocation() : name;
+                // get the bundle version
+                String version = webBundle.getBundle().getHeaders().get(Constants.BUNDLE_VERSION);
+                name = ((version != null)) ? name + " (" + version + ")" : name;
+                long bundleId = webBundle.getBundle().getBundleId();
+                int level = webBundle.getBundle().adapt(BundleStartLevel.class).getStartLevel();
+                if (!contextPath.startsWith("/")) {
+                    contextPath = "/" + contextPath;
+                }
+
                 try {
                     CompositeData data = new CompositeDataSupport(webType,
                             new String[]{"ID", "State", "Web-State", "Level", "Web-ContextPath", "Name"},
-                            new Object[]{webBundle.getBundleId(),
-                                    webBundle.getState(),
-                                    webBundle.getWebState(),
-                                    webBundle.getLevel(),
-                                    webBundle.getContextPath(),
-                                    webBundle.getName()});
+                            new Object[]{webBundle.getBundle().getBundleId(),
+                                    getStateString(webBundle.getBundle()),
+                                    webBundle.getDeploymentState(),
+                                    level,
+                                    contextPath,
+                                    name});
                     table.put(data);
                 } catch (Exception e) {
                     e.printStackTrace();
@@ -147,4 +167,29 @@ public class WebMBeanImpl extends StandardMBean implements WebMBean {
         }
     }
 
+    /**
+     * Return a string representation of the bundle state.
+     *
+     * TODO use an util method provided by bundle core
+     *
+     * @param bundle the target bundle.
+     * @return the string representation of the state
+     */
+    private String getStateString(Bundle bundle) {
+        int state = bundle.getState();
+        if (state == Bundle.ACTIVE) {
+            return "Active     ";
+        } else if (state == Bundle.INSTALLED) {
+            return "Installed  ";
+        } else if (state == Bundle.RESOLVED) {
+            return "Resolved   ";
+        } else if (state == Bundle.STARTING) {
+            return "Starting   ";
+        } else if (state == Bundle.STOPPING) {
+            return "Stopping   ";
+        } else {
+            return "Unknown    ";
+        }
+    }
+
 }
diff --git a/webconsole/http/src/main/java/org/apache/karaf/webconsole/http/Activator.java b/webconsole/http/src/main/java/org/apache/karaf/webconsole/http/Activator.java
index e6a115e..ac60902 100644
--- a/webconsole/http/src/main/java/org/apache/karaf/webconsole/http/Activator.java
+++ b/webconsole/http/src/main/java/org/apache/karaf/webconsole/http/Activator.java
@@ -24,15 +24,15 @@ import org.apache.karaf.http.core.ProxyService;
 import org.apache.karaf.util.tracker.BaseActivator;
 import org.apache.karaf.util.tracker.annotation.RequireService;
 import org.apache.karaf.util.tracker.annotation.Services;
-import org.ops4j.pax.web.service.spi.ServletListener;
-import org.ops4j.pax.web.service.spi.WebListener;
+import org.ops4j.pax.web.service.WebContainer;
 
-@Services(requires = @RequireService(ProxyService.class))
+@Services(requires = {
+        @RequireService(WebContainer.class),
+        @RequireService(ProxyService.class)
+})
 public class Activator extends BaseActivator {
 
     private HttpPlugin httpPlugin;
-    private ServletEventHandler eaHandler;
-    private WebEventHandler webEaHandler;
 
     @Override
     protected void doStart() throws Exception {
@@ -40,21 +40,14 @@ public class Activator extends BaseActivator {
         if (proxyService == null) {
             return;
         }
-
-        eaHandler = new ServletEventHandler();
-        eaHandler.setBundleContext(bundleContext);
-        eaHandler.init();
-        register(ServletListener.class, eaHandler);
-
-        webEaHandler = new WebEventHandler();
-        webEaHandler.setBundleContext(bundleContext);
-        webEaHandler.init();
-        register(WebListener.class, webEaHandler);
+        WebContainer webContainer = getTrackedService(WebContainer.class);
+        if (webContainer == null) {
+            return;
+        }
 
         httpPlugin = new HttpPlugin();
         httpPlugin.setBundleContext(bundleContext);
-        httpPlugin.setServletEventHandler(eaHandler);
-        httpPlugin.setWebEventHandler(webEaHandler);
+        httpPlugin.setWebContainer(webContainer);
         httpPlugin.setProxyService(proxyService);
         httpPlugin.start();
 
@@ -70,14 +63,6 @@ public class Activator extends BaseActivator {
             httpPlugin.stop();
             httpPlugin = null;
         }
-        if (eaHandler != null) {
-            eaHandler.destroy();
-            eaHandler = null;
-        }
-        if (webEaHandler != null) {
-            webEaHandler.destroy();
-            webEaHandler = null;
-        }
     }
 
 }
diff --git a/webconsole/http/src/main/java/org/apache/karaf/webconsole/http/HttpPlugin.java b/webconsole/http/src/main/java/org/apache/karaf/webconsole/http/HttpPlugin.java
index bfb2504..7373447 100644
--- a/webconsole/http/src/main/java/org/apache/karaf/webconsole/http/HttpPlugin.java
+++ b/webconsole/http/src/main/java/org/apache/karaf/webconsole/http/HttpPlugin.java
@@ -21,13 +21,11 @@ import java.io.InputStream;
 import java.io.PrintWriter;
 import java.net.URL;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
-import javax.servlet.Servlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
@@ -36,14 +34,15 @@ import org.apache.felix.webconsole.AbstractWebConsolePlugin;
 import org.apache.felix.webconsole.WebConsoleConstants;
 import org.apache.karaf.http.core.Proxy;
 import org.apache.karaf.http.core.ProxyService;
-import org.ops4j.pax.web.service.spi.ServletEvent;
-import org.ops4j.pax.web.service.spi.WebEvent;
+import org.ops4j.pax.web.service.WebContainer;
+import org.ops4j.pax.web.service.spi.model.info.ServletInfo;
+import org.ops4j.pax.web.service.spi.model.info.WebApplicationInfo;
+import org.ops4j.pax.web.service.spi.model.views.ReportWebContainerView;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-
 /**
  * WebConsole plugin to use with HTTP service.
  */
@@ -54,9 +53,8 @@ public class HttpPlugin extends AbstractWebConsolePlugin {
     public static final String NAME = "http";
     public static final String LABEL = "Http";
     private ClassLoader classLoader;
-    private String featuresJs = "/http/res/ui/http-contexts.js";
-    private ServletEventHandler servletEventHandler;
-    private WebEventHandler webEventHandler;
+    private final String featuresJs = "/http/res/ui/http-contexts.js";
+    private WebContainer webContainer;
     private BundleContext bundleContext;
     private ProxyService proxyService;
 
@@ -116,7 +114,7 @@ public class HttpPlugin extends AbstractWebConsolePlugin {
 
     protected URL getResource(String path) {
         path = path.substring(NAME.length() + 1);
-        if (path == null || path.isEmpty()) {
+        if (path.isEmpty()) {
             return null;
         }
         URL url = this.classLoader.getResource(path);
@@ -149,7 +147,7 @@ public class HttpPlugin extends AbstractWebConsolePlugin {
         final List<ServletDetails> servlets = this.getServletDetails();
         final List<WebDetail> web = this.getWebDetails();
         final Map<String, Proxy> proxies = proxyService.getProxies();
-        final String statusLine = this.getStatusLine(servlets, web);
+        final String statusLine = this.getStatusLine(servlets);
         final JSONWriter jw = new JSONWriter(pw);
 
         jw.object();
@@ -168,15 +166,19 @@ public class HttpPlugin extends AbstractWebConsolePlugin {
             jw.key("servletName");
             jw.value(servlet.getServletName());
             jw.key("state");
-            jw.value(servlet.getState());
-            jw.key("alias");
-            jw.value(servlet.getAlias());
+            jw.value(servlet.getType());
             jw.key("urls");
             jw.array();
             for (String url : servlet.getUrls()) {
                 jw.value(url);
             }
             jw.endArray();
+            jw.key("contexts");
+            jw.array();
+            for (String url : servlet.getContexts()) {
+                jw.value(url);
+            }
+            jw.endArray();
             jw.endObject();
         }
         jw.endArray();
@@ -215,49 +217,43 @@ public class HttpPlugin extends AbstractWebConsolePlugin {
     }
 
     protected List<ServletDetails> getServletDetails() {
+        List<ServletDetails> result = new ArrayList<>();
 
-        Collection<ServletEvent> events = servletEventHandler.getServletEvents();
-        List<ServletDetails> result = new ArrayList<>(events.size());
+        ReportWebContainerView view = webContainer.adapt(ReportWebContainerView.class);
 
-        for (ServletEvent event : events) {
-            Servlet servlet = event.getServlet();
-            String servletClassName = " ";
-            if (servlet != null) {
-                servletClassName = servlet.getClass().getName();
-                servletClassName = servletClassName.substring(servletClassName.lastIndexOf(".") + 1);
-            }
-            String servletName = event.getServletName() != null ? event.getServletName() : " ";
+        for (ServletInfo info : view.listServlets()) {
+            String servletClassName = info.getServletClass();
+            String servletName = info.getServletName();
             if (servletName.contains(".")) {
                 servletName = servletName.substring(servletName.lastIndexOf(".") + 1);
             }
 
-            String alias = event.getAlias() != null ? event.getAlias() : " ";
-
-            String[] urls = event.getUrlParameter() != null ? event.getUrlParameter() : new String[]{""};
+            String[] urls = info.getMapping() != null ? info.getMapping() : new String[] { "" };
+            String[] contexts = info.getContexts() != null ? info.getContexts() : new String[] { "" };
 
             ServletDetails details = new ServletDetails();
-            details.setId(event.getBundle().getBundleId());
-            details.setAlias(alias);
+            details.setId(info.getBundle().getBundleId());
             details.setServlet(servletClassName);
             details.setServletName(servletName);
-            details.setState(getStateString(event.getType()));
+            details.setType(info.getType());
             details.setUrls(urls);
+            details.setContexts(contexts);
             result.add(details);
         }
         return result;
     }
 
     protected List<WebDetail> getWebDetails() {
-        Map<Long, WebEvent> bundleEvents = webEventHandler.getBundleEvents();
-
         List<WebDetail> result = new ArrayList<>();
 
-        for (WebEvent event : bundleEvents.values()) {
+        ReportWebContainerView view = webContainer.adapt(ReportWebContainerView.class);
+
+        for (WebApplicationInfo info : view.listWebApplications()) {
 
             WebDetail webDetail = new WebDetail();
-            webDetail.setBundleId(event.getBundle().getBundleId());
-            webDetail.setContextPath(event.getContextPath().trim().concat("/"));
-            int state = bundleContext.getBundle(event.getBundle().getBundleId()).getState();
+            webDetail.setBundleId(info.getBundle().getBundleId());
+            webDetail.setContextPath(info.getContextPath().trim());
+            int state = bundleContext.getBundle(info.getBundle().getBundleId()).getState();
             String stateStr;
             if (state == Bundle.ACTIVE) {
                 stateStr = "Active";
@@ -274,21 +270,21 @@ public class HttpPlugin extends AbstractWebConsolePlugin {
             }
             webDetail.setState(stateStr);
 
-            webDetail.setWebState(getStateString(event.getType()));
+            webDetail.setWebState(info.getDeploymentState());
             result.add(webDetail);
         }
 
         return result;
     }
 
-    public String getStatusLine(List<ServletDetails> servlets, List<WebDetail> web) {
-        Map<String, Integer> states = new HashMap<>();
+    public String getStatusLine(List<ServletDetails> servlets) {
+        Map<String, Integer> types = new HashMap<>();
         for (ServletDetails servlet : servlets) {
-            states.merge(servlet.getState(), 1, Integer::sum);
+            types.merge(servlet.getType(), 1, Integer::sum);
         }
         StringBuilder stateSummary = new StringBuilder();
         boolean first = true;
-        for (Entry<String, Integer> state : states.entrySet()) {
+        for (Entry<String, Integer> state : types.entrySet()) {
             if (!first) {
                 stateSummary.append(", ");
             }
@@ -296,34 +292,11 @@ public class HttpPlugin extends AbstractWebConsolePlugin {
             stateSummary.append(state.getValue()).append(" ").append(state.getKey());
         }
 
-        return "Http contexts: " + stateSummary.toString();
-    }
-
-    public String getStateString(int type) {
-        switch (type) {
-            case WebEvent.DEPLOYING:
-                return "Deploying";
-            case WebEvent.DEPLOYED:
-                return "Deployed";
-            case WebEvent.UNDEPLOYING:
-                return "Undeploying";
-            case WebEvent.UNDEPLOYED:
-                return "Undeployed";
-            case WebEvent.FAILED:
-                return "Failed";
-            case WebEvent.WAITING:
-                return "Waiting";
-            default:
-                return "Failed";
-        }
-    }
-
-    public void setServletEventHandler(ServletEventHandler eventHandler) {
-        this.servletEventHandler = eventHandler;
+        return "Http contexts: " + stateSummary;
     }
 
-    public void setWebEventHandler(WebEventHandler eventHandler) {
-        this.webEventHandler = eventHandler;
+    public void setWebContainer(WebContainer webContainer) {
+        this.webContainer = webContainer;
     }
 
     public void setBundleContext(BundleContext bundleContext) {
diff --git a/webconsole/http/src/main/java/org/apache/karaf/webconsole/http/ServletDetails.java b/webconsole/http/src/main/java/org/apache/karaf/webconsole/http/ServletDetails.java
index bb869d7..4eeb19c 100644
--- a/webconsole/http/src/main/java/org/apache/karaf/webconsole/http/ServletDetails.java
+++ b/webconsole/http/src/main/java/org/apache/karaf/webconsole/http/ServletDetails.java
@@ -20,17 +20,9 @@ public class ServletDetails {
     private long id;
     private String servlet;
     private String servletName;
-    private String state;
-    private String alias;
+    private String type;
     private String[] urls;
-
-    public String getAlias() {
-        return alias;
-    }
-
-    public void setAlias(String alias) {
-        this.alias = alias;
-    }
+    private String[] contexts;
 
     public long getId() {
         return id;
@@ -56,12 +48,12 @@ public class ServletDetails {
         this.servletName = servletName;
     }
 
-    public String getState() {
-        return state;
+    public String getType() {
+        return type;
     }
 
-    public void setState(String state) {
-        this.state = state;
+    public void setType(String type) {
+        this.type = type;
     }
 
     public String[] getUrls() {
@@ -72,4 +64,11 @@ public class ServletDetails {
         this.urls = urls;
     }
 
+    public String[] getContexts() {
+        return contexts;
+    }
+
+    public void setContexts(String[] contexts) {
+        this.contexts = contexts;
+    }
 }
diff --git a/webconsole/http/src/main/java/org/apache/karaf/webconsole/http/ServletEventHandler.java b/webconsole/http/src/main/java/org/apache/karaf/webconsole/http/ServletEventHandler.java
deleted file mode 100644
index f27dc04..0000000
--- a/webconsole/http/src/main/java/org/apache/karaf/webconsole/http/ServletEventHandler.java
+++ /dev/null
@@ -1,72 +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.karaf.webconsole.http;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.ops4j.pax.web.service.spi.ServletEvent;
-import org.ops4j.pax.web.service.spi.ServletListener;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleEvent;
-import org.osgi.framework.BundleListener;
-
-public class ServletEventHandler implements ServletListener, BundleListener {
-
-    BundleContext bundleContext;
-    Map<String, ServletEvent> servletEvents = new HashMap<>();
-
-    public void setBundleContext(BundleContext bundleContext) {
-        this.bundleContext = bundleContext;
-    }
-
-    public void init() {
-        bundleContext.addBundleListener(this);
-    }
-
-    public void destroy() {
-        bundleContext.removeBundleListener(this);
-    }
-
-    @Override
-    public void bundleChanged(BundleEvent event) {
-        if (event.getType() == BundleEvent.UNINSTALLED
-                || event.getType() == BundleEvent.UNRESOLVED
-                || event.getType() == BundleEvent.STOPPED) {
-            removeEventsForBundle(event.getBundle());
-        }
-    }
-
-    public synchronized void servletEvent(ServletEvent event) {
-        servletEvents.put(event.getServletName(), event);
-    }
-
-    /**
-     * @return the servletEvents
-     */
-    public synchronized Collection<ServletEvent> getServletEvents() {
-        return new ArrayList<>(servletEvents.values());
-    }
-
-    public synchronized void removeEventsForBundle(Bundle bundle) {
-        servletEvents.entrySet().removeIf(entry -> entry.getValue().getBundle() == bundle);
-    }
-
-}
diff --git a/webconsole/http/src/main/java/org/apache/karaf/webconsole/http/WebEventHandler.java b/webconsole/http/src/main/java/org/apache/karaf/webconsole/http/WebEventHandler.java
deleted file mode 100644
index adfcf40..0000000
--- a/webconsole/http/src/main/java/org/apache/karaf/webconsole/http/WebEventHandler.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/* Copyright 2011 Achim.
- *
- * Licensed 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.karaf.webconsole.http;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.ops4j.pax.web.service.spi.WebEvent;
-import org.ops4j.pax.web.service.spi.WebListener;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleEvent;
-import org.osgi.framework.BundleListener;
-
-public class WebEventHandler implements WebListener, BundleListener {
-
-    BundleContext bundleContext;
-    private final Map<Long, WebEvent> bundleEvents = new HashMap<>();
-
-    public void setBundleContext(BundleContext bundleContext) {
-        this.bundleContext = bundleContext;
-    }
-
-    public void init() {
-        bundleContext.addBundleListener(this);
-    }
-
-    public void destroy() {
-        bundleContext.removeBundleListener(this);
-    }
-
-    @Override
-    public void bundleChanged(BundleEvent event) {
-        if (event.getType() == BundleEvent.UNINSTALLED
-                || event.getType() == BundleEvent.UNRESOLVED
-                || event.getType() == BundleEvent.STOPPED) {
-            removeEventsForBundle(event.getBundle());
-        }
-    }
-
-    @Override
-    public synchronized void webEvent(WebEvent event) {
-        bundleEvents.put(event.getBundle().getBundleId(), event);
-    }
-
-    public synchronized Map<Long, WebEvent> getBundleEvents() {
-        return new HashMap<>(bundleEvents);
-    }
-
-    public synchronized void removeEventsForBundle(Bundle bundle) {
-        bundleEvents.remove(bundle.getBundleId());
-    }
-
-}
diff --git a/webconsole/http/src/main/resources/res/ui/http-contexts.js b/webconsole/http/src/main/resources/res/ui/http-contexts.js
index d1eae05..47307f9 100644
--- a/webconsole/http/src/main/resources/res/ui/http-contexts.js
+++ b/webconsole/http/src/main/resources/res/ui/http-contexts.js
@@ -24,7 +24,7 @@ function renderFeatures( data ) {
 
 function renderView() {
     renderStatusLine();
-    renderTable( "HTTP Contexts", "context_table", ["ID", "Servlet", "Name", "State", "Alias", "urls"] );
+    renderTable( "HTTP Contexts", "context_table", ["ID", "Servlet", "Name", "Type", "urls", "contexts"] );
     renderTable( "Web Contexts", "webctxt_table", ["ID", "BundleState", "Web Context", "State"] );
     renderTable(" HTTP Proxies", "proxy_table", ["URL", "ProxyTo"]);
     renderStatusLine();
@@ -106,14 +106,18 @@ function renderContextData( /* Element */ parent, /* Object */ context ) {
     parent.appendChild( td( null, null, [ text( context.id ) ] ) );
     parent.appendChild( td( null, null, [ text( context.servlet ) ] ) );
     parent.appendChild( td( null, null, [ text( context.servletName ) ] ) );
-    parent.appendChild( td( null, null, [ text( context.state ) ] ) );
-    parent.appendChild( td( null, null, [ text( context.alias ) ] ) );
-    
+    parent.appendChild( td( null, null, [ text( context.type ) ] ) );
+
     var urlBox = td( null, null );
     for ( var idx in context.urls ) {
       urlBox.appendChild( link( trimUrl(context.urls[idx]), context.urls[idx] ) );
     }
-    
+
+    var contextBox = td( null, null );
+    for ( var idx in context.contexts ) {
+      urlBox.appendChild( text( context.contexts[idx]  ) );
+    }
+
     parent.appendChild( urlBox );
 }
 

[karaf] 03/03: [KARAF-7406] Update Karaf 4.4 manual to show new features of Pax Web 8

Posted by gg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ggrzybek pushed a commit to branch KARAF-7392
in repository https://gitbox.apache.org/repos/asf/karaf.git

commit 122d1bb75526ce9d2216c1e4b411b369e950dc20
Author: Grzegorz Grzybek <gr...@gmail.com>
AuthorDate: Wed Mar 30 12:53:25 2022 +0200

    [KARAF-7406] Update Karaf 4.4 manual to show new features of Pax Web 8
---
 manual/src/main/asciidoc/user-guide/console.adoc   |   8 +-
 manual/src/main/asciidoc/user-guide/http.adoc      |  69 +++-
 manual/src/main/asciidoc/user-guide/kar.adoc       |  49 +--
 .../src/main/asciidoc/user-guide/provisioning.adoc |  98 +++---
 manual/src/main/asciidoc/user-guide/urls.adoc      |   2 +-
 .../src/main/asciidoc/user-guide/webcontainer.adoc | 361 +++++++++++++--------
 .../web/management/internal/WebMBeanImpl.java      |  11 +-
 7 files changed, 390 insertions(+), 208 deletions(-)

diff --git a/manual/src/main/asciidoc/user-guide/console.adoc b/manual/src/main/asciidoc/user-guide/console.adoc
index 08fe392..22e1a9c 100644
--- a/manual/src/main/asciidoc/user-guide/console.adoc
+++ b/manual/src/main/asciidoc/user-guide/console.adoc
@@ -288,11 +288,9 @@ Like on most Unix environments, the Karaf console supports some key bindings:
 You can pipe the output of one command as input to another one. It's a pipe, using the | character:
 
 ----
-karaf@root()> feature:list |grep -i war
-pax-war                       | 4.1.4                            |          | Uninstalled | org.ops4j.pax.web-4.1.4  | Provide support of a full WebContainer
-pax-war-tomcat                | 4.1.4                            |          | Uninstalled | org.ops4j.pax.web-4.1.4  |
-war                           | 4.0.0                            |          | Uninstalled | standard-4.0.0           | Turn Karaf as a full WebContainer
-blueprint-web                 | 4.0.0                            |          | Uninstalled | standard-4.0.0           | Provides an OSGI-aware Servlet ContextListener fo
+karaf@root()> feature:list | grep -i felix
+felix-httplite                    │ 0.1.6            │          │ Uninstalled │ standard-4.4.0           │ Felix Httplite HTTP Service
+felix-http                        │ 4.1.12           │          │ Uninstalled │ standard-4.4.0           │ Felix HTTP Service
 ----
 
 ===== Grep, more, find, ...
diff --git a/manual/src/main/asciidoc/user-guide/http.adoc b/manual/src/main/asciidoc/user-guide/http.adoc
index d48b4f8..50de469 100644
--- a/manual/src/main/asciidoc/user-guide/http.adoc
+++ b/manual/src/main/asciidoc/user-guide/http.adoc
@@ -14,22 +14,26 @@
 
 ==== Http Service
 
-Apache Karaf supports several Http Services:
+_Http Service_ should mean an implementation of OSGi CMPN Chapter 102 "Http Service" specification.
 
-* `http` feature installs Http Service powered by Pax Web
-* `felix-http` feature installs Http Service powered by Apache Felix HTTP
+Apache Karaf supports several Http Service implementations:
+
+* `http` feature installs Http Service implementation powered by Pax Web
+* `felix-http` feature installs Http Service implementation powered by Apache Felix HTTP
+
+NOTE: Felix HTTP implementation is also an implementation of OSGi CMPN Chapter 140 "Whiteboard Service" specification.
+
+NOTE: Pax Web also contains implementations of OSGi CMPN Chapter 140 "Whiteboard Service" and OSGi CMPN Chapter 128 "Web Applications" specification, but these are installed using additional features.
 
 ===== Installing the Http Service
 
-If you want to use Pax Web Http Service, you have to install the `http` feature:
+If you want to use Pax Web Http Service implementation, you have to install the `http` feature:
 
 ----
 root@karaf()> feature:install http
 ----
 
-NB: the HTTP service will be actually bound only when at least one web application will use it.
-
-If you want to use Apache Felix Http Service, you have to install `felix-http` feature:
+If you want to use Apache Felix Http Service implementation, you have to install `felix-http` feature:
 
 ----
 root@karaf()> feature:install felix-http
@@ -43,6 +47,57 @@ root@karaf()> feature:install webconsole
 
 Then, you can test the HTTP service by accessing the Apache Karaf WebConsole pointing your browser to [http://localhost:8181/system/console].
 
+====== More information about Pax Web implementation
+
+Pax Web 8 itself contains properly defined and tested Karaf features. However Karaf was always providing own web-related features in `org.apache.karaf.features/standard` feature repository.
+
+For completeness, here's a full list of features provided by Pax Web:
+
+.Core features
+
+* `pax-web-specs` - several API related bundles that can be used (or can be treated as reference) when the runtime (like Karaf) doesn't provide necessary APIs (servlet API, EL API, Annotation API)
+* `pax-web-core` - fundamental Pax Web API/SPI bundles which don't register any OSGi services
+
+.Runtime features
+
+Pax Web in all versions (and in particular in version 8) was always aiming to provide support for all major web container technologies. That's why there are 3 sets of features for Jetty, Tomcat and Undertow support. These features only install relevant web container bundles without any bundles specific to OSGi CMPN specifications.
+
+* Jetty
+** `pax-web-jetty` - required `org.eclipse.jetty` bundles with Servlet API bundle
+** `pax-web-jetty-websockets` - required `org.eclipse.jetty.websocket` bundles with WebSocket API bundle
+** `pax-web-jetty-http2` - required `org.eclipse.jetty.http2` bundles
+** `pax-web-jetty-http2-jdk8` - optional Jetty ALPN bundles when running on JDK8
+** `pax-web-jetty-http2-jdk9` - optional Jetty ALPN bundles when running on JDK9+
+* Tomcat
+** `pax-web-tomcat` - required Tomcat bundles (repackaged `org.apache.tomcat` libraries), including HTTP/2 support
+** `pax-web-tomcat-websockets` required Tomcat bundles for WebSocket support (repackaged `org.apache.tomcat` libraries)
+* Undertow
+** `pax-web-undertow` - required Undertow bundles, including HTTP/2 support
+** `pax-web-undertow-websockets` - required Undertow bundles for WebSocket support
+
+.OSGi CMPN Http Service features
+
+* `pax-web-http-jetty` - implementation of OSGi CMPN Chapter 102 "Http Service" specification based on Jetty 9.4
+* `pax-web-http-tomcat` - implementation of OSGi CMPN Chapter 102 "Http Service" specification based on Tomcat 9.0
+* `pax-web-http-undertow` - implementation of OSGi CMPN Chapter 102 "Http Service" specification based on Undertow 2.2
+
+.Additional features
+
+* `pax-web-jsp` - support for Java Server Pages (not mentioned in OSGi CMPN specifications)
+* `pax-web-whiteboard` - support for OSGi CMPN Chapter 140 "Whiteboard Service" specification
+* `pax-web-war` - support for OSGi CMPN Chapter 128 "Web Applications" specification (WABs and WARs)
+* `pax-web-karaf` - Karaf commands implemented by Pax Web itself
+
+====== Additional features that include Pax Web features
+
+Karaf itself provides more features than just `felix-http` and `http`. Simply because there are many Pax Web features, there's support for more web containers and there are more technologies to cover (like websockets and JSPs), but also because of some kind of backward compatibility, here's a list of Pax Web related features defined in Karaf:
+
+* `http` - the _main_ feature mentioned at the start of this chapter. This feature only includes `pax-web-http` feature, also defined in Karaf
+* `pax-web-http` - includes `pax-web-http-jetty` feature from Pax Web and also Http JMX and WebConsole bundles from Karaf
+* `pax-web-http-whiteboard` and `http-whiteboard` (its alias) - include `pax-web-http-jetty`, `pax-web-whiteboard` and `pax-web-websockets` features from Pax Web
+* `pax-web-http-war` and `war` (its alias) - include `pax-web-http-jetty`, `pax-web-war`, `pax-web-jsp` and `pax-web-websockets` features from Pax Web
+* `jetty` - includes `pax-web-jetty`, so it's only used to install Jetty bundles. This feature is used as feature-dependency of many CXF and Camel features.
+
 ===== Configuring the HTTPService
 
 By default the HTTPService listens on port 8181 you can change the port by creating a file `etc/org.ops4j.pax.web.cfg` (if you use the Pax Web Http Service) with the following content:
diff --git a/manual/src/main/asciidoc/user-guide/kar.adoc b/manual/src/main/asciidoc/user-guide/kar.adoc
index 3d40718..cebfcd9 100644
--- a/manual/src/main/asciidoc/user-guide/kar.adoc
+++ b/manual/src/main/asciidoc/user-guide/kar.adoc
@@ -173,26 +173,36 @@ The `feature:repo-list` command gives you the list of registered features reposi
 karaf@root()> feature:repo-list
 Repository                       | URL
 -------------------------------------------------------------------------------------------------------
-standard-4.0.0                   | mvn:org.apache.karaf.features/standard/4.0.0/xml/features
-enterprise-4.0.0                 | mvn:org.apache.karaf.features/enterprise/4.0.0/xml/features
-spring-4.0.0                     | mvn:org.apache.karaf.features/spring/4.0.0/xml/features
-org.ops4j.pax.web-4.1.4          | mvn:org.ops4j.pax.web/pax-web-features/4.1.4/xml/features
+standard-4.4.0                   | mvn:org.apache.karaf.features/standard/4.4.0/xml/features
+enterprise-4.4.0                 | mvn:org.apache.karaf.features/enterprise/4.4.0/xml/features
+spring-4.4.0                     | mvn:org.apache.karaf.features/spring/4.4.0/xml/features
+org.ops4j.pax.web-8.0.2          | mvn:org.ops4j.pax.web/pax-web-features/8.0.2/xml/features
 ----
 
 You can use one of these features repositories to create the kar file:
 
 ----
-karaf@root()> kar:create org.ops4j.pax.web-4.1.4
-Adding feature pax-jetty
-Adding feature pax-http-whiteboard
-Adding feature pax-war
-Adding feature pax-http-tomcat
-Adding feature pax-war-tomcat
-Adding feature pax-http
-Adding feature pax-http-jetty
-Adding feature pax-jsf-support
-Adding feature pax-jetty-spdy
-Kar file created : /home/jbonofre/Downloads/apache-karaf-4.0.0/data/kar/org.ops4j.pax.web-4.1.4.kar
+karaf@root()> kar:create org.ops4j.pax.web-8.0.2
+Adding feature pax-web-karaf
+Adding feature pax-web-core
+Adding feature pax-web-http-tomcat
+Adding feature pax-web-websockets
+Adding feature pax-web-jetty
+Adding feature pax-web-undertow
+Adding feature pax-web-jetty-http2
+Adding feature pax-web-http-undertow
+Adding feature pax-web-whiteboard
+Adding feature pax-web-tomcat-websockets
+Adding feature pax-web-jsp
+Adding feature pax-web-undertow-websockets
+Adding feature pax-web-war
+Adding feature pax-web-jetty-websockets
+Adding feature pax-web-tomcat
+Adding feature pax-web-jetty-http2-jdk8
+Adding feature pax-web-http-jetty
+Adding feature pax-web-jetty-http2-jdk9
+Adding feature pax-web-specs
+Kar file created : /data/servers/apache-karaf-4.4.0-SNAPSHOT/data/kar/org.ops4j.pax.web-8.0.2.kar
 ----
 
 You can see that the KAR file has been created in the `KARAF_DATA/kar` folder.
@@ -202,10 +212,11 @@ By default, the `kar:create` command creates a KAR file, packaging all features
 You can provide the list of features that you want to package into the KAR file:
 
 ----
-karaf@root()> kar:create org.ops4j.pax.web-4.1.4 pax-jetty pax-tomcat
-Adding feature pax-jetty
-Adding feature pax-tomcat
-Kar file created : /opt/apache-karaf-4.1.4/data/kar/org.ops4j.pax.web-4.1.4.kar
+karaf@root()> kar:create org.ops4j.pax.web-8.0.2 pax-web-http-jetty pax-web-jetty
+Adding feature pax-web-core
+Adding feature pax-web-jetty
+Adding feature pax-web-http-jetty
+Kar file created : /data/servers/apache-karaf-4.4.0-SNAPSHOT/data/kar/org.ops4j.pax.web-8.0.2.kar
 ----
 
 ===== `kar:install`
diff --git a/manual/src/main/asciidoc/user-guide/provisioning.adoc b/manual/src/main/asciidoc/user-guide/provisioning.adoc
index c5a30cb..3c781d8 100644
--- a/manual/src/main/asciidoc/user-guide/provisioning.adoc
+++ b/manual/src/main/asciidoc/user-guide/provisioning.adoc
@@ -508,13 +508,21 @@ The `feature:repo-list` command lists all registered feature repositories:
 
 ----
 karaf@root()> feature:repo-list
-Repository               | URL
+Repository                        | URL
 --------------------------------------------------------------------------------------
-org.ops4j.pax.cdi-0.12.0 | mvn:org.ops4j.pax.cdi/pax-cdi-features/0.12.0/xml/features
-org.ops4j.pax.web-4.1.4  | mvn:org.ops4j.pax.web/pax-web-features/4.1.4/xml/features
-standard-4.0.0           | mvn:org.apache.karaf.features/standard/4.0.0/xml/features
-enterprise-4.0.0         | mvn:org.apache.karaf.features/enterprise/4.0.0/xml/features
-spring-4.0.0             | mvn:org.apache.karaf.features/spring/4.0.0/xml/features
+pax-jms-1.1.0                     │ mvn:org.ops4j.pax.jms/pax-jms-features/1.1.0/xml/features
+standard-4.4.0                    │ mvn:org.apache.karaf.features/standard/4.4.0/xml/features
+org.ops4j.pax.jdbc-1.5.0          │ mvn:org.ops4j.pax.jdbc/pax-jdbc-features/1.5.0/xml/features
+aries-jpa-2.7.3                   │ mvn:org.apache.aries.jpa/jpa-features/2.7.3/xml/features
+framework-4.4.0                   │ mvn:org.apache.karaf.features/framework/4.4.0/xml/features
+org.ops4j.pax.web-8.0.2           │ mvn:org.ops4j.pax.web/pax-web-features/8.0.2/xml/features
+pax-transx-0.5.0                  │ mvn:org.ops4j.pax.transx/pax-transx-features/0.5.0/xml/features
+openjpa-3.2.0                     │ mvn:org.apache.openjpa/openjpa-features/3.2.0/xml/features
+specs-4.4.0                       │ mvn:org.apache.karaf.features/specs/4.4.0/xml/features
+hibernate-validator-osgi-features │ mvn:org.hibernate.validator/hibernate-validator-osgi-karaf-features/7.0.1.Final/xml/features
+spring-4.4.0                      │ mvn:org.apache.karaf.features/spring/4.4.0/xml/features
+enterprise-4.4.0                  │ mvn:org.apache.karaf.features/enterprise/4.4.0/xml/features
+org.ops4j.pax.cdi-1.1.4           │ mvn:org.ops4j.pax.cdi/pax-cdi-features/1.1.4/xml/features
 ----
 
 Each repository has a name and the URL to the features XML.
@@ -527,13 +535,21 @@ so update the features definition), you can use the `-r` option:
 karaf@root()> feature:repo-list -r
 Reloading all repositories from their urls
 
-Repository               | URL
+Repository                        | URL
 --------------------------------------------------------------------------------------
-org.ops4j.pax.cdi-0.12.0 | mvn:org.ops4j.pax.cdi/pax-cdi-features/0.12.0/xml/features
-org.ops4j.pax.web-4.1.4  | mvn:org.ops4j.pax.web/pax-web-features/4.1.4/xml/features
-standard-4.0.0           | mvn:org.apache.karaf.features/standard/4.0.0/xml/features
-enterprise-4.0.0         | mvn:org.apache.karaf.features/enterprise/4.0.0/xml/features
-spring-4.0.0             | mvn:org.apache.karaf.features/spring/4.0.0/xml/features
+pax-jms-1.1.0                     │ mvn:org.ops4j.pax.jms/pax-jms-features/1.1.0/xml/features
+standard-4.4.0                    │ mvn:org.apache.karaf.features/standard/4.4.0/xml/features
+org.ops4j.pax.jdbc-1.5.0          │ mvn:org.ops4j.pax.jdbc/pax-jdbc-features/1.5.0/xml/features
+aries-jpa-2.7.3                   │ mvn:org.apache.aries.jpa/jpa-features/2.7.3/xml/features
+framework-4.4.0                   │ mvn:org.apache.karaf.features/framework/4.4.0/xml/features
+org.ops4j.pax.web-8.0.2           │ mvn:org.ops4j.pax.web/pax-web-features/8.0.2/xml/features
+pax-transx-0.5.0                  │ mvn:org.ops4j.pax.transx/pax-transx-features/0.5.0/xml/features
+openjpa-3.2.0                     │ mvn:org.apache.openjpa/openjpa-features/3.2.0/xml/features
+specs-4.4.0                       │ mvn:org.apache.karaf.features/specs/4.4.0/xml/features
+hibernate-validator-osgi-features │ mvn:org.hibernate.validator/hibernate-validator-osgi-karaf-features/7.0.1.Final/xml/features
+spring-4.4.0                      │ mvn:org.apache.karaf.features/spring/4.4.0/xml/features
+enterprise-4.4.0                  │ mvn:org.apache.karaf.features/enterprise/4.4.0/xml/features
+org.ops4j.pax.cdi-1.1.4           │ mvn:org.ops4j.pax.cdi/pax-cdi-features/1.1.4/xml/features
 ----
 
 ===== `feature:repo-add`
@@ -639,18 +655,18 @@ Without argument, the command refreshes all features repository:
 ----
 karaf@root()> feature:repo-refresh
 Refreshing feature url mvn:org.ops4j.pax.cdi/pax-cdi-features/0.12.0/xml/features
-Refreshing feature url mvn:org.ops4j.pax.web/pax-web-features/4.1.4/xml/features
-Refreshing feature url mvn:org.apache.karaf.features/standard/4.0.0/xml/features
-Refreshing feature url mvn:org.apache.karaf.features/enterprise/4.0.0/xml/features
-Refreshing feature url mvn:org.apache.karaf.features/spring/4.0.0/xml/features
+Refreshing feature url mvn:org.ops4j.pax.web/pax-web-features/8.0.2/xml/features
+Refreshing feature url mvn:org.apache.karaf.features/standard/4.4.0/xml/features
+Refreshing feature url mvn:org.apache.karaf.features/enterprise/4.4.0/xml/features
+Refreshing feature url mvn:org.apache.karaf.features/spring/4.4.0/xml/features
 ----
 
 Instead of refreshing all features repositories, you can specify the features repository to refresh, by providing the URL
 or the features repository name (and optionally version):
 
 ----
-karaf@root()> feature:repo-refresh mvn:org.apache.karaf.features/standard/4.0.0/xml/features
-Refreshing feature url mvn:org.apache.karaf.features/standard/4.0.0/xml/features
+karaf@root()> feature:repo-refresh mvn:org.apache.karaf.features/standard/4.4.0/xml/features
+Refreshing feature url mvn:org.apache.karaf.features/standard/4.4.0/xml/features
 ----
 
 ----
@@ -730,25 +746,25 @@ Using the `-i` option displays only installed features:
 karaf@root()> feature:list -i
 Name            | Version | Required | State   | Repository     | Description
 -------------------------------------------------------------------------------------------------------------------
-aries-proxy     | 4.0.0   |          | Started | standard-4.0.0 | Aries Proxy
-aries-blueprint | 4.0.0   | x        | Started | standard-4.0.0 | Aries Blueprint
-feature         | 4.0.0   | x        | Started | standard-4.0.0 | Features Support
-shell           | 4.0.0   | x        | Started | standard-4.0.0 | Karaf Shell
-shell-compat    | 4.0.0   | x        | Started | standard-4.0.0 | Karaf Shell Compatibility
-deployer        | 4.0.0   | x        | Started | standard-4.0.0 | Karaf Deployer
-bundle          | 4.0.0   | x        | Started | standard-4.0.0 | Provide Bundle support
-config          | 4.0.0   | x        | Started | standard-4.0.0 | Provide OSGi ConfigAdmin support
-diagnostic      | 4.0.0   | x        | Started | standard-4.0.0 | Provide Diagnostic support
-instance        | 4.0.0   | x        | Started | standard-4.0.0 | Provide Instance support
-jaas            | 4.0.0   | x        | Started | standard-4.0.0 | Provide JAAS support
-log             | 4.0.0   | x        | Started | standard-4.0.0 | Provide Log support
-package         | 4.0.0   | x        | Started | standard-4.0.0 | Package commands and mbeans
-service         | 4.0.0   | x        | Started | standard-4.0.0 | Provide Service support
-system          | 4.0.0   | x        | Started | standard-4.0.0 | Provide System support
-kar             | 4.0.0   | x        | Started | standard-4.0.0 | Provide KAR (KARaf archive) support
-ssh             | 4.0.0   | x        | Started | standard-4.0.0 | Provide a SSHd server on Karaf
-management      | 4.0.0   | x        | Started | standard-4.0.0 | Provide a JMX MBeanServer and a set of MBeans in
-wrap            | 0.0.0   | x        | Started | standard-4.0.0 | Wrap URL handler
+aries-proxy     | 4.4.0   |          | Started | standard-4.4.0 | Aries Proxy
+aries-blueprint | 4.4.0   | x        | Started | standard-4.4.0 | Aries Blueprint
+feature         | 4.4.0   | x        | Started | standard-4.4.0 | Features Support
+shell           | 4.4.0   | x        | Started | standard-4.4.0 | Karaf Shell
+shell-compat    | 4.4.0   | x        | Started | standard-4.4.0 | Karaf Shell Compatibility
+deployer        | 4.4.0   | x        | Started | standard-4.4.0 | Karaf Deployer
+bundle          | 4.4.0   | x        | Started | standard-4.4.0 | Provide Bundle support
+config          | 4.4.0   | x        | Started | standard-4.4.0 | Provide OSGi ConfigAdmin support
+diagnostic      | 4.4.0   | x        | Started | standard-4.4.0 | Provide Diagnostic support
+instance        | 4.4.0   | x        | Started | standard-4.4.0 | Provide Instance support
+jaas            | 4.4.0   | x        | Started | standard-4.4.0 | Provide JAAS support
+log             | 4.4.0   | x        | Started | standard-4.4.0 | Provide Log support
+package         | 4.4.0   | x        | Started | standard-4.4.0 | Package commands and mbeans
+service         | 4.4.0   | x        | Started | standard-4.4.0 | Provide Service support
+system          | 4.4.0   | x        | Started | standard-4.4.0 | Provide System support
+kar             | 4.4.0   | x        | Started | standard-4.4.0 | Provide KAR (KARaf archive) support
+ssh             | 4.4.0   | x        | Started | standard-4.4.0 | Provide a SSHd server on Karaf
+management      | 4.4.0   | x        | Started | standard-4.4.0 | Provide a JMX MBeanServer and a set of MBeans in
+wrap            | 0.0.0   | x        | Started | standard-4.4.0 | Wrap URL handler
 ----
 
 ===== `feature:install`
@@ -766,7 +782,7 @@ We can simulate an installation using `-t` or `--simulate` option: it just displ
 
 ----
 karaf@root()> feature:install -t -v eventadmin
-Adding features: eventadmin/[4.0.0,4.0.0]
+Adding features: eventadmin/[4.4.0,4.4.0]
 No deployment change.
   Managing bundle:
     org.apache.felix.metatype / 1.0.12
@@ -775,7 +791,7 @@ No deployment change.
 You can specify a feature version to install:
 
 ----
-karaf@root()> feature:install eventadmin/4.0.0
+karaf@root()> feature:install eventadmin/4.4.0
 ----
 
 By default, the `feature:install` command is not verbose. If you want to have some details about actions performed by the `feature:install`
@@ -783,7 +799,7 @@ command, you can use the `-v` option:
 
 ----
 karaf@root()> feature:install -v eventadmin
-Adding features: eventadmin/[4.0.0,4.0.0]
+Adding features: eventadmin/[4.4.0,4.4.0]
 No deployment change.
 Done.
 ----
@@ -794,7 +810,7 @@ bundles, you can use the `-r` option:
 
 ----
 karaf@root()> feature:install -v -r eventadmin
-Adding features: eventadmin/[4.0.0,4.0.0]
+Adding features: eventadmin/[4.4.0,4.4.0]
 No deployment change.
 Done.
 ----
diff --git a/manual/src/main/asciidoc/user-guide/urls.adoc b/manual/src/main/asciidoc/user-guide/urls.adoc
index 347f683..611908b 100644
--- a/manual/src/main/asciidoc/user-guide/urls.adoc
+++ b/manual/src/main/asciidoc/user-guide/urls.adoc
@@ -47,7 +47,7 @@ The equivalent of the above bundle would be:
 In addition to being less verbose, the Maven url handlers can also resolve snapshots and can use a local copy of the jar if one is available in your Maven local repository.
 
 The `org.ops4j.pax.url.mvn` bundle resolves `mvn` URLs. It can be configured using the file `etc/org.ops4j.pax.url.mvn.cfg`.
-Full reference of `org.ops4j.pax.url.mvn` PID configuration can be found on https://ops4j1.jira.com/wiki/display/paxurl/Aether+Configuration[the pax-web Wiki page].
+Full reference of `org.ops4j.pax.url.mvn` PID configuration can be found on https://ops4j1.jira.com/wiki/display/paxurl/Aether+Configuration[the pax-url Wiki page].
 
 The most important property is:
 
diff --git a/manual/src/main/asciidoc/user-guide/webcontainer.adoc b/manual/src/main/asciidoc/user-guide/webcontainer.adoc
index aebdb3f..b58c706 100644
--- a/manual/src/main/asciidoc/user-guide/webcontainer.adoc
+++ b/manual/src/main/asciidoc/user-guide/webcontainer.adoc
@@ -14,7 +14,7 @@
 
 ==== WebContainer (JSP/Servlet)
 
-Apache Karaf can act as a complete WebContainer, fully supporting the JSP/Servlet specifications.
+Apache Karaf can act as a complete WebContainer, fully supporting the JSP/Servlet/WebSockets specifications.
 
 Apache Karaf WebContainer supports both:
 
@@ -27,6 +27,13 @@ To enable the Apache Karaf WebContainer, you just have to install the `war` feat
 karaf@root()> feature:install war
 ----
 
+However, `war` feature is just an alias for `pax-web-http-war` which itself contains these Pax Web specific features:
+
+* pax-web-http-jetty - OSGi CMPN Http Service implementation using Jetty web container
+* pax-web-war - OSGi CMPN Web Applications implementation (web container agnostic)
+* pax-web-jsp - JSP support (no related OSGi CMPN specification)
+* pax-web-websockets - WebSockets support (no related OSGi CMPN specification)
+
 [NOTE]
 ====
 The installation of the `webconsole` feature automatically installs the `war` feature.
@@ -40,8 +47,7 @@ The `war` feature provides:
 
 ===== Configuration
 
-The default port used by the WebContainer is 8181. Note: the connector is actually bound only when at least a servlet or webapplication is using it.
-It means that just installing the `http` or `war` feature doesn't bind the connector.
+The default port used by the WebContainer is 8181. In Pax Web 8, due to internal refactoring, installation of this feature will automatically start the web container without any web applications available.
 
 By default, Karaf creates an internal Jetty connector that you can configure via `etc/org.ops4j.pax.web.cfg`:
 
@@ -88,100 +94,130 @@ The default Apache Karaf WebContainer `etc/jetty.xml` contains:
 ----
 <?xml version="1.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.
+
+    Copyright 2021 OPS4J.
+
+    Licensed 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.
+
 -->
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//
-DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
-
-<Configure class="org.eclipse.jetty.server.Server">
-
-    <!-- =========================================================== -->
-    <!-- Set connectors -->
-    <!-- =========================================================== -->
-    <!-- One of each type! -->
-    <!-- =========================================================== -->
-
-    <!-- Use this connector for many frequently idle connections and for
-        threadless continuations. -->
-    <Call name="addConnector">
-        <Arg>
-            <New class="org.eclipse.jetty.server.nio.SelectChannelConnector">
-                <Set name="host">
-                    <Property name="jetty.host" />
-                </Set>
-                <Set name="port">
-                    <Property name="jetty.port" default="8181" />
-                </Set>
-                <Set name="maxIdleTime">300000</Set>
-                <Set name="Acceptors">2</Set>
-                <Set name="statsOn">false</Set>
-                <Set name="confidentialPort">8443</Set>
-                <Set name="lowResourcesConnections">20000</Set>
-                <Set name="lowResourcesMaxIdleTime">5000</Set>
-            </New>
-        </Arg>
-    </Call>
-
-    <!-- =========================================================== -->
-    <!-- Configure Authentication Realms -->
-    <!-- Realms may be configured for the entire server here, or -->
-    <!-- they can be configured for a specific web app in a context -->
-    <!-- configuration (see $(jetty.home)/contexts/test.xml for an -->
-    <!-- example). -->
-    <!-- =========================================================== -->
-    <Call name="addBean">
-        <Arg>
-            <New class="org.eclipse.jetty.plus.jaas.JAASLoginService">
-                <Set name="name">karaf</Set>
-                <Set name="loginModuleName">karaf</Set>
-                <Set name="roleClassNames">
-                    <Array type="java.lang.String">
-                        <Item>org.apache.karaf.jaas.boot.principal.RolePrincipal
-                        </Item>
-                    </Array>
-                </Set>
-            </New>
-        </Arg>
-    </Call>
-    <Call name="addBean">
-        <Arg>
-            <New class="org.eclipse.jetty.plus.jaas.JAASLoginService">
-                <Set name="name">default</Set>
-                <Set name="loginModuleName">karaf</Set>
-                <Set name="roleClassNames">
-                    <Array type="java.lang.String">
-                        <Item>org.apache.karaf.jaas.boot.principal.RolePrincipal
-                        </Item>
-                    </Array>
-                </Set>
-            </New>
-        </Arg>
-    </Call>
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
+
+<!-- Object named "Server" of org.eclipse.jetty.server.Server class is configured by pax-web-jetty -->
+<Configure id="Server" class="org.eclipse.jetty.server.Server">
+
+	<!-- =========================================================== -->
+	<!-- Set connectors -->
+	<!-- =========================================================== -->
+	<!-- One of each type! -->
+	<!-- =========================================================== -->
+
+	<!-- Use this connector for many frequently idle connections and for
+		threadless continuations. -->
+	<!--	<New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration">-->
+	<!--		<Set name="secureScheme">https</Set>-->
+	<!--		<Set name="securePort">-->
+	<!--			<Property name="jetty.secure.port" default="8443" />-->
+	<!--		</Set>-->
+	<!--		<Set name="outputBufferSize">32768</Set>-->
+	<!--		<Set name="requestHeaderSize">8192</Set>-->
+	<!--		<Set name="responseHeaderSize">8192</Set>-->
+	<!--		<Set name="sendServerVersion">true</Set>-->
+	<!--		<Set name="sendDateHeader">false</Set>-->
+	<!--		<Set name="headerCacheSize">512</Set>-->
+	<!--	</New>-->
+
+	<!-- =========================================================== -->
+	<!-- Special server connectors -->
+	<!-- =========================================================== -->
+	<!-- This is a sample for alternative connectors, enable if needed -->
+	<!-- =========================================================== -->
+	<!--
+	<Call name="addConnector">
+		<Arg>
+			<New class="org.eclipse.jetty.server.ServerConnector">
+				<Arg name="server">
+					<Ref refid="Server" />
+				</Arg>
+				<Arg name="factories">
+					<Array type="org.eclipse.jetty.server.ConnectionFactory">
+						<Item>
+							<New class="org.eclipse.jetty.server.HttpConnectionFactory">
+								<Arg name="config">
+									<Ref refid="httpConfig" />
+								</Arg>
+							</New>
+						</Item>
+					</Array>
+				</Arg>
+				<Set name="host">
+					<Property name="jetty.host" default="localhost" />
+				</Set>
+				<Set name="port">
+					<Property name="jetty.port" default="8282" />
+				</Set>
+				<Set name="idleTimeout">
+					<Property name="http.timeout" default="30000" />
+				</Set>
+				<Set name="name">jettyConn1</Set>
+			</New>
+		</Arg>
+	</Call>
+	 -->
+
+	<!-- =========================================================== -->
+	<!-- Configure Authentication Realms -->
+	<!-- Realms may be configured for the entire server here, or -->
+	<!-- they can be configured for a specific web app in a context -->
+	<!-- configuration (see $(jetty.home)/contexts/test.xml for an -->
+	<!-- example). -->
+	<!-- =========================================================== -->
+	<!--
+	<Call name="addBean">
+		<Arg>
+			<New class="org.eclipse.jetty.jaas.JAASLoginService">
+				<Set name="name">karaf</Set>
+				<Set name="loginModuleName">karaf</Set>
+				<Set name="roleClassNames">
+					<Array type="java.lang.String">
+						<Item>org.apache.karaf.jaas.boot.principal.RolePrincipal</Item>
+					</Array>
+				</Set>
+			</New>
+		</Arg>
+	</Call>
+	<Call name="addBean">
+		<Arg>
+			<New class="org.eclipse.jetty.jaas.JAASLoginService">
+				<Set name="name">default</Set>
+				<Set name="loginModuleName">karaf</Set>
+				<Set name="roleClassNames">
+					<Array type="java.lang.String">
+						<Item>org.apache.karaf.jaas.boot.principal.RolePrincipal</Item>
+					</Array>
+				</Set>
+			</New>
+		</Arg>
+	</Call>
+	-->
 
 </Configure>
 ----
 
-The `SelectChannelConnector` defines the default connector of the WebContainer.
+Pax Web 8 reads `org.ops4j.pax.web` PID configuration which ensures that the default (and secure - if enabled) connetors are running even if there's no specific connector defined in `etc/jetty.xml`.
 
-This connector defines the 8181 port number for the HTTP protocol (`port` property), and the 8443 port number for the
-HTTPS protocol (`confidentialPort` property).
+The above XML configuration contains (disabled by default) `<Call name="addConnector">` element which shows how to configure additional connector.
 
-By default, Apache Karaf bind these ports on all network interfaces (`0.0.0.0`). You can config the `host` property
+By default, Apache Karaf bind these ports on all network interfaces (`0.0.0.0`). You can config the `jetty.host` property
 to bind on a specific network interface (with a given IP address).
 
 The following resources give you details about advanced `etc/jetty.xml` configurations:
@@ -204,7 +240,7 @@ A WAB is a standard WAR or JAR archive containing at least the following propert
 * `Bundle-ManifestVersion: 2` defines that the bundle follows the rules of R4 specification.
 * `Bundle-SymbolicName` specifies a unique, non-localizable name for the bundle. This name should be based on the
  reverse domain name convention.
-* `Web-ContextPath` specifies the location of the web application.
+* `Web-ContextPath` specifies the context path (must start with `/`) of the web application.
 
 WAB can be deployed directly in Apache Karaf, for instance, by dropping the archive in the `deploy` folder, or using the
 `bundle:install` command.
@@ -212,7 +248,58 @@ WAB can be deployed directly in Apache Karaf, for instance, by dropping the arch
 For instance, the Apache Karaf manual (documentation) is available as a WAB that you can deploy directly in a running instance:
 
 ----
-karaf@root()> bundle:install -s mvn:org.apache.karaf/manual/4.0.0/war
+karaf@root()> bundle:install -s mvn:org.apache.karaf/manual/4.4.0
+----
+
+When `pax-web-karaf` feature is installed, there are new commands available and we can already investigate the details about just installed WAB. For example we can see high-level overview of the deployed WABs - together with context path and base URL (which is calculated based on actual information from `org.ops4j.pax.web` PID).
+
+[source,options="nowrap"]
+----
+karaf@root()> web:wab-list
+Context Path   │ Bundle ID │ Symbolic Name           │ State    │ Base URL
+───────────────┼───────────┼─────────────────────────┼──────────┼────────────────────────────────────
+/documentation │ 72        │ org.apache.karaf.manual │ Deployed │ http://127.0.0.1:8181/documentation
+----
+
+We can see the details about selected WAB:
+
+[source,options="nowrap"]
+----
+karaf@root()> web:wab-info 72
+
+Apache Karaf :: Manual (72)
+---------------------------
+Context Path: /documentation
+Deployment State: Deployed
+WAB ClassPath:
+ - bundle://57d1482b-7ade-42b4-950a-f81d26159dda_72.0:0/
+ServletContainerInitializers:
+ - org.ops4j.pax.web.jsp.JasperInitializer
+Container web fragments (reachable bundles without /META-INF/web-fragment.xml):
+ - (70) org.ops4j.pax.web.pax-web-jsp/8.0.2
+----
+
+`web:context-list` shows information of the web contexts (those created for web applications, but also the ones related to HttpService and Whiteboard web elements):
+
+[source,options="nowrap"]
+----
+karaf@root()> web:context-list
+Bundle ID │ Symbolic Name           │ Context Path   │ Context Name   │ Rank │ Service ID │ Type │ Scope   │ Registration Properties
+──────────┼─────────────────────────┼────────────────┼────────────────┼──────┼────────────┼──────┼─────────┼─────────────────────────────────────────────────
+72        │ org.apache.karaf.manual │ /documentation │ /documentation │ MAX  │ 0          │ WAB  │ static* │ osgi.http.whiteboard.context.path=/documentation
+
+*) This context is using ServletContextHelper/HttpContext without resolving an org.osgi.framework.ServiceReference.
+----
+
+Finally, `web:servlet-list` shows all the servlets for all deployed web applications:
+
+[source,options="nowrap"]
+----
+karaf@root()> web:servlet-list
+Bundle ID │ Name    │ Class                                                               │ Context Path(s) │ URLs          │ Type │ Context Filter
+──────────┼─────────┼─────────────────────────────────────────────────────────────────────┼─────────────────┼───────────────┼──────┼───────────────
+72        │ default │ org.ops4j.pax.web.service.tomcat.internal.web.TomcatResourceServlet │ /documentation  │ /             │ WAB  │ -
+72        │ jsp     │ org.ops4j.pax.web.jsp.JspServlet                                    │ /documentation  │ *.jspx, *.jsp │ WAB  │ -
 ----
 
 ====== WAR (WebApplication aRchive)
@@ -223,8 +310,27 @@ Using the `webbundle` prefix and providing headers directly on the URL, Apache K
 
 For instance, you can deploy the Apache Tomcat sample non-OSGi "classical" WAR with the following command:
 
+[source,options="nowrap"]
 ----
-karaf@root()> bundle:install -s "webbundle:http://tomcat.apache.org/tomcat-7.0-doc/appdev/sample/sample.war?Bundle-SymbolicName=tomcat-sample&Web-ContextPath=/sample"
+karaf@root()> bundle:install -s "webbundle:https://tomcat.apache.org/tomcat-9.0-doc/appdev/sample/sample.war?Bundle-SymbolicName=tomcat-sample&Web-ContextPath=/tomcat-docs"
+Bundle ID: 76
+karaf@root()> web:wab-list
+Context Path   │ Bundle ID │ Symbolic Name           │ State    │ Base URL
+───────────────┼───────────┼─────────────────────────┼──────────┼────────────────────────────────────
+/documentation │ 72        │ org.apache.karaf.manual │ Deployed │ http://127.0.0.1:8181/documentation
+/tomcat-docs   │ 76        │ tomcat-sample           │ Deployed │ http://127.0.0.1:8181/tomcat-docs
+karaf@root()> web:wab-info 76
+
+tomcat-sample (76)
+------------------
+Context Path: /tomcat-docs
+Deployment State: Deployed
+WAB ClassPath:
+ - bundle://57d1482b-7ade-42b4-950a-f81d26159dda_76.0:0/WEB-INF/classes/
+ServletContainerInitializers:
+ - org.ops4j.pax.web.jsp.JasperInitializer
+Container web fragments (reachable bundles without /META-INF/web-fragment.xml):
+ - (70) org.ops4j.pax.web.pax-web-jsp/8.0.2
 ----
 
 You can note the `webbundle` prefix, and the `Bundle-SymbolicName` and `Web-ContextPath` headers on the URL.
@@ -238,61 +344,52 @@ You can use the Karaf `ProxyService` programmatically, or via the corresponding
 
 ===== Commands
 
-====== `http:list`
+NOTE: This part of documentation is new for Karaf 4.4.0 with Pax Web 8.
 
-The `http:list` lists the available Servlets deployed in the WebContainer.
+====== `web:servlet-list`
+
+The `web:servlet-list` (previously `http:list`) lists the available Servlets deployed in the WebContainer.
 
 For instance, if you have installed the Apache Karaf WebConsole, you can see the WebConsole Servlets:
 
+[source,options="nowrap"]
 ----
-karaf@root()> http:list
-ID  | Servlet          | Servlet-Name   | State       | Alias               | Url
------------------------------------------------------------------------------------------------------
-113 | ResourceServlet  | /res           | Deployed    | /system/console/res | [/system/console/res/*]
-113 | KarafOsgiManager | ServletModel-2 | Undeployed  | /system/console     | [/system/console/*]
-113 | KarafOsgiManager | ServletModel-5 | Deployed    | /system/console     | [/system/console/*]
+karaf@root()> web:servlet-list
+Bundle ID │ Name                                                          │ Class                                                             │ Context Path(s) │ URLs                  │ Type        │ Context Filter
+──────────┼───────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────┼─────────────────┼───────────────────────┼─────────────┼───────────────
+93        │ default-d975426d-f19e-4b5a-a889-80603beb34c9                  │ org.ops4j.pax.web.service.jetty.internal.web.JettyResourceServlet │ /               │ /system/console/res/* │ HttpService │ -
+93        │ org.apache.felix.webconsole.internal.servlet.KarafOsgiManager │ org.apache.felix.webconsole.internal.servlet.KarafOsgiManager     │ /               │ /system/console/*     │ HttpService │ -
 ----
 
-The `ID` is the ID of the bundle which provides the servlet (`113` here).
-
-The `State` is the current state of the Servlet (`Deployed` or `Undeployed`).
+The `Bundle ID` is the ID of the bundle which provides the servlet (`93` here).
 
-The `Url` is the URL where the Servlet is available.
+The `Name` and `Class` show name and FQCN of the servlet.
 
-====== `web:list`
+The `Context Path(s)` column shows the main context path that hosts the servlet.
 
-The `web:list` command lists the WebApplication Bundles ("native" WAB or "wrapped WAR") deployed in the WebContainer.
+The `URLs` shows the mapping URI patterns defined for the Servlet.
 
-For instance, if you installed the Apache Karaf manual WAR file as described previously, you can see it with `web:list`:
+`Type` column shows the source of servlet registration (can be `WAB`, `HttpService` or `Whiteboard`).
 
-----
-karaf@root()> web:list
-ID  | State       | Web-State   | Level | Web-ContextPath | Name
----------------------------------------------------------------------------------------------------
-111 | Active      | Deployed    | 80    | /karaf-doc      | Apache Karaf :: Manual (4.0.0)
-----
+Finally `Context Filter` shows the Whiteboard context selection filter for the servlet.
 
-====== `web:stop`
+====== `web:wab-list`
 
-The `web:stop` command stops a web application in the WebContainer. The `web:stop` command expects a `id` argument
-corresponding to the bundle ID (as displayed by the `web:list` command).
+The `web:wab-list` (previously `web:list`) command lists the WebApplication Bundles ("native" WAB or "wrapped WAR") deployed in the WebContainer.
 
-For instance, to stop the Apache Karaf manual web application:
+For instance, if you installed the Apache Karaf manual WAR file as described previously, you can see it with `web:wab-list`:
 
+[source,options="nowrap"]
 ----
-karaf@root()> web:stop 111
+karaf@root()> web:wab-list
+Context Path   │ Bundle ID │ Symbolic Name           │ State    │ Base URL
+───────────────┼───────────┼─────────────────────────┼──────────┼────────────────────────────────────
+/documentation │ 72        │ org.apache.karaf.manual │ Deployed │ http://127.0.0.1:8181/documentation
 ----
 
-====== `web:start`
+====== `web:start` and `web:stop`
 
-The `web:start` command starts a web application in the WebContainer. The `web:start` command expects a `id` argument
-corresponding to the bundle ID (as displayed by the `web:list` command).
-
-For instance, to start the Apache Karaf manual web application:
-
-----
-karaf@root()> web:start 111
-----
+These two commands were removed from Karaf 4.4 because Pax Web 8 conforms fully to OSGi CMPN Web Applications specification. A WAB associated with bundle has a lifecycle tied to the lifecycle of the bundle. To stop a web application, one has to stop the bundle.
 
 ====== `http:proxy-list`
 
@@ -360,11 +457,12 @@ The ObjectName to use is `org.apache.karaf:type=http,name=*`.
 
 The `Servlets` attribute provides a tabular data providing the list of deployed Servlets including:
 
-* `Alias` is the Servlet URL alias.
 * `Bundle-ID` is the ID of the bundle which provides this Servlet.
+* `Context-Path` is the context path(s) of the target web application.
 * `Servlet` is the class name of the Servlet.
-* `State` is the current Servlet state (`Deployed` or `Undeployed`).
-* `URL` is the URL of the Servlet (the Servlet context path).
+* `Servlet Name` is the name of the Servlet.
+* `Type` is the Servlet type indicating its origin (HttpService, Whiteboard or WAB)
+* `URL` is the list of URL mappings of the Servlet.
 
 The `Proxies` attribute provides a tabular data providing the list of HTTP proxies including:
 
@@ -389,6 +487,7 @@ The ObjectName to use is `org.apache.karaf:type=web,name=*`.
 
 The `WebBundles` attribute provides a tabular data providing the list of deployed Web Applications including:
 
+* `Context Name` is the name of the web context used by the Web Application.
 * `ID` is the ID of the bundle providing the Web Application.
 * `Level` is the bundle start level.
 * `Name` is the bundle symbolic name providing the Web Application.
diff --git a/web/src/main/java/org/apache/karaf/web/management/internal/WebMBeanImpl.java b/web/src/main/java/org/apache/karaf/web/management/internal/WebMBeanImpl.java
index a601d25..f27aa97 100644
--- a/web/src/main/java/org/apache/karaf/web/management/internal/WebMBeanImpl.java
+++ b/web/src/main/java/org/apache/karaf/web/management/internal/WebMBeanImpl.java
@@ -49,19 +49,21 @@ public class WebMBeanImpl extends StandardMBean implements WebMBean {
     public TabularData getWebBundles() throws MBeanException {
         try {
             CompositeType webType = new CompositeType("Web Bundle", "An OSGi Web bundle",
-                    new String[]{"ID", "State", "Web-State", "Level", "Web-ContextPath", "Name"},
+                    new String[]{"ID", "Context Name", "State", "Web-State", "Level", "Web-ContextPath", "Name"},
                     new String[]{"ID of the bundle",
+                            "Name of the context",
                             "OSGi state of the bundle",
                             "Web state of the bundle",
                             "Start level of the bundle",
                             "Web context path",
                             "Name of the bundle"},
-                    new OpenType[]{SimpleType.LONG, SimpleType.STRING, SimpleType.STRING, SimpleType.INTEGER, SimpleType.STRING, SimpleType.STRING});
+                    new OpenType[]{SimpleType.LONG, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.INTEGER, SimpleType.STRING, SimpleType.STRING});
             TabularType tableType = new TabularType("Web Bundles", "Table of web bundles", webType,
-                    new String[]{"ID"});
+                    new String[]{"ID", "Context Name"});
             TabularData table = new TabularDataSupport(tableType);
             for (WebApplicationInfo webBundle : webContainerService.list()) {
                 String contextPath = webBundle.getContextPath();
+                String contextName = webBundle.getName();
 
                 // get the bundle name
                 String name = webBundle.getBundle().getHeaders().get(Constants.BUNDLE_NAME);
@@ -80,8 +82,9 @@ public class WebMBeanImpl extends StandardMBean implements WebMBean {
 
                 try {
                     CompositeData data = new CompositeDataSupport(webType,
-                            new String[]{"ID", "State", "Web-State", "Level", "Web-ContextPath", "Name"},
+                            new String[]{"ID", "Context Name", "State", "Web-State", "Level", "Web-ContextPath", "Name"},
                             new Object[]{webBundle.getBundle().getBundleId(),
+                                    contextName,
                                     getStateString(webBundle.getBundle()),
                                     webBundle.getDeploymentState(),
                                     level,