Counterproposal for Service References in WSDL 2.0

Roberto Chinnici, Sun Microsystems, Inc.

October 31th, 2003


This document details our counterproposal for service references, thus discharging our action item dated 2003-09-23.

1. Overview

We identified three separate requirements around service references:

(R1)  Providing a normative, extensible, fully typed, WSDL-friendly notion of service reference.

(R2)  Providing a normative URL-based notion of service reference as a first-class complex type.

(R3)  Providing a facility to annotate arbitrary schema types with interface/binding information. Likely, this functionality would make most sense when applied to URI-derived types.

Section 2 below describes our solution to R1, involving the introduction of a new attribute and a small set of rules describing how to handle it in the context of the wsdl:Service type. Section 3 provides examples of how the newly introduced constructs can be used to address several use cases involving service references.

Section 4 describes one simple approach to identifying the WSDL document associated with a given WSDL construct when the latter is used in a standalone form (i.e. outside of a wsdl:definitions element). This section is independent from the others and can be refactored as a separate proposal.

Section 5 shows an example of how a type satisfying R2 could be defined along the lines of section 2. Section 6 contains samples of the newly introduced type, mirroring the contents of section 3.

Finally, section 7 shows how to define a couple of attributes that satisfy R3.

At this stage, we'd like to propose that the solution to R1 described in section 2 be adopted by the working group as normative, whereas those corresponding to R2 and R3 could be defined non-normatively as examples of how other specifications may build on WSDL 2.0.

2. Service references based on wsdl:Service

We propose to define a global attribute wsdlx:serviceReference of type xs:boolean (namespace "wsdlx" to be defined, but different from the wsdl namespace) as follows:

<xs:schema targetNamespace="http://www.w3.org/@@@@/@@/wsdlx"
           xmlns:tns="http://www.w3.org/@@@@/@@/wsdlx">
  <xs:attribute name="serviceReference" type="xs:boolean"/>
</xs:schema>

Then we propose adding the following rules to the spec:

NOTE - Here's the simple idea: any element information item whose type is a complex type ultimately derived from wsdl:Service and that carries an attribute information item wsdlx:serviceReference with a value of "true" must be treated as a service reference. It turns out that writing this in spec-ese is an exercise in obfuscation.

Definition: a complex type definition component T is 'ultimately derived from wsdl:Service' if it satifies either 1 or 2 below:
  1. T has the following properties:
      - a {name} property with a value of "Service"
      - a {target namespace} with a value of
               "http://www.w3.org/@@@@/@@/wsdl"
  2. T has a {base type definition} property whose value is a complex type ultimately derived from wsdl:Service.

Any element informations item with the following infoset properties:
 - an attribute information item among its [attributes] with:
      - a [local name] of "serviceReference"
      - a [namespace name] of "http://www.w3.org/@@@@/@@/wsdlx"
      - a value of "true" of type xs:boolean
 - a PSVI [type definition] isomorphic to a complex type definition component which is ultimately derived from wsdl:Service MUST be treated as a reference to a web service.

For convenience, we can define a wsdlx:ServiceReference type that fixes the presence and value of the wsdlx:serviceReference attribute as follows:

<xs:schema targetNamespace="http://www.w3.org/@@@@/@@/wsdlx"
           xmlns:tns="http://www.w3.org/@@@@/@@/wsdlx">
  <xs:attribute name="serviceReference" type="xs:boolean"/>
  <xs:complexType name="ServiceReference">
    <xs:complexContent>
      <xs:restriction base="wsdl:Service">
        <xs:attribute ref="tns:serviceReference"
                      use="required"
                      fixed="true"/>
      </xs:restriction>
    </xs:complexContent>
  </xs:complexType>
</xs:schema>

There is nothing special with this type or its name and any other similar type would do just as well.

3. Examples

The following examples have been adapted from Arthur's proposal (incidentally, the original examples contained an error; the "name" attribute of a wsdl:Service is REQUIRED, so we added fictitious service names where needed).

Example 3a -- Service element

