Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [virgo-dev] Would you like to try debugging a Gemini Blueprint issue (with ECF)?

Hi Dmitry,

Ok...so it seems that what we have here is two extenders...ECF is making proxies for remote services and then then blueprint is proxying some/all services to allow service dependencies to be resolved immediately (essentially extending declarative services).

The problem...for this use case...apparently comes when blueprint proxies the proxy that ECF creates for a remote service.  ECF has as a feature the ability to get to the IRemoteServiceProxy interface on the remote service proxy.  When blueprint creates it's proxy, this interface is not on the objectclass and so the blueprint proxy doesn't expose it.

So far does this square with your thinking Dmitry?

Now...assuming we're on the right track, question is what to do about it.   Possibilities (please add if I'm missing some):

1) ECF could add IRemoteServiceProxy to it's proxy.  I'm hesitant to do this, only because the rs/rsa spec says that only what the remote service host puts on the objectclass is what the proxy should have on it's objectclass.
2) Through some option or config, blueprint could be told *not* create a proxy for remote services.  There's a OSGi-specified property (service.imported) that means that it's a remote service.  Is there something that allows blueprint to be configured to ignore/not automatically create proxies for certain services?
3) Is it possible to extend Blueprint to have it add other interfaces (e.g. IRemoteServiceProxy) during it's proxy construction?  If so, I could create an ECF remote services extension for Blueprint to do this for ECF remote services.

And then there are two workarounds...one from blueprint

a) As Dmitry indicated:  ServiceReference nativeReference = ((ServiceReferenceProxy)serviceReference).getTargetServiceReference().   Then the ECF proxy could be accessed directly via the nativeReference.

and the other from ECF remote services

b) ECF sets the value of OSGi's 'service.imported' property to an instance of IRemoteService...which for this use case may meet their needs (to make asynchronous remote method calls).  What I'm saying is that if blueprint just copies the nativeReference service properties into it's proxy's properties, then client code could simply get the value of 'service.imported' and cast it to IRemoteService...and use that to make async remote calls.

Reactions or further thoughts?

Thanks,

Scott



On 2/5/2013 5:58 PM, Dmitry Sklyut wrote:
Scott,

Just want to get one point clear - blueprint has absolutely nothing to do with remote service admin spec. 

Blueprint is declarative services on steroids.  The reason why it applies proxies is to allow importers to start up right away without waiting for all dependencies, lazy init, apply thread context classloader, etc. 

So again, nothing to do with remote admin. Just dependency injection and managing dynamics of services. 


The reason I brought up OBJECTCLASS is to show a way how non-declared service interface on the importer side can still be satisfied. 

Hope this clears a picture a bit. 

-- 
Dmitry Sklyut
Sent with Sparrow

On Tuesday, February 5, 2013 at 20:07, Scott Lewis wrote:

Hi Dmitry,

On 2/5/2013 4:40 PM, Dmitry Sklyut wrote:
Scott,

The sequence of events is:

1 service is publisher on remote host

Yes...but key point:  It's published by ECF remote services (not Gemini blueprint)

2 service consumed by ECF on client and proxied

Ok.

3 blueprint applies its proxy to the ECF proxied object, but only for the interfaces defined in the importing definition that is on <reference/> XML tag.

Why does blueprint do this?   It seems to me that at least according to the Remote Service Admin spec (122), that this proxying-of-the-proxy should not be done for configs that are not Gemini's (i.e. are ECF configs).  I believe that's the whole purpose of the remote service configs...i.e. to allow multiple distribution systems to coexist, and *not* interfere with each other.


So, ECF proxy is applied, blueprint finds and delivers correct service reference but it wraps it in its own proxy. greedy-proxy or defining multiple interfaces to proxy (last one cannot be done with the blueprint specification XML as it allows for a single interface only) will work around this situation. 

For greedy-proxy to work all implemented interfaces and non-final classes must be defined in OJECTCLASS property.

This can't be part of ECF's remote service admin implementation...as the objectclass property is only specified to have the same service interfaces given in the original remote service publisher (1).  And that publisher is not going to have the IRemoteServiceProxy in it's objectclass.

Scott



To work around limitations of the spec, the <bean/> definitions can be used to directly register an "import factory" and define missing interfaces. 

Regards,

-- 
Dmitry Sklyut
Sent with Sparrow

On Tuesday, February 5, 2013 at 18:50, Scott Lewis wrote:

Hi Dmitry,

On 2/5/2013 2:48 PM, Dmitry Sklyut wrote:
Scott,

