Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the proper way of disabling an OSGi service at service start?

I have created an OSGi bundle with an exposed (declarative) service. If I, when activate is called, notice that something is amiss such that I can not provide the service, I need to prevent it from being exposed. At the moment the activation function looks like so:

public void activate(ComponentContext context, Map<String, Object> properties) {
    pid = (String) properties.get(Constants.SERVICE_PID);
    try {
       ...
    }
    catch(Exception e) {
        context.disableComponent(pid);
    }
}

Another alternative is to just wrap/propagate the exception (or throw a new one, depending) like this:

public void activate(ComponentContext context, Map<String, Object> properties) {
    try {
       ...
    }
    catch(Exception e) {
        throw new ComponentException("Some reason");
    }
}

I can not find the correct behavior specified in the section on declarative services in the OSGi Service Platform Service Compendium, but I might be missing something

like image 848
Henrik Gustafsson Avatar asked Oct 14 '09 14:10

Henrik Gustafsson


2 Answers

Hmm, for me it seems logical that an Exception should be thrown if an error occurs. Basically, what you're doing then is mimicking the behavior of a BundleActivator in the start method. The bundle enters the ACTIVE state when the start method returns without an Exception (otherwise it remains in RESOLVED). I found a somewhat fitting paragraph in the DS specification (I highlighted the interesting part):

A component instance must complete activation before it can be deactivated. Once the component configuration is deactivated or fails to activate due to an exception, SCR must unbind all the component’s bound services and discard all references to the component instance associated with the activation.

Section 112.5.6 P.320 in the OSGi 4.2 cmpn spec

I agree that this is not crystal clear, so if you want to be on the safe side (better safe than sorry), I would recommend to do the combination (allowed by the spec).

public void activate(ComponentContext context, Map<String, Object> properties) {
    try {
       ...
    } catch(Exception e) {
        context.disableComponent((String) properties.get(Constants.SERVICE_PID));
        // not sure if a CE is best here... Maybe just rethrow the original one
        throw new ComponentException("Some reason");
    }
}

Cheers, Mirko

like image 159
Mirko Jahn Avatar answered Oct 13 '22 01:10

Mirko Jahn


A component disabling itself is very unlikely to be an appropriate OSGI design. What will enable the component when the situation improves? The enabled/disabled state is intended to be a different logical level than activated/deactivated.

Properly designed OSGI code should deal correctly with code that throws a ComponentException (or other exception) when activation fails. Assuming the component registers a service, the service reference will be available but attempting to get the service will return null. DS will deal correctly with references to the service, and any code that directly attempts to get the service from the service reference must deal properly with the possibility that the service is not actually available.

However, this can be confusing. In Felix DS I implemented an extension whereby components can change their own service properties, although this has not been accepted into the spec. Using this extension, a component can add a service property such as active=true when activation or modification succeeds and remove it when modification fails or on deactivation. Clients of the service can filter on this service property, e.g. (active=true).

like image 42
David Jencks Avatar answered Oct 13 '22 00:10

David Jencks