In this example, the schema allows passing values of type wsdl:Service, a subset of which may be identified at runtime as being service references.
<xs:schema targetNamespace="http://hr.example.com">
  <xs:element name="DepartmentNumber" type="xs:string"/>
  <xs:element name="Department">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="Manager" type="wsdl:Service"/>
        <xs:element name="Engineer" type="wsdl:Service"
            minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
      <xs:attribute name="deptno" type="xs:string"/>
    </xs:complexType>
  </xs:element>
</xs:schema>

A sample message:

<soap:Envelope>
  <soap:Body>
    <hr:Department deptNo="123" xmlns:hr="http://hr.example.com" >
      <hr:Manager name="JudySmith" interface="hr:Manager"
                  wsdlx:serviceReference="true">
        <wsdl:endpoint binding="hr:ManagerSOAP">
          <soap:address location="http://hr.example.com/smith/judy">
    </wsdl:endpoint>
      </hr:Manager>
      <hr:Engineer name="TomJones" interface="hr:Engineer">
        <wsdl:endpoint binding="hr:EngineerSOAP">
          <soap:address location="http://hr.example.com/jones/tom"/>
        </wsdl:endpoint>
      </hr:Engineer>
    </hr:Department>
  </soap:Body>
</soap:Envelope>

Notice that the manager is a service reference but the engineer isn't (he gets enough spam as it is).

Example 3b -- Service reference

In this example, the schema constrains the values to be actual service references by means of the wsdlx:ServiceReference type introduced in section 1.

<xs:schema targetNamespace="http://hr.example.com"
        xmlns:wsdlx="http://www.w3.org/@@@@/@@/wsdlx">
  <xs:element name="DepartmentNumber" type="xs:string"/>
  <xs:element name="Department">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="Manager" type="wsdlx:ServiceReference"/>
        <xs:element name="Engineer" type="wsdlx:ServiceReference"
            minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
      <xs:attribute name="deptno" type="xs:string"/>
      <xs:attribute ref="wsdl:descriptionLocation"/>
    </xs:complexType>
  </xs:element>
</xs:schema>

A sample message:

<soap:Envelope>
  <soap:Body>
    <hr:Department deptNo="123" xmlns:hr="http://hr.example.com" >
      <hr:Manager name="JudySmith" interface="hr:Manager"
          wsdlx:serviceReference="true">
        <wsdl:endpoint binding="hr:ManagerSOAP">
          <soap:address location="http://hr.example.com/smith/judy">
    </wsdl:endpoint>
      </hr:Manager>
      <hr:Engineer name="TomJones" interface="hr:Engineer"
          wsdlx:serviceReference="true">
        <wsdl:endpoint binding="hr:EngineerSOAP">
          <soap:address location="http://hr.example.com/jones/tom"/>
        </wsdl:endpoint>
      </hr:Engineer>
    </hr:Department>
  </soap:Body>
</soap:Envelope>

Example 3c -- Service reference locking down the interface

In this example, the schema constrains the service references to be for a statically specified interface.

<xs:schema targetNamespace="http://hr.example.com"
        xmlns:wsdlx="http://www.w3.org/@@@@/@@/wsdlx">
  <xs:complexType name="ManagerServiceReference">
    <xs:complexContent>
      <xs:restriction base='wsdl:ServiceReference'>
        <xs:attribute name="interface"
                      type="xs:QName"
                      use="required"
                      fixed="hr:Manager"/>
      </xs:restriction>
    </xs:complexContent>
  </xs:complexType>
  <xs:complexType name="EngineerServiceReference">
    <xs:complexContent>
      <xs:restriction base='wsdlx:ServiceReference'>
        <xs:attribute name="interface"
                      type="xs:QName"
                      use="required"
                      fixed="hr:Engineer"/>
      </xs:restriction>
    </xs:complexContent>
  </xs:complexType>
  <xs:element name="DepartmentNumber" type="xs:string"/>
  <xs:element name="Department">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="Manager" type="tns:ManagerServiceReference"/>
        <xs:element name="Engineer" type="tns:EngineerServiceReference"
            minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
      <xs:attribute name="deptno" type="xs:string"/>
      <xs:attribute ref="wsdl:descriptionLocation"/>
    </xs:complexType>
  </xs:element>
