Web Services research

Matts on 2001-08-24T10:25:45

My research into web services (dot net and Perl) is over, thank god. And here is the results.

It should be noted that the goal was to provide an interface over the web to our "API", which is implemented as a COM object. So some of this stuff won't be applicable to other web services type stuff.

First off, Perl.

SOAP::Lite rocks. It's really quite cool, and Paul Kulchenko is incredibly responsive to questions and bug fixes. It made exporting this COM object as a web service almost too trivial. Like about 15 lines of Perl. Incredible stuff Paul!

However the downside is that it's still quite hard to use that object in dot NET, due to it still being pretty hard to use SOAP in dot NET without a WSDL file. The same is true for Java SOAP stuff, FWIW. The reason being that those languages aren't dynamic. i.e. you can't compile something like object.method() in those languages and have it resolve method() at runtime. It has to be compile time. Equally all the parameters to method() have to be compile time type checked. Oh the joys of type safety. There are ways around it, such as using an Invoke("method", [parameters]) type call, but it is still very ugly to do that. Anyway, in conclusion, since SOAP::Lite doesn't create the WSDL file for us (though it will, with our plans for Attribute::WebService), we have to investigate alternatives for now.

One such alternative, for what it's worth, is to create the WSDL from my XML dump of the COM type library. That should be relatively simple. But I just haven't got it working. Yet.

Oh, and SOAP::Lite is also a bit slow, only managing 1 request per second against the object. Not sparkling.

Next up, dot NET...

C-Sharp is nice for people used to C++ or C and who don't know Java. For people who know Java, it is just Java with a different syntax. I love garbage collection. I think it's very important to have GC in a language. I wish we had GC in XS (actually this is possible if you bring in boehm, but it's rather large to ship with every XS module :-).

C-Sharp also has a fairly comprehensive set of classes shipped with it. They seem pretty decent, but no better than the Java counterparts (except that C-Sharp guis will be faster than Java Swing guis, though I can't help but wonder if they would be any faster than Visual J++ Win32 guis).

In theory web services in C-Sharp (and dot NET in general) should be pretty simple. And they are. There's some really nice things it does. For example, when you create a web service and compile+deploy it, you can go the the web page it creates with a browser, and you can view the WSDL for the web service, you can view information about each web service, it gives you example SOAP code you can use to call the service, and it even gives you a simple HTML form you can fill in to test the web service. Neato. It also creates the service as a simple HTTP/XML server, where you can send params in the querystring or in a POST body, and have it send back raw XML, rather than SOAP. I thought that was great, until I realised that of course this still breaks HTTP semantics. Often you will be doing what should be a PUT request against some resource, but with dot NET you'd be doing it over HTTP GET or POST. Nuts.

However... there's a problem. Our COM object obviously can't be serialised over the network, it has to be passed by reference. Now dot NET can do that, but only if you derive your object from MarshalByRefObject. If you don't do that, it tries to serialise it. Unfortunately dot NET creates the stub to access your COM object with a utility. Now if that utility created C-Sharp code it would be no problem to change the inheritance tree. Or if C-Sharp supported multiple inheritance it would be no problem. But no, it only supports multiple interface inheritance, like Java. And the utility creates bytecode directly, no c-sharp there. Harumph. Oh how I wish for open source tools!

There's a way around this though. You can create a COM object accessor class yourself, by hand. So I could have done that. But there's umpteen objects with a lot of methods there, and I didn't want to do all that typing and likely introduce errors.

So, I had a choice - create WSDL from the com object typelib for the SOAP::Lite version, or create C-Sharp from the com object typelib for the dot NET version.

There was also something irritating about all of this. Our COM object is starting to return all of its results back as XML, simply because all the results are rendered to HTML in ASP pages, and they're moving from iterating over recordsets in VBScript to using XSLT to style some XML. A much better model for them (although they're still using the old XSL working draft in MSXML2, not XSLT 1.0, much to my dismay). So, in serialising all of this over SOAP or plain XML, we'd be encoding XML in XML. i.e. we'd have to escape all those '<' characters as '&lt;' (I wonder how that will render here...[1]). It just seems stupid to have to do that, and only serves to increase bandwidth use.

Then I had a vision. I'd already given a talk about why SOAP sucks, so why not put that into action. And also it gave me an opportunity to put AxKit into work here...

So I created an AxKit provider module, which sent accesses to URLs to our COM object. The XML returned simply got returned via AxKit, and potentially styled by a stylesheet. We could even apply a "SOAPify" stylesheet to it to return the body as a SOAP response. Nice. And it performs damn well too. At least 3 times faster than the SOAP::Lite server (though that may be an unfair test, but who cares about fairness :-)

Anyway, I'll have to submit my writeup of this now, and see what happens. I hope they choose AxKit :-)

[1] Initially it rendered it as "... '' characters as '<'", so I had to fix it up using entities. pudge: that's not very "plain old text" :-)