[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [ecf-dev] Using a container multiple times

Hi Robert,

On 11/4/2010 1:20 PM, Robert Onslow wrote:
Thanks Scott.


So if I am publishing the SharedObject *as well as* the Remote Service via the same container, what's the best way of picking up the container which the ECF implementation of OSGI 4.2 has created under the bonnet, in order to adapt it to a ISharedObjectContainer? Can I pick it up from the OSGI framework?

There are at least three ways that I can think of...I can't say which one is obviously the best.


1) Create the container upon app startup/before the OSGi 4.2 remote service is registered. The default behavior (implemented by DefaultHost/ProxyContainerFinder class, in org.eclipse.ecf.osgi.services.distribution) is to use/reuse an existing compatible container for OSGi host and proxy...so at application startup you can create the container in advance of the OSGi 4.2 register/lookup behavior.

2) Define new IHost/ProxyContainerFinders and have them be used by the ECF OSGi 4.2 implementation. Container finders are responsible for finding/selecting a local container for remote service registration (host) or remote service lookup (proxy),. It's easy to customize their behavior (i.e. to adapt to ISharedObjectContainer and add a DistributedEventAdmin instance) by creating (e.g.) subclass of DefaultHostContainerFinder and DefaultProxyContainerFinder, and registering your container finders using the OSGI whiteboard pattern. There is some documentation for this on this wiki page [1]

3) Define/create a brand new provider (that extends the ECF generic server and client providers), that includes adding a DistributedEventAdmin instance to the container upon construction.

A couple of trade offs: 3 gives the most flexibility, but probably requires the most work. 1 is very easy to do, but is fairly inflexible. 2 is customizing the ECF OSGi 4.2 remote services impl behavior, so you might have to be a little careful about side effects on other ECF remote services (if you have any others in your use context).

Thanks,

Scott

[1] http://wiki.eclipse.org/Customizing_and_Extending_ECF_Remote_Services




Robert

On Thu, Nov 4, 2010 at 5:23 PM, Scott Lewis<slewis@xxxxxxxxxxxxx> wrote:
Hi Robert,

On 11/4/2010 9:18 AM, Robert Onslow wrote:
Dear All

On the server side, I have create a container and registered a shared
object on it.

I would like to publish a remote service over it as well. I tried:

final IContainer container =
manager.getContainerFactory().createContainer("ecf.generic.server");
final ISharedObjectContainer sharedObjectContainer =
(ISharedObjectContainer)
container.getAdapter(ISharedObjectContainer.class)
ISharedObjectManager manager1 =
sharedObjectContainer.getSharedObjectManager();
Properties props = new Properties();
props.put(EventConstants.EVENT_TOPIC, "uk_co_xlegal_xbundle3_remote");

manager1.addSharedObject(IDFactory.getDefault().createStringID("uk.co.xlegal.xbundle3.remote"),
(ISharedObject) admin, props);

//now share the StateProvider service

IRemoteServiceContainerAdapter rsc = (IRemoteServiceContainerAdapter)
((IAdaptable) container).getAdapter(IRemoteServiceContainerAdapter.class);
StateProvider provider = (StateProvider)
localStateServiceTracker.getService();


rsc.registerRemoteService(new String[]{StateProvider.class.getName()}, provider, null);

...

I am not seeing the service on the client side. I have connected, and
am successfully synchronizing the EventAdmin.
But if I register a tracker for the remote service, the remote service
is never found.

remoteStateProviderTracker = new ServiceTracker(context,
StateProvider.class.getName(), new ServiceTrackerCustomizer() {

                        @Override
                        public Object addingService(ServiceReference
reference) {
//never reaching here

                                StateProvider provider = (StateProvider)
context.getService(reference);
                                Map<String, Object>    state =
provider.provideState();
                                List<String>    openBundleURIs =
(List<String>) state.get("openBundleURIs");

                                for (String uri : openBundleURIs)
                                        syncWithBundleURI(uri);
                                return provider;


}

                        @Override
                        public void modifiedService(ServiceReference
reference,
                                        Object service) {
                                // TODO Auto-generated method stub

                        }

                        @Override
                        public void removedService(ServiceReference
reference,
                                        Object service) {

                        }

                });

remoteStateProviderTracker.open();

Is it possible to use a server container in this way?

The short answer to your question is 'yes'.

But I'll give a slightly longer answer...and of course answer any follow up
questions as needed.

One thing I should briefly explain about remote services...the ECF remote
services API pre-dated the OSGi 4.2 remote services spec implementation.  In
fact, the OSGi remote services implementation actually *uses* the ECF remote
services API to expose OSGi services remotely.  One implication of this
layering (which is described graphically here [1]), is that it's possible to
use ECF remote services *without* the OSGi 4.2 remote services
implementation.

So on your service host/server side, when you call

rsc.registerRemoteService(new String[]{StateProvider.class.getName()},
provider, null);

this makes the StateProvider service available to the ECF remote service API
on the client side...but *not* the OSGi service registry.  So, on the
client, you could call something like this

IRemoteServiceReference[] refs =
rsc.getRemoteServiceReferences(StateProvider.class.getName(),null);

Note that there is also a RemoteServiceTracker class
(org.eclipse.ecf.remoteservice.util.tracker.RemoteServiceTracker).
  Instances of RemoteServiceTracker have the same general behavior as OSGi
ServiceTrackers, but are based upon the ECF remote service API (rather than
the OSGi service registry).

With the code above, I believe that's why your ServiceTracker doesn't
discover the service...because the OSGi ServiceTracker only tracks service
that are in the OSGi service registry.  And you are registering the remote
service via rsc.registerRemoteService (the ECF remote service API directly).

The ECF implementation of the OSGi 4.2 remote services specification,
however, makes *any* direct use of the ECF remote services API unnecessary.
  That is, on the host/server-side, as per the OSGI spec, when an OSGi
registration like this is done:

props.put("service.exported.configs","ecf.generic.server");
props.put("service.exported.interfaces","*");
ServiceRegistration reg =
bundleContext.registerService(StateProvider.class.getName(),service, props);

the ECF impl of OSGi remote services intercepts this call..and ends up
calling the ECF registerRemoteService method *for you* (as well as
publishing the meta-data about the remote service via some discovery).

Then on the client/proxy side, the ECF implementation of OSGi 4.2 remote
services uses the discovery to asynchronously discover the remote service
meta-data, and then it turns around and calls the ECF
getRemoteServiceReferences method for you, creates a proxy, and registers
this proxy in the OSGi service registry...thus triggering detection by
ServiceTrackers that are responding to the given service.  Just for
reference, the ECF impl of OSGi 4.2 remote services is in the bundles:
  org.eclipse.ecf.osgi.services.discovery and
org.eclipse.ecf.osgi.services.distribution.

So in short, you can use the ECF remote services API directly, by using
registerRemoteService (as you are doing on the host above), and
getRemoteServiceReferences/RemoteServiceTracker on the client, or you can
use the ECF impl of the OSGi 4.2 remote services specification (i.e. in the
bundles given above)...along with some discovery, and use
BundleContext.registerService (host), and
getServiceReferences/ServiceTracker/DS on the client.  Both mechanisms are
available...and things are layered as shown in this diagram [1].

Scott

[1] http://wiki.eclipse.org/OSGi_4.2_Remote_Services_and_ECF


_______________________________________________ ecf-dev mailing list ecf-dev@xxxxxxxxxxx https://dev.eclipse.org/mailman/listinfo/ecf-dev