Introduction
Pax Web 8 was released on October 20th. While the main blog post summarizing all the changes is still work-in-progress, let me show you how it works with Karaf 4.4.
Here's a list of Karaf command invocations, where the commands are provided by two different bundles:
pax-web-karaf
- this is the bundle that provides Karaf commands to check the information about installed Web Applications. This bundle is supposed to replace all the commands that were so far available in Karaf itself (see Karaf'sweb:list
andhttp:list
commands)org.ops4j.pax.web.samples/showcase
- this bundle providessample:hs
andsample:whiteboard
commands that can be used to register/unregister various Web elements and contexts
Detailed presentation
First web:context-list
presents the contexts
A context is very broad term. Contexts can be:
- implementations of
javax.servlet.ServletContext
- these objects are identified by a context path path and in JavaEE sense, there's one such context per Java Web Application - objects that implement
org.osgi.service.http.HttpContext
interface (HttpService scenario) or extendorg.osgi.service.http.context.ServletContextHelper
abstract class (Whiteboard scenario) - these contexts are the the objects that OSGi developers deal with directly (or reference directly during Whiteboard registration) - objects of
org.ops4j.pax.web.service.spi.model.OsgiContextModel
class - this is an internal Pax Web 8 class that's used to unify the experience related toorg.osgi.service.http.HttpContext
andorg.osgi.service.http.context.ServletContextHelper
contexts. These objects are how the user-facing OSGi services (HttpContext
andServletContextHelper
) are tracked internally.
When Karaf starts with Pax Web 8, there's only one OSGi context:
karaf@root()> web:context-list Bundle ID │ Symbolic Name │ Context Path │ Context Name │ Rank │ Service ID │ Type │ Scope │ Registration Properties ──────────┼───────────────────────────────────────────────┼──────────────┼──────────────┼──────┼────────────┼────────────┼─────────┼────────────────────────────────────────── 77 │ org.ops4j.pax.web.pax-web-extender-whiteboard │ / │ default │ 0 │ 0 │ Whiteboard │ static* │ osgi.http.whiteboard.context.name=default │ │ │ │ │ │ │ │ osgi.http.whiteboard.context.path=/ *) This context is using ServletContextHelper/HttpContext without resolving an org.osgi.framework.ServiceReference.
There's quite a lot of information in this single line:
- The bundle that has registered this OSGi context is
pax-web-extender-whiteboard
and that's the behavior defined in 140.2 The Servlet Context chapter of OSGi CMPN R7 specification. The context path is/
and the name isdefault
. - Service rank and Service ID are
0
, so if one wants to override default Whiteboard context, it's enough to register aorg.osgi.service.http.context.ServletContextHelper
with higher ranking. - Type ==
Whiteboard
means that the OSGi context comes from Whitboard part of Pax Web. It also means that there are other types of contexts (namely -HttpService
andWAB
). - Scope ==
static*
effectively means that this OSGi context is special and treated as default in Pax Web. - Finally we can see (some) registration properties that can be used when targetting given OSGi context.
Quite low-level command shows how interesting bundles reference Pax Web services. The Usage Count
is obtained via reflection (for now - Felix specific).
The purpose of this command is to verify if the bundles properly get and unget Pax Web services, so we have no resource leaks.
Initially, only two Pax Web extenders obtained an instance of org.osgi.service.http.HttpService
, org.ops4j.pax.web.service.WebContainer
.
karaf@root()> web:meta --web-usage-count Registering Bundle: org.ops4j.pax.web.pax-web-runtime [71] Service ID: 109 Service Scope: bundle Usage Counts for bundles referencing the service: Bundle ID │ Symbolic Name │ Service ID │ Scope │ Service objectClass │ Usage Count ──────────┼───────────────────────────────────────────────┼────────────┼───────────┼─────────────────────────────────────────────────────────────────────────────┼──────────── 75 │ org.ops4j.pax.web.pax-web-extender-war │ 90 │ singleton │ [org.ops4j.pax.web.service.spi.model.events.WebApplicationEventListener] │ 1 75 │ org.ops4j.pax.web.pax-web-extender-war │ 109 │ bundle │ [org.osgi.service.http.HttpService, org.ops4j.pax.web.service.WebContainer] │ 1 77 │ org.ops4j.pax.web.pax-web-extender-whiteboard │ 109 │ bundle │ [org.osgi.service.http.HttpService, org.ops4j.pax.web.service.WebContainer] │ 1 111 │ org.ops4j.pax.web.pax-web-karaf │ 109 │ bundle │ [org.osgi.service.http.HttpService, org.ops4j.pax.web.service.WebContainer] │ 0
Let's use sample command to Whiteboard-register a org.osgi.service.http.context.ServletContextHelper
with custom name and non-default context path.
karaf@root()> sample:whiteboard context c1 /c1 >> Using context for bundle org.ops4j.pax.web.samples.showcase [110] >> Registering org.osgi.service.http.context.ServletContextHelper with "c1" name, "/c1" context path and for org.ops4j.pax.web.samples.showcase [110].
Let's register a javax.servlet.http.HttpServlet
Whiteboard service, targetting the above context.
karaf@root()> sample:whiteboard servlet s1 /s1/* c1 >> Using context for bundle org.ops4j.pax.web.samples.showcase [110] >> Registering a servlet with "s1" name, "/s1/*" pattern, "(osgi.http.whiteboard.context.name=c1)" context selector and for org.ops4j.pax.web.samples.showcase [110]. >>>> Registered successfully. You can test it using `curl -i http://127.0.0.1:8181/c1/s1/anything`
The thing to highlight is that the servlet was registered with osgi.http.whiteboard.context.select=(osgi.http.whiteboard.context.name=c1)
registration property. That's the Whiteboard-way to select a target OSGi context, where this servlet should be registered to.
This is exactly the reason why Pax Web 8 was started in the first place! A servlet may target more contexts and it should be available in all of them.
We can check that the servlet is working directly from Karaf
karaf@root()> exec curl -i http://127.0.0.1:8181/c1/s1/anything % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 225 0 225 0 0 5032 0 --:--:-- --:--:-- --:--:-- 5113 HTTP/1.1 200 OK Date: Tue, 23 Nov 2021 14:27:06 GMT Content-Type: text/plain;charset=utf-8 Transfer-Encoding: chunked Servlet: s1 Servlet Config: org.ops4j.pax.web.service.spi.servlet.OsgiInitializedServlet$1@332abd96 Servlet Context: org.ops4j.pax.web.service.spi.servlet.OsgiScopedServletContext@34453e72 Configured name (Whiteboard): /s1/*
As expected, there are now more contexts
karaf@root()> context-list Bundle ID │ Symbolic Name │ Context Path │ Context Name │ Rank │ Service ID │ Type │ Scope │ Registration Properties ──────────┼───────────────────────────────────────────────┼──────────────┼──────────────┼──────┼────────────┼────────────┼───────────┼────────────────────────────────────────── 77 │ org.ops4j.pax.web.pax-web-extender-whiteboard │ / │ default │ 0 │ 0 │ Whiteboard │ static* │ osgi.http.whiteboard.context.name=default │ │ │ │ │ │ │ │ osgi.http.whiteboard.context.path=/ 110 │ org.ops4j.pax.web.samples.showcase │ /c1 │ c1 │ 0 │ 117 │ Whiteboard │ singleton │ osgi.http.whiteboard.context.name=c1 │ │ │ │ │ │ │ │ osgi.http.whiteboard.context.path=/c1 *) This context is using ServletContextHelper/HttpContext without resolving an org.osgi.framework.ServiceReference.
And the usage count has changed
karaf@root()> web:meta --web-usage-count Registering Bundle: org.ops4j.pax.web.pax-web-runtime [71] Service ID: 109 Service Scope: bundle Usage Counts for bundles referencing the service: Bundle ID │ Symbolic Name │ Service ID │ Scope │ Service objectClass │ Usage Count ──────────┼───────────────────────────────────────────────┼────────────┼───────────┼─────────────────────────────────────────────────────────────────────────────┼──────────── 75 │ org.ops4j.pax.web.pax-web-extender-war │ 90 │ singleton │ [org.ops4j.pax.web.service.spi.model.events.WebApplicationEventListener] │ 1 75 │ org.ops4j.pax.web.pax-web-extender-war │ 109 │ bundle │ [org.osgi.service.http.HttpService, org.ops4j.pax.web.service.WebContainer] │ 1 77 │ org.ops4j.pax.web.pax-web-extender-whiteboard │ 109 │ bundle │ [org.osgi.service.http.HttpService, org.ops4j.pax.web.service.WebContainer] │ 1 110 │ org.ops4j.pax.web.samples.showcase │ 109 │ bundle │ [org.osgi.service.http.HttpService, org.ops4j.pax.web.service.WebContainer] │ 1 110 │ org.ops4j.pax.web.samples.showcase │ 117 │ singleton │ [org.osgi.service.http.context.ServletContextHelper] │ 2 110 │ org.ops4j.pax.web.samples.showcase │ 119 │ singleton │ [javax.servlet.http.HttpServlet] │ 1 110 │ org.ops4j.pax.web.samples.showcase │ 111 │ singleton │ [org.osgi.service.http.runtime.HttpServiceRuntime] │ 0 111 │ org.ops4j.pax.web.pax-web-karaf │ 109 │ bundle │ [org.osgi.service.http.HttpService, org.ops4j.pax.web.service.WebContainer] │ 0
Now there's more to explain:
- The interesting rows are the ones related to bundle
org.ops4j.pax.web.samples.showcase
, as it's the bundle that is used to register Whiteboard services. - The usage count for
org.osgi.service.http.HttpService
/org.ops4j.pax.web.service.WebContainer
is exactly1
, as the instance of the service is cached for entire Whiteboard Web Application - The usage count for
javax.servlet.http.HttpServlet
OSGi service is exactly1
. What's more, it was0
before servletsinit()
method was called. - The usage count for
org.osgi.service.http.context.ServletContextHelper
OSGi service is2
. That's because it was dereferenced twice:- To obtain default OSGi context for requests that do not use target servlet (for example - only a request chain containing filters)
- To obtain an OSGi context for the servlet. This is required, so the servlet (which may be registered by different bundle than the one registering the
ServletContextHelper
) gets its own bundle-scoped instance, so Whiteboard specification is satisfied.
- The usage count for
org.osgi.service.http.runtime.HttpServiceRuntime
is0
because it was only used by the command itself to provide user with examplecurl
invocation.
A Whiteboard Web Application is a collection of Whiteboard-registered Web elements and contexts, registered by single bundle. One bundle may register web elements targetting different context paths and one context path (equivalent of JavaEE Web Application) may be populated by web elements coming from different bundles.
Now let's unregister the context, which was targetted by the servlet.
karaf@root()> sample:whiteboard -d -s 117 context >> Using context for bundle org.ops4j.pax.web.samples.showcase [110] >> Unregistering org.osgi.service.http.context.ServletContextHelper with 117 service.id and for org.ops4j.pax.web.samples.showcase [110]. >>>> Unregistered org.apache.felix.framework.ServiceRegistrationImpl@5840e742 successfully. karaf@root()> exec curl -i http://127.0.0.1:8181/c1/s1/anything % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 371 100 371 0 0 65443 0 --:--:-- --:--:-- --:--:-- 74200 HTTP/1.1 404 Not Found Cache-Control: must-revalidate,no-cache,no-store Content-Type: text/html;charset=iso-8859-1 Content-Length: 371
See? We've got expected 404
What's more, we can see this information in the logs:
(WhiteboardExtenderContext.java:446) : Unregistering ServletModel{id=ServletModel-5,name='s1',urlPatterns=[/s1/*],contexts=[{WB,OCM-3,c1,/c1}]} because its context selection filter doesn't match any context
No worries - when proper context is registered again, the servlet will move to this new context. We'll see it later.
context-list
command shows again only one context
karaf@root()> context-list Bundle ID │ Symbolic Name │ Context Path │ Context Name │ Rank │ Service ID │ Type │ Scope │ Registration Properties ──────────┼───────────────────────────────────────────────┼──────────────┼──────────────┼──────┼────────────┼────────────┼─────────┼────────────────────────────────────────── 77 │ org.ops4j.pax.web.pax-web-extender-whiteboard │ / │ default │ 0 │ 0 │ Whiteboard │ static* │ osgi.http.whiteboard.context.name=default │ │ │ │ │ │ │ │ osgi.http.whiteboard.context.path=/ *) This context is using ServletContextHelper/HttpContext without resolving an org.osgi.framework.ServiceReference.
The usage counts has changed too
karaf@root()> web:meta --web-usage-count Registering Bundle: org.ops4j.pax.web.pax-web-runtime [71] Service ID: 109 Service Scope: bundle Usage Counts for bundles referencing the service: Bundle ID │ Symbolic Name │ Service ID │ Scope │ Service objectClass │ Usage Count ──────────┼───────────────────────────────────────────────┼────────────┼───────────┼─────────────────────────────────────────────────────────────────────────────┼──────────── 75 │ org.ops4j.pax.web.pax-web-extender-war │ 90 │ singleton │ [org.ops4j.pax.web.service.spi.model.events.WebApplicationEventListener] │ 1 75 │ org.ops4j.pax.web.pax-web-extender-war │ 109 │ bundle │ [org.osgi.service.http.HttpService, org.ops4j.pax.web.service.WebContainer] │ 1 77 │ org.ops4j.pax.web.pax-web-extender-whiteboard │ 109 │ bundle │ [org.osgi.service.http.HttpService, org.ops4j.pax.web.service.WebContainer] │ 1 110 │ org.ops4j.pax.web.samples.showcase │ 109 │ bundle │ [org.osgi.service.http.HttpService, org.ops4j.pax.web.service.WebContainer] │ 1 110 │ org.ops4j.pax.web.samples.showcase │ 119 │ singleton │ [javax.servlet.http.HttpServlet] │ 0 110 │ org.ops4j.pax.web.samples.showcase │ 111 │ singleton │ [org.osgi.service.http.runtime.HttpServiceRuntime] │ 0 111 │ org.ops4j.pax.web.pax-web-karaf │ 109 │ bundle │ [org.osgi.service.http.HttpService, org.ops4j.pax.web.service.WebContainer] │ 0
Important observation:
- Usage count for
javax.servlet.http.HttpServlet
dropped to0
, as the servlet has been stopped (destroy()
was called on it). - There are no more references for
org.osgi.service.http.context.ServletContextHelper
, because this service was unregistered completely. - There's still one usage for
org.osgi.service.http.HttpService
/org.ops4j.pax.web.service.WebContainer
because the Whiteboard Web Application is still there. It'll be removed completely when the bundle110
is stopped.
Let's see Pax Web 8 magic in action. Registering new OSGi context that can satisfy already registered servlet, automatically redeploys the servlet to new matching context!
karaf@root()> sample:whiteboard context c1 /c2 >> Using context for bundle org.ops4j.pax.web.samples.showcase [110] >> Registering org.osgi.service.http.context.ServletContextHelper with "c1" name, "/c2" context path and for org.ops4j.pax.web.samples.showcase [110].
We've registered a c1
context (the name used before), but with different context path: /c2
instead of /c1
.
Let's check the usage counts
karaf@root()> web:meta --web-usage-count Registering Bundle: org.ops4j.pax.web.pax-web-runtime [71] Service ID: 109 Service Scope: bundle Usage Counts for bundles referencing the service: Bundle ID │ Symbolic Name │ Service ID │ Scope │ Service objectClass │ Usage Count ──────────┼───────────────────────────────────────────────┼────────────┼───────────┼─────────────────────────────────────────────────────────────────────────────┼──────────── 75 │ org.ops4j.pax.web.pax-web-extender-war │ 90 │ singleton │ [org.ops4j.pax.web.service.spi.model.events.WebApplicationEventListener] │ 1 75 │ org.ops4j.pax.web.pax-web-extender-war │ 109 │ bundle │ [org.osgi.service.http.HttpService, org.ops4j.pax.web.service.WebContainer] │ 1 77 │ org.ops4j.pax.web.pax-web-extender-whiteboard │ 109 │ bundle │ [org.osgi.service.http.HttpService, org.ops4j.pax.web.service.WebContainer] │ 1 110 │ org.ops4j.pax.web.samples.showcase │ 109 │ bundle │ [org.osgi.service.http.HttpService, org.ops4j.pax.web.service.WebContainer] │ 1 110 │ org.ops4j.pax.web.samples.showcase │ 119 │ singleton │ [javax.servlet.http.HttpServlet] │ 0 110 │ org.ops4j.pax.web.samples.showcase │ 111 │ singleton │ [org.osgi.service.http.runtime.HttpServiceRuntime] │ 0 110 │ org.ops4j.pax.web.samples.showcase │ 120 │ singleton │ [org.osgi.service.http.context.ServletContextHelper] │ 2 111 │ org.ops4j.pax.web.pax-web-karaf │ 109 │ bundle │ [org.osgi.service.http.HttpService, org.ops4j.pax.web.service.WebContainer] │ 0
The new org.osgi.service.http.context.ServletContextHelper
is already referenced twice (the same reasons as above), but the javax.servlet.http.HttpServlet
is referenced 0 times - because the servlet wasn't called yet (thus no init()
was called on it).
Servlet is available in new context and not available in the old one
karaf@root()> exec curl -i http://127.0.0.1:8181/c1/s1/anything % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 371 100 371 0 0 201k 0 --:--:-- --:--:-- --:--:-- 362k HTTP/1.1 404 Not Found Cache-Control: must-revalidate,no-cache,no-store Content-Type: text/html;charset=iso-8859-1 Content-Length: 371 karaf@root()> exec curl -i http://127.0.0.1:8181/c2/s1/anything % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 225 0 225 0 0 124k 0 --:--:-- --:--:-- --:--:-- 219k HTTP/1.1 200 OK Date: Tue, 23 Nov 2021 14:29:32 GMT Content-Type: text/plain;charset=utf-8 Transfer-Encoding: chunked Servlet: s1 Servlet Config: org.ops4j.pax.web.service.spi.servlet.OsgiInitializedServlet$1@2e0bd609 Servlet Context: org.ops4j.pax.web.service.spi.servlet.OsgiScopedServletContext@6b095dac Configured name (Whiteboard): /s1/*
context-list
at this stage
karaf@root()> context-list Bundle ID │ Symbolic Name │ Context Path │ Context Name │ Rank │ Service ID │ Type │ Scope │ Registration Properties ──────────┼───────────────────────────────────────────────┼──────────────┼──────────────┼──────┼────────────┼────────────┼───────────┼────────────────────────────────────────── 77 │ org.ops4j.pax.web.pax-web-extender-whiteboard │ / │ default │ 0 │ 0 │ Whiteboard │ static* │ osgi.http.whiteboard.context.name=default │ │ │ │ │ │ │ │ osgi.http.whiteboard.context.path=/ 110 │ org.ops4j.pax.web.samples.showcase │ /c2 │ c1 │ 0 │ 120 │ Whiteboard │ singleton │ osgi.http.whiteboard.context.name=c1 │ │ │ │ │ │ │ │ osgi.http.whiteboard.context.path=/c2 *) This context is using ServletContextHelper/HttpContext without resolving an org.osgi.framework.ServiceReference.
Usage counts still shows no leakage
karaf@root()> web:meta --web-usage-count Registering Bundle: org.ops4j.pax.web.pax-web-runtime [71] Service ID: 109 Service Scope: bundle Usage Counts for bundles referencing the service: Bundle ID │ Symbolic Name │ Service ID │ Scope │ Service objectClass │ Usage Count ──────────┼───────────────────────────────────────────────┼────────────┼───────────┼─────────────────────────────────────────────────────────────────────────────┼──────────── 75 │ org.ops4j.pax.web.pax-web-extender-war │ 90 │ singleton │ [org.ops4j.pax.web.service.spi.model.events.WebApplicationEventListener] │ 1 75 │ org.ops4j.pax.web.pax-web-extender-war │ 109 │ bundle │ [org.osgi.service.http.HttpService, org.ops4j.pax.web.service.WebContainer] │ 1 77 │ org.ops4j.pax.web.pax-web-extender-whiteboard │ 109 │ bundle │ [org.osgi.service.http.HttpService, org.ops4j.pax.web.service.WebContainer] │ 1 110 │ org.ops4j.pax.web.samples.showcase │ 109 │ bundle │ [org.osgi.service.http.HttpService, org.ops4j.pax.web.service.WebContainer] │ 1 110 │ org.ops4j.pax.web.samples.showcase │ 119 │ singleton │ [javax.servlet.http.HttpServlet] │ 1 110 │ org.ops4j.pax.web.samples.showcase │ 111 │ singleton │ [org.osgi.service.http.runtime.HttpServiceRuntime] │ 0 110 │ org.ops4j.pax.web.samples.showcase │ 120 │ singleton │ [org.osgi.service.http.context.ServletContextHelper] │ 2 111 │ org.ops4j.pax.web.pax-web-karaf │ 109 │ bundle │ [org.osgi.service.http.HttpService, org.ops4j.pax.web.service.WebContainer] │ 0
Let's unregister the servlet this time
karaf@root()> sample:whiteboard -d servlet s1 >> Using context for bundle org.ops4j.pax.web.samples.showcase [110] >>>> Unregistered org.apache.felix.framework.ServiceRegistrationImpl@68ed9dd9 successfully. karaf@root()> web:meta --web-usage-count Registering Bundle: org.ops4j.pax.web.pax-web-runtime [71] Service ID: 109 Service Scope: bundle Usage Counts for bundles referencing the service: Bundle ID │ Symbolic Name │ Service ID │ Scope │ Service objectClass │ Usage Count ──────────┼───────────────────────────────────────────────┼────────────┼───────────┼─────────────────────────────────────────────────────────────────────────────┼──────────── 75 │ org.ops4j.pax.web.pax-web-extender-war │ 90 │ singleton │ [org.ops4j.pax.web.service.spi.model.events.WebApplicationEventListener] │ 1 75 │ org.ops4j.pax.web.pax-web-extender-war │ 109 │ bundle │ [org.osgi.service.http.HttpService, org.ops4j.pax.web.service.WebContainer] │ 1 77 │ org.ops4j.pax.web.pax-web-extender-whiteboard │ 109 │ bundle │ [org.osgi.service.http.HttpService, org.ops4j.pax.web.service.WebContainer] │ 1 110 │ org.ops4j.pax.web.samples.showcase │ 109 │ bundle │ [org.osgi.service.http.HttpService, org.ops4j.pax.web.service.WebContainer] │ 1 110 │ org.ops4j.pax.web.samples.showcase │ 111 │ singleton │ [org.osgi.service.http.runtime.HttpServiceRuntime] │ 0 110 │ org.ops4j.pax.web.samples.showcase │ 120 │ singleton │ [org.osgi.service.http.context.ServletContextHelper] │ 1 111 │ org.ops4j.pax.web.pax-web-karaf │ 109 │ bundle │ [org.osgi.service.http.HttpService, org.ops4j.pax.web.service.WebContainer] │ 0
See that the org.osgi.service.http.context.ServletContextHelper
is now referenced only once - as the default OSGi context for /c2
context path.
Let's unregister the Whiteboard context
karaf@root()> sample:whiteboard -d -s 120 context >> Using context for bundle org.ops4j.pax.web.samples.showcase [110] >> Unregistering org.osgi.service.http.context.ServletContextHelper with 120 service.id and for org.ops4j.pax.web.samples.showcase [110]. >>>> Unregistered org.apache.felix.framework.ServiceRegistrationImpl@1ff977fd successfully. karaf@root()> web:meta --web-usage-count Registering Bundle: org.ops4j.pax.web.pax-web-runtime [71] Service ID: 109 Service Scope: bundle Usage Counts for bundles referencing the service: Bundle ID │ Symbolic Name │ Service ID │ Scope │ Service objectClass │ Usage Count ──────────┼───────────────────────────────────────────────┼────────────┼───────────┼─────────────────────────────────────────────────────────────────────────────┼──────────── 75 │ org.ops4j.pax.web.pax-web-extender-war │ 90 │ singleton │ [org.ops4j.pax.web.service.spi.model.events.WebApplicationEventListener] │ 1 75 │ org.ops4j.pax.web.pax-web-extender-war │ 109 │ bundle │ [org.osgi.service.http.HttpService, org.ops4j.pax.web.service.WebContainer] │ 1 77 │ org.ops4j.pax.web.pax-web-extender-whiteboard │ 109 │ bundle │ [org.osgi.service.http.HttpService, org.ops4j.pax.web.service.WebContainer] │ 1 110 │ org.ops4j.pax.web.samples.showcase │ 109 │ bundle │ [org.osgi.service.http.HttpService, org.ops4j.pax.web.service.WebContainer] │ 1 110 │ org.ops4j.pax.web.samples.showcase │ 111 │ singleton │ [org.osgi.service.http.runtime.HttpServiceRuntime] │ 0 111 │ org.ops4j.pax.web.pax-web-karaf │ 109 │ bundle │ [org.osgi.service.http.HttpService, org.ops4j.pax.web.service.WebContainer] │ 0 karaf@root()> context-list Bundle ID │ Symbolic Name │ Context Path │ Context Name │ Rank │ Service ID │ Type │ Scope │ Registration Properties ──────────┼───────────────────────────────────────────────┼──────────────┼──────────────┼──────┼────────────┼────────────┼─────────┼────────────────────────────────────────── 77 │ org.ops4j.pax.web.pax-web-extender-whiteboard │ / │ default │ 0 │ 0 │ Whiteboard │ static* │ osgi.http.whiteboard.context.name=default │ │ │ │ │ │ │ │ osgi.http.whiteboard.context.path=/ *) This context is using ServletContextHelper/HttpContext without resolving an org.osgi.framework.ServiceReference.
See - no more custom context and the usage counts show that there's only one extra reference for org.osgi.service.http.HttpService
/org.ops4j.pax.web.service.WebContainer
- kept by our showcase
bundle.
The last reference should be gone when bundle 110
is stopped
karaf@root()> web:meta --web-usage-count Registering Bundle: org.ops4j.pax.web.pax-web-runtime [71] Service ID: 109 Service Scope: bundle Usage Counts for bundles referencing the service: Bundle ID │ Symbolic Name │ Service ID │ Scope │ Service objectClass │ Usage Count ──────────┼───────────────────────────────────────────────┼────────────┼───────────┼─────────────────────────────────────────────────────────────────────────────┼──────────── 75 │ org.ops4j.pax.web.pax-web-extender-war │ 90 │ singleton │ [org.ops4j.pax.web.service.spi.model.events.WebApplicationEventListener] │ 1 75 │ org.ops4j.pax.web.pax-web-extender-war │ 109 │ bundle │ [org.osgi.service.http.HttpService, org.ops4j.pax.web.service.WebContainer] │ 1 77 │ org.ops4j.pax.web.pax-web-extender-whiteboard │ 109 │ bundle │ [org.osgi.service.http.HttpService, org.ops4j.pax.web.service.WebContainer] │ 1 111 │ org.ops4j.pax.web.pax-web-karaf │ 109 │ bundle │ [org.osgi.service.http.HttpService, org.ops4j.pax.web.service.WebContainer] │ 0Everything is nicely cleaned up!
Summary
I know I should've written much more about Pax Web 8, but the day will eventually come...