PDA

View Full Version : client-side proxy


smhinsey
12-27-2005, 04:14 PM
I'm a little confused about whether or not there is any advantage in using the client-side proxy support over using Resharper to extract an interface from the Web Reference/wsdl.exe generated class and using standard DI to swap out the implementation. Can someone who's more familiar with what's going on clue me in a little? I feel like I am missing something obvious.

I should add that it is my goal to avoid sharing a common service contract/interface definition assembly between the client and the server, so that colors my take on the issue.

Aleks Seovic
12-27-2005, 07:34 PM
If you are talking about current implementation of WebServiceProxyFactory, the only difference is that it allows you to regenerate your proxy class from VS.NET and not have to remember to add interface implementation to it. Other than that, you are right -- it does pretty much the same thing.

However, I need to put things in a perspective by saying that this is not our long-term goal. Bruno Baia is currently working on the web service proxy implementation that simply takes a local service interface and a web service URL and generates a full-blown client-side web service proxy based on those two things, without the need to generate proxy class using wsdl.exe or VS.NET first.

We will also add the ability to specify whether you want Spring to generate basic or WSE-enabled web service proxy, as well as a number of out-of-the-box aspects that will allow you to transparently add things such as encryption and digital signatures both on the client and the server when using WSE.

Our goal is the same as yours -- to avoid sharing of common service contract definition assembly, because in most cases where you would use web services you probably won't control both ends of the pipe. However, there is also an overarching goal of treating client-side service interface as a central piece that enables service location transparency. As long as the client always talks to a well-defined service interface, we can easily swap service implementation using DI, by providing either dynamically generated proxy, or in more complex cases by allowing you to plug in a custom adapter implementation. Thus, one of the primary goals of the current web service proxy implementation was to encourage users to decouple their clients from the different types of remote services by allowing them to code against interfaces regardless of the underlying remoting technology (and we do support quite a few at this point: .NET Remoting, Web Services, COM+ components, and even Java RMI objects and EJBs via IIOP.NET integration. If you want to see an example, take a look at ServiceClient and related projects in src/POC directory).

So, to answer your question, as long as you code your clients against well-defined service interfaces and treat those interfaces as primary development artifacts and not something that is simply generated by ReSharper when needed, there is no particular reason why you should use existing web service proxy factory. However, there is also no good reason not to use it -- it will allow you to do the same thing without having to remember to declare interface implementation on a VS.NET/WSDL.exe-generated proxy class if you ever regenerate it. It will also make the upgrade path much easier, and I do believe that we will provide enough reasons for its use in the coming months as we complete the work that we started.

Regards,

Aleks

smhinsey
12-27-2005, 07:53 PM
I am a little uncomfortable with having an implementor of a service contract rely on duck typing at runtime to ensure compliance with the contract. Can you talk more about why this is beneficial? It seems like the goal should be for the service contract to be explicitly agreed to by implementors, rather than having an implicit agreement.

I am interested to see how Bruno's work progresses in this area. I think it's part of .NET that's pretty sorely underrepresented in terms of advancement and design.

My understanding of this is that you'd like service contracts to exist in a larger context than as they are defined by WSDL. This seems to relate closely with the WCF model. Is there meaningful intersection there?

Aleks Seovic
12-27-2005, 09:26 PM
I'm not quite sure what makes you uncomfortable, if you could explain it in more detail I'll do my best to respond.

As for the service contract, I do believe that it should exist in the larger context than any particular service implementation technology, and from that point of view WSDL is nothing more than a web services-specific contract definition.

In my opinion, real contract on the client side should be defined as an interface by the client-side developer, based on their needs. If that contract is a direct subset of the contract exposed by the actual service, great -- we will be able to implement a proxy class that hides the details of the underlying service implementation technology completely transparently. If it's not, than it is the client application developer's responsibility to implement an adapter for the service in order to enforce the contract.

In the first case, application is completely decoupled from the service implementation and in the second case the adapter is tightly coupled to the service but client application is still decoupled from the adapter by the service interface.

Is there an overlap between our model and WCF? I don't think so. I think WCF will fit nicely within our model, between client-side business interface and server-side service implementation, just like ASP.NET web services, .NET Remoting, COM+ components and Java Remoting/EJB fit within it right now. For example, we will be able to export any object on the server as an Indigo/WCF service by creating a dynamic delegating proxy for it and adding necessary attributes to proxy methods, as defined in the Spring config file. On the client side, we might not need the proxy factory, but if we do we will implement one in order to preserve the semantics of the current model.

Looking at it from that angle, adopting our programming model now might be the easiest way to migrate to WCF in the future by simply modifying exporter definitions on the server and proxy factory definitions on the client.

Hope this clarifies things further,

Aleks

smhinsey
12-27-2005, 09:43 PM
As an example, let's say I have a couple of web services that I want to consume to check the status of an order in our SAP ERP system. I find out the URL for their WSDL and use Visual Studio's Web References to create local proxies. I then extract an interface from the proxy, removing all of the web service specific methods and properties, and apply that interface both to the proxy and to a local mock object that acts as a stand in for the real service proxy for the purposes of test and development. I can swap between the service mock object and the service proxy object using standard DI. I think we're pretty clear on that scenario.

In general what makes me uncomfortable is the notion of the client owning a sub- or super- set of the contract. I can't really make up my mind about whether or not that is a bad thing, but it makes me nervous. Could you give me an example of a service that you might only want to implement a subset of? I'm wondering if we're both taking two different approaches to this.

