The World’s Leading Microsoft .NET Magazine
   
 
The .NET Addict's Blog

My Top Tags

                                                           

My RSS Feeds








I heart FeedBurner

Latest Diggs - Programming

Computers Blogs - Blog Top Sites

Site Hits

Total: 4,891,931
since: 19 Jan 2005

Consuming a WSDL Web Service From Cocoa - Failed Attempt #1

posted Fri 27 Jun 08

I've said it many times before and I'll continue to say it - I hate WSDL. I've never liked the standard and I've always thought it was overly complex. I don't like the idea of adding layers of complexity that introduce friction in the development process when there are easier, simpler ways of accomplishing the same task.

Don't get me wrong, there are a lot of people who have a valid need for all of those WS-* standards and once you get into that kind of complexity then yes, stuff like WSDL seems like a necessary evil. But when all I want to do is have a web server hock up some data that my client application can display for the user and allow them to interact with it, it seems like needless bloat to me.

So anyway, first thing I tried to do was create a stub Objective-C class that wraps around my web service. I was actually pretty surprised to find that there is a tool that lets you do this, it's called WSMakeStubs and you run it from the command line (reminds me of the old days of dropping down and firing up soapsuds from the command line in .NET 1.0). And yes, for those of you unfamiliar with .NET, there really was a SOAP dissection tool called soapsuds.

Here's the command line that I issued from inside terminal:
WSMakeStubs -x ObjC -name SampleService -url http://mybox/webservice1/service1.asmx?wsdl

This gave me a class called SampleService that derived from another class that contained all of the plumbing code to communicate with the web service.

Great!, I think to myself. I'll just add these bad boys to my Xcode project and then rig up a controller, set up some bindings in IB and we'll be good to go. No dice.

When I added the class files to the project, and made sure I had the WebservicesCore framework available to my project and I attempted to build - I got 10 errors and 6 warnings. So I took a quick look. My web service has two methods, "HelloWorld" and "GetPeople", returning a string and an array of strings respectively. First thing I notice is that the generated class header had defined interfaces for each method, twice. Then I noticed that it implemented each of those classes twice.

Then I found a page on Wikibooks that tells me that there are memory leaks in the generated web services stub code, so I follow some of that, but unfortunately some of the code it says I'm supposed to replace doesn't exist in my generated code.

Now that my code is finally compiling I have a class called Service1Service and it has static methods on it, one of them is called GetPeople, so I figure I can do the following (given that there are no arguments to my GetPeople method):

id result = [Service1Service GetPeople:NULL]; 

But nope. This doesn't work, some kind of complaint about a dictionary getting a nil item inserted into it at runtime prevents anything from happening. So I figure I'll check the Apple documentation ... but the web services core documentation doesn't actually show you HOW to use classes generated by WSMakeStubs.

Knowing how good Apple is with samples, I take a look at their sample code. Sure enough, in /Developer/Examples/WebServices/XmethodsInspector, the README.txt there informs me that this is an example of how to use code generated by WSMakeStubs in Cocoa... problem is, the sample doesn't actually contain generated code from WSMakeStubs, and there are no instructions on what the command line should be for generating the stubs. Obviously when you attempt to build this sample, it fails miserably.

So I decide to look at the code. Turns out, in this sample, when you want to execute a method on the service with no params, you just invoke the method name without any parameters. When I attempt to do that, I end up with the expected warning about Service1Service not being able to respond to a method called 'GetPeople'.

So at this point I'm left with absolutely zero documentation from Apple on how to use code generated by WSMakeStubs, no mention from them as to why the generator failed and created 2 copies of each (though I suspect this is because the host WS is publishing both regular GET and SOAP methods with the same name). The sample for WSMakeStubs is missing the stubs(!!!) and won't compile, and all the public information I can find about WSMakeStubs refers to bugs in the generated code, not actual samples for invoking it.

Conclusion: Come on people, this is web services. This crap is completely ubiquitous and Microsoft tools have been able to right-click and "Add Web Service Reference" for years now, and it's a ridiculously smooth experience. The WSMakeStubs tool is still version 0.2 and hasn't been updated or modified once since it was originally released back in the good old days. I realize that WSDL sucks, but some people actually need to do it, and making it this much of a pain in the ass to do it from Cocoa doesn't make me want to write Mac-based web service clients.

