An SOA odyssey

Tuesday, May 17, 2005

Service Contract

The second category of our Services Platform is Service Contract defined as "The request and (optional) response schemas for each operation exposed by a service, the security protocols, and the bindings associated with a service." Here we define "binding" as the combination of the transport protocol (e.g., HTTP, .NET remoting, MSMQ), the headers (WS-Security, WS-ReliableMessaging), and the encoding method (compressed binary, text, etc.). The W3C defines it as a concrete protocol and data format specification for a particular port type.

In looking at what was out there to define service contracts it should come as no surprise that we landed on Web Services Description Language (WSDL) 1.1. The rationale of course is that WSDL descriptions can be referenced by our service directory (UDDI), and the combination of WSDL and UDDI is expected to promote the use of Web services worldwide. When we made this decision version 2.0 was in draft status. However, the .NET Framework 1.1 generates WSDL documents compatible with WSDL 1.1 and we plan on using the generated documents as starting points for our WSDL contracts.

Of course, WSDL 1.1 defines only a SOAP/HTTP binding. In our architecture we also want to allow services to be invoked over MSMQ for reliability. As a result we needed to publish a WSDL extension schema we could use to add information that service consumers could use to invoke our services using MSMQ and receive responses.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace=
"http://schemas.compassion.org/common/wsdl/2005-04-14" elementFormDefault="qualified" attributeFormDefault="unqualified" id="CIWSDL">
<xs:element name="requestQueue">
<xs:complexType>
<xs:attribute name="location" type="xs:anyURI" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="responseQueue">
<xs:complexType>
<xs:attribute name="location" type="xs:anyURI" use="required"/>
</xs:complexType>
</xs:element>
</xs:schema>

As you can see this schema includes requestQueue and responseQueue elements that are to be used in the WSDL 1.1 port element to identify the MSMQ queues through which services can be invoked and responses received.

The following is an example WSDL document that uses the WSDL extension schema.

<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns="http://tempuri.org/"
xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
targetNamespace="http://tempuri.org/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:ca="http://schemas.compassion.com/common/wsdl/2005-04-14/">
<wsdl:types>
<s:schema elementFormDefault="qualified"
targetNamespace="http://tempuri.org/">
<s:element name="HelloWorld">
<s:complexType />
</s:element>
<s:element name="HelloWorldResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1"
name="HelloWorldResult" type="s:string" />
</s:sequence>
</s:complexType>
</s:element>
</s:schema>
</wsdl:types>
<wsdl:message name="HelloWorldSoapIn">
<wsdl:part name="parameters"
element="tns:HelloWorld" />
</wsdl:message>
<wsdl:message name="HelloWorldSoapOut">
<wsdl:part name="parameters"
element="tns:HelloWorldResponse" />
</wsdl:message>
<wsdl:portType name="Service1Soap">
<wsdl:operation name="HelloWorld">
<wsdl:input message="tns:HelloWorldSoapIn" />
<wsdl:output message="tns:HelloWorldSoapOut" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="Service1Soap"
type="tns:Service1Soap">
<soap:binding
transport=http://schemas.xmlsoap.org/soap/http
style="document" />
<wsdl:operation name="HelloWorld">
<soap:operation
soapAction=http://tempuri.org/HelloWorld
style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:binding name="Service1SoapMSMQ"
type="tns:Service1SoapMSMQ">
<soap:binding
transport=http://schemas.xmlsoap.org/soap/msmq
style="document" />
<wsdl:operation name="HelloWorld">
<soap:operation
soapAction="http://tempuri.org/HelloWorld"
style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="Service1">
<wsdl:port name="Service1Soap"
binding="tns:Service1Soap">
<soap:address
location="http://win2k3dev/ProcessCreditCard/Service1.asmx" />
</wsdl:port>
<wsdl:port name="Service1SoapMSMQ"
binding="tns:Service1SoapMSMQ">
<ci:requestQueue
location="urn:DIRECT=OS:compassion.com\RequestQ" />
<ci:responseQueue
location="urn:DIRECT=OS:compassion.com\ResponseQ" />

</wsdl:port>
</wsdl:service>
</wsdl:definitions>

Here the WSDL contract defines two ports. The first is a SOAP port that uses HTTP as the transport while the second is a SOAP port that uses MSMQ as the transport. The requestQueue and responseQueue elements are located inside the port.

It should be noted that the transport is defined in the binding element located within the Service1SoapMSMQ element. By convention, and utilizing section 3.3 of the SOAP 1.1 specification (http://www.w3.org/TR/wsdl), the transport attribute is set to http://schemas.xmlsoap.org/soap/msmq to denote to a service consumer that the binding uses MSMQ as a transport.

0 Comments:

Post a Comment

<< Home