</xs:schema>

A sample message:

<soap:Envelope>
  <soap:Body>
    <hr:Department deptNo="123" xmlns:hr="http://hr.example.com" >
      <hr:Manager name="JudySmith" interface="hr:Manager"
          wsdlx:serviceReference="true">
        <wsdl:endpoint binding="hr:ManagerSOAP">
          <soap:address location="http://hr.example.com/smith/judy">
    </wsdl:endpoint>
      </hr:Manager>
      <hr:Engineer name="TomJones" interface="hr:Engineer"
          wsdlx:serviceReference="true">
        <wsdl:endpoint binding="hr:EngineerSOAP">
          <soap:address location="http://hr.example.com/jones/tom"/>
        </wsdl:endpoint>
      </hr:Engineer>
    </hr:Department>
  </soap:Body>
</soap:Envelope>

Please note that the SOAP message is the same in all these examples! Only the statically specified constraints in the WSDL document have been progressively tightened.

Example 3d -- Service reference locking down interface and binding

Yet more of the same, this time restricting the element content of wsdl:Service. We'll spare you the details.

4. How to refer to a WSDL document from a message

At the last f2f, we identified a need to associate an element in the wsdl namespace embedded in a message with the WSDL document it's defined in. Limiting ourselves to service references for the time being, a simple solution could be to define the following attribute:

<xs:schema targetNamespace="http://www.w3.org/@@@@/@@/wsdlx"
           xmlns:tns="http://www.w3.org/@@@@/@@/wsdlx">
  <xs:attribute name="wsdlLocation" type="xs:anyURI"/>
</xs:schema>

Then specify that when a value ultimately of type wsdl:Service carries such an attribute, its value is a hint on the location of a WSDL document whose target namespace is the namespace the service is defined in.

As already stated in the introduction, this part of the proposal is completely independent and it can (and probably should) be addressed separately.

5. Using URI-based service references

In this section we show an example of what a complex type wrapper for URIs would look like.

We define the following complex type (essentially a URI wrapper with interface and binding information):

<xs:schema targetNamespace="http://example/urisvcref">
  <xs:complexType name="URIServiceReference">
    <xs:simpleContent>
      <xs:extension base="xs:anyURI">
        <xs:attribute name="interface" type="xs:QName" use="required"/>
        <xs:attribute name="binding" type="xs:QName" use="required"/>
        <xs:attribute ref="wsdlx:serviceReference"
                      use="required"
                      fixed="true"/>
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>
</xs:schema>

To be consistent with section 2 we have this type use the wsdl:serviceReference attribute too. Clearly, the WSDL 2.0 spec itself wouldn't have anything to say on how this attribute would affect users of URIServiceReference, but the spec for the URIServiceReference complex type likely would.

6. Examples

This section contains examples of the URIServiceReference type, showing how a schema can progressively lock down its properties.

Example 6a -- URI service reference

In this example, akin to 3b, the URI service reference is unconstrained, so actual values can point to arbitrary interfaces and bindings.

<xs:schema targetNamespace="http://hr.example.com">
  <xs:element name="DepartmentNumber" type="xs:string"/>
  <xs:element name="Department">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="Manager" type="uriref:URIServiceReference"/>
        <xs:element name="Engineer" type="uriref:URIServiceReference"
             minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
      <xs:attribute name="deptno" type="xs:string"/>
    </xs:complexType>
  </xs:element>
</xs:schema>

A sample message:

<soap:Envelope>
  <soap:Body>
    <hr:Department deptNo="123" xmlns:hr="http://hr.example.com">
      <hr:Manager
          interface="hr:Manager"
          binding="hr:ManagerSOAP"
          wsdlx:serviceReference="true">
         http://hr.example.com/smith/judy
      </hr:Manager>
      <hr:Engineer
          interface="hr:Engineer"
          binding="hr:EngineerSOAP">
         http://hr.example.com/jones/tom
      </hr:Engineer>
    </hr:Department>
  </soap:Body>
</soap:Envelope>

