[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)?

Agree 100% with stipulation that I have not tested 1&2 and have no idea about 3 :)



-- 
Dmitry Sklyut
Sent with Sparrow

On Tuesday, February 5, 2013 at 22:19, Scott Lewis wrote:

Hi Dmitry,

On 2/5/2013 7:03 PM, Dmitry Sklyut wrote:
<stuff deleted>

When blueprint creates it's proxy, this interface is not on the objectclass and so the blueprint proxy doesn't expose it.
 
Actually not fully true.  objectclass has very little to do with blueprint proxy (outside of greedy-proxy support mentioned before).  From this post http://www.eclipse.org/forums/index.php/t/452118/  blueprint config

<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>
interface o.e.e.e.r.hello.IHello is what gets proxied.

Ok.

 

So far does this square with your thinking Dmitry?

Outside of the above comment - yes. 

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.

Ok.  no problem.
 
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?

Blueprint will always create a proxy - that is at the core of how it works.  
 
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.

There is actually no need to extend Gemini Blueprint to do it.  It already does it: http://www.eclipse.org/gemini/blueprint/documentation/reference/1.0.2.RELEASE/html/service-registry.html#service-registry:refs:singular:interface.  One only needs to change xml configuration namespace from http://www.osgi.org/xmlns/blueprint/v1.0.0 to  http://www.springframework.org/schema/osgi.

So is this a viable option for the use case on the forum posting?   Could they just be instructed how to make this change and create any necessary meta-data?


But it is possible, with very little effort actually, to add an extension point where Gemini Blueprint can be told what interfaces to proxy based on service properties or whatever. 

Some examples.


1. Blueprint by the spec:

{code}
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" default-activation="eager">
    <bean id="consumer" class="org.eclipse.ecf.examples.internal.remoteservices.hello.ds.consumer.HelloClientComponent"/>

    <service ref="consumer" interface="org.eclipse.ecf.examples.remoteservices.hello.IHello" depends-on="host"/>
     
    <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>
</blueprint>
{code}

              
2. Gemini Blueprint extension:
{code}
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:osgi="http://www.springframework.org/schema/osgi"

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi-2.0.xsd">

<bean id="consumer" class="org.eclipse.ecf.examples.internal.remoteservices.hello.ds.consumer.HelloClientComponent"/>

<osgi:service ref="consumer" interface="org.eclipse.ecf.examples.remoteservices.hello.IHello" depends-on="host"/>
<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>
</beans>
{code}
In the Gemini Blueprint extension - you can proxy 2+ interfaces.  You can't do it in the "by the book" blueprint.

Ok....that sounds good to me.  Perhaps the folks on the forum thread would be willing to do this...in order to get access to the ECF IRemoteServiceProxy.  They could decide for themselves whether they would rather do this/above...or one of the other solutions/workarounds below.

 Both of the above configurations will do exactly identical thing.  Create a "local" component.  Publish it as a service. Set-up an import proxy on IHello interface and deploy service listener.  In option 1 - blueprint can only proxy IHello, in option 2 - IHello AND IRemoteServiceProxy.

Again...seems like a good option to me.  I don't know how 'spec required' the folks are on the forum thread.




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.

This is really is a last resort type of a thing...  If you resort to this - it might be better to just use ServiceTracker or a direct bundleContext lookups.

Ok.   Still...I guess this could be left up to them...if this is what they prefer.

 

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.

This is still a viable option as well...

so to summarize...I think we have three possible solutions:

1) Use springframework.org schema...and add the extra available interfaces (i.e. both IHello and IRemoteServiceProxy)
2) Use getTargetServiceReference() (last resort)
3)  Use 'service.imported' service property to get/use IRemoteService (rather than IRemoteServiceProxy).

It looks like 3 would be the easiest...if they are willing to write code (I can provide them with example code if they wish), whereas 1 would be the easiest if they are willing to use the non-blueprint schema.  Agreed?

Thanks,

Scott






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


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




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

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