I looked over this issue and here is what can be done (all config examples are based on github example provided in the forum post).

First bad news: I don't think it can be done with vanilla Blueprint xml config.

Good news it can be done with a little help from ECF and change in configuration on the blueprint side.


BUT for greedy-proxying to work - ECF must publish its proxy with all interfaces advertised in reference.getProperty(Constants.OBJECTCLASS).
Including org.eclipse.ecf.remoteservice.IRemoteServiceProxy

Hmm. I'm not sure if I understand what you are saying. ECF's remote
service admin does create and import the proxy with all interfaces that
are advertised in objectclass. If ECF's remote service admin is used
(e.g. as per the ECF examples), this does happen...but it seems to me
that Gemini is somehow pre-empting and/or circumventing the operation of
the ECF Remote Service Admin on the import side (I'm not sure of this,
it's just a hypothesis). With ECF's proxy creation and publishing,
IRemoteServiceProxy will be automatically added to the proxy...whether
or not it appears in objectclass...and this happens fine in the ECF
remote service examples because the proxy creation and publishing is
done via the ECF remote service admin importService call.

I think the best solution should be to let the ECF remote service admin
create and publish the proxy on the consumer/import side. I'm still not
sure why this isn't just happening in this case...as it does in the
example code (without Gemini). I think it would/will be much
preferable to have ECF create and publish the proxy (as it should for
ECF-exported remote services) than to try to get blueprints impl to
import remote services exported by blueprint (it seems that's what you
are attempting to do below...but I might be mistaken about your intent
though). In any event, my reading of the remote service admin spec
allows multiple distribution providers co-exist and not interfere with
each other...by only responding to the appropriate discovered remote
services (i.e. those exported via a compatible config).

Scott





On blueprint side:

1. use spring osgi namespace and you can change <reference/> to a <list/> and enable greedy-proxying

Instead of <blueprint..></blueprint> use:



Instead of reference
<reference
id="host" interface="org.eclipse.ecf.examples.remoteservices.hello.IHello"
availability="mandatory">
<reference-listener bind-method="bindHello">
<ref component-id="consumer" />
</reference-listener>
</reference>

Use list
<osgi:list id="hostInListWithGreedy"
interface="org.eclipse.ecf.examples.remoteservices.hello.IHello"
greedy-proxying="true" cardinality="1..N">
<osgi:listener bind-method="bindHello">
<ref bean="consumer" />
</osgi:listener>
</osgi:list>

Or use to specify 2 interfaces vs. 1.

<osgi:reference id="host" cardinality="1..1">
<osgi:interfaces>
<value>org.eclipse.ecf.examples.remoteservices.hello.IHello</value>
<value>org.eclipse.ecf.remoteservice.IRemoteServiceProxy</value>
</osgi:interfaces>
<osgi:listener bind-method="bindHello">
<ref bean="consumer"/>
</osgi:listener>
</osgi:reference>


2. Instead of osgi:reference or osgi:list - use bean configuration
(something like this in spring bean style)

<bean id="host2" class="org.eclipse.gemini.blueprint.service.importer.support.OsgiServiceProxyFactoryBean">
<property name="availability" value="MANDATORY"/>
<property name="interfaces">
<list>
<value>org.eclipse.ecf.examples.remoteservices.hello.IHello</value>
<value>org.eclipse.ecf.remoteservice.IRemoteServiceProxy</value>
</list>
</property>
<property name="listeners">
<list>
<bean class="org.eclipse.gemini.blueprint.config.internal.adapter.OsgiServiceLifecycleListenerAdapter">
<property name="bindMethod" value="bindHello"/>
<property name="targetBeanName" value="consumer"/>
<!-- or -->
<property name="target" ref="consumer"/>
</bean>
</list>
</property>
</bean>

There is a similar bean for <list/> OsgiServiceCollectionProxyFactoryBean that can be configured with greedy-proxying also.

I don't think there is anything blueprint can do to expose org.eclipse.ecf.remoteservice.IRemoteServiceProxy without knowing that it exists if it is not in the OBJECTCLASS property.

Another way forward for now is to get the target service object from within Blueprint proxy.

ala.

ServiceReference nativeReference = ((ServiceReferenceProxy)serviceReference).getTargetServiceReference()

This way it is as naked as DS service object.

Hope this is all clear. I forked the blueECF github project and will push changes to it later today.


Regards,


_______________________________________________
virgo-dev mailing list



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

_______________________________________________
virgo-dev mailing list



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


Back to the top