Search code examples
osgipax-webosgi-http-service

Specs: OSGi HTTP Whiteboard and ServletContextHelper


I need some precision about the ServletContextHelper behavior related to the Http Whiteboard Specification when multiple bundle use the same ServletContextHelper

The spec says :

The Http Whiteboard implementation must create a separate ServletContext instance for each ServletContextHelper service. Whiteboard services can be associated with the Servlet Context Helper by using the osgi.http.whiteboard.context.select property. If this property is not set, the default Servlet Context Helper is used.

If I understand correctly, all Servlet or Filter using the same ServletContextHelper reference are bound to the same 'ServletContext'

Then :

Some implementations of the ServletContextHelper may be implemented using a Service Factory, for example to provide resources from the associated bundle, as the default implementation does. Therefore the Whiteboard implementation must get the Servlet Context Helper using the Bundle Context of the bundle that registered the Whiteboard service.

So if a bundle A registers a Servlet with the ServletContextHelper X, and the bundle B registers a Filter with the same reference of ServletContextHelper, then the Servlet and Filter are registered to the same ServletContext, but their init methods are called with two different instances of ServletContext (in order to implements the getClassLoader() methods differently) ?

Moreover, what is the behavior of the "default" ServletContextHelper ? is there always a "default" ServletContextHelper registered ? is it shared between bundles or is there only one instance by bundles ?


Solution

  • I work on Pax Web 8, where I really want to get the behavior right.

    140.2.7 Relation to the Servlet Container chapter of OSGi CMPN specification shows a picture, where there are actually three layers of javax.servlet.ServletContext objects:

    • the ServletContext implementation specific to real Servlet container. In Pax Web it's one of:
      • org.eclipse.jetty.servlet.ServletContextHandler.Context
      • org.apache.catalina.core.ApplicationContext
      • io.undertow.servlet.spec.ServletContextImpl
    • the ServletContext implementation in 1:1 relation with the org.osgi.service.http.context.ServletContextHelper OSGi service
    • the ServletContext that's implementing the service-factory contract for each Whiteboard bundle where all but getClassLoader() methods delegate to the above SCH and getClassLoader() returns bundle.adapt(BundleWiring.class).getClassLoader()

    The problem is related to the double-responsibility principle assumed with org.osgi.service.http.context.ServletContextHelper. It is used both to implement functional aspects (handleSecurity()) and resource-separation aspects (getResource()).

    So you're right - if Bundle A registers a servlet and Bundle B registers a filter, both will use the same instance of ServletContext (supported by the referenced ServletContextHelper), but their init() methods will be provided with different, bundle-specific instance of ServletContext.

    This is simply implemented by delegation, there are two implementations:

    • org.ops4j.pax.web.service.spi.servlet.OsgiServletContext implements the 1:1 behavior
    • org.ops4j.pax.web.service.spi.servlet.OsgiScopedServletContext implements getClassLoader() and delegates all other methods to the above OsgiServletContext