PDA

View Full Version : WebServiceExporter and WebServiceProxyFactory


spmva
05-14-2005, 12:04 PM
I was extremely pleased to see the addition of web support with Spring. Having downloaded an interim build (Spring.Net-2005-5-10.zip) recently, I wanted to try working with some of the web services functions.

Thus far, I've been unable to get dependency injection (as described in the wiki) to work for my web services. I've also failed at client-side proxy generation.

I was just wondering if the WebServiceExporter and the WebServiceProxyFactory are working as described in the wiki (and I'm just doing something wrong) or if there are some differences between how the code works now and what is in the wiki.

Mark Pollack
05-15-2005, 07:15 AM
Hi,

I just fixed a small bug in WebServiceExporter that required you to specify the namespace property. This would result in an error along the lines of: [ArgumentNullException: Key cannot be null. Parameter name: key]. It could be you found some other issue. Can you post a minimal example of what you are doing? Send me a private message here and we can exchange files more easily if that is easier for you. I'll double check WebServiceProxyFactory/wiki docs usage in a little while.

Cheers,
Mark

spmva
05-15-2005, 01:18 PM
I noticed that namespace issue early on and simply added that value to get past that exception, but thanks for making that fix.

Currently, Spring seems to be able to get through the entire initialization process without error. My problems occur at run-time.

Speaking for the WebServiceExporter:

If I just do a simple test through my the Visual Studio IDE, my service is clearly visible. The methods I mark to be exported in my config file show up. I click on one of those methods and the page appears with the option to invoke the method given some parameters. I type in a parameter and get a "page cannot be displayed" page.

Running the same exposed method via a simple unit test, using NUnit also fails, with a somewhat more telling exception.

[nunit2] 2) Mip.Service.Admin.Impl.Test.TestUserService.Test_G etMe : Sys
tem.Web.Services.Protocols.SoapException : Server was unable to process request.
--> Specified cast is not valid.
[nunit2] at System.Web.Services.Protocols.SoapHttpClientProtoc ol.ReadRespo
nse(SoapClientMessage message, WebResponse response, Stream responseStream, Bool
ean asyncCall)
[nunit2] at System.Web.Services.Protocols.SoapHttpClientProtoc ol.Invoke(St
ring methodName, Object[] parameters)
[nunit2] at Mip.WebService.UserService.GetMe() in C:\work\source\MipServices\TestMipSoa\Web References\Mip.WebService\
Reference.cs:line 37
[nunit2] at Mip.Service.Admin.Impl.Test.TestUserService.Test_G etMe()
in c:\work\source\mipservices\testmipsoa\mip\serv
ice\admin\impl\test\testuserservice.cs:line 43

I get that same exception for all of my tests. The web service method GetMe() simply returns a string. I'm not sure why that can't cast properly.

In any case, here is a snippet from my web.config (the reference to "Admin.UserComponent" is defined elsewhere in the config file):
<object id="UserService" type="Mip.Service.Admin.Impl.UserService, Mip" abstract="true">
<property name="UserComponent">
<ref object="Admin.UserComponent"/>
</property>
</object>

<object id="UserServiceExporter" type="Spring.Web.Services.WebServiceExporter, Spring.Web">
<property name="TargetName"><value>UserService</value></property>
<property name="Namespace"><value>http://www.mycompany.com/mip/services</value></property>
<property name="Description"><value>Service for managing users.</value></property>
<property name="ExposeAllMethods"><value>false</value></property>
<property name="Methods">
<dictionary>
<entry key="FindById">
<object type="System.Web.Services.WebMethodAttribute, System.Web.Services">
<property name="Description">
<value>Finds a user by their unique identification.</value>
</property>
</object>
</entry>
<entry key="GetMe">
<object type="System.Web.Services.WebMethodAttribute, System.Web.Services">
<property name="Description">
<value>Finds a user by their unique identification.</value>
</property>
</object>
</entry>
</dictionary>
</property>
</object>


