WSDL 1.1 Extensions for REST has been edited by Alexis Midon (Jul 16, 2008).

(View changes)

Content:

WSDL 1.1 Extensions for better HTTP/REST description

The Resource-Oriented Architecture defines four concepts:

  1. Resources
  2. Their names (URIs)
  3. Their representations
  4. The link bet ween them

and four properties:

  1. Addressability
  2. Statelesness
  3. Connectedness
  4. A uniform interface

HTTP binding as defined in WSDL 1.1 is not well suitable to describe services implementing these concepts and properties, mainly because a port type may access 4 different locations/resources but with only one HTTP method.

To better describe RESTful services, and turn a port type into a "resource type", ODE brings a set of 4 extensions:

  1. one HTTP method per operation (instead of one per binding)
  2. a unique URI Template for all operations
  3. access to HTTP headers
  4. fault support

Further details below.

In this page, we use an imaginary blog service as a use case to illustrate and make things more palpable. We will focus on the resources defined by the following URI template:

http://blog.org/post/{id}

Let's assume that such a resource accept four operations:

  • GET to retrieve a post
  • DELETE to delete it
  • PUT to update the post
  • POST to add a comment to a post



One verb per operation

According to the WSDL 1.1 specification, the verb describing the HTTP method has to be at the binding level. Which implies that the same HTTP method is used by all operations of a given port type. But RESTful web services leverage HTTP methods as a uniform interface to describe operation on resources. So for instance, if you want to use the following HTTP operations – GET, POST, PUT, DELETE – for a given resource, four different bindings would be required. And consequently four port types and four ports. Quite verbose and unusable, isn't it?

So, this extension is to push down the HTTP verb at the operation level. And if an operation does not have its own verb, then the verb defined at the binding level will be used.
This extension is declared in the namespace: http://www.apache.org/ode/type/extension/http

Please note that ODE supports GET, POST, PUT, DELETE only.

<definitions ...
                  xmlns:odex="http://www.apache.org/ode/type/extension/http"/>

    <!-- many wsdl elements are ommited to highlight the interesting part -->

    <binding name="blogBinding" type="blogPortType">
        <operation name="GET">
            <odex:binding verb="GET" />
        </operation>
        <operation name="DELETE">
            <odex:binding verb="DELETE"/>
        </operation>
    </binding>
</definitions>

URI Template

A RESTful service exposed a set of resources, each of them being accessible through a uniform interface: HTTP methods for a web service. So we need a way to define four operations (at most) for a single resource.

Moreover it's very likely that the resource URI actually describes a set of resources. For instance, the set of posts contained in our imaginary blog: http://blog.org/post/\{post_id}.

HTTP binding offers the http:operation element to set the path of an operation. While the service address is set in the http:address of the wsdl:port element.
So one could imagine splitting the URL this way:

<definitions ...
                  xmlns:odex="http://www.apache.org/ode/type/extension/http"/>

   <service name="blogService">
        <port name="blogPort" binding="blogPortType">
             <http:address location="http://blog.org"/>
        </port>
    </service>

    <binding name="blogBinding" type="blogPortType">
        <operation name="PUT">
            <odex:binding verb="PUT" />
            <http:operation location="post/(post_id)"/>
            <input>
                 <http:urlReplacement/>
             </input>
             <output/>
        </operation>
    </binding>
</definitions>

However, here 3 issues show up:

  1. the location is not accessible from the End Point Reference. => ODE cannot process it before invoking the external service.
  2. http:urlReplacement is only accepted for GET => what about the uniform interface?!
  3. http:urlReplacement requires all parts of the operation input message to be mentioned in the operation location. Meaning that:
    • => the resource id (in the present example) must be a part of the message.
    • _=> no parts may be stored in the HTTP body. this conflicts with a PUT operation for instance. With a PUT you would like to set the id in the url and the resource data in the HTTP request body.

To solve this, ODE allows http:operation elements to be omitted or empty, and the full resource URI to be set in a single place, the http:address element.
Please note that curly brackets '{}' are the preferred argument delimiters in URI templates. So that they could be manipulated with XPath Function. Parentheses are still supported nevertheless.

In addition, the http:urlReplacement is relaxed: all parts are not required in the URI template anymore. One part could go in the URI, another in the request body.

