To migrate existing modules with our proprietary Bosch Http Service implementation (deprecated) to the Http Service implementation of Equinox, follow the steps below.
Fix Import-Package Versions for Servlet API
The default HttpService implementation now is the one of Equinox. It works with Sevlet API 3.1.0 and that is the version of javax.servlet.* packages exported in the framework(and when it used to be started with httpnext startup parameter before). The version of the Bosch HttpService implementation, when the httpnext startup parameter was omitted, used to be 2.5.0.
If a module has to work with both implementations it can import Servlet packages with a version range:
Import-Package: javax.servlet;version="[2.5.0,4.0.0)", javax.servlet.http;version="[2.5.0,4.0.0)"
Alternatively, javax.servlet.* packages can be imported with no version specified:
Import-Package: javax.servlet, javax.servlet.http
Use the Correct HttpContext for User Authentication
As of Bosch IoT Gateway SDK 9.3.0 this step is no longer needed, since the default HttpContext now delegates handleSecurity to the default ServletContextHelper.
The default HttpContext implementation, which is returned by the Equinox HttpService.createDefaultHttpContext() and is used when servlets/resources are registered in HttpService without specifying a custom HttpContext, does not handle user authentication and instead permits all requests – HttpContext.handleSecurity always returns true.
This behavior is different in the Bosch HttpService implementation (deprecated) – its context will delegate user authentication to an HttpContext registered by com.prosyst.mbs.osgi.http.bundle or com.prosyst.mbs.osgi.http.extender bundles.
This means that when the default HttpContext is used with the deprecated Bosch HttpService implementation, user authentication is applied, but with Equinox implementation all requests are permitted without any authentication.
To use the user authentication, provided by com.prosyst.mbs.osgi.http.extender bundle, modules have two options:
Whiteboard Servlet and Resource Registration
The simplest option is to register servlets and resources using the whiteboard pattern. The Equinox implementation supports Http Whiteboard Specification from OSGi Compendium Release 6. The Bosch implementation (deprecated) supports older specification from Apache Felix, which has been extended to support whiteboard registration of HTTP resources.
When the Equinox HttpService implementation is used, a default org.osgi.service.http.context.ServletContextHelper is registered by com.prosyst.mbs.osgi.http.jetty bundle. This ServletContextHelper delegates authentication to the default HttpContext registered by the com.prosyst.mbs.osgi.http.extender bundle. Servlets and resources, which have not explicitly specified ServletContextHelper in their whiteboard registration, will use the default one and have authentication handled for them.
With the Bosch implementation (deprecated), servlets and resources which do not specify HttpContext with their whiteboard registration are registered in the HttpService using the default HttpContext, which, again, delegates user authentication to the HttpContext from com.prosyst.mbs.osgi.http.extender bundle.
The following is an example that works correctly with both implementations:
import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
import com.prosyst.mbs.services.http.WhiteboardConstants;
...
private static ServiceRegistration<Servlet> registerServlet(BundleContext bc) {
Dictionary<String, String> properties = new Hashtable<String, String>();
// Bosch implementation servlet properties
properties.put(WhiteboardConstants.SERVLET_ALIAS_PROPERTY, ALIAS);
// OSGi Compendium servlet properties
properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, ALIAS + "/*");
return bc.registerService(Servlet.class, new SimpleServlet(), properties);
}
private static ServiceRegistration<Servlet> registerResources(BundleContext bc) {
Dictionary<String, String> properties = new Hashtable<String, String>();
// Bosch implementation resource properties
properties.put(WhiteboardConstants.RESOURCES_ALIAS_PROPERTY, ALIAS + "/images");
properties.put(WhiteboardConstants.RESOURCES_NAME_PROPERTY, "/images");
// OSGi Compendium resource properties
properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PATTERN, ALIAS + "/images/*");
properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PREFIX, "/images");
return bc.registerService(Servlet.class, new HttpServlet() {}, properties);
}
...
Both packages – org.osgi.service.http.whiteboard and com.prosyst.mbs.services.http, are provided by com.prosyst.mbs.osgi.api bundle.
Properties from the Bosch implementation (deprecated) – com.prosyst.mbs.services.http.WhiteboardConstants, are accepted only on services with object class javax.servlet.Servlet. If a convenient Servlet instance is not at hand, an anonymous HttpServlet instance can be used:
• bc.registerService(Servlet.class, new HttpServlet() {}, properties);
Also, the Equinox implementation does not allow a single service registration to have whiteboard, servlet and alias properties, so a separate Servlet instance should be used for registering resources.
Track the Custom HttpContext
A slightly more complicated option is to track the deprecated Bosch HttpContext service and use it when registering servlet/resources that require authentication.
The deprecated Bosch HttpContext is registered with service property role equal to default_context. The following example uses Declarative Services annotations to track the default context and register a servlet only when it is available:
import javax.servlet.ServletException;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.http.HttpContext;
import org.osgi.service.http.HttpService;
import org.osgi.service.http.NamespaceException;
@Component
public class Activator {
private static final String ALIAS = "/test";
@Reference
private HttpService httpService;
@Reference(target = "(role=default_context)")
private HttpContext httpContext;
@Activate
void start() throws ServletException, NamespaceException {
httpService.registerServlet(ALIAS, new SimpleServlet(), null, httpContext);
}
@Deactivate
void stop() {
httpService.unregister(ALIAS);
}
}
The example works correctly with both Equinox and Bosch HttpService implementations.
Use Standardized Alternatives to Proprietary APIs
Some interfaces and methods in com.prosyst.mbs.services.http package, which have good standardized alternatives, are not supported with the Equinox HttpService implementation. Although still supported with the Bosch HttpService implementation, they are deprecated and will be discontinued in the future. The following is a table with these interfaces and their alternative replacements:
Interface/Method |
Alternative |
|---|---|
com.prosyst.mbs.services.http.FiltersManager |
Whiteboard javax.servlet.Filter registration. |
com.prosyst.mbs.services.http.RequestFilter |
Whiteboard javax.servlet.Filter registration. |
com.prosyst.mbs.services.http.HttpHelper methods:
|
Direct connect, using java.net.HttpURLConnection. |
com.prosyst.mbs.services.http.HttpHelper methods:
|
The same functionality can be achieved using a whiteboard javax.servlet.Filter service registration. |
com.prosyst.mbs.services.http.HttpHelper method:
|
To achieve the same functionality, com.prosyst.mbs.services.useradmin.SimpleLogin service can be used. |