In my last post, I said that a Universal Data Transfer Object schema was key to having a Standardized Service Contract. This post will go into some detail on how that is designed and why.
First of all, for Services to be reusable, they need to be agnostic of the composition or application that access them, in other words they should not need to know who makes the request or what they will do with the response.
This is tricky since a service has needs for data in the request and where to put the response. If for example a service needs an invoice number to look-up the total amount and zip code to calculate taxes, then that service is not agnostic in context, as it only applies if an invoice is referenced by an invoice number.
If however a similar service does not need an invoice number just a total number and a zip code to calculate the taxes in its response, then it is reusable for any consumer that needs to calculate taxes for an amount in a zip code.
Since virtually every service has a different set of parameters it needs in the request and will return a different set of values in its response, this means that the orchestration or composite service controller or some facade will typically need to do data transformation to populate the request and process the response.
The Universal Data Transfer Object is the message format that attempts to accommodate these needs.
Let's first look at the most universal web services schema the SOAP schema. If you look at it at http://schemas.xmlsoap.org/wsdl/soap/ you will find it has some fixed elements that are required and is easily extensible with WSDL to include any payload in the body and response that you might need.
Now look at the needs of a SOA. Its not just one service, it could be a dozen or even more in one application flow. So a single request schema won't work and a single response schema either.
So borrowing the concept from WSDL/SOAP we created the UDTO
I won't put it all up here in this post, but essentially it looks like this psuedo xsd
<UDTO>
<eventKey/>
<messageVariables>
<inputParam unbounded>
</inputParam>
<outputValues unbounded>
</outputValues>
</messageVariables>
<atomicRequest>
<any/>
</atomicRequest>
<atomicResponse>
<any/>
</atomicResponse>
<originalRequest>
<any/>
</originalRequest>
<originalResponse>
<any/>
</originalResponse>
We have additional elements for fixed elements that we use for security and message handling, but the core is what you see. When a service defines it its service contract that it needs three params, we can place them in the inputParam array easily without a lot of heavy lifting a mapping node in broker or an XSL transform is typically enough and fast enough.
Similarly the service contract says it will put its values in the output array too and can easily be mapped or transformed.
Sometimes the service needs more structure, and in that case we allow the service to specify a schema for its atomicRequest element payload and put its values in the atomicResponse element and we handle those with a service facade that populates the Request and processes the Response.
Everything is held in the message as it flows through the system so subsequent service have access to the responses from the previous services.
Since this is a blog post and not a book chapter (yet) that's all for now. Watch this blog for more details.