<definitions ...
                  xmlns:odex="http://www.apache.org/ode/type/extension/http"/>

   <service name="blogService">
        <port name="blogPort" binding="blogPortType">
             <!-- here is the full URI template, using curly brackets -->
             <http:address location="http://blog.org/post/{post_id}"/>
        </port>
    </service>

    <binding name="blogBinding" type="blogPortType">
        <operation name="PUT">
             <odex:binding verb="PUT" />
             <!-- location attribute intentionally blank -->
             <http:operation location=""/>
             <input>
                 <http:urlReplacement/>
                 <!-- an additional part can be mapped to the request body even if urlReplacement is used-->
                 <mime:content type="text/xml" part="post_content"/>
             </input>
             <output/>
        </operation>
    </binding>
</definitions>

HTTP Headers manipulation

HHTP protocal convey a lot of information in Request/Response Headers. Caching information, Content description for instance. All this data is completely left out by WSDL 1.1 HTTP Binding. To fix this, ODE provides a header element. This element can be used to insert a part or a static value into a given HTTP request header (standard or custom). And the way around, a HTTP request header into a part. Also note that all HTTP response headers are inserted into the message headers, and thus are available from the BPEL process.

<definitions ...
                  xmlns:odex="http://www.apache.org/ode/type/extension/http"/>

    <binding name="blogBinding" type="blogPortType">
        <operation name="PUT">
             <odex:binding verb="PUT" />
             <http:operation location=""/>
             <input>
                 <http:urlReplacement/>
                 <mime:content type="text/xml" part="post_content"/>
                 <!-- set a standard request header from a part -->
                 <odex:header name="Authorization" part="credentials_part"/>
                 <!-- set a custom request header with a static value -->
                 <odex:header name="MyCustomHeader" value="[EMAIL PROTECTED]" />
             </input>
             <output>
                 <mime:content type="text/xml" part="post_content"/>
                 <!-- set 1 response header to a part -->
                 <odex:header name="Age" part="age_part"/>
             </output>
        </operation>
    </binding>
</definitions>

For every HTTP response, in addition to HTTP response headers, the Status-Line is passed as a message header. To save some painful XPath string manipulations, the Status-line is already parsed into the following structure:

<Status-Line>
   <HTTP-Version>HTTP/1.1</HTTP-Version>
   <Status-Code>200</Status-Code>
   <Reason-Phrase>OK</Reason-Phrase>
   <!-- the original unaltered Status-Line -->
   <original>HTTP/1.1 200 OK</original>
</Status-Line>

So that you can write the following BPEL lines:

<assign>
            <copy>
                <from variable="postMsg" header="Status-Line"/>
                <to>$statusLine</to>
            </copy>
        </assign>
        <if>
            <condition>number($statusLine/Status-Code) > 200 and number($statusLine/Status-Code) < 300</condition>
            <assign>
                 <copy>
                     <from>'Request successful!!!'</from>
                     <to>$outputVar.TestPart</to>
                 </copy>
             </assign>
        </if>

Fault Support

Another domain completely neglected by WSDL 1.1 HTTP Binding is Fault management. The world is not even mentioned in the HTTP Binding section.
ODE allows you to bind a fault with HTTP Binding. If a Server Error 5xx is returned, ODE checks that a fault is declared in the WSDL for the current operation and that the response body contains the expected XML element then reply with a fault ; else reply with a failure.
For other codes (3xx & 4xx), a failure is bubbled back.

Useful Information

Note that 3xx errors should be pretty rare since by default the first hundred redirections are followed. You can tweak this value by setting the property http.protocol.max-redirects in the [enpoint-configuration.properties] of your process.

<definitions ...
                  xmlns:odex="http://www.apache.org/ode/type/extension/http"/>

   <portType name="BlogPortType">
        <operation name="PUT">
            <input message="..."/>
            <output message="..."/>
            <fault name="UpdateFault" message="tns:UpdateFault"/>
        </operation>
    </portType>

    <binding name="blogBinding" type="blogPortType">
        <operation name="PUT">
             <odex:binding verb="PUT" />
             <http:operation location=""/>
             <input> ... </input>
             <output> ...  </output>
             <!-- fault binding -->
             <fault name="UpdateException">
                 <!-- name attribute is optional if there is only one fault for this operation -->
                 <!-- <odex:fault name="UpdateFault"/> -->
                 <odex:fault/>
             </fault>
        </operation>
    </binding>
</definitions>

Reply via email to