[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[equinox-dev] Declarative Services use case and inconsistencies between old and new (ProSyst-contributed) implementations

Hi all,

We've recently switched to the ProSyst implementation of SCR in hopes of overcoming many of the issues the old one had.  I've encountered an implementation detail with the new version that affects one of my standard practices.

We use the whiteboard pattern in a bunch of places to register extensions to certain things (similar to the use of Eclipse's Extension registry).  With many of the extension objects, service properties are used to define some metadata. 

My general methodology is to declare a component that has a reference to the particular extension interface with cardinality 0..n.  I then create a bind method that looks something like this:

public void extensionAdded(ServiceReference extensionRef) {
  String extensionId = (String) extensionRef.getProperty("extension.id");
  String extensionName = (String) extensionRef.getProperty(" extension.name");
  IExtension extension = (IExtension) componentContext.locateService("extensions", extensionRef);
  registerExtension(extensionId, extensionName, extension);
}

It's necessary to have a bind method that takes type ServiceReference in order to get these service properties.  AFAIK there is no way to get service properties after this method has been called other than storing them locally (there is no "locateServiceReferences()" method).

This used to work with the original implementation of SCR, however the ProSyst implementation returns null when I call locateService(String, ServiceReference) from within the bind method.  I've tracked the issue down to the following code at ComponentReference.java:250:

try {
  bindMethod.invoke(instance.getInstance(), params);
} catch (Throwable t) {
  Activator.log.error(
      "[SCR] Error while trying to bind reference "
       + this, t);
       // rethrow exception so resolver is eventually notified that
       // this component is bad
       // throw t;
 } finally {
** serviceReferences.addElement(serviceReference);
   SCRUtil.release(params);
 }

The marked line is the issue.  The bound ServiceReference is being added to the ComponentReference's list of tracked ServiceReference after the bind method is being invoked.  The locateService(String, ServiceReference) method fails to match the passed ServiceReference to this internal list, and thus returns null.  I can only assume that the original SCR implementation ( org.eclipse.equinox.ds) stores the ServiceReference before invoking the bind method.

I couldn't find anything in the DS spec that was clear about which way to act in this situation, which is why I'm posting here and not in a bug report.  Should I be able to locate the service object for a ServiceReference from within the bind method?  If not, how can I ever get service properties for DS-controlled references?

At this point I'm going to patch the code locally to add the ServiceReference before invoking the bind method and hope that is the correct behavior. :)

Thanks,
Jeremy Volkman