Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 337643

Summary: [remoteserviceadmin] classloader for proxy creation must be able to access IRemoteServiceProxy
Product: [RT] ECF Reporter: Martin Petzold <mpetzold>
Component: ecf.remoteservicesAssignee: Scott Lewis <slewis>
Status: RESOLVED FIXED QA Contact:
Severity: major    
Priority: P3 CC: slewis
Version: 3.5.0   
Target Milestone: 3.5.0   
Hardware: PC   
OS: Windows Vista   
Whiteboard:
Attachments:
Description Flags
Remote Services have no Proxy Service on Consumer side with service.imported=* set none

Description Martin Petzold CLA 2011-02-19 10:51:58 EST
Somehow the registration of remote services has changed. Now I don't have any service with the "service.imported=*" property set on consumer end!

Something to do with the equals of EndpointDescription?

----- Provider Registration (Provider)

final Properties propsA = new Properties();
propsA.put("service.exported.interfaces", "*");
propsA.put("service.exported.configs", "ecf.r_osgi.peer");
Activator.getContext().registerService(ServiceA.class.getName(),
        new ServiceAImpl(), propsA);

----- Consumer Tracker

public class ServiceATracker extends ServiceTracker {

    public ServiceATracker() throws InvalidSyntaxException {
        super(Activator.getContext(), ServiceA.class.getName(), null);

----- Consumer Output (but nothing about the RS property!)

test.service.ServiceA has come...
ecf.rsvc.cid -> r-osgi://jumper:9279
ecf.rsvc.ranking -> 0
ecf.rsvc.id -> 57
service.uri -> r-osgi://jumper:9279#57
ecf.robjectClass -> [Ljava.lang.String;@23000bcf
service.id -> 57
objectClass -> [Ljava.lang.String;@580754fc

-----
Comment 1 Scott Lewis CLA 2011-02-19 11:46:39 EST
(In reply to comment #0)
> Somehow the registration of remote services has changed. Now I don't have any
> service with the "service.imported=*" property set on consumer end!
> 
> Something to do with the equals of EndpointDescription?
> 
> ----- Provider Registration (Provider)
> 
> final Properties propsA = new Properties();
> propsA.put("service.exported.interfaces", "*");
> propsA.put("service.exported.configs", "ecf.r_osgi.peer");
> Activator.getContext().registerService(ServiceA.class.getName(),
>         new ServiceAImpl(), propsA);
> 
> ----- Consumer Tracker
> 
> public class ServiceATracker extends ServiceTracker {
> 
>     public ServiceATracker() throws InvalidSyntaxException {
>         super(Activator.getContext(), ServiceA.class.getName(), null);
> 
> ----- Consumer Output (but nothing about the RS property!)
> 
> test.service.ServiceA has come...
> ecf.rsvc.cid -> r-osgi://jumper:9279
> ecf.rsvc.ranking -> 0
> ecf.rsvc.id -> 57
> service.uri -> r-osgi://jumper:9279#57
> ecf.robjectClass -> [Ljava.lang.String;@23000bcf
> service.id -> 57
> objectClass -> [Ljava.lang.String;@580754fc
> 
> -----

I believe this is the r-osgi - registered service...not the proxy service registered by the ECF RSA implementation upon import.  

Martin...I'm going to move this bug from critical to major.  Before full diagnosis, I don't think it justifies critical.
Comment 2 Martin Petzold CLA 2011-02-20 04:38:04 EST
For me this bug does not depend on https://bugs.eclipse.org.

My concern about "org.eclipse.ecf.osgi.services.discovery.allowLoopbackReference" was just because I had this in my mind, I did not use this property, just tested it again. Even though good to have it implemented again, whatever it can be used for.
Comment 3 Martin Petzold CLA 2011-02-20 04:42:49 EST
Created attachment 189357 [details]
Remote Services have no Proxy Service on Consumer side with service.imported=* set

Remote Services have no Proxy Service on Consumer side with service.imported=* set. Example RS usage from documentation is used. No container creation by hand, should work (and does) automaticly.

Remote Service is present, but only some r-osgi proxy no RS conform proxy -> switch tracker filter to see it.
Comment 4 Martin Petzold CLA 2011-02-20 04:56:40 EST
Also with "ecf.generic.server" no remote service (proxy) is registered on consumer end. Is this something about automatic container creation? This is one difference to the "org.eclipse.ecf.examples.remoteservices.hello.host/consumer)" example, this does work for me, proxies with service.imported=* are present in the example!

I set this bug to critical because it has something to do with the new remoteserviceadmin implementation and there is a different behaviour with remote service registration.
Comment 5 Scott Lewis CLA 2011-02-20 10:34:52 EST
After thinking about this bug, and realizing that you are using a ServiceTracker to track/discovery remote services I think this could be the following issue:

The ServiceTracker class has two 'open' methods:

public void open()

and

public void open(boolean trackAllServices)

I suspect that you are currently using open() and with the Remote Services Admin it's necessary to use serviceTracker.open(true).  See more about this below, but could you try opening with open(true) rather than open() and see if things then work for you?  Given that your proxy/consumer discovery isn't happening for the generic provider either, I now don't believe this has anything to do with r-osgi localhost handling as I did yesterday.

The RSA implementation has some new logic for proxy classloading as given in the OSGi 4.2 enterprise specification, section 122.5.6.  For some reason that I'm not completely clear on, this proxy classloding logic seems to require the ServiceTracker.open(true) method to be used by clients rather than ServiceTracker.open() (because ServiceTracker.open() calls ServiceTracker.open(false)).

The javadocs in ServiceTracker.open(boolean trackAllServices) for trackAllServices is this:

	 * @param trackAllServices If {@code true}, then this
	 *        {@code ServiceTracker} will track all matching services
	 *        regardless of class loader accessibility. If {@code false},
	 *        then this {@code ServiceTracker} will only track matching
	 *        services which are class loader accessible to the bundle whose
	 *        {@code BundleContext} is used by this
	 *        {@code ServiceTracker}.


'only track matching services which are class loader accessible' is the key part.  I'm not clear on why the proxying logic in 122.5.6 seems to make the services 'not classloader accessible'...but it seems to do so.  I'm going to consult with the folks responsible for the ServiceTracker and the spec to understand this better.

In the mean time, please try ServiceTracker.open(true) in your code, and lets see if this fixes things for this use case.
Comment 6 Martin Petzold CLA 2011-02-20 10:45:41 EST
Very interesting!

But We should also think abut the getServiceReferences(...). In my opinion it's very important to get the same behaviour with both getServiceReferences(...) and ServiceTracker, using the same class/filter.
Comment 7 Martin Petzold CLA 2011-02-20 10:47:39 EST
The RS is now beeing dicovered (still set to ecf.generic) and there is one service with the service.imported=* set, well for the first.

But there are also Exceptions (further down: interface org.eclipse.ecf.remoteservice.IRemoteServiceProxy is not visible from class loader):

org.osgi.framework.ServiceException: Exception in org.eclipse.ecf.osgi.services.remoteserviceadmin.RemoteServiceAdmin$ProxyServiceFactory.getService()
	at org.eclipse.osgi.internal.serviceregistry.ServiceUse.getService(ServiceUse.java:130)
	at org.eclipse.osgi.internal.serviceregistry.ServiceRegistrationImpl.getService(ServiceRegistrationImpl.java:447)
	at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.getService(ServiceRegistry.java:430)
	at org.eclipse.osgi.framework.internal.core.BundleContextImpl.getService(BundleContextImpl.java:667)
	at test.consumer.ServiceATracker.addingService(ServiceATracker.java:18)
	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:756)
	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.ecf.osgi.services.remoteserviceadmin.RemoteServiceAdmin.createAndRegisterProxy(RemoteServiceAdmin.java:1428)
	at org.eclipse.ecf.osgi.services.remoteserviceadmin.RemoteServiceAdmin.importService(RemoteServiceAdmin.java:1865)
	at org.eclipse.ecf.osgi.services.remoteserviceadmin.RemoteServiceAdmin.importService(RemoteServiceAdmin.java:295)
	at org.eclipse.ecf.osgi.services.remoteserviceadmin.AbstractTopologyManager.handleEndpointAdded(AbstractTopologyManager.java:207)
	at org.eclipse.ecf.internal.osgi.services.distribution.BasicTopologyManager.endpointAdded(BasicTopologyManager.java:45)
	at org.eclipse.ecf.osgi.services.remoteserviceadmin.EndpointDescriptionLocator$1.dispatchEvent(EndpointDescriptionLocator.java:149)
	at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:227)
	at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:337)
Caused by: org.osgi.framework.ServiceException: ProxyServiceFactory cannot create proxy for clientBundle=RSConsumer from serviceReference={test.service.ServiceA}={service.imported=org.eclipse.ecf.provider.remoteservice.generic.RemoteServiceImpl@5289e2f1, service.imported.configs=[ecf.generic.client], service.id=54}
	at org.eclipse.ecf.osgi.services.remoteserviceadmin.RemoteServiceAdmin.createProxy(RemoteServiceAdmin.java:1526)
	at org.eclipse.ecf.osgi.services.remoteserviceadmin.RemoteServiceAdmin.access$4(RemoteServiceAdmin.java:1494)
	at org.eclipse.ecf.osgi.services.remoteserviceadmin.RemoteServiceAdmin$ProxyServiceFactory.getService(RemoteServiceAdmin.java:1482)
	at org.eclipse.osgi.internal.serviceregistry.ServiceUse$1.run(ServiceUse.java:120)
	at java.security.AccessController.doPrivileged(Native Method)
	at org.eclipse.osgi.internal.serviceregistry.ServiceUse.getService(ServiceUse.java:118)
	... 25 more
Caused by: org.eclipse.ecf.core.util.ECFException: Failed to create proxy
	at org.eclipse.ecf.remoteservice.AbstractRemoteService.getProxy(AbstractRemoteService.java:118)
	at org.eclipse.ecf.osgi.services.remoteserviceadmin.RemoteServiceAdmin.createProxy(RemoteServiceAdmin.java:1523)
	... 30 more
Caused by: java.lang.IllegalArgumentException: interface org.eclipse.ecf.remoteservice.IRemoteServiceProxy is not visible from class loader
	at java.lang.reflect.Proxy.getProxyClass(Unknown Source)
	at java.lang.reflect.Proxy.newProxyInstance(Unknown Source)
	at org.eclipse.ecf.remoteservice.AbstractRemoteService.createProxy(AbstractRemoteService.java:132)
	at org.eclipse.ecf.remoteservice.AbstractRemoteService.getProxy(AbstractRemoteService.java:116)
	... 31 more
-----
test.service.ServiceA has come...
service.imported -> org.eclipse.ecf.provider.remoteservice.generic.RemoteServiceImpl@5289e2f1
service.imported.configs -> [Ljava.lang.String;@26b31b77
objectClass -> [Ljava.lang.String;@38d0357a
service.id -> 54
-----
Comment 8 Martin Petzold CLA 2011-02-20 10:50:53 EST
Just to get safer behaviour of RS/RSA with the new implementation we should add some more test cases to the build/junit soon. I will open a bug for this and will think about some.
Comment 9 Scott Lewis CLA 2011-02-20 10:56:55 EST
(In reply to comment #6)
> Very interesting!
> 
> But We should also think abut the getServiceReferences(...). In my opinion it's
> very important to get the same behaviour with both getServiceReferences(...)
> and ServiceTracker, using the same class/filter.

The ServiceTracker uses/is based upon getServiceReferences...so if it works appropriately for one then it works for the other.
Comment 10 Scott Lewis CLA 2011-02-20 11:09:35 EST
(In reply to comment #7)
> The RS is now beeing dicovered (still set to ecf.generic) and there is one
> service with the service.imported=* set, well for the first.
> 
> But there are also Exceptions (further down: interface
> org.eclipse.ecf.remoteservice.IRemoteServiceProxy is not visible from class
> loader):
> 

<stuff deleted>

Ok, this is great info.  I assume that neither of your bundles imports the org.eclipse.ecf.remoteservice package, right?  

This is a bug/problem with the RSA impl...as the proxy should be created with IRemoteServiceProxy even if your code doesn't import org.eclipse.ecf.remoteservice package.  

As a temporary work around (i.e. while I fix this issue generally...hopefully today), is to simply add org.eclipse.ecf.remoteservice package to the bundle that declares the services interface (i.e. ServiceA)...and this exception should then go away.
Comment 11 Martin Petzold CLA 2011-02-20 11:17:58 EST
(In reply to comment #10)
> (In reply to comment #7)
> > [...]
> This is a bug/problem with the RSA impl...as the proxy should be created with
> IRemoteServiceProxy even if your code doesn't import
> org.eclipse.ecf.remoteservice package.  
> 

Nope, I don't import any packages of ECF, remained always this strict because it should be pure OSGi. In my simulation project I do use async calls at the moment, so there it is imported (I will have to keep this in mind!).

> As a temporary work around (i.e. while I fix this issue generally...hopefully
> today), is to simply add org.eclipse.ecf.remoteservice package to the bundle
> that declares the services interface (i.e. ServiceA)...and this exception
> should then go away.

Okay, thanks!

But if I now would use open(true), in other cases I use getServiceReferences(...), what would be the equivalent there? I really need equal behaviour for these two.
Comment 12 Scott Lewis CLA 2011-02-20 11:28:58 EST
(In reply to comment #11)
<stuff deleted>

>Nope, I don't import any packages of ECF, remained always this strict because
>it should be pure OSGi. In my simulation project I do use async calls at the
>moment, so there it is imported (I will have to keep this in mind!).

Yes, currently there is no async support in OSGi (rather only ECF has it).

> But if I now would use open(true), in other cases I use
> getServiceReferences(...), what would be the equivalent there? I really need
> equal behaviour for these two.

I think that getServiceReferences doesn't care about classloader compatibility and will return all references (whether classloader compatible or not). 

But if you want to make sure, just take a look at the use of getServiceReferences in ServiceTracker...I think the classloader compatibility stuff is because of the service listener/notification.

I should have a fix for this bug later today...and would appreciate running with your test code, as currently my examples/test cases import the org.eclipse.ecf.remoteservice package...so don't show this problem...and modifying them would be fairly involved.  

We should move forward with your contributions from 337666 also...which will help the situation.
Comment 13 Scott Lewis CLA 2011-02-20 11:30:48 EST
BTW, I also posted a question about ServiceTracker.open() and classloader compatibility to osgi-dev...to get some clarity from the ServiceTracker implementers and/or spec authors about this.
Comment 14 Martin Petzold CLA 2011-02-20 12:33:15 EST
In my test case getServiceReferences has the same behaviour as ServiceTracker.open() and *not* ServiceTracker.open(true)!

##### ServiceTracker with open(true) and *no* filter #####
-----
test.service.ServiceA has come...
ecf.rsvc.cid -> r-osgi://jumper:9279
ecf.rsvc.ranking -> 0
ecf.rsvc.id -> 57
service.uri -> r-osgi://jumper:9279#57
ecf.robjectClass -> [Ljava.lang.String;@38ffd135
service.id -> 56
objectClass -> [Ljava.lang.String;@23000bcf
-----
-----
test.service.ServiceA has come...
ecf.rsvc.ranking -> 0
service.uri -> r-osgi://jumper:9279#57
service.imported -> org.eclipse.ecf.internal.provider.r_osgi.RemoteServiceImpl@4cc72243
service.imported.configs -> [Ljava.lang.String;@259a8416
ecf.rsvc.cid -> r-osgi://jumper:9279
objectClass -> [Ljava.lang.String;@4355d3a3
service.id -> 57
-----
##### End ServiceTracker  #####

##### getServiceReferences with *no* filter #####
-----
ecf.rsvc.cid -> r-osgi://jumper:9279
ecf.rsvc.ranking -> 0
ecf.rsvc.id -> 57
service.uri -> r-osgi://jumper:9279#57
ecf.robjectClass -> [Ljava.lang.String;@6328edf2
service.id -> 56
objectClass -> [Ljava.lang.String;@141dddba
-----
##### End getServiceReferences #####
Comment 15 Scott Lewis CLA 2011-02-20 17:20:00 EST
(In reply to comment #14)
> In my test case getServiceReferences has the same behaviour as
> ServiceTracker.open() and *not* ServiceTracker.open(true)!
> 
<stuff deleted>

Martin...I'm discussing the OSGi class compatibility stuff on osgi-dev mailing list right now with Neil Bartlet, as it's not apparent to me what (if anything) is wrong with our RSA impl for proxy creation (i.e. the impl of OSGi spec section 122.5.6)...and it seems that this behavior of ServiceTracker is either some issue with that implementation, or some bug in the framework classloader compatibility checking.

See this thread:

https://mail.osgi.org/pipermail/osgi-dev/2011-February/002972.html
Comment 16 Scott Lewis CLA 2011-02-20 17:27:12 EST
I've released a fix to master for this bug...i.e. the IllegalArgumentException  thrown during proxy creation as described in comment 7.

Note that the fix is in the org.eclipse.ecf.remoteservice bundle, in the org.eclipse.ecf.remoteservice.AbstractRemoteService class (not in the remote service admin impl bundle directly, but rather its dependent in org.eclipse.ecf.remoteservice).

Martin I would appreciate it if you would test this new code against your example and verify that it eliminates the IllegalArgumentException for IRemoteServiceProxy class loading for proxy creation (i.e. the error you describe in comment 7).  Then your or I can resolve the bug.
Comment 17 Martin Petzold CLA 2011-02-20 17:28:28 EST
(In reply to comment #15)
> (In reply to comment #14)
> > In my test case getServiceReferences has the same behaviour as
> > ServiceTracker.open() and *not* ServiceTracker.open(true)!
> > 
> <stuff deleted>
> 
> Martin...I'm discussing the OSGi class compatibility stuff on osgi-dev mailing
> list right now with Neil Bartlet, as it's not apparent to me what (if anything)
> is wrong with our RSA impl for proxy creation (i.e. the impl of OSGi spec
> section 122.5.6)...and it seems that this behavior of ServiceTracker is either
> some issue with that implementation, or some bug in the framework classloader
> compatibility checking.
> 
> See this thread:
> 
> https://mail.osgi.org/pipermail/osgi-dev/2011-February/002972.html

Yeah, this might be the best. I'm also reading that list and your posts. I don't think I can help with this, it's far to deep inside OSGi.
Comment 18 Martin Petzold CLA 2011-02-20 17:50:59 EST
Bug from #7 seems resolved. But this bug in total issen't because we have still the problem with the servie proxies: With tracker.open(false) and getServiceReferrences there are no RS proxies registered (this is totaly against the spec and docs). I also would like to set the title back to this fact then, or open a new bug.

Please see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=337345 I had to reopen, a new Exception came up with my recent update (it's about the EndpointDescription I guess).

This is really a lot again, even it's only small things. Hope we will be rid of most of the problems soon. What I can do is testing, some debugging, docs and using but I can't really get into all of this that deep in short time to be able to do good patching...I'm sorry about this.
Comment 19 Scott Lewis CLA 2011-02-20 17:55:54 EST
(In reply to comment #18)
> Bug from #7 seems resolved. But this bug in total issen't because we have still
> the problem with the servie proxies: With tracker.open(false) and
> getServiceReferrences there are no RS proxies registered (this is totaly
> against the spec and docs). I also would like to set the title back to this
> fact then, or open a new bug.

Please open a new bug for that then.

> 
> Please see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=337345 I had to
> reopen, a new Exception came up with my recent update (it's about the
> EndpointDescription I guess).

Like I will say there shortly, I think what you are experiencing is due to an issue caused by the fix for bug 337653.

> 
> This is really a lot again, even it's only small things. Hope we will be rid of
> most of the problems soon. What I can do is testing, some debugging, docs and
> using but I can't really get into all of this that deep in short time to be
> able to do good patching...I'm sorry about this.

No reason to be sorry...finding and resolving these issues is a necessary thing for any reasonably complex system...and RSA over OSGi is a reasonably complex thing.

On the contrary...your testing, finding and reporting bugs is greatly appreciated...as I don't have the bandwidth to write all the desired/necessary tests and docs...as well as write the thing, and fix the subtle issues.

I'm pretty confident that RSA is quite close to completion, and these reports and fixes are making that happen...so please keep them coming...and be patient.
Comment 20 Martin Petzold CLA 2011-02-20 18:13:42 EST
This is working now -> resolved fixed.