I think the disconnect here is that I'm not thinking about services in a compositional way. When I think about a service contract, I think of it as something a service provider proposes as an absolute definition for how to interact with the service. You seem to be taking more of a "we'll implement the contract however we need to" approach. I think the key distinction here is that the former approach is oriented more towards an environment where there may be organizational boundaries, but business rules are the same, and the latter approach is aimed a world where services are completely tabula rasa when it comes to a provider's knowledge of a consumer's business logic or even intent.

Aleks Seovic
12-28-2005, 12:54 AM
I don't really see the difference between the approaches -- as long as you have an interface on the client side, it doesn't really matter if it was coded by hand or extracted by ReSharper.

I guess what you are nervous about is that there is no way to determine if your interface matches proxy class at compile time, but I don't see that as a big problem. In the case of proxy factory, if interface and proxy class do not match, an exception will be thrown during context initialization, so it's an easy problem to catch. Also, once we finish proxy factory that generates proxy based on the interface they will always be in sync by definition.

Bottom line is that client-side proxy generated by WSDL or VS.NET has only infrastructure-related code in it and as such it can easily be generated by the framework based on the business interface and/or WSDL.

Now, when would be useful to proxy only subset of the service? The short and obvious answer is whenever you only need a subset of the operations exported by the service. To use your example, if your application only cares about CheckOrderStatus operation of the OrderManager service, there is no reason why your client-side interface should contain PlaceOrder method, even though OrderManager service has both.

Second, less obvious example is when you want to break one all-encompassing, god-like service into multiple more specific services. Every once in a while I run into an existing service that tries to do too much by providing a facade to pretty much all of the backend functionality.

For example, let's say that you need to use a StoreManager web service that exports operations for customer management, order management and product management. It is probably a good idea to create ICustomerManager, IOrderManager and IProductManager interfaces in order to define contract for each specific service and to use dynamically generated proxies that forward all the calls to the same service endpoint.

From my point of view, service provider does specify an absolute contract on how to interact with its service. However, that does not mean that I as a client developer need to support the whole contract or that client shouldn't be as decoupled from the service as possible. For one, as you noted, decoupling the client from the service using an interface greatly simplifies testing. Secondly, I might decide to use a similar service from a different provider instead in the future and decoupling makes this much, much simpler.

What I expect will happen most often in these cases is that users will define initial client-side service interface based on the real service they want to use and will simply use proxy factory on the client to create a proxy. Later, if they decide to use different service, possibly from a different provider for whatever reason, they will probably need to implement an adapter for it and use the adapter instead of the proxy factory. This is also a scenario in which separating very coarse all-encompassing services into multiple finer grained services early on really pays off -- there is a much better chance that it will be possible to implement several finely grained adapters in the future if switching to a different service provider than to implement one big adapter.

Also, as you pointed out, I do tend to see service providers as completely oblivious to consumer's business logic and intent. They simply provide a service, and as long as the consumer invokes their services in a prescribed fashion they couldn't care less for what they are used for. This absolutely makes sense from a framework perspective and it would be dangerous and restrictive to assume anything. However, I do not think this has anything to do with how I think service consumers should be developed -- these are two completely separate topics.

Later,

Aleks

Bruno Baia
12-28-2005, 04:15 PM
Hi,

2 weeks ago, i added some samples of the new WebServiceProxyFactory in CVS :

U can find them here :
"Spring.Net / src / POC / WebServices"

Hope it can helps you.

Regards,
Bruno on vacations :)

smhinsey
12-28-2005, 07:04 PM
I think I am coming around to your point of view, Aleks. Thanks for the discussion.

smhinsey
12-28-2005, 07:09 PM
Bruno or Aleks,

For my case where I'd like to swap out a local mock implementation of the service proxy, would you suggest doing that by changing the value of ProxyClass on WebServiceProxyFactory, or some other way?

Thanks,
Shawn

Aleks Seovic
12-29-2005, 01:57 AM
No, you should simply inject your mock object during unit testing and proxy factory in production (or full integration testing) into you client class.

You would typically inject mock object directly, without using Spring, into a client class that you are testing:


MyClient client= new MyClient();
client.OrderManager = new MyMockOrderManager();

// do assertions


However, in a production environment you would use Spring DI to inject proxy factory for the OrderManager service into client:


<object id="client" type="MyClient, MyApp">
<property name="OrderManager" ref="orderManager"/>
</object>

<object id="orderManager" type="Spring.Web.Services.WebServiceProxyFactory, Spring.Services">
<property name="ServiceInterface" value="IOrderManager, MyApp"/>
<property name="ProxyClass" value="OrderManagerProxy, MyApp"/>
</object>


Keep in mind that above 'orderManager' definition will likely change to something like this when we finish new implementation that doesn't require WSDL.exe-generated proxy:


<object id="orderManager" type="Spring.Web.Services.WebServiceProxyFactory, Spring.Services">
<property name="ServiceInterface" value="IOrderManager, MyApp"/>
<property name="Uri" value="http://myserver/sap/OrderManager"/>
</object>


HTH,

Aleks

smhinsey
12-29-2005, 03:04 PM
Right, that's the approach I was taking, albeit without using the WebServiceProxyFactory.

I think this approach is much more compelling with the latter, URI based example.