Wednesday, June 27, 2007

Rails + SOAP4R != Fun

The next step of this project (now that I have figured out how to bind to the WSDL) is to put up a test service implementation of the WSDL and then validate it using either a SOAP 1.2 message validator, or barring that, a test client that a colleague is developing in .NET.

Consuming web services through rails is easy.

I'm learning that serving anything through rails is hard.

I may be able to use ActionWebService (I've heard from some that this uses soap4r behind the scenes), but my guess is not. So, next up is to figure out how to bind the soap4r servant stub to Rails - possibly through the native rest interface. SOAP operates over HTTP using the POST method, so if I can find a way to trigger the SOAP4R servant stub and pass it the input, and trap/send the output, this may work. Possibly through routes.rb.

Two Steps Back, Three Steps Forward

Alrighty, well I had a change of plans. After thinking about this for a while and doing some research, the wsdl2ruby tool finally generates some code. I ended up changing the WSDL in a couple of places to get it to generate code successfully:
  1. Changed xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" namespace decleration to xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
  2. Changed corresponding 'soap12:' tags to 'soap:'
So here's the updated WSDL. Aside from the SOAP12 changes, I had to add back in some fault messages that I'd removed in error, ooops. Turns out that was generating a lot of the errors.

Now it is clear that we aren't doing much in the WSDL that isn't supported by SOAP4r - or at least enough to generate the WSDL. So, the real questions is: how much has the functional SOAP layer changed, and how much of a pain is it going to be to alter the existing soap4r code to add these things? At this point, I'm not too worried about making this packageable, or fully implementing the spec: just what I would need to add in order for MTOM to work and allow me to bind to our .NET node running the WSDL.

One outstanding question: will the standalone server allow more than one operation in the portType def?

Tuesday, June 26, 2007

Diving Deeper

I've been diving into the SOAP4R code a little to get a lay of the land and figure out where any MTOM hooks would be possible. BTW, if you haven't checked out the ruby-debug gem, I highly recommend it. Here's a short screencast on basic useage (if you are familiar with gdb, then this is cake).

After running through the code a few times with the debugger, I have a basic sense as to what the wsdl2ruby.rb file is doing (and where it's generating errors). I've been using this document/literal WSDL which includes the SOAP12 schema (just to try out). Given that SOAP4R doesn't have support for SOAP1.2, I didn't really expect this to work - and it doesn't. Keeps bombing out when it is building the definitions:
ignored element: {http://schemas.xmlsoap.org/wsdl/soap12/}binding
ignored element: {http://schemas.xmlsoap.org/wsdl/soap12/}operation
ignored element: {http://schemas.xmlsoap.org/wsdl/soap12/}body
ignored element: {http://schemas.xmlsoap.org/wsdl/soap12/}fault
ignored element: {http://schemas.xmlsoap.org/wsdl/soap12/}address
Also, wsdl2ruby doesn't seem to like it when the service and definition elements are named the same: it is using the names of the elements to name the files, and runs into a collision when it creates the 'service' library because the definitions library (of the same name) has already been created. I'd be curious if there is anything in the WS-I profile (or WSDL spec for that matter) that prohibits naming the defs and service the same.

The other interesting tidbit is that if I replace the SOAP12 namespace to SOAP and rename the definitions element so that it does not conflict, wsdl2ruby binds fine and generates all the correct code without errors! So, I'm at least working with a WSDL that is bindable, aside from some minor details. However, I would like to keep the SOAP12 refs in there, as MTOM is technically only supported by SOAP12 (although I don't know of any technical issue in the MTOM/XOP spec that would preclude using it with SOAP11).

So, here's my overview of the WSDL2ruby.rb file (the version in lib\ruby\1.8\wsdl\soap, rather than the wrapper version included in the soap4r distribution. I'm running soap4r 1.5.6.

This file does two main things: 1) parses the WSDL using the XSD::XMLparser engine and, 2) dumps the class definitions, type mappings, and client/server stub code (including the driver and servant) into files. The WSDL parsing is the interesting part, and where it keeps barfing. Specifically, when trying to import the 'binding' element, it compares the imported element name with the the DefinitionsName variable and throws an unknown element error (line 115 of lib/ruby/1.8/wsdl/parser.rb). The value of DefinitionsName is 'definitions' which is obviously not 'binding'. Next up is figuring out where DefinitionsName comes from, or is defined, and what it means.

Monday, June 25, 2007

Kickoff

Welcome all! This blog will document my efforts to create/extend MTOM (Message Transmission and Optimization Mechanism) functionality in Ruby (mainly through the SOAP4R library). MTOM was added as a W3C recommendation with SOAP 1.2 back almost a year ago and was created to allow for inline attachment of payloads in a SOAP message, without having to hack the stack with DIME or SwA. MTOM (and the optimization component XOP) are pretty cool, as the user at either end sees only a unified infoset, with binary represented by the xsd:base64encoded type. There are no hooks, one simply has stick the binary data in a base64encoded element and MTOM/XOP takes over the rest. Currently, MTOM is implemented in .NET 2 and Xfire, thought I haven't explored any other toolkits, so it may be elsewhere too.

This blog will document my progress, and hopefully provide some needed assistance to people who are stuck down the black hole called ruby SOAP support.