Monday, October 19, 2009

Contract-First Web Services in practice - part 2 of 5

This is article is the second part of a five article series on a working example of SOA at work. In the last article I introduced the challenge, coming up with a fairly robust WSDL which could be implemented in multiple different programming languages consistently.

The service we are creating has one operation. The input for this sample operation takes an xml message with one element as well as an array of a nested object. The output returns an array of the same input objects (I had to redact the more meaningful input and output messages as they were work related). It initially seems complicated because I'm trying to capture all the complexities of xml structures and how the map to data structures that programmers in modern programming languages often take for granted. Ok, enough introduction, let's get onto the WSDL.

Click the expand source link and voila! That's the WSDL. Now to run you through the xml elements that constitute this WSDL.

Exceptions in SOAP are xml messages that can be defined in the schema. For this example, the exception is aptly named ServiceException, and it has an element named "message" which happens to be a string.

  1. <!-- Exception message, contains a string with the field message -->
  2. <xsd:complexType name="ServiceException">
  3. <xsd:sequence>
  4. <xsd:element name="message" nillable="true" type="xsd:string"/>
  5. </xsd:sequence>
  6. </xsd:complexType>
Arrays & Collections
There are several ways to represent arrays in XML. I've chosen for this sample, the simplest way which is to use the xml attribute "maxOccurs" and set it to "unbounded".
  1. <!-- A sample field with two elements, FieldName and FieldValue -->
  2. <xsd:complexType name="SampleField">
  3. <xsd:sequence>
  4. <xsd:element minOccurs="1" maxOccurs="1" name="FieldName" type="xsd:string"/>
  5. <xsd:element minOccurs="1" maxOccurs="1" name="FieldValue" type="xsd:string"/>
  6. </xsd:sequence>
  7. </xsd:complexType>
  8. <!-- An array of sample fields -->
  9. <xsd:complexType name="ArrayOfSampleField">
  10. <xsd:sequence>
  11. <xsd:element minOccurs="0" maxOccurs="unbounded" name="SampleField" nillable="true" type="tns:SampleField"/>
  12. </xsd:sequence>
  13. </xsd:complexType>
Declarative SOAP Exceptions
For this sample, soap exceptions are declared in the WSDL, this is in order to detect multiple exceptions. In this sample, we only have ServiceException, but could have included others, to programmatically detect which exception was thrown. This declaration is achieved by using the "fault" element. Note that the exception needs to be declared in both the binding and port type.
  1. <binding name="SampleServiceBinding" type="tns:SampleServicePortType">
  2. <soap:binding style="document" transport=""/>
  3. <operation name="SampleOperation">
  4. <soap:operation soapAction="urn://SampleService#SampleOperation"/>
  5. <input>
  6. <soap:body use="literal"/>
  7. </input>
  8. <output>
  9. <soap:body use="literal"/>
  10. </output>
  11. <fault name="ServiceException">
  12. <soap:fault name="ServiceException" use="literal"/>
  13. </fault>
  14. </operation>
  15. </binding>
That's it for the most part. In the next article, I'll be looking at the PHP implementation of this WSDL.

Wednesday, October 14, 2009

Contract-First Web Services in practice - part 1 of 5.

I've recently been working on a SaaS project where I'm integrating different ISVs (Independent Software Vendors) into a SaaS aggregation platform with a market place environment. Users come to the marketplace, purchase subscriptions to the ISVs' applications and realtime provisioning is expected. An exciting opportunity to test a SOA paradigm as SOAP web-services are a crucial medium of the SOA model and was the first solution to jump to my mind.

Once my approach was selected, my next task was to define a service specification that I would expect the ISVs to implement. This started out as a document with a list of methods and attributes encompassing the functionality I would expect the ISVs to expose. Once this was done, I needed to create a reference implementation in .NET, Java and PHP, and that's where the problems began.

My aim was to create a single WSDL which could easily be implemented in the 3 main programming languages so that only a single client is written. The main issues I had to address are summarized below:

  • Creating a consistent doc/literal format style WSDL
  • Working effectively with arrays in XSD schema
  • Working effectively with typed exceptions - what is the best way of creating Soap Faults?
  • JAX-WS, JAX-RPC, Axis, .NET ASMX, WCF, PHP-SOAP, NU-SOAP - just a snapshot of the different SOAP stacks in common use.
  • Contract-First SOA
I'll be detailing the challenges I faced in a series of 5 tutorials on how to create a non-trivial WSDL and implement it in the 3 programming languages.