If I choose not to use the WebServiceExporter and add the [WebMethod] [WebService] attributes directly to the service class (as described in the wiki under, "Removing the need for .asmx files"), the tests run fine from within Visual Studio and in my unit tests. In that working case, my web.config file just looks like this:

<object name="EventService.webservice" type="Mip.Service.Event.Impl.EventService, Mip" abstract="true">
</object>

Please note that unlike the documentation in the wiki, it appears to be imperative that the service object name be suffixed with ".webservice". I guess the WebServiceExporter appends that suffix when it creates the web service. If you choose not to use the exporter and fail to append that suffix, the web service will not be found.

That makes the following example from the wiki somewhat misleading (again from "Removing the need for .asmx files" under item 2 "Create object definition for your web service"):

<object name="HelloWorldWebService" type="MyComany.MyApp.Services.HelloWorldService, MyAssembly" abstract="true"/>

I also noted possible problems if you change the configuration of the WebServiceHandlerFactory to attempt to use an extension other than .asmx. I'm not sure if it is expected behavior or not, but when I attempted to change the extension, the web services could no longer be found when testing through Visual Studio. Haven't tried through unit testing yet, but I suspect that the problem would be the same. The wiki seemed to indicate that you could change the extension to anything you wanted, but perhaps I misunderstood.

If the information I've provided here doesn't give you any insight, I'll follow up with some more background code.

Best Regards,

Steve

Mark Pollack
05-15-2005, 04:15 PM
Hi,

Thanks for such a detailed response. I noticed the .webservice doc issue as well and added it to the wiki as well. (hmmm now looking I don't see it there - seems like Aleks and I are overwriting each other on the wiki) I'll get back to you soon. Thanks again.

Cheers,
Mark

Mark Pollack
05-23-2005, 04:37 PM
Hi,

I've made a sample project along the lines of your listing and haven't reproduced the issue. I'll send you a private message on the forums here with my email - it would be great if you could send me some sample code to help out. (I realize a sample app on our part would also help bootstrap usage greatly...)

Cheers,
Mark

Aleks Seovic
05-24-2005, 02:14 AM
Just a quick note -- you cannot inject dependencies into web services unless you use the exporter to define them. Even though appending '.webservice' seems to work, it is an undocumented feature that won't support dependency injection.

Creation of the web service instance is performed deep within the .Net framework, and there is no hook that would allow us to inject dependencies after it's created. Exporter creates a proxy that solves this problem -- .Net creates instance of the proxy, and proxy creates and configures instance of the actual target service within its constructor.

If you don't need to inject any dependencies you can append '.webservice' to definition name and avoid having to create the exporter, but I would not recommend that.

Later,

Aleks

spmva
05-24-2005, 11:49 AM
thanks for the support. i have resolved my own issue. a dumb mistake on my part. had i posted the right part of my web.config, i'm sure the issue would have been spotted immediately. i was actually so excited about using the web service enhancements that i never really bothered to read the rest of the spring.web documentation (the earlier parts that is). as such, i defined this portion of my web.config as i always would:

<context type="Spring.Context.Support.XmlApplicationContext, Spring.Core">
<resource uri="config://spring/objects"/>
</context>

i never changed to:

<context type="Spring.Context.Support.WebApplicationContext, Spring.Web">
<resource uri="config://spring/objects"/>
</context>

i only realized it after working with some of your other spring web functions. perhaps you might amend the wiki page for web services to simply note that little change, so that jump ahead guys like me don't hit the same problem. then again, maybe we deserve what we get for not reading carefully <smiley_emoticon>.

in any case, i suppose that that change should fix my WebServiceProxyFactory issues as well.

Aleks Seovic
05-24-2005, 12:33 PM
Yeah, that would definitely cause problems as server side WS proxy generated by exporter relies on WebApplicationContext to retreive configured instance of the target service.

Glad the issue is resolved,

Aleks