You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@tuscany.apache.org by "Millies, Sebastian" <Se...@softwareag.com> on 2011/11/16 10:40:15 UTC

Dynamic service references ?

Hello there,

can references in composite files somehow be made dynamic? In particular, can I define or override
the endpoints in a web service reference at run time?

My question pertains to Tuscany 1.6.

Let me go into some detail to explain the real problem I want to solve. I have a set of items that need
to be sent to SAP backend systems. These SAP systems expose the same interface (remote function
modules and web services). Every item has an endpointProperties attribute that determines which
system it needs to go to.

Currently, this is done outside of Tuscany: The connection is created on the fly using SAP Java Connector
(JCo) exploiting the endpointProperties. A remote call is made through this connection using SAP’s proprietary
RFC protocol.

I’d like to change this to a service-based setup with Tuscany, exploiting SAP web services. The motivation for this
is twofold: First it removes  a dependency on proprietary technology (including native code), second it opens up
the possibility to connect in a generic way to non-SAP systems that offer compatible interfaces .

So on my side (the Tuscany SAP client side) I go through the usual steps:

a)      expose function module as a web service

b)      get the wsdl

c)       use wsimport to create a service interface from the wsdl

d)      remove JAX-WS annotations, make interface remotable, and ensure method names are identical to operation names in wsdl

e)      add an attribute of the interface type to my service implementation and annotate it with @Reference

f)       define the reference to the SAP service in my composite file

I understand (correctly, I hope, I have not tested this) that I can override whatever endpoint is specified in the wsdl by
specifying the uri attribute on the web service binding. Here’s a snippet from an example composite file:

  <sca:reference name="bapiCostcenterGetList" promote="servercomponent/bapiCostcenterGetList">
       <sca:interface.java interface="bapi.ZWSBAPICOSTCENTERGETLIST"/>
       <!--  wsdlElement="<TargetNamespace>#wsdl.port(<SvcName>/<PortName>)" -->
       <sca:binding.ws wsdlElement="urn:sap-com:document:sap:rfc:functions#wsdl.port(ZWS_BAPI_COSTCENTER_GETLISTService/ZWS_BAPI_COSTCENTER_GETLIST)"
       <!--  Override service endpoint -->
       uri="http://sapd01.me.corp.ids-scheer.com:8000/sap/bc/srt/rfc/sap/zws_bapi_costcenter_getlist/100/zws_bapi_costcenter_getlist/zws_bapi_costcenter_getlist" />
    </sca:reference>

As compared to the dynamic approach with hard-coded RFC calls, the connection endpoint is now hard-wired in the composite file.
Is there a way to define Tuscany web service references with dynamic endpoints? Or alternatively, could I perhaps use the endpointProperties
and modify the injected service proxy before making a remote call? Or is  there some entirely different route that does not involve steps a) to f) above?

How would you deal with this type of situation?


n  Sebastian
IDS Scheer Consulting GmbH
Geschäftsführer/Managing Directors: Kamyar Niroumand, Ivo Totev
Sitz/Registered office: Altenkesseler Straße 17, 66115 Saarbrücken, Germany - Registergericht/Commercial register: Saarbrücken HRB 19681
http://www.softwareag.com


Re: Dynamic service references ?

