Registering OSGi services

You can create an object and register it as an OSGi service for use by third-party features.

About this task

By using plain old Java code, you 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 you register the object, you can specify what interfaces it provides, and supply a property map. A ServiceRegistration object is returned; if necessary, you can use the ServiceRegistration object to change the properties at any time. When the service is completed, you 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, you can retrieve the best match or all the matches. You can then use the returned ServiceReference that provides the properties to do further matching in your code. You can use the ServiceReference to get the actual service object. When you have finished using the service, you use the BundleContext to release the service.

Procedure

  1. Declare the service interface by adding the following code in your bundle.
    package com.ibm.foo.simple;
    
    /**
     * Our multifunctional sample interface
     */
    public interface Foo
    {
    }
  2. 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() {
    
        }
    }
  3. Use the BundleContext to register the service, modify the service properties, and unregister the service directly in your 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 you can modify the service properties at any time
            sr.setProperties( serviceProperties );
        }
    
        public void unregisterFoo() {
            //when you are done unregister the service using the service registration
            sr.unregister();
        }
    
    }
  4. 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 );
            }
        }
    }