Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[ecf-dev] Customizing the consumption of remote services

Hi Folks,

On the ecf newsgroup there was a question about the client discovery and handling of multiple remote services...i.e. where the remote services comes from more than one target framework. I've included the original posting and my response below, as there are some design issues here. Also, it gave me a chance to provide some more documentation about an aspect of ECF remote services that is kind of cool...the ability to easily extend and customize the behavior.

The discussion began with reference to the r-osgi provider specifically, but in fact most of the issues are not with the r-osgi provider...but rather with the remote services consumer/client behavior in the face of multiple remote services on a network (and multiple frameworks hosting those services).

See below for discussion. Feel free to jump in with questions and/or observations.



Hi Rado,

First, with your permission (Rado), I would like to move this discussion over to ecf-dev at mailing list. Is this OK with you? Here is the page for joining that mailing list:

The reason that I would like to move this discussion over to the ECF dev mailing list is that the handling of this use case (multiple remote services) has a number implications...and I would like to get input from you and others in the ECF mailing list.

So in this particular case, on the client you have created *one* instance of the r-osgi container/client. When the first service endpoint is discovered, that client is used to connect, get the remote service reference for, and create the local proxy for the remote service endpoint (in your xml file, this is likely the r-osgi://localhost:9279 endpoint).

When the *second* endpoint is 'discovered' (I put quotes around this because you are using the local/file-based discovery, so it's just being discovered because of the reading of the xml file), there is only *one* r-osgi client, and since it's already connected to the first endpoint, the no remote service container is found to handle the second remote service endpoint, and so it can't handle it without either:

1) disconnecting from the first one...and reconnecting to the second one
2) creating a new remote service container/client to handle this second remote service

Note that the selection between 1 and 2 is an important client-side policy choice, because it will determine how/whether both remote services can be used simultaneously. Further, selection of these strategies has other effects if there are > 2 services that are discovered (using file-based discovery and/or other discovery providers).

There are other upsides and downsides to both approaches (1 or 2). So, for example, 2 requires more resources on the client (since there are > 1 client container instances).

So the strategy selection in these use cases (on the client side) are sort of important...and the current OSGi 4.2 specification does not say anything about how these situations are to be least partially because this is kind of a policy-level choice (i.e. some applications/clients will want to do things one way, others will want to do things different ways).

Now, ECF has built in some flexibility into our implementation, so that either/both approaches can be implemented fairly easily. This API is new, and I would consider it still provisional (it's marked internal in ECF 3.2, precisely because it likely will undergo some changes once we/others get some more experience with it).

Specifically, we have something called the IProxyContainerFinder service, which is responsible for *selecting* IContainer instances...on the client...when they are discovered. There is some documentation (not enough yet, I know), on this mechanism for extending/customizing the ECF remote service impl in the wiki here:

What happens is this:

discovery provider
  --> discovers remote service
--> IProxyContainerFinder is selected (the service instance with highest priority is selected) --> IProxyContainerFinder.findProxyContainers is called and returns an array of IRemoteServiceContainers. The given discovered remote service is then registered with *all* of the IRemoteServiceContainers returned.

The implementation of the findProxyContainers determines which container instance is used to handle the discovered remote service.

If *no* custom/user-defined IProxyContainerFinder instances are present, then a default one is created...and this is an instance of class DefaultProxyContainerFinder. (Note that the DefaultProxyContainerFinder is API also, so it can be easily subclassed to create your own IProxyContainerFinder instance).

Now...the DefaultProxyContainerFinder already has the ability to do strategy 2 as described above (i.e. create a new container instance of compatible type), when a second/nth remote service is discovered. As described briefly on the wiki page, the DefaultProxyContainerFinder has a flag (which can be set in the constructor) that indicates whether an appropriate IContainer instance should be created dynamically (i.e. strategy 2). This flag is set to *false* by default...for security reasons (if it was on by default, clients would be subject to possibly severe denial of service attacks). There's some discussion of this design choice on this bug:

So I *believe* that if you were to use the the System property for DefaultProxyContainerFinder (see the wiki page), your use case described below would/could work, because with auto create container flag set to 'true' a new/second container instance would be created when your second remote service was discovered.

If you want to do 1 (or variations thereof), it would be necessary to create your own IProxyContainerFinder (e.g. by extending DefaultProxyContainerFinder class and registering the service as shown on the wiki), and in your impl of findProxyContainers you would/could explicitly disconnect the client container (i.e. IContainer.disconnect()), before returning from findProxyContainers.

This IProxyContainerFinder (and IHostContainerFinder for that matter) are ECF-specific mechanisms...which aren't specified at all by the OSGi 4.2 spec...but I put them in place to support more complex use cases (i.e. with many remote services). If we need to adjust them/add to them or simplify them then we are open to doing this, as like I said above they are provisional at this point, and I am interested in making them as easy to use for as many use cases as possible (for example, perhaps we could consider implementing strategy 1 in DefaultProxyContainerFinder as well as 2).

One more thing. There was a bug filed recently describing a race condition in the ECF 3.2 implementation with multiple remote services discovered via file-based discovery (as yours is doing). That bug is here:

This race condition has since been fixed/addressed, but note that the fix is *not* in ECF 3.2 released version, as we only learned about it since the 3.2 release. Currently our plan is to next have an ECF 3.3 release for Helios in June, but if we get enough support and desire we could consider a 3.2.1 release before June to make this fix available. Also, the fix is in the CVS repo (HEAD), so you can get the appropriate bundle and try it out if you wish.

Does this make sense? Rado please let me know if it will be ok to move this discussion to ecf-dev at mailing list and we will continue this discussion further.



a340859@xxxxxxxxxx wrote:

I am trying to run a file-based discovery with the r-OSGI provider.
I am utilizing the org.eclipse.ecf.examples.remoteservices.hello.consumer

Everything is running just fine with one host and one consumer.
However when I start an additional host (on a separate machine) the consumer discovers only one of them. My OSGI-INF/remote-service/hello-service-description-generic.xm l file is:

<?xml version="1.0" encoding="UTF-8"?>
<service-descriptions xmlns="";>
<provide interface="org.eclipse.ecf.examples.remoteservices.hello.IHello"/>
    <property name="ecf.sp.cid">r-osgi://localhost:9279</property>
    <property name="ecf.sp.cns">ecf.namespace.r_osgi</property>
    <property name="ecf.sp.ect">ecf.r_osgi.peer</property>
<provide interface="org.eclipse.ecf.examples.remoteservices.hello.IHello"/>
    <property name="ecf.sp.cid">r-osgi://</property>
    <property name="ecf.sp.cns">ecf.namespace.r_osgi</property>
    <property name="ecf.sp.ect">ecf.r_osgi.peer</property>

In fact, only the first <service-description> entry is discovered.
Is this the right way to have more than one provider for a given service?

Thanks in advance.


Back to the top