Dirk Fauth Dirk Fauth - 1 year ago 153
Java Question

OSGi modify event method not called

I'm playing around with OSGi DS components and the ConfigurationAdmin.

I created a simple configurable component

public class ConfigurableService {

private String message;

public void activate(Map<String, Object> params) {
System.out.println("Activate configurable");
message = (String) params.get("msg");

public void modified(Map<String, Object> params) {
System.out.println("Modify configurable");
message = (String) params.get("msg");

public void deactivate(Map<String, Object> params) {
System.out.println("Deactivate configurable");
message = (String) params.get("msg");

public void execute() {
System.out.println("Service says: " + message);

Then I created a Felix Gogo shell command component to trigger the configuration via ConfigurationAdmin

@Component(property = {
CommandProcessor.COMMAND_SCOPE + "=fipro",
CommandProcessor.COMMAND_FUNCTION + "=configure"
service = ConfigurationCommand.class
public class ConfigurationCommand {

private ConfigurationAdmin cm;

public void setConfigAdmin(ConfigurationAdmin cm) {
this.cm = cm;

public void configure(String input) throws IOException {
Configuration config = cm.getConfiguration("com.bosch.osgi.config.ConfigurableService");
Hashtable<String, Object> props = new Hashtable<>();
props.put("msg", input);

And at last I created another Felix Gogo shell command component that makes use of the

@Component(property = {
CommandProcessor.COMMAND_SCOPE + "=fipro",
CommandProcessor.COMMAND_FUNCTION + "=welcome"
service = WelcomeCommand.class
public class WelcomeCommand {

private ConfigurableService service;

public void setConfigurable(ConfigurableService service) {
this.service = service;

public void updatedConfigurable(ConfigurableService service, Map<String, Object> properties) {
System.out.println("ConfigurableService updated");

public void welcome() {

If I start an OSGi application with the bundles that contain these components, I expect that on executing
initially, I will see that the component is activated and the service output is null because no configuration is applied yet (sure this changes on consecutive calls). If I afterwards execute
configure Dirk
I expect that the method annotated with
is executed to indicate that the service configuration has been updated. I also expect that the
method in the
is executed. At least that is my understanding from reading the spec.

Now I observe different behavior in Equinox and Felix.


The modified method is called as expected and the
is configured correctly. But the
updatedConfigurable(<Service>, <Map>)
is not called. Only if I change the method signature to take a
the updated method gets called.

The specification says that all reference event methods support the following method signatures

void <method-name>(ServiceReference);
void <method-name>(<parameter-type>);
void <method-name>(<parameter-type>, Map);

Is there an exception for the updated method I haven't seen in the spec or is this an issue in Equinox where I should raise a ticket for?


If I run the same example on Felix in Bndtools, neither the modified nor the update methods get called. I checked the
and there is a ConfigurationAdmin available so there is no exception on updating the configuration. But it gets never applied somehow.

Am I missing something on running the example on Felix?


Adding console outputs to every lifecycle event method creates the following output:

Welcome to Apache Felix Gogo

g! ConfigurationCommand: Activate
ConfigurableService: Activate
WelcomeCommand: Activate
Service says: null
g! configure Dirk
g! welcome
Service says: null
g! exit 0
WelcomeCommand: Deactivate
ConfigurableService: Deactivate
ConfigurationCommand: Deactivate

As you can see, the modify and updated events are never called.

Answer Source

I think the problem is the lifecycle for Gogo commands.

Gogo does not hold on to service objects while a command is not running. It tracks the ServiceReference but does not call getService until you actually invoke the welcome command. Therefore when you invoke welcome, the WelcomeCommand component will be instantiated, which forces the instantiation of the ConfigurableService at that time.

Later when the welcome command completes, the WelcomeCommand is released, therefore both WelcomeCommand and ConfigurableService will be GC'd. Therefore no instance of ConfigurableService ever lives long enough to receive the Modified event.

To address this, try making WelcomeCommand immediate:

@Component(immediate = true, ...)


On further discussion with Dirk over email, it turns out that the issue is location binding. In Config Admin, configurations are by default "bound" to the bundle which creates them, in this case the bundle that contains ConfigurationCommand. Once bound they cannot be consumed by another bundle, so the ConfigurableService never sees the config.

To create an unbound configuration that can be used by any bundle, call the two-arg version of ConfigAdmin.getConfiguration() and pass null for the second arg.