[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [ecf-dev] Mapping ServiceReferences to FrameworkUUIDs (probable race condition in RSA?)

Hi Patrick,

On 4/6/2011 1:09 AM, Patrick D. wrote:
Hello ECF Team,

I'm working on a software that has to know where exactly services are and what osgi framework exported them.

It might help if you describe a little more about what your use case is. The reason I say this is that the RSA approach is to allow flexibility in exporting and importing of remote services (and therefore 'knowing' where they are, etc) by allowing new topology managers to be created...and the exporting and importing be explicitly controlled (by calling RemoteServiceAdmin service's exportService(ServiceReference,Map) and importService(EndpointDescription).

ECF currently has a single topology manager: BasicTopologyManager, which implements the service EventHook (to export) and the EndpointListener (to discover and import remote services). But the BasicTopologyManager is not at all intended to be the only topology manager...others are free to create other topology managers as needed (based upon ECF topology managers if they wish, but this is not at all required).

As it's not possible to find out what framework a ServiceReference points to, the IProxyDistributionListener and the IHostDiscoveryListener were used in the past to map ServiceReferences to URLs and the URLs to a framework.
That's no longer possible in ECF 3.5, because the listeners were removed for being obsolete. I understand, that the RSA is the new way to go.

What information are you looking for about the endpoint? I guess I'm not clear on what you want to get from the remote endpoint (via the EndpointDescription). And what do you wish to do with it...e.g. you could use it to determine whether a remote service is imported (i.e. with your own TopologyManager, you could filter on and/or look at the relevant property in the EndpointDescription and then use that to decide whether to call RemoteServiceAdmin.importService...or to do something else.

The first thing I tried was using the new EndPointListener. It failed, because there's no way to get the corresponding ServiceReference as long as the service was not imported.

Right...prior to the service being imported, the only information available (via the discovery part of RSA) is the EndpointDescription.

So my new approach is the following using an EventHook:

public void event(final ServiceEvent pEvent, final Collection pContexts) {

    // If a service was registered
    if (pEvent.getType() == ServiceEvent.REGISTERED) {
        final ServiceReference reference = pEvent.getServiceReference();

        // If the service was imported into the framework
        if (reference.getProperty("service.imported") != null) {

final RemoteServiceAdmin rsa = getRemoteServiceAdmin();
for (final ImportReference importReference : rsa.getImportedEndpoints()) {
if (importReference.getImportedService().equals(reference)) {

resolved(reference, importReference.getImportedEndpoint().getFrameworkUUID());

The idea is to wait for the service to be actually imported into the framework, then ask the RSA for the endpoint so I get both the endpoint and the ServiceReference. It doesn't work, becacuse rsa.getImportedEndpoints() is always empty. I used the debugger to step through the code and it seems that the imported endpoint does get added, but too late to catch it inside the EventHook. This was not what I expected. Shouldn't the RSA reflect the imported services as seen by the framework?

Only if the topology manager actually imports them. It's possible that this is a bug, however...if they are actually imported, and rsa.getImportedEndpoints() still doesn't return them. If you think this is what you are seeing (i.e. the service does get imported by RSA, but then subsequently does not return anything from rsa.getImportedEndpoints()...then please open a bug report and it will be examined.

If that's how it's supposed to work, do you suggest any other strategies to map a ServiceReference to the framework that exported it?

I'm still a little unclear...do you mean the proxy/imported ServiceReference...and finding out what framework exported it? If this is what you mean, how do you mean to 'identify' the framework that exported it? The reason I ask about this is that there are several pieces of information in the EndpointDescription that *might* satisfy your needs...e.g.

endpoint.id (in ECF's impl this is the provider-defined 'uri' for the ECF container)
example: r-osgi://foo.com:9278
also accessed through EndpointDescription.getId()

endpoint.framework.uuid  RSA-specified unique OSGi framework id
example:  70cd3d4b-4931-0010-1b63-d64101cefd5e
also accessed through EndpointDescription.getFrameworkId()

endpoint.service.id   The id of the ServiceReference on the *exporter*
example:  50
also accessed through EndpointDescription.getServiceId()

Are any of these (or their combination) useful for what you have in mind?

Note that you can also set the OSGi standard service.pid (a persistent id for your remote service) on remote service export...if your remote service has a persistent id (i.e. one that is durable over framework restarts). You can then detect/filter/use this service.pid. Also...you can explicitly set any custom property on exported remote service...and then use that for your application.

Another question...once you have the identification information you are looking for...how do you wish to use them? Reason I ask: If you want to control the import and export yourself, then it would be best to just create your own topology manager.