Posted by Simon Nash <na...@apache.org>.
Jon Giddy wrote:
> On 16/11/11 13:29, Simon Nash wrote:
>> Millies, Sebastian wrote:
>>>
>>>
>>> can references in composite files somehow be made dynamic? In 
>>> particular, can I define or override
>>>
>>> the endpoints in a web service reference at run time?
>>>
>>>
>>>
>>> I understand (correctly, I hope, I have not tested this) that I can 
>>> override whatever endpoint is specified in the wsdl by
>>>
>>> specifying the uri attribute on the web service binding.
> I don't think this works, as the Uri has been read during startup before 
> you get a chance to modify it.
>>>
>>>
>>> Is there a way to define Tuscany web service references with dynamic 
>>> endpoints? Or alternatively, could I perhaps use the endpointProperties
>>>
>>> and modify the injected service proxy before making a remote call? Or 
>>> is  there some entirely different route that does not involve steps 
>>> a) to f) above?
>>>
>>>
>>>
>>> How would you deal with this type of situation?
>>>
>>>
>>>
>>
>> It might be possible to use service references for this.  A service
>> reference can be serialized/deserialized to/from XML.  So you could
>> use runtime code to create the XML-equivalent form of the service
>> reference that you need, then deserialize the XML to create the
>> service reference.
> 
> We tried something like this, but failed to get it to work fully.
> 
> We have a client that needs to talk to multiple identical services, and 
> got it working successfully using multiplicity references. However, this 
> is a static solution where the client knows all the services it will use 
> at startup.
> 
> We then tried a solution where, as each service starts up, it creates a 
> ServiceReference to itself, marshals that into Base64, and calls an 
> endpoint on the client, passing in its ServiceReference, which is stored 
> in an internal directory (basically a HashMap). The client is then able 
> to retrieve the endpoints from its internal directory and use them.
> 
> However, a service registering with a client is a little bizarre. We 
> really wanted the service to register its ServiceReference with a 
> directory service, and for the client to retrieve the 
> ServiceReference(s) from the directory service. That is, replace the 
> internal HashMap with an external service. This would be the classic 
> Publish-Find-Bind model of Service Oriented Architecture.
> 
> However, we couldn't get it to work. The client can get the Base64 
> encoded ServiceReference, and perform the same actions as before, but we 
> get a NullPointerException when attempting to use the reference.
> 
> It would be great to know if anyone else succeeds at this, as we feel so 
> close to achieving dynamic binding in Tuscany,...and yet so far.
> 
> Jon.
> 
> 
> 
I think it's unlikely that this could work with Base64 serialization.
This would presumably be a Base64 representation of the Java-serialized
form of the server's ServiceReferenceImpl object.  Deserializing this
on the client machine isn't likely to be successful.

I think the first approach is working because Tuscany recognizes service
references as arguments to service invocations and does special magic
(actually serializes them to XML) when passing them on the wire.
So I'd guess that the Tuscany server is converting Base64 to a
server-side service reference object, and is then converting this object
to XML for passing on the wire to the client.  The Tuscany client
deserializes this XML to a working client-side service reference.

So I think the only approach that hsa a chance of working would be
to store the XML form in the directory and have the client retrieve
this XML form from the directory and deserialize it.

As to the magic formula for doing this....I'll try some experiments,
but I'm very busy with another project right now so it's likely to
be a few days before I have any news.

   Simon


Re: Dynamic service references ?

Posted by Jon Giddy <jo...@gmail.com>.
On 16/11/11 13:29, Simon Nash wrote:
> Millies, Sebastian wrote:
>>
>>
>> can references in composite files somehow be made dynamic? In 
>> particular, can I define or override
>>
>> the endpoints in a web service reference at run time?
>>
>>
>>
>> I understand (correctly, I hope, I have not tested this) that I can 
>> override whatever endpoint is specified in the wsdl by
>>
>> specifying the uri attribute on the web service binding.
I don't think this works, as the Uri has been read during startup before 
you get a chance to modify it.
>>
>>
>> Is there a way to define Tuscany web service references with dynamic 
>> endpoints? Or alternatively, could I perhaps use the endpointProperties
>>
>> and modify the injected service proxy before making a remote call? Or 
>> is  there some entirely different route that does not involve steps 
>> a) to f) above?
>>
>>
>>
>> How would you deal with this type of situation?
>>
>>
>>
>
> It might be possible to use service references for this.  A service
> reference can be serialized/deserialized to/from XML.  So you could
> use runtime code to create the XML-equivalent form of the service
> reference that you need, then deserialize the XML to create the
> service reference.

We tried something like this, but failed to get it to work fully.

We have a client that needs to talk to multiple identical services, and 
got it working successfully using multiplicity references. However, this 
is a static solution where the client knows all the services it will use 
at startup.

We then tried a solution where, as each service starts up, it creates a 
ServiceReference to itself, marshals that into Base64, and calls an 
endpoint on the client, passing in its ServiceReference, which is stored 
in an internal directory (basically a HashMap). The client is then able 
to retrieve the endpoints from its internal directory and use them.

However, a service registering with a client is a little bizarre. We 
really wanted the service to register its ServiceReference with a 
directory service, and for the client to retrieve the 
ServiceReference(s) from the directory service. That is, replace the 
internal HashMap with an external service. This would be the classic 
Publish-Find-Bind model of Service Oriented Architecture.

However, we couldn't get it to work. The client can get the Base64 
encoded ServiceReference, and perform the same actions as before, but we 
get a NullPointerException when attempting to use the reference.

