Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [ecf-dev] trouble creating proxy, when my service interface is in a distinct bundle

Hi David,

David Donohue wrote:
Hello again Scott,
I will take a look at your code over the next few days to try to figure out
what's going on, and what can be done to have the proxy class load properly.
I appreciate it very much

Just for my the intended purpose of the ecfService extension
point just to make it easier to create a container instance and register a
remote service?
Well yes.  I am seeking to simplify things for 2 roles: the plugin
contributor and the person packaging a new distributed application.
For the plugin contributor, she need not worry about how to expose her
class as an ECF or OSGi service.  She need only write her code to do
her function of interest (e.g. look up or store info in a DB), and
provide a Java interface.
For the person packaging a new distributed application, consisting of
a set of distinct servers performing various client and server
functions, she would only need to package the proper set of bundles
and configure each server with a plugin specifying which servers are
produced and which are consumed, and by which server.

<stuff deleted>

So by changing only a configuration bundle, I can change the functions
performed by a particular server.  And I need not put code for
registering containers or services in multiple places.  [I'd be happy
to contribute this code if it might be helpful.]  My other extension
type, "ecfServer" tells which servers to connect to, using which
protocol.  It sounds similar to the one you have built perhaps.

Hmmm...interesting. Since I've recently been implementing the OSGI r4.2 remote services spec, I've been coming at things slightly differently (i.e. as dictated by the spec), but I think we are all headed in similar directions :). As I see it, that general direction is to make:

1) the registration (service host) of remote services easier by using a consistent the case I've been working with...of the OSGi remote services spec. The OSGi specified mechanism is the bundleContext.registerService method. *And* with declarative services...the same registration method (i.e. bundleContext.registerService) is invoked declaratively (i.e. using the declarative services xml).

2) The lookup (service consumer) of remote services easier by using a consistent mechanism...again in the case I've been working with...of the OSGi remote services specified mechanisms (specifically: bundleContext.getServiceReferences)

So I *think* that we are actually on rather similar paths my case by implementing the OSGi-specified patterns for using the OSGI service registry for remote service registration and lookup (i.e. the implementation that I am just completing)...and in my case assuming the use of declarative services (DS) to declaratively register remote services (service host) and inject remote services (service consumer) into application code.

If you don't mind (David), I'm going to use this as an opportunity to describe ECF's implementation of the OSGi 4.2 remote services specification (chap 13 in compendium), so that everyone can get a clearer idea of what it's doing (and use the extensibility features that I've already put in...if needed).

Here, for example, is some test code for registering a remote service with the OSGi-specified standard service properties:

Properties props = new Properties();
// This uses the *OSGi standard* remote services property 'service.exported.configs' to specify the provider props.put(IDistributionConstants.SERVICE_EXPORTED_CONFIGS, "ecf.generic.server"); // This uses a standard ECF service property (across all providers) to specify the new container's ID props.put(IDistributionConstants.SERVICE_EXPORTED_CONTAINER_FACTORY_ARGUMENTS, "ecftcp://localhost:3888/server"); // this is the OSGi standard remote services property that specifies which interface(s) are to be exported
props.put(IDistributionConstants.SERVICE_EXPORTED_INTERFACES, "*");

// Then we just register as an OSGi remote service and the distribution happens bundleContext.registerService(new String[] { "" }, new Hello(), props);

With the new ECF implementation its *unnecessary* to create a container instance prior to calling the above code. For backward compatibility, its perfectly fine for you to create an ecf generic server container instance prior to calling the above code, but it's not necessary now. As part of the bundleContext.registerService call, ECF's remote services distribution implementation (in bundle) will examine the arguments above and *create a new instance* of "ecf.generic.server" container (with the container factory args as given)...and then distribute the given exported interfaces over the ecf.generic.server distribution provider.

Now, of course, since declarative services allows you to declare services to be registered, and you can provide service properties (e.g. like the above), you can specify the above via a DS declaration of a service component...and so with declarative services and this ECF remote services implementation there *no* java code required (you can continue to use java if you like, of course...both to create/control a container and to register/unregister the service). And all done with

a) OSGi standard mechanisms (OSGi 4.2 remote services spec, OSGi core spec, and OSGi declarative services) b) Done in a transport-independent way via ECF's transport independent remote services API (so moving to/using other transports is very easy).

And so the use of OSGi services and the declarative services stuff provide a very good way to do declarative remote services. Further, it's all standardized, so you can move among ECF providers easily (e.g. ecf generic, r-osgi, JMS, JavaGroups, xmpp, skype, so far), or even use other (non-ECF) implementations of the OSGi 4.2 remote services if you wish. You can even include multiple ECF providers *and* other implementations of the remote services spec (e.g. CXF) in a single framework if you wish.


Note the following extensibility mechanism *does not have to be used*...but is rather present so that those that wish to customize the behavior described above can do so without using internals.

I've built into the ECF implementation flexibility in how the host container is found/selected (i.e. the ECF IContainer instance(s) that are to be used to distribute a given registered service). Specifically, there is an ECF distribution service interface:

In the ECF implementation, when the registerService is actually called implementers of this interface are consulted to find the appropriate ECF container(s) to handle/distribute the remote service being registered. There is a default, with a very low service priority, that first tries to match among the all existing ECF containers, and then, if none appropriate are found that way, it will create a new container (as above).

Folks that wish to customize this behavior can simply create an implementation of IHostContainerFinder, implement the IHostContainerFinder.findHostContainers method, and register their impl as an osgi service using the whiteboard pattern. And then at remote service registration time, ECF's impl will consult *your* host container finder to find/select the remote service containers to use to distribute a given remote service. You can choose to eagerly create an IContainer, lazily create an IContainer, create a new one for every service, reuse the same one for every service, etc. Of course if you don't need/want this flexibility, then you can just leave it do the default implementation (which is in class for reference). You can also examine/use/reuse the Default host container finder code if you wish.

So that's the approach for the remote service registration for the service host. I'll describe the mechanisms around the service consumer (i.e. the proxy side of things) in subsequent postings.


Back to the top