| Summary: | ClassNotFoundException with r-osgi and ECF (not with r-osgi only) | ||
|---|---|---|---|
| Product: | [RT] ECF | Reporter: | Franky Bridelance <franky.bugzilla> |
| Component: | ecf.protocols | Assignee: | Markus Kuppe <bugs.eclipse.org> |
| Status: | RESOLVED FIXED | QA Contact: | |
| Severity: | normal | ||
| Priority: | P3 | CC: | bugs.eclipse.org, slewis |
| Version: | 3.2.0 | ||
| Target Milestone: | 3.4.0 | ||
| Hardware: | All | ||
| OS: | All | ||
| Whiteboard: | |||
| Attachments: | |||
Created attachment 179370 [details]
Test bundles to reproduce the CNFE
Thanks for the detailed bug report. For the sake of completeness, please also attach the stack trace. Markus...is this a known issue/duplicate? It looks somewhat familiar to me. Franky: Thanks for the compliment in the bug report...we're doing all we can with resources available. We do appreciate both your usage and bug reports. If you can, please consider joining/participating on the ecf-dev mailing list (see https://dev.eclipse.org/mailman/listinfo/ecf-dev for joining info). (In reply to comment #3) > Markus...is this a known issue/duplicate? It looks somewhat familiar to me. From first sight it looks related to bug #302399. (In reply to comment #2) > Thanks for the detailed bug report. For the sake of completeness, please also > attach the stack trace. Hi Markus, Here's the stacktrace. Please not that you don't see the stacktrace in the console, the CNFE is just catched in the try-catch block around code in RemoteServiceRegistration.java:130. java.lang.ClassNotFoundException: org.myorg.classbpkg.ClassB at ch.ethz.iks.r_osgi.impl.CodeAnalyzer.visit(CodeAnalyzer.java:290) at ch.ethz.iks.r_osgi.impl.CodeAnalyzer.analyze(CodeAnalyzer.java:202) at ch.ethz.iks.r_osgi.impl.RemoteServiceRegistration.<init>(RemoteServiceRegistration.java:130) at ch.ethz.iks.r_osgi.impl.RemoteOSGiServiceImpl$3.addingService(RemoteOSGiServiceImpl.java:497) at org.osgi.util.tracker.ServiceTracker$Tracked.customizerAdding(ServiceTracker.java:896) at org.osgi.util.tracker.AbstractTracked.trackAdding(AbstractTracked.java:261) at org.osgi.util.tracker.AbstractTracked.track(AbstractTracked.java:233) at org.osgi.util.tracker.ServiceTracker$Tracked.serviceChanged(ServiceTracker.java:840) at org.eclipse.osgi.internal.serviceregistry.FilteredServiceListener.serviceChanged(FilteredServiceListener.java:104) at org.eclipse.osgi.framework.internal.core.BundleContextImpl.dispatchEvent(BundleContextImpl.java:933) at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:227) at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:149) at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.publishServiceEventPrivileged(ServiceRegistry.java:755) at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.publishServiceEvent(ServiceRegistry.java:710) at org.eclipse.osgi.internal.serviceregistry.ServiceRegistrationImpl.register(ServiceRegistrationImpl.java:129) at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.registerService(ServiceRegistry.java:206) at org.eclipse.osgi.framework.internal.core.BundleContextImpl.registerService(BundleContextImpl.java:507) at org.eclipse.ecf.internal.provider.r_osgi.R_OSGiRemoteServiceContainer.registerRemoteService(R_OSGiRemoteServiceContainer.java:390) at org.eclipse.ecf.internal.osgi.services.distribution.EventHookImpl.handleRegisteredServiceEvent(EventHookImpl.java:118) at org.eclipse.ecf.internal.osgi.services.distribution.Activator.start(Activator.java:182) at org.eclipse.osgi.framework.internal.core.BundleContextImpl$1.run(BundleContextImpl.java:783) at java.security.AccessController.doPrivileged(Native Method) at org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:774) at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(BundleContextImpl.java:755) at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:352) at org.eclipse.osgi.framework.internal.core.AbstractBundle.resume(AbstractBundle.java:370) at org.eclipse.osgi.framework.internal.core.Framework.resumeBundle(Framework.java:1068) at org.eclipse.osgi.framework.internal.core.StartLevelManager.resumeBundles(StartLevelManager.java:557) at org.eclipse.osgi.framework.internal.core.StartLevelManager.incFWSL(StartLevelManager.java:464) at org.eclipse.osgi.framework.internal.core.StartLevelManager.doSetStartLevel(StartLevelManager.java:248) at org.eclipse.osgi.framework.internal.core.StartLevelManager.dispatchEvent(StartLevelManager.java:445) at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:227) at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:337) After some investigation I think a LinkageError reported on the mailinglist [0] has the same root cause. [0] http://markmail.org/message/oe7w36nmqudbxgpc#query:+page:1+mid:6qa6vknk23f57dsm+state:results Created attachment 179563 [details]
Use BundleContext of original Bundle registering the service instead of r-OSGi provider BundleContext (as suggested by Frank)
Created attachment 179564 [details]
mylyn/context/zip
(In reply to comment #6) > After some investigation I think a LinkageError reported on the mailinglist [0] > has the same root cause. > > [0] > http://markmail.org/message/oe7w36nmqudbxgpc#query:+page:1+mid:6qa6vknk23f57dsm+state:results Scratch this, created bug #326221 to track it. (In reply to comment #0) > So this looks like a bug but I can't say where the fix should be: in r-osgi > bundle or in ecf.provider.r_osgi bundle? I would tend to say that the > ecf.provider.r_osgi bundle should register the service with the bundle context > of the bundle providing the service instead of its own bundle context (unless > there's a good reason not to do so), like when impersonating a bundle in the > extender model but here it's not an extender and getting the bundle context of > the original service might be a little tricky... Franky, can you try the patch and tell me if it fixes your problems and does not cause new ones? Released patch to HEAD Created attachment 179719 [details]
mylyn/context/zip
(In reply to comment #10) > (In reply to comment #0) > > So this looks like a bug but I can't say where the fix should be: in r-osgi > > bundle or in ecf.provider.r_osgi bundle? I would tend to say that the > > ecf.provider.r_osgi bundle should register the service with the bundle context > > of the bundle providing the service instead of its own bundle context (unless > > there's a good reason not to do so), like when impersonating a bundle in the > > extender model but here it's not an extender and getting the bundle context of > > the original service might be a little tricky... > Franky, can you try the patch and tell me if it fixes your problems and does > not cause new ones? Hi Markus, Sorry for the late reply I've been away for a while. I'll try it out. Thanks (In reply to comment #10) > (In reply to comment #0) > > So this looks like a bug but I can't say where the fix should be: in r-osgi > > bundle or in ecf.provider.r_osgi bundle? I would tend to say that the > > ecf.provider.r_osgi bundle should register the service with the bundle context > > of the bundle providing the service instead of its own bundle context (unless > > there's a good reason not to do so), like when impersonating a bundle in the > > extender model but here it's not an extender and getting the bundle context of > > the original service might be a little tricky... > Franky, can you try the patch and tell me if it fixes your problems and does > not cause new ones? Hi Markus, I've tested the fix: remote service registration and remote service call is now ok. Thanks! With the latest code (as of 10/1/2010), if I run the hello example host from the product config I get an NPE that appears to be associated with the code added for this bug: i.e. in R_OSGiRemoteServiceContainer // register the service with the local framework but use the original BundleContext // http://bugs.eclipse.org/325950 final PackageAdmin pkgAdmin = Activator.getDefault().getPackageAdmin(); final Bundle bundle = pkgAdmin.getBundle(service.getClass()); final BundleContext bundleContext = bundle.getBundleContext(); // NPE on next line (408) because bundleContext is null final ServiceRegistration reg = bundleContext.registerService(clazzes, service, props); ... Here's the stack trace !ENTRY org.eclipse.osgi 4 0 2010-10-01 22:07:06.087 !MESSAGE An unexpected runtime error has occurred. !STACK 0 java.lang.NullPointerException at org.eclipse.ecf.internal.provider.r_osgi.R_OSGiRemoteServiceContainer.registerRemoteService(R_OSGiRemoteServiceContainer.java:408) at org.eclipse.ecf.internal.osgi.services.distribution.EventHookImpl.handleRegisteredServiceEvent(EventHookImpl.java:118) at org.eclipse.ecf.internal.osgi.services.distribution.EventHookImpl.event(EventHookImpl.java:62) at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.notifyEventHooksPrivileged(ServiceRegistry.java:1143) at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.publishServiceEventPrivileged(ServiceRegistry.java:743) at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.publishServiceEvent(ServiceRegistry.java:711) at org.eclipse.osgi.internal.serviceregistry.ServiceRegistrationImpl.register(ServiceRegistrationImpl.java:130) at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.registerService(ServiceRegistry.java:206) at org.eclipse.osgi.framework.internal.core.BundleContextImpl.registerService(BundleContextImpl.java:507) at org.eclipse.osgi.framework.internal.core.BundleContextImpl.registerService(BundleContextImpl.java:525) at org.eclipse.ecf.internal.examples.remoteservices.hello.host.HelloHostApplication.registerHelloRemoteService(HelloHostApplication.java:82) at org.eclipse.ecf.internal.examples.remoteservices.hello.host.HelloHostApplication.start(HelloHostApplication.java:55) at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196) at org.eclipse.equinox.internal.app.AnyThreadAppLauncher.run(AnyThreadAppLauncher.java:26) at java.lang.Thread.run(Thread.java:619) Is this due to some start ordering issue and availability of bundleContext? It's because org.eclipse.ecf.examples.remoteservices.hello.impl.Hello is in bundle org.eclipse.ecf.examples.remoteservices.hello and never started (correctly). PackageAdmin return the .hello bundle and not hello.host which registered the service. Apparently PackageAdmin does not work for cases where the service object class comes from a bundle that is never activated. A viable solution would be to extend org.eclipse.ecf.remoteservice.IRemoteServiceContainerAdapter.registerRemoteService(String[], Object, Dictionary) so that it also passes the bundle which registered the service initially (for examples as a Dictionary property) as part of the registerRemoteService call (better yet the original ServiceReference instance). However, this probably makes no sense at all for scenarios where IRemoteServiceContainerAdapter is used outside the OSGi context and RemoteServiceProviders definitely have to remove it from the properties since ServiceReference is not serializable and thus will cause problems subsequently. Still, we IMO need to find a way to pass the org.osgi.framework.ServiceReference to the remote service container that is called by the EventHook. Currently EventHook makes no use of the ServiceReference bundle information. Alternatively does anybody know how to receive the bundle registering the service by the service impl instance? For the moment I implemented a fall back workaround to the r-OSGi provider BundleContext if PackageAdmin does not return a BundleContext. (In reply to comment #17) > A viable solution would be to extend > org.eclipse.ecf.remoteservice.IRemoteServiceContainerAdapter.registerRemoteService(String[], > Object, Dictionary) so that it also passes the bundle which registered the > service initially (for examples as a Dictionary property) as part of the > registerRemoteService call (better yet the original ServiceReference instance). > However, this probably makes no sense at all for scenarios where > IRemoteServiceContainerAdapter is used outside the OSGi context and > RemoteServiceProviders definitely have to remove it from the properties since > ServiceReference is not serializable and thus will cause problems subsequently. > Still, we IMO need to find a way to pass the > org.osgi.framework.ServiceReference to the remote service container that is > called by the EventHook. Currently EventHook makes no use of the > ServiceReference bundle information. Alternatively does anybody know how to > receive the bundle registering the service by the service impl instance? I don't think there's some way to do this because the service impl instance is just a plain object and it could be registered as a service several times by different bundles (although I would not encourage to do this). It's the service reference that can provide the registering bundle but unfortunately IRemoteServiceContainerAdapter.registerRemoteService does not have the service reference. One possible (heavy) solution is to get all service references with a filter created from the clazzes argument and if you get more than one service reference back get compare the service of the service references with the given service argument. Something like (didn't try out the code...): StringBuffer filterBuffer = new StringBuffer("(&"); for (String clazz : clazzes) { filterBuffer.append("(objectClass="); filterBuffer.append(clazz); filterBuffer.append(")"); } filterBuffer.append(")"); ServiceReference[] refs = context.getAllServiceReferences(null, filter); BundleContext bundleContext = null; for (ServiceReference ref : refs) { Object serv = context.getService(ref); // check on instance equality if (serv == service) { bundleContext = ref.getBundle().getBundleContext(); } } final ServiceRegistration reg = bundleContext.registerService(clazzes, service, props); Given that we add to org.eclipse.ecf.remoteservice.IRemoteServiceContainerAdapter in 3.4 anyway, I wonder if: IRemoteServiceContainerAdapter.registerRemoteService(ServiceReference) next to: IRemoteServiceContainerAdapter.registerRemoteService(String[], Object, Dictionary) makes sense?! (In reply to comment #20) > Given that we add to > org.eclipse.ecf.remoteservice.IRemoteServiceContainerAdapter in 3.4 anyway, I > wonder if: > > IRemoteServiceContainerAdapter.registerRemoteService(ServiceReference) > > next to: > > IRemoteServiceContainerAdapter.registerRemoteService(String[], Object, > Dictionary) > > makes sense?! Hmmm. I'm not sure. (In reply to comment #21) > Hmmm. I'm not sure. Why? (In reply to comment #22) > (In reply to comment #21) > > Hmmm. I'm not sure. > > Why? Well, that's what I'm not sure about :). There are a couple of things that concern me (but I'm frankly not sure yet how valid they are): a) Currently, the remote services API (itself rather than provider/impl) doesn't refer to OSGi classes, and so is able to run/be used outside of OSGi context. AFAIK no one is doing this, but it is in the back of my mind as something that can be done...and that I might wish to do (e.g. Android). b) Currently there is just one registerRemoteService method...and this makes things simpler and unambiguous for consumers. c) Adding a new register method here means all rs providers have to support it...and a new register method is quite new semantics (rather than generalization of existing semantics as the new getRemoteServiceReference method was). So I'm not sure. I would like to think about it and discuss further (on this bug is fine with me). (In reply to comment #23) > a) Currently, the remote services API (itself rather than provider/impl) > doesn't refer to OSGi classes, and so is able to run/be used outside of OSGi > context. AFAIK no one is doing this, but it is in the back of my mind as > something that can be done...and that I might wish to do (e.g. Android). Why not run Apache Felix on Android? And I'm certain that there are more places in ECF that prevent usage outside of OSGi. E.g. InvalidSyntaxException on org.eclipse.ecf.remoteservice.IRemoteServiceContainerAdapter.getRemoteServiceReferences(ID, ID[], String, String) and org.eclipse.ecf.remoteservice.IRemoteServiceContainerAdapter.createRemoteFilter(String) > b) Currently there is just one registerRemoteService method...and this makes > things simpler and unambiguous for consumers. True, but the same can be said about any other enhancement to any interface. > c) Adding a new register method here means all rs providers have to support > it...and a new register method is quite new semantics (rather than > generalization of existing semantics as the new getRemoteServiceReference > method was). What is so new about its semantics? But to make it even clearer I am happy with IRemoteServiceContainerAdapter.registerRemoteService(String[], ServiceReference, Dictionary) In general I'm trying to fix this bug and not adding API for the mere fun of it. IMO it is on you to propose an alternative if an API enhancement is to be avoided. (In reply to comment #24) > (In reply to comment #23) > > > a) Currently, the remote services API (itself rather than provider/impl) > > doesn't refer to OSGi classes, and so is able to run/be used outside of OSGi > > context. AFAIK no one is doing this, but it is in the back of my mind as > > something that can be done...and that I might wish to do (e.g. Android). > > Why not run Apache Felix on Android? Because running any OSGi framework on Android is a much bigger proposition (e.g. it requires lots more code...and a bunch of other runtime support...and I'm not at all confident in Felix-on-Android...or any OSGi framework for that matter...at this point). >And I'm certain that there are more places > in ECF that prevent usage outside of OSGi. E.g. InvalidSyntaxException on > org.eclipse.ecf.remoteservice.IRemoteServiceContainerAdapter.getRemoteServiceReferences(ID, > ID[], String, String) and > >org.eclipse.ecf.remoteservice.IRemoteServiceContainerAdapter.createRemoteFilter>(String) True...but these existing referenced classes are trivial in their extent compared with ServiceReference. > > > b) Currently there is just one registerRemoteService method...and this makes > > things simpler and unambiguous for consumers. > > True, but the same can be said about any other enhancement to any interface. > > > c) Adding a new register method here means all rs providers have to support > > it...and a new register method is quite new semantics (rather than > > generalization of existing semantics as the new getRemoteServiceReference > > method was). > > What is so new about its semantics? But to make it even clearer I am happy with > IRemoteServiceContainerAdapter.registerRemoteService(String[], > ServiceReference, > Dictionary) > > > In general I'm trying to fix this bug and not adding API for the mere fun of > it. I know that Markus...no need to say that. >IMO it is on you to propose an alternative if an API enhancement is to be > avoided. Ok...let me think about it then. Here's one alternative: How about an r-OSGi-specific remote service property: serviceReference=<theServiceReference>? Or another: A sub-interface of IRemoteServiceContainerAdapter with this new registerRemoteService method? (In reply to comment #25) > Here's one alternative: How about an r-OSGi-specific remote service property: > serviceReference=<theServiceReference>? Problem is, that all containers need to know about this property to remove it from the dictionary. Otherwise it will cause churn one the container tries to serialize the dictionary. > Or another: A sub-interface of IRemoteServiceContainerAdapter with this new > registerRemoteService method? A sub interface that e.g. EventHookImpl tries to use via instanceof? (In reply to comment #26) > (In reply to comment #25) > > Here's one alternative: How about an r-OSGi-specific remote service property: > > serviceReference=<theServiceReference>? > > Problem is, that all containers need to know about this property to remove it > from the dictionary. Otherwise it will cause churn one the container tries to > serialize the dictionary. We could make it an ECF-standard remote property (i.e. on o.e.e.remoteservices.constants). If the API is changed/enhanced then all the providers need to know about it as well, so I don't see this as a huge downside. > > > Or another: A sub-interface of IRemoteServiceContainerAdapter with this new > > registerRemoteService method? > > A sub interface that e.g. EventHookImpl tries to use via instanceof? Yeah, I suppose. (In reply to comment #27) > (In reply to comment #26) > > (In reply to comment #25) > > > Here's one alternative: How about an r-OSGi-specific remote service property: > > > serviceReference=<theServiceReference>? > > > > Problem is, that all containers need to know about this property to remove it > > from the dictionary. Otherwise it will cause churn one the container tries to > > serialize the dictionary. > > We could make it an ECF-standard remote property (i.e. on > o.e.e.remoteservices.constants). If the API is changed/enhanced then all the > providers need to know about it as well, so I don't see this as a huge > downside. > > > > > > Or another: A sub-interface of IRemoteServiceContainerAdapter with this new > > > registerRemoteService method? > > > > A sub interface that e.g. EventHookImpl tries to use via instanceof? > > Yeah, I suppose. Right now I prefer the second alternative... it does not involve any API change or changes to other providers. Created attachment 180372 [details]
IOSGiRemoteServiceContainerAdapter as sketched out in last comment
Created attachment 180373 [details]
mylyn/context/zip
(In reply to comment #29) > Created an attachment (id=180372) [details] > IOSGiRemoteServiceContainerAdapter as sketched out in last comment WRT the new API (IOSGiRemoteServiceContainerAdapter) method signature: 1) The javadoc for serviceReference parameter says this: + * <li>Must be equal to + * org.osgi.framework.ServiceReference.getProperty + * (org.osgi.framework.Constants.OBJECTCLASS)</li> + * </ul> Is this intended to be the javadoc for the first parameter...i.e. clazzes? If this is true (clazzes must be equal to OBJECTCLASS property value), then perhaps the signature should be IRemoteServiceReference registerRemoteService(ServiceReference serviceReference, Dictionary properties) (In reply to comment #31) > (In reply to comment #29) > > Created an attachment (id=180372) [details] [details] > > IOSGiRemoteServiceContainerAdapter as sketched out in last comment > > > WRT the new API (IOSGiRemoteServiceContainerAdapter) method signature: > > 1) The javadoc for serviceReference parameter says this: > + * <li>Must be equal to > + * org.osgi.framework.ServiceReference.getProperty > + * (org.osgi.framework.Constants.OBJECTCLASS)</li> > + * </ul> > > Is this intended to be the javadoc for the first parameter...i.e. clazzes? > > If this is true (clazzes must be equal to OBJECTCLASS property value), then > perhaps the signature should be > > IRemoteServiceReference registerRemoteService(ServiceReference > serviceReference, Dictionary properties) I thought about this too this morning under the shower and figured it should be rephrased to "Must be equals or a subset..." (In reply to comment #32) > > If this is true (clazzes must be equal to OBJECTCLASS property value), then > > perhaps the signature should be > > > > IRemoteServiceReference registerRemoteService(ServiceReference > > serviceReference, Dictionary properties) > > I thought about this too this morning under the shower and figured it should be > rephrased to "Must be equals or a subset..." What is the use case even for it being a subset? Wouldn't it be clearer to eliminate clazzes completely...and use the OBJECTCLASS and/or the osgi remote service interfaces property? (In reply to comment #33) > What is the use case even for it being a subset? Wouldn't it be clearer to > eliminate clazzes completely...and use the OBJECTCLASS and/or the osgi remote > service interfaces property? Depends, for remote services you can expect a remote service interface property set. But what happens if the method is used outside the remote service context by consumers who just have a (local) ServiceReference and what a certain set of interfaces remoted? (In reply to comment #34) > (In reply to comment #33) > > > What is the use case even for it being a subset? Wouldn't it be clearer to > > eliminate clazzes completely...and use the OBJECTCLASS and/or the osgi remote > > service interfaces property? > > Depends, for remote services you can expect a remote service interface property > set. But what happens if the method is used outside the remote service context > by consumers who just have a (local) ServiceReference and what a certain set of > interfaces remoted? We could insist that the remote service interface property be set...either in the ServiceReference properties...or in the Dictionary properties...for this registerRemoteService. (In reply to comment #35) > We could insist that the remote service interface property be set...either in > the ServiceReference properties...or in the Dictionary properties...for this > registerRemoteService. If we do, we can certainly remove the String[], but why restrict it? (In reply to comment #36) > (In reply to comment #35) > > > We could insist that the remote service interface property be set...either in > > the ServiceReference properties...or in the Dictionary properties...for this > > registerRemoteService. > > If we do, we can certainly remove the String[], but why restrict it? It just seems to me that the presence of clazzes String[] allows folks to get into all sorts of weird situations with use of the api...e.g. disagreement between clazzes and objectclass property, or disagreement between clazzes, objectclass and remote service interface property values. And I guess I'm not clear on when would be a valid case to actually use classes...without it just reproducing objectclass and/or remote service interface prop value. And requiring people to provide something...under lots of contraints for correctness...just increases the opportunities for error. (In reply to comment #37) > It just seems to me that the presence of clazzes String[] allows folks to get > into all sorts of weird situations with use of the api...e.g. disagreement > between clazzes and objectclass property, or disagreement between clazzes, > objectclass and remote service interface property values. > > And I guess I'm not clear on when would be a valid case to actually use > classes...without it just reproducing objectclass and/or remote service > interface prop value. And requiring people to provide something...under lots of > contraints for correctness...just increases the opportunities for error. I can think of cases where consumers use the interface outside the scope of "OSGi remote services" thus don't set "service.exported.interfaces" and do not intent to remote all interfaces listed in the objectclass property. (In reply to comment #38) > (In reply to comment #37) > > It just seems to me that the presence of clazzes String[] allows folks to get > > into all sorts of weird situations with use of the api...e.g. disagreement > > between clazzes and objectclass property, or disagreement between clazzes, > > objectclass and remote service interface property values. > > > > And I guess I'm not clear on when would be a valid case to actually use > > classes...without it just reproducing objectclass and/or remote service > > interface prop value. And requiring people to provide something...under lots of > > contraints for correctness...just increases the opportunities for error. > > I can think of cases where consumers use the interface outside the scope of > "OSGi remote services" thus don't set "service.exported.interfaces" and do not > intent to remote all interfaces listed in the objectclass property. Ok...it just seems to me that having a clazzes array passed in explicitly...with the constraint that it must be a subset of the interfaces exposed via the ServiceReference objectclass property...seems prone to error. But, I suppose since this method is going to be on a special sub-interface (IOSGiRemoteServiceContainerAdapter), and probably only going to be implemented by the r-osgi provider...and only used in the OSGi remote services implementation code (right?)...then it's ok to have the clazzes array...and document the necessary constraints. (In reply to comment #39) > Ok...it just seems to me that having a clazzes array passed in > explicitly...with the constraint that it must be a subset of the interfaces > exposed via the ServiceReference objectclass property...seems prone to error. It is a String[] and not a Class[]. Exactly like the bundleContext.registerService(String[], ..., Dictionary) Released IOSGiRemote... interface to HEAD |
Build Identifier: ECF 3.2.0.v20100219-1253 Hi, I'm new to this forum and I first would like to say that you - ECF guys - are doing great work! I'm using ECF implementation of the OSGi 4.2 Remote Service specification and it works like a charm. Up till now I was using ecf generic as communication protocol but due to limitations (I'll post another topic about this) I decided to replace it with r-osgi. The move was easily done but I immediately encountered a CNFE during the remote service registration in the r-osgi bundle. Some investigation told me that it only happens when using r-osgi in combination with ECF: registering the service directly to r-osgi does not produce the CNFE. Here are some details: The CNFE happens with following code (I've also attached the test bundles): + Bundle A - package org.myorg.pkga - public class ClassA { private ClassB myClassB; } - package org.myorg.pkgb - public ClassB { } - package org.myorg.service.itf - public interface MyService { void someMethod(ClassA arg); } - MANIFEST.MF with Export-Package: org.myorg.pkga,org.myorg.pkgb,org.myorg.service.itf + Bundle B - package org.myorg.service.impl - public class MyServiceImpl implements MyService { void someMethod(ClassA arg) { // do something } } - public class Activator implements BundleActivator { public void start(...) { // works with direct r-osgi registration //properties.put(RemoteOSGiService.R_OSGi_REGISTRATION, Boolean.TRUE); // does not work with ECF OSGi 4.2 Remote Service registration properties.put("service.exported.interfaces", "*"); properties.put("service.exported.configs", "ecf.r_osgi.peer"); context.registerService(MyService.class.getName(), new MyServiceImpl(), properties); } } - MANIFEST.MF with Import-Package: org.myorg.pkga, org.myorg.service.itf + Target platform containing the needed r-osgi and ecf bundles The CNFE happens in the ch.ethz.iks.r_osgi.impl.RemoteServiceRegistration constructor during CodeAnalyzer.analyze method call. Apparently the CodeAnalyzer relies on the classloader of the registered service and the Import-Package and Export-Package headers of the bundle registering the service and that's where the direct r-osgi and ECF registrations differ: - When registering the service with the r-osgi property, the service registration is handled directly by r-osgi bundle: classloader and the Import/Export-Package headers are from Bundle B - when registering the service with the ECF (OSGi Remote Service) properties, the service registration is first handled by the ecf.provider.r_osgi bundle which will re-register the service with the r-osgi property and this service registration will then be handled by the r-osgi bundle: classloader is still from Bundle B (is easily retrieved from service object) but the Import/Export-Package headers are from ecf.provider.r_osgi bundle (are retrieved from the servicereference object). Because the CodeAnalyzer doesn't get the expected Import/Export-Package headers (the ones from Bundle B) a CNFE is thrown during the call. So this looks like a bug but I can't say where the fix should be: in r-osgi bundle or in ecf.provider.r_osgi bundle? I would tend to say that the ecf.provider.r_osgi bundle should register the service with the bundle context of the bundle providing the service instead of its own bundle context (unless there's a good reason not to do so), like when impersonating a bundle in the extender model but here it's not an extender and getting the bundle context of the original service might be a little tricky... Reproducible: Always Steps to Reproduce: 1. Deploy the attached bundles in target platform containing r-osgi and ecf 2. 3.