Register OSGi services
We can create an object and register it as an OSGi service for use by third-party features.
By using plain old Java code, we can create an object, and then register it as a service using the BundleContext class. Because the code has to run, you typically register the object in a BundleActivator interface. When we register the object, we can specify what interfaces it provides, and supply a property map. A ServiceRegistration object is returned; if necessary, we can use the ServiceRegistration object to change the properties at any time. When the service is completed, we use the ServiceRegistration object to unregister the service.
To obtain a service, you query the BundleContext for a service that implements a required interface and, optionally, supply an LDAP-syntax filter to match the service properties. Depending on the method you call, we can retrieve the best match or all the matches. We can then use the returned ServiceReference that provides the properties to do further matching in the code. We can use the ServiceReference to get the actual service object. When we have finished using the service, we use the BundleContext to release the service.
- Declare the service interface by adding the following code in the bundle.
package com.ibm.foo.simple; /** * Our multifunctional sample interface */ public interface Foo { }
- Specify the implementation code of the interface.
package com.ibm.foo.simple; /** * The implementation of the Foo interface */ public class FooImpl implements Foo { public FooImpl() { } public FooImpl(String vendor) { } /** * used by the ServiceFactory implementation. */ public void destroy() { } }- Use the BundleContext to register the service, modify the service properties, and unregister the service directly in the code.
import java.util.Dictionary; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; /** * Registers and unregsiters a Foo service directly, * and shows how to modify the service properties in code. */ public class FooController { private final BundleContext bundleContext; private ServiceRegistration<Foo> sr; public FooController( BundleContext bundleContext ) { this.bundleContext = bundleContext; } public void register(Dictionary<String, Object> serviceProperties) { Foo foo = new FooImpl(); //typed service registration with one interface sr = bundleContext.registerService( Foo.class, foo, serviceProperties ); //or //untyped service registration with one interface sr = (ServiceRegistration<Foo>)bundleContext.registerService( Foo.class.getName(), foo, serviceProperties ); //or //untyped service registration with more than one interface (or class) sr = (ServiceRegistration<Foo>)bundleContext.registerService(new String[] { Foo.class.getName(), FooImpl.class.getName()}, foo, serviceProperties ); } public void modifyFoo(Dictionary<String, Object> serviceProperties) { //with the service registration we can modify the service properties at any time sr.setProperties( serviceProperties ); } public void unregisterFoo() { //when we are done unregister the service using the service registration sr.unregister(); } }
- Obtain and return the service from another class:
package com.ibm.foo.simple; import java.util.Collection; import org.osgi.framework.BundleContext; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; /** * A simple Foo client that directly obtains the Foo service and returns it when done. */ public class FooUser { private final BundleContext bundleContext; public FooUser( BundleContext bundleContext ) { this.bundleContext = bundleContext; } /** * assume there's only one Foo */ public void useFooSimple() { ServiceReference<Foo> sr = bundleContext.getServiceReference( Foo.class ); String[] propertyKeys = sr.getPropertyKeys(); for (String key: propertyKeys) { Object prop = sr.getProperty( key ); //think about whether this is the Foo we want.... } Foo foo = bundleContext.getService( sr ); try { //use foo } finally { //we're done bundleContext.ungetService( sr ); } } /** * Use a filter to select a particular Foo. Note we get a collection back and have to pick one. * @throws InvalidSyntaxException */ public void useFooFilter() throws InvalidSyntaxException { Collection<ServiceReference<Foo>> srs = bundleContext.getServiceReferences( Foo.class, "(&(service.vendor=IBM)(id='myFoo')" ); ServiceReference<Foo> sr = srs.iterator().next(); String[] propertyKeys = sr.getPropertyKeys(); for (String key: propertyKeys) { Object prop = sr.getProperty( key ); //think about whether this is the Foo we want.... } Foo foo = bundleContext.getService( sr ); try { //use foo } finally { //we're done bundleContext.ungetService( sr ); } } }
Parent topic: Work with the OSGi service registry