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

Scott
I have decided to go with the ECF method at the moment, because it
gives me more control over discovery etc. and I can also like to
retain responsibility for creating the container

So on the client side, I will wait for the container connection, then
pick up the shared object, then pick up the remote service:

container = manager.getContainerFactory().createContainer("ecf.generic.client");
container.addListener(new IContainerListener() {

@Override
public void handleEvent(IContainerEvent event) {
	if (event instanceof IContainerConnectedEvent)
	try {
ID id = IDFactory.getDefault().createID(container.getConnectNamespace(),
uri.toString());
//pick up the shared object														ISharedObjectContainer soc =
(ISharedObjectContainer) ((IAdaptable)
container).getAdapter(ISharedObjectContainer.class);
														
													ISharedObjectManager manager = soc.getSharedObjectManager();
EventAdmin admin = new DistributedEventAdmin(context);
ID id1 = IDFactory.getDefault().createStringID("uk.co.xlegal.xbundle3.remote");
Properties props = new Properties();
props.put(EventConstants.EVENT_TOPIC, "uk_co_xlegal_xbundle3_remote");
manager.addSharedObject(id1, (ISharedObject) admin, props);
((DistributedEventAdmin) admin).start();
					
//now pick up the remote service									
IRemoteServiceContainerAdapter rsc = (IRemoteServiceContainerAdapter)
((IAdaptable) container).getAdapter(IRemoteServiceContainerAdapter.class);
														IRemoteServiceReference[] refs =
rsc.getRemoteServiceReferences(((IContainerConnectedEvent)
event).getTargetID(), StateProvider.class.getName(), null);
StateProvider provider = (StateProvider) rsc.getRemoteService(refs[0]);
Map<String, Object> state = provider.provideState();
syncBundles(state);
														
} catch (Exception e) {
														Log.log(Log.ERROR, e.getMessage());
}
}
});
container.connect(id, null);

I'm finding that refs is null. Looking inside rsc, I see that the
remoteRegistry array is empty.
Have I missed a step in initialising the
IRemoteServiceContainerAdapter on the client side?


Robert


On Thu, Nov 4, 2010 at 8:20 PM, Robert Onslow <ronslow@xxxxxxxxxxxx> 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?
>
>
>
> 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
>>
>
>
>
> --
> Robert Onslow
> XLegal Limited
>



-- 
Robert Onslow
XLegal Limited