It would be great to know if anyone else succeeds at this, as we feel so 
close to achieving dynamic binding in Tuscany,...and yet so far.

Jon.


Re: Dynamic service references ?

Posted by Simon Nash <na...@apache.org>.
Millies, Sebastian wrote:
> Hello there,
> 
>  
> 
> can references in composite files somehow be made dynamic? In 
> particular, can I define or override
> 
> the endpoints in a web service reference at run time?
> 
>  
> 
> My question pertains to Tuscany 1.6.
> 
>  
> 
> Let me go into some detail to explain the real problem I want to solve. 
> I have a set of items that need
> 
> to be sent to SAP backend systems. These SAP systems expose the same 
> interface (remote function
> 
> modules and web services). Every item has an endpointProperties 
> attribute that determines which
> 
> system it needs to go to.
> 
>  
> 
> Currently, this is done outside of Tuscany: The connection is created on 
> the fly using SAP Java Connector
> 
> (JCo) exploiting the endpointProperties. A remote call is made through 
> this connection using SAP’s proprietary
> 
> RFC protocol.
> 
>  
> 
> I’d like to change this to a service-based setup with Tuscany, 
> exploiting SAP web services. The motivation for this
> 
> is twofold: First it removes  a dependency on proprietary technology 
> (including native code), second it opens up
> 
> the possibility to connect in a generic way to non-SAP systems that 
> offer compatible interfaces .
> 
>  
> 
> So on my side (the Tuscany SAP client side) I go through the usual steps:
> 
> a)      expose function module as a web service
> 
> b)      get the wsdl
> 
> c)       use wsimport to create a service interface from the wsdl
> 
> d)      remove JAX-WS annotations, make interface remotable, and ensure 
> method names are identical to operation names in wsdl
> 
> e)      add an attribute of the interface type to my service 
> implementation and annotate it with @Reference
> 
> f)       define the reference to the SAP service in my composite file
> 
>  
> 
> I understand (correctly, I hope, I have not tested this) that I can 
> override whatever endpoint is specified in the wsdl by
> 
> specifying the uri attribute on the web service binding. Here’s a 
> snippet from an example composite file:
> 
>  
> 
>   <sca:reference name=/"bapiCostcenterGetList"/ 
> promote=/"servercomponent/bapiCostcenterGetList"/>
> 
>        <sca:interface.java interface=/"bapi.ZWSBAPICOSTCENTERGETLIST"//>
> 
>        <!--  
> wsdlElement="<TargetNamespace>#wsdl.port(<SvcName>/<PortName>)" -->
> 
>        <sca:binding.ws 
> wsdlElement=/"urn:sap-com:document:sap:rfc:functions#wsdl.port(ZWS_BAPI_COSTCENTER_GETLISTService/ZWS_BAPI_COSTCENTER_GETLIST)"/
> 
>        <!--  Override service endpoint -->
> 
>        
> uri=/"http://sapd01.me.corp.ids-scheer.com:8000/sap/bc/srt/rfc/sap/zws_bapi_costcenter_getlist/100/zws_bapi_costcenter_getlist/zws_bapi_costcenter_getlist"/ 
> />
> 
>     </sca:reference>
> 
>  
> 
> As compared to the dynamic approach with hard-coded RFC calls, the 
> connection endpoint is now hard-wired in the composite file.
> 
> Is there a way to define Tuscany web service references with dynamic 
> endpoints? Or alternatively, could I perhaps use the endpointProperties
> 
> and modify the injected service proxy before making a remote call? Or 
> is  there some entirely different route that does not involve steps a) 
> to f) above?
> 
>  
> 
> How would you deal with this type of situation?
> 
>  
> 
> n  Sebastian
> 
> IDS Scheer Consulting GmbH
> Geschäftsführer/Managing Directors: Kamyar Niroumand, Ivo Totev
> Sitz/Registered office: Altenkesseler Straße 17, 66115 Saarbrücken, 
> Germany - Registergericht/Commercial register: Saarbrücken HRB 19681
> *http://www.softwareag.com*
> 
 >
It might be possible to use service references for this.  A service
reference can be serialized/deserialized to/from XML.  So you could
use runtime code to create the XML-equivalent form of the service
reference that you need, then deserialize the XML to create the
service reference.

Another option is to create a node using a dynamically constructed
in-memory composite file.  There's a 1.x API for doing this but
I don't recall the exact details at present.

   Simon