links: digg this    del.icio.us    technorati    reddit

AddThis Social Bookmark Button




1. Kevin Hoffman left...
Fri 27 Jun 08 8:30 am

Before you Cocoa people flame me for this, I realize that there is probably some 30-line set of code you can call on WSGeneratedObj to invoke the web service... but I am coming at this from the point of view of a .NET developer with years of Web Service development. When I use a tool to generate web service stubs on it, I fully expect that it will have methods that correspond to server-side methods that I can invoke quickly and easily without any hassle, and certainly without referring to SOAP anywhere in my invocation.


2. Simon Fell left...
Fri 27 Jun 08 10:09 am :: http://www.pocketsoap.com/weblog/

The WS support in cocoa is based on circa 2001 rpc/encoded soap, even if you got your stub working, chances are its not going to work with the web service anyway, between the bugs and lack of features (missing parts of the http headers, numerous options in the WS classes don't do anything etc) its not worth the hassle. Fortunately, there's a reasonable xml parser and HTTP stack, so its fairly easy to just whip up your own stub. (this is what i ended up doing). I think this underscores Apple's disinterest in the enterprise market.


3. Kevin Hoffman left...
Fri 27 Jun 08 10:12 am

That's complete crap. Desktop applications are spending more and more time consuming services from the Internet, including web services and the overused buzzphrase of "Cloud services". I can't believe that Apple would completely drop the ball and leave developers in the lurch when it comes to web services when they provide so many other ridiculously powerful APIs.


4. Kevin Hoffman left...
Fri 27 Jun 08 10:15 am

What about generating a client-side WSDL proxy in Mono/C# and then doing some kind of Cocoa-mono bridge to invoke it? Is such a thing even possible? I would love to see an example of this if someone knows where I could find it.


5. Rob left...
Fri 27 Jun 08 10:30 am

Ever consider REST? I don't know what kind of support there is in ObjC/Cocoa, but it might be a simpler way to go...

http://www.25hoursaday.com/weblog/2007/11/15/WSIsToRESTAsTheoryIsToPractice .aspx


6. Kevin Hoffman left...
Fri 27 Jun 08 10:32 am

Of course I've considered REST, and I know that it's really easy to bust out a RESTful POX client in Cocoa using just NSUrl and the XML parsing classes... But that's not the point. The point is that the rest of the world may not be as forward-thinking as those of us who actually create RESTful services. There is a lot of legacy code and even new code in WSDL out there and Apple seems to be unsupportive of people who want to access WSDL services.


7. Kevin Hoffman left...
Fri 27 Jun 08 11:14 am

I found some documentation that shows how you can use the ObjCsharp bridge in the mono framework to invoke .NET methods through mono, but in typical OSS fashion, they show you a couple lines of code and expect you to be a contributor so you know exactly how to integrate the ObjCsharp stuff into your Cocoa app. If anybody knows how to do this, I would love it if you could drop me a hint!


8. JulesLt left...
Fri 27 Jun 08 1:45 pm

I'm guessing that Apple's efforts around WS-* have largely been concentrated on WebObjects, but even so that's more about producing than consuming.

I also guess that the amount of enterprise Cocoa development is extremely low - most shops with a mix of Macs and Windows machines would go Java or web-client for internal enterprise apps.

But you're right - it's amazing they haven't sorted this, particularly with the iPhone (which is much more about having Cocoa clients to web servers).


9. Kevin Hoffman left...
Fri 27 Jun 08 1:55 pm

Exactly. One can assume without knowing anything about the iPhone SDK that if the experience of consuming WSDL services from Cocoa on Leopard is a huge pain in the ass, it's going to be even worse on the iPhone due to it being a subset of Leopard.


10. James Gregurich left...
Fri 27 Jun 08 5:44 pm

a lead you can explore:

http://blog.phanfare.com/2005/10/web-service-integration-mac-vs-pc/

-James


11. Chris Hanson left...
Sat 28 Jun 08 4:19 pm :: http://chanson.livejournal.com/

WSMakeStubs hasn't entirely been left alone; one sign of that is illustrated by the difference between what it generated and what that Wikibook showed. Also, since WebServicesCore is part of the CoreServices umbrella framework that's what you should link, not WebServicesCore.

That said, I'd probably also look to other frameworks if I were trying to write something using SOAP web services for Mac OS X. WebServicesCore has never had anywhere near the feature set available in other environments - like .NET or Java - and as Simon points out its view of the world may not coincide with your service's.

Finally, as always, if you run into bugs or if there are things you want improved or implemented in Mac OS X or the developer tools, file a bug at http://bugreport.apple.com/.


12. Chris Hanson left...
Sat 28 Jun 08 4:25 pm :: http://chanson.livejournal.com/

The WSMakeStubs tool hasn't entirely been left alone; one sign of that is illustrated by the difference between what it generated and what that Wikibook showed. Also, since WebServicesCore is part of the CoreServices.framework umbrella framework that's what you should link, not WebServicesCore.framework itself.

That said, I'd probably also look to other frameworks if I were trying to write something using SOAP web services for Mac OS X. WebServicesCore has never had anywhere near the feature set available in other environments - like .NET or Java - and as Simon points out its view of the world may not coincide with your service's.

Finally, as always, if you run into bugs or if there are things you want improved or implemented in Mac OS X or the developer tools, file a bug at [http://bugreport.apple.com/].


13. Johan Strandler left...
Sun 29 Jun 08 12:58 am

Thanks Kevin for lifting this subject. I have spent years wondering of the lack of connection between Apple/Cocoa/WebServices. The result: I dropped Cococa developemt altogehter. However, with the iPhone, this lack of WSDL tooling is becoming a pain in the ass.

A big thing is that a very credible and known Cocoa developer with a history in other environments (this is you Kevin) speaks up, I hope this makes some impact on Apple. I agree with you that WSDL is appaling in many ways, but as you say: I't is the thing used out there. To me, the very point of making a Coccoa client based on web services is that you want to do a wonderful client application based on services other has made out there.

One thing that puzzles me is the lack of reaction in the ObjC community during these years. I come from the Java world, and the normal case there is that some "pissed off" developer would make a high quality open source framework for the lacking features. Eventually, if the OS project provides true developer value and becomes popular, the framework would end upp in the official Java stack through the Java community process. Seems that there are different cultures in the Cocoa/ObjC world than Java. Perhaps I should have done it myself, but I'm lazy I guess. :-)


14. Kevin Hoffman left...
Mon 30 Jun 08 7:38 am

Chris, as you yourself said, Cocoa's support for WSDL-based web services is substantially less than that of .NET... When new developers from the .NET world start looking at Cocoa and they come across and see that the native WSDL support is lacking... as someone already mentioned, they might be inclined to just give up.


15. James Gregurich left...
Mon 30 Jun 08 11:18 am

As I have said in the past, mac development is mostly desktop-centric. No one has really cared so far about consuming web services on a mac because they aren't being used heavily in enterprises. However, the landscape is definitely changing and web service stuff appears to be coming out of the IT closet.

I suppose the result will be either Apple or some 3rd party will do a web service framework eventually.


16. pmont left...
Tue 08 Jul 08 5:27 pm

http://forums.macrumors.com/showthread.php?t=509880

You may want to read this guys journey into web services on the mac


17. Leslie left...
Sun 14 Sep 08 6:44 pm

Well, here is some code for using WSDL from COCOA:

- (void)loginToWSDLService { doLogin *mLogin = [[doLogin alloc] init]; ; ; ; }

- (void) invocationCompleted:(doLogin*) invocation { NSLog(@"result %@",); }

//OK, 'doLogin' is a category generated for me by WSMakeStubs. Using WSDL from objective-C/COCOA is really simple but lack of documentation is source of frustration.


18. Kevin Hoffman left...
Sun 14 Sep 08 7:06 pm

I haven't yet had WSMakeStubs work. Every single WSDL service I've attempted it on has resulted in a set of ObjC code that doesn't even compile, let alone work at runtime.


Tag Related Posts