Snippets / GetService aQute - Software Consultancy
Search
*

Get a Service (Classic and with Component)

Purpose

Show to obtain a service from the service registry.

Prerequisites

Instructions

Components and services

The easy way to work with a service is using a component. A component uses a short name for a service. Notice that the service is dynamic; it can be registered and unregistered at any moment in time. For components, there are two different ways of working with a component service.

  • locate - The service can be located by its short name whenever it is needed.
  • bean wise - The service component runtime calls get and set methods named in the component description

The following snippet shows both methods. The activate method, called when the component is activated, uses the ComponentContext to find the service in the service registry. However, in the bnd file we will use a set method.

  package aQute.getservice;

  import org.osgi.service.component.*;
  import org.osgi.service.log.*;

  public class GetServiceComponent {
    public void activate(ComponentContext context) {
       LogService log = (LogService) context.locateService("log");
       log.log( LogService.LOG_INFO, "[GetService] activated");
    }
    public void setLog(LogService log) {
      log.log( LogService.LOG_INFO, "[GetService] setLog called");    
    }
  }

The bnd file uses a convention for the service name with respect to the set/unset method. If the name is all upper case, no set/unset methods are used. Lower case names create a set/unset method but can also be used in the locateService methods.

  Private-Package: aQute.getservice
  Service-Component: aQute.getservice.GetServiceComponent; \ 
log=org.osgi.service.log.LogService

The service component uses all the defaults for the reference.

  • static - The reference is static (will not change during the life of the component; when the reference becomes unavailable, the component is deactivated). If you want dynamic, add ;dynamic:="log".
  • mandatory - There needs to be at least one service. If you want optional, add ;optional:="log".
  • unary - Only one service is needed, even if there are more. If you want to be called for multiple services, use ;multiple:="log".

Classic services

Before there were components, one had to get the service from the Bundle Context or use a Tracker. The following example shows how to get the service in the classic way inside a Bundle Activator.

  package aQute.getservice;

  import org.osgi.framework.*;
  import org.osgi.service.log.*;

  public class GetServiceActivator implements BundleActivator {
    BundleContext context;

    public void start(BundleContext context) throws Exception {
      this.context = context;
      log("[GetServiceActivator] start");
    }

    public void stop(BundleContext context) throws Exception {
      log("[GetServiceActivator] stop");
    }

    LogService getLog() {
      ServiceReference logRef = context
          .getServiceReference(LogService.class.getName());
      if (logRef != null) return (LogService) context
          .getService(logRef);
      return null;
    }

    void log(String message) {
      LogService log = getLog();

      if (log != null) {
        log.log(LogService.LOG_INFO, message);
      } else System.out.println("LOG " + message );
    }
  }

Best practice is not to spell out the class name, but to get the class and get the name. Such code is always ok, even if the service name is changed. So:

   BAD:  context.getServiceReference(
       "org.osgi.service.log.LogService");
   GOOD: context.getServiceReference(
       LogService.class.getName());

The appropriate bnd file, which will start the code:

  Private-Package: aQute.getservice
  Bundle-Activator: aQute.getservice.GetServiceActivator

Links

Copyright 2006 aQute SARL, All Rights Reserved