Thursday, June 10, 2010

How to use Config Admin?

Config Admin is one of the most powerful services the OSGi standardized but is often badly understood. The only reason why it seems hard is because it was designed for highly dynamic long living environments. Most applications start, read their configuration, do something, and then die because someone types control-C or the application exists the VM. In a dynamic environment your configuration can change at any time and you're expected to react to these changes. Users tend to like this model.

What we did is merge the initial "get my configuration" phase that so many people are so used to with the notification that there is a configuration change. With the intent to simplify the coding we only have one mechanism: update. The initial phase is a guarantee that the the Configuration Admin service will update you, even if there is no data provided yet. Many programmers hate this model because they do not feel in charge, they want to grab their configuration when they need and not wait until some louse Config Admin calls them. Though this is feasible, it just a lot more work. Relax, and leave the initiative to Config Admin and it all falls into its place.

The key concept of Config Admin is that the receiver of the configuration registers a Managed Service with a property called service.pid. The value of the property is some unique identification. The Config Admin will then call the service's update(Dictionary) method. If it has a configuration for that service.pid, the value will be a set of properties in the Dictionary. If there has been no configuration set, it will call will null. The key thing is to let the Config Admin control you instead of trying to be charge. Another type of Inversion of Control ...

Lets do a simple example of an echo service on an internet port:

public EchoServer implements ManagedService, BundleActivator {
EchoServerImpl server = EchoServerImpl(-1); // Dummy server

public void update(Dictionary props ) {
int port = -1;

if ( props != null) {
Object o = props.get("port");
if ( o != null )
port = (Integer) o;
}
if ( server.getPort() != port ) {
server.quit();
server = new EchoServerImpl(port);
}
}
}
To set Config Admin data, take a look at the Felix Webconsole, Felix FileInstall, or the Knopflerfish environment. They all support a range of (G)UIs to create configuration records.

Peter Kriens

2 comments:

  1. Thanks for the explanation!
    My scenario goes a little bit beyond what this post covers though (and what I have not found in other examples either).

    Basically my use case is:
    0) the service can be individually configured by a consumer -> ManagedServiceFactory
    1) a consumer wants to provide configuration for a service instance
    2) afterwards wants to retrieve the service instance from the service registry

    Fortunately I was able figure it out with the help of Neil's OSGi book [0].

    The key to successfully retrieve the corresponding configured service instance from the service registry, is to have the ManagedServiceFactory register the service instance only after configuration at the service registry. In addition it sets a marker property by which the consumer is later able to identify the service instance (e.g. by using a Filter).
    As a marker property one can either use an application domain identifier, or the service pid that the consumer gets from the Configuration.getPid().

    My code showing this will be available later from [1].

    [0] http://njbartlett.name/blog/osgibook/
    [1] http://github.com/lemmy/org.eclipse.ecf.discovery.dnssd

    ReplyDelete
  2. Thanks for the article. I find it unfortunately that Eclipse does not include the implementation into its Eclipse RCP / Plugin Development download.

    ReplyDelete