Http Whiteboard – Simply Simple – Part III

This is the next part in the series about the OSGi http whiteboard. In my last post I explained how to create an own application servlet context and how to register web components with this context.

Bundle Resources

Doing as outlined in that post, resource handling (the get resource methods on the servlet context) might not work as you expect as you can’t get resources from the bundle where you web component is defined in. If you want this, you need first of all need to register your ServletContextHelper with the service scope Bundle – this ensures that every using bundle gets its own instance of the ServletContextHelper. And with that a servlet from bundle A gets only resources from bundle A, while the servlet from bundle B gets only the resources from that bundle – although they are registered within the same servlet context.

Now using DS this looks a little bit complicated, here is the code:

import java.net.URL;
import java.util.Set;

import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.ServiceScope;
import org.osgi.service.http.context.ServletContextHelper;
import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;

@Component(
        service = ServletContextHelper.class,
        scope = ServiceScope.BUNDLE,
        property = {
                HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME + "=" + AppServletContext.NAME,
                HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH + "=/guessinggame"
        })
public class AppServletContext extends ServletContextHelper {

    public static final String NAME = "game";

    private ServletContextHelper delegatee;

    @Activate
    private void activate(final ComponentContext ctx) {
        delegatee = new ServletContextHelper(ctx.getUsingBundle()) {};
    }

    @Override
    public URL getResource(String name) {
        return delegatee.getResource(name);
    }

    @Override
    public String getMimeType(String name) {
        return delegatee.getMimeType(name);
    }

    @Override
    public Set<String> getResourcePaths(String path) {
        return delegatee.getResourcePaths(path);
    }

    @Override
    public String getRealPath(String path) {
        return delegatee.getRealPath(path);
    }

As you can see in the above example, the ServletContextHelper is registered with the Bundle scope. In order to use the provided functionality of the abstract class ServletContextHelper in the activate method a delegatee is created with the bundle using the ServletContextHelper. The different methods then delegate to the delegatee.

This example looks a little bit complicated, but it is due to the fact that ServletContextHelper only provides to set the bundle through the constructor. And with Declarative Services this is currently a little bit more work to do. But for the upcoming OSGi R7 release, constructor injection is planned, then this should look much cleaner.