Example 6b -- URI service reference locking down the interface

In this example, akin to 3c, the type definition constrains its values to refer to a specified interface.

<xs:schema targetNamespace="http://hr.example.com">
  <xs:complexType name="ManagerServiceReference">
    <xs:restriction base="uriref:URIServiceReference">
      <xs:attribute name="interface" value="hr:Manager" fixed="true"/>
    </xs:restriction>
  </xs:complexType>
  <xs:complexType name="EmployeeServiceReference">
    <xs:restriction base="uriref:URIServiceReference">
      <xs:attribute name="interface" value="hr:Employee" fixed="true"/>
    </xs:restriction>
  </xs:complexType>
  <xs:element name="DepartmentNumber" type="xs:string"/>
  <xs:element name="Department">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="Manager" type="tns:ManagerServiceReference"/>
        <xs:element name="Engineer" type="tns:EmployeeServiceReference"
             minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
      <xs:attribute name="deptno" type="xs:string"/>
    </xs:complexType>
  </xs:element>
</xs:schema

A sample message:

<soap:Envelope>
  <soap:Body>
    <hr:Department deptNo="123" xmlns:hr="http://hr.example.com">
      <hr:Manager
          interface="hr:Manager"
          binding="hr:ManagerSOAP"
          wsdlx:serviceReference="true">
         http://hr.example.com/smith/judy
      </hr:Manager>
      <hr:Engineer
          interface="hr:Engineer"
          binding="hr:EngineerSOAP">
         http://hr.example.com/jones/tom
      </hr:Engineer>
    </hr:Department>
  </soap:Body>
</soap:Envelope>

Example 6c -- URI service reference locking down interface and binding

Similar to 3d, more of the same stuff. We spare you the details here as well.

7. Handling URIs using schema annotations

In certain cases, it may not be desirable to use a URI wrapper type like URIServiceReference. Schema annotations can then be used to provide static interface and/or binding information on top of regular simple type declarations.

Here's a quick-and-dirty example. Let's define the following attributes:

<xs:schema targetNamespace="http://www.w3.org/@@@@/@@/wsdlx2"
           xmlns:tns="http://www.w3.org/@@@@/@@/wsdlx2">
  <xs:attribute name="interface" type="xs:QName"/>
  <xs:attribute name="binding" type="xs:QName"/>
</xs:schema>

Here's how we can use them as schema annotations:

<xs:schema targetNamespace="http://hr.example.com">
  <xs:simpleType name="ManagerServiceReference"
     wsdlx2:interface="hr:Manager"
     wsdlx2:binding="hr:ManagerSOAP>
    <xs:restriction base="xs:anyURI"/>
  </xs:simpleType>
  <xs:simpleType name="EmployeeServiceReference"
     wsdlx2:interface="hr:Employee"
     wsdlx2:binding="hr:EmployeeSOAP>
    <xs:restriction base="xs:anyURI"/>
  </xs:simpleType>
  <xs:element name="DepartmentNumber" type="xs:string"/>
  <xs:element name="Department">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="Manager" type="tns:ManagerServiceReference"/>
        <xs:element name="Engineer" type="tns:EmployeeServiceReference"
             minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
      <xs:attribute name="deptno" type="xs:string"/>
    </xs:complexType>
  </xs:element>
</xs:schema>

This schema annotates the ManagerServiceReference and EmployeeServiceReference types, in turn simple types derived from xs:anyURI, as being associated with particular interfaces and bindings.

Here's a sample message using the schema above:

<soap:Envelope>
  <soap:Body>
    <hr:Department deptNo="123" xmlns:hr="http://hr.example.com">
      <hr:Manager>http://hr.example.com/smith/judy</hr:Manager>
      <hr:Engineer>http://hr.example.com/jones/tom</hr:Engineer>
    </hr:Department>
  </soap:Body>
</soap:Envelope>

8. Conclusions

It's all schema!

9. Acknowledgments

This proposal arose out of several conversations with Glen Daniels. We'd like to thank Umit Yalcinalp and Arthur Ryman for their constructive comments. Umit also spotted an error in our usage of XML Schema.