Archive for the ‘SOAP and WS-*’ Category

Field Manual for Lightweight WS/SOA governance

November 2, 2009

I’ve recently worked for several companies that were publishing web services without any clear-cut consistency or strategic vision. The following blog outlines some observations and suggestions for a coherent approach to developing and managing web services. The focus is on SOAP services but most points equally apply to REST as well.

The context is a medium-sized company that needs to develop one or more public-facing web services. Most of the following guidelines are applicable for internal-facing services, but public services have more of an emphasis on security and interoperability.

The focus is on solidly grounded pragmatics. I’ve been inspired by some of Thomas Erl’s writings but I find much of his advice overwhelming. The intent of this blog is to distill some essential SOA guidelines that I have seen work in practice. This blog can be seen as a field manual for an SOA lite framework.

Developing web services – especially public ones – is one place where “agile/iterative” development can come up short. Once an API is published it id basically fixed in stone. As the number of clients grow, the cost of change proportinally increases. Having a solid grasp of some of the industry best practices and key tenets of SOA/WS development can pay huge dividends in the overall life cycle of your service.

Some service features to be considered:

  • Common namespace
  • Common service endpoint
  • Service implementation
  • Schema validation
  • Security
  • Interoperability
  • Contract versioning and evolution
  • Error Handling
  • Client usage and packaging
  • Testing
  • Documentation

Common Namespace

The namespaces used in each service – both for the WSDL and external imported XSDs should be be based on a common prefix.

Note that the namespace is not an addressable URL – its not tied to any running server – a common confusion.  So we have the liberty to choose whatever we want. Some prefer URNs over URLs to avoid this confusion though the latter are more familiar to the masses. Some APIs such as Flick don’t even use a namespace! eBay interestingly enough uses both URLs and URNs for different APIs! How about some “SOA governance”! If this kind of stuff turns you on, go surf the programmableweb for more details. For example:

Sample URNs:

  • eBay Shopping API: urn:ebay:apis:eBLBaseComponents
  • eBay Trading API: urn:ebay:apis:eBLBaseComponents
  • eBay Merchant Data API: urn:ebay:apis:eBLBaseComponents
  • eBay PayPal: urn:ebay:api:PayPalAPI
  • Yahoo Search API: urn:yahoo:srch
  • Yahoo Map API: urn:yahoo:maps
  • Microsoft Health API schemas: urn:com.microsoft.wc.thing.types
  • Salesforce API: urn:partner.soap.sforce.com

Sample URLs:

eBay WSDL using URN style:

<wsdl:definitions
xmlns:wsdl=”http://schemas.xmlsoap.org/wsdl/&#8221;
xmlns:xs=”http://www.w3.org/2001/XMLSchema&#8221;
xmlns:wsdlsoap=”http://schemas.xmlsoap.org/wsdl/soap/&#8221;
xmlns:ns=”urn:ebay:apis:eBLBaseComponents
xmlns=”urn:ebay:apis:eBLBaseComponents”
targetNamespace=”urn:ebay:apis:eBLBaseComponents”>

Amazon S3 WSDL using URL style:

<wsdl:definitions
targetNamespace=”http://s3.amazonaws.com/doc/2006-03-01/
xmlns:tns=”http://s3.amazonaws.com/doc/2006-03-01/&#8221;
xmlns:wsdl=”http://schemas.xmlsoap.org/wsdl/&#8221;
xmlns:wsdlsoap=”http://schemas.xmlsoap.org/wsdl/soap/&#8221;
xmlns:xsd=”http://www.w3.org/2001/XMLSchema”&gt;

Common Service Endpoint

Having a common service endpoint is similar to the problem of a common namespace. The structure of the URL depends on the kinds of  services you support (SOAP or REST).

If you only have one type of web service (SOAP or REST), then you obviously do not need to have a top-level qualifier. If you support both services, then a separation such as the following  makes sense:

In either case, a bit of “governance” can give your services a professional feel. I’ve seen all too many cases where every developer invents their own URL without any coordination. Non-technical managers might not care but customers do notice. Look at it as a branding issue. Don’t you want all your services to sport the snappy same brand name? An example of “anarchy” is:

Schema Validation

You need to make an informed decision if you will support schema validation. This has two dimensions: outbound and inbound message validation.

The (JAX-WS) 2.1 spec only provides for optional validation – here’s what section 1.1 says:

JAX-WS 2.0 will allow full use of JAXB provided facilities including binding customization and optional
schema validation.

Mandating validation simplifies the service provider implementation as well as the client – it removes the inherent ambiguity of non-validation mode but sacrifices “flexibility”. Though validation by definition cannot be faster than non-validation, the guarantees of a validating mode are much stronger, and do provide well-known benefits of type-safety. There are many more ambiguities and undefined behaviors resulting from a non-validating mode.

For example, the CXF JAX-WS implementation doesn’t even accept its own advertised validation mode, so you are force to operate in non-validating mode.

Here’s the Spring-based configuration stanza that is supposed to turn on validation. Unfortunately it prevents any requests from suceeding by complaining about illegal XML when stub-generated client code is invoked! Go figure!

  <jaxws:endpoint id="videoServic" implementor="#videoServiceImpl" address="/soap/video" >
       <jaxws:properties>
          <entry key="schema-validation-enabled" value="true"/>
       </jaxws:properties>
  </jaxws:endpoint>

The corresponding server-side error message for a prefectly legitimate request is:

    Nov 7, 2009 12:55:47 AM org.apache.cxf.phase.PhaseInterceptorChain doIntercept
    WARNING: Interceptor has thrown exception, unwinding now
    org.apache.cxf.interceptor.Fault: Marshalling Error: cvc-elt.1: Cannot find the declaration of   element 'ns1:VideoAssets'.
    at org.apache.cxf.jaxb.JAXBEncoderDecoder.marshall(JAXBEncoderDecoder.java:160)
    at org.apache.cxf.jaxb.io.DataWriterImpl.write(DataWriterImpl.java:169)

The well-known SOA tenet “be strict in what you emit but be generous in what you consume” has a nice ring to it in the abstract, but with the “all or nothing” nature of XSD schemas, it becomes more difficult to implement. Other XML schemas such as RelaxNG have better abilities to handle these issues but unfortunately they have less mindshare and tools in the Java WS space.

It is interesting to note that Atom and AtomPub do not even provide a definitive schema though mention is made of it in RelaxNG. Although this is not relevant to a SOAP web services, it has a major impact on REST services. In section 1.3 the Atom Syndication Format spec states:

Some sections of this specification are illustrated with fragments of a non-normative RELAX NG Compact schema [RELAX-NG]. However, the text of this specification provides the definition of conformance. A complete schema appears in Appendix B.

Service implementation

The focus of this blog is on Java-based solutions especially JAX-WS . There are currently three open source JAX-WS implementations:

  • Metro – Sun’s RI intended to be production quality
  • CXF – Apache merger of XFire and Celtix
  • Axis2 – Another Apache implementation not related to Axis1

The first issue that you must tackle is whether you want to develop your service in a contract-first or code-first style. JAX-WS annotations have blurred this division, since you can now specific WSDL features from within your Java code using annotations. Not only do you have to have knowledge of WSDL, you also have to know how the annotations map to WSDL which can be challenging and depends on how faithful each vendor is.

There are advantages and disadvantages to both approaches.

Another issue is toolkit evaluation. I’ve noticed that many developers do not do an adequate job in “taking the toolkit around the block for a spin” before investing all their eggs in one basket. Ultimately it is the manager’s job to make sure that developers do not skip this step. If you know that you will be using WS security or MTOM, you should develop some non-trivial “spike” proof-of-concepts. Its risk-mitigation – better to be surprised earlier than later. I’ve seen some quite spectacular production blow-ups due to the lack of platform evaluation that literally ended up costing millions of dollars. Draw up a list of key features to evaluate. And don’t forget performance since SOAP as XML dialect is hardly efficient.

Interoperability

You should definitely make sure you comply with latest WS-I profile. Your customers’ platforms will drive this issue. Adequately testing different platforms in which you don’t have experience can be a challenge. If you are a Java shop, it might prove too costly (time consuming) to go out and implement a full suite of tests in C#. You should have at least one platform that has a comprehensive set of tests, and certainly have smoke tests for the platforms you plan to support. In one of my recent projects, just doing a small C# smoke test revealed problems with the name “System” as it seems to be a reserved word in the C# world.

Security

Once your services are being accessed outside the firewall, its a whole new ballgame. WS* security standards can be overwhelming, and I’ve found organizations often skimp here and hope for the best.

Dennis Sonoski has written some great articles on the practical implications of WS security:

Contract versioning and evolution

If you intend to change your service contracts, then you must at some point be aware of this issue. I’ve found that many organizations are in a hurry to roll out services and do not address this topic at all, and ultimately  pay the price downstream. A bit of foresight can alleviate some of the inherent pains of contract versioning.

Some versioning resources from the “big boys”:

Error Handling

There is no reason not to have a common reusable set of SOAP faults for all your services. This is a good example where you can get a “big bang for your buck” with XSD schema reuse between WSDLs.

Make sure you don’t “leak” provider-specific stack traces or error messages. Not only is it bad form and confusing for a user to see a cryptic Hibernate-related error message in a SOAP fault, its also a security risk since this gives the bad guys hints on how to crack your system. Remapping and “cleansing” error messages can be a surprisingly big chore, but if you tackle this problem early on, it will be much simpler to solve.

Instead of  a try-catch for every provider method, you can use Spring’s AOP exception advice mechanism to remap all lower-level exceptions to your SOAP fault. Below is an example that shows how all exceptions thrown within the service provider class VideoServiceImpl are mapped into a VideoServiceFault.

Spring Exception Advice Java

    package com.andre.video.ws.soap.aop;
    import org.springframework.aop.ThrowsAdvice;
    import java.lang.reflect.Method;
    import com.andre.video.ws.soap.VideoServiceFault;

    public class ExceptionAdvice implements ThrowsAdvice  {
        public void afterThrowing(Method method, Object[] args, Object target, Exception ex) throws Exception {
            throw new VideoServiceFault(ex.getMessage());
      }
    }

Spring XML Configuration

    <bean id="exceptionAdvice"  class="com.andre.video.ws.soap.aop.ExceptionAdvice"/>
    <aop:config>
        <aop:pointcut id="exceptionPointcut"
           expression="execution(* com.andre.video.ws.soap.server.VideoServiceImpl*.*(..))" />
      <aop:advisor id="exceptionAdvisor" advice-ref="exceptionAdvice" pointcut-ref="exceptionPointcut" />
    </aop:config>

Client Usage and Packaging

You must absolutely test you service with client stubs generated from the WSDL. Depending on your resources and customers, you should have clients in several languages. For example, if the service is implemented in Java, and you have Java and Flex clients, then it behooves you to have tests in both languages.

Some issues:

  • Stub generation
  • Client packages – stubs, javadoc, samples

You must decide if you want to provide your clients with pre-generated stubs. Perhaps its enough to provide them with just a WSDL. Maybe the customers expect something more especially if they have made a specific request for this.

Testing

This is closely related to the Client Usage and Packaging section.

Some issues:

  • Emedded web server tests vs. external web server
  • Leverage testng testing framework for its suite fixture capability that allows you to load only once an expensive package instead of for every class with JUnit’s class fixture
  • How to pump in bad XML that cannot ever be exercised by stubs-based clients?
  • Performance testing – JMeter, Grinder. testng has some simple multithreaded annotations that can be used for simple load tests

Documentation

Last but not least is documentation. A WSDL is a necessary but hardly sufficient form of documentation. The semantics of some services can be quite self-evident and need minimal explanation. Other services can have complex semantics that require extensive text and examples. Again, examples from major API publishers can be useful:

You can use XSD’s ability to have documentation elements. I’m not sure how JAX-WS supports this if at all – this is a TBD research item for me.

One of the most thrilling experiences I recently had was to write the entire user documentation with a business analyst for our REST API. Trust me, you’ll never look at your API in the same way after having to document it in detail every feature.

Other

Some other issues:

  • Throttling
  • Service management
  • Client service consoles

Using Flex’s WebService and auto-binding of SOAP data to DataGrids, you can very quickly develop useful service consoles that can exercise much the functionality of you service. The service console can be leveraged by developers, testers, professional service folks and even business analysts.

For an example, see a sample Flex web service console.

Advertisements

Review of “Web Services – Contract – Design and Versioning” Book

October 19, 2009

The renowned SOA author Thomas Erl has just released a new book Web Services – Contract – Design and Versioning. It is quite a lengthy book totaling more than 700 pages! It would be nice to have a more digestible primer for those who can’t afford the time to read that many pages. I haven’t read the whole book yet, but I have been reading some quite interesting chapters at my local Border’s bookstore.

Sidebar: Though a small branch, it surprisingly has two copies of the book and yet nothing else by Erl. Go figure! I’d bet that I’m the only one who has touched the book so far (the bookstore is in a non-geek part of town).

Reading books like this sort of bum me out a bit. They sound so common-sensical and self-evident that one wonders why doesn’t everyone just follow these precepts. The style of writing is cogent and idealistic. There is truly little one can disagree with. We’re all against nuclear war, right?

One problem with the book is a lack of pragmatics – rarely does one encounter such ideal circumstances in the the real world. The SOA/WS trenches “out there” are very messy and it would have been nice to address the discrepancy between what ought to be and what is. Rarely are managers well-versed in such SOA good practices to be able to understand the need (cost) to spend some up-front time thinking about schema reuse (e.g. decouple XSD from WSDL) and the various approaches and implications of contract versioning and service evolution.

Come to think of it, Erl’s next book should be devoted to the topic of effectively applying SOA/WS best practices in a less-than-ideal world where non-technical office politics most often rule! Something along the lines of Yourdon’s Death March – how about the “Implementing SOA ideals in a Death March-like project”.

I did like the discussion of the trade-offs between an XSD separate from WSDL and a combined WSDL/XSD. There is a brief mention that although desirable, this and other “best practices” are often constrained by subpar tool implememtations. I wish this topic would have been explored further – in fact a whole chapter should have been devoted to the problem how tools (i.e. stubs) limit service providers’ and clients’ abilities to truly take full advantage of WS*. Dealing with raw WSDL is a difficult chore, and tools that automate much of the mundane chores of WSDL/code mapping also introduce non-trivial complexities. Not much new here, but in my experience tools have often given “lazy” (either time-constrained or non-curious) developers a false sense of security when dealing with SOAP. Again, a dash of pragmatics would have been helpful.

The book is definitely geared toward “big-enterprise” SOA/WS, in fact “huge-enterprise” where there are well-thought out plans and strategies regarding contracts and services. It would have been good to touch upon smaller-scale WS roll-outs – be they public or internal departmental. In my experience there is a significant difference between external-facing web services on the public internet and intranet-based services. This difference can lead to quite different strategies and tactics in design and deployment.

For a public service, you would definitely want to opt for contract-first design (WSDL to stubs) for inter-op reasons and have more of an awareness of contract versioning since you have little control over your clients. For an internal service, you can get away with a code-first approach since it is so much faster to develop, and you most probably have less inter-op concerns since you control both the server and client . New incompatible versions can be rolled out with much less pain. These days in the Java world JAX-WS annotations reduce (but do not eliminate) the impedance mismatch between code-first and contract-first strategies.

One complaint is that a chapter’s authors are not identified! With so many eminent authors, it is a pity that the interested reader cannot follow up. For example, in chapter 22.1 (p. 659) there is a pretty theoretical section on compatibility which I just happened to recognize from David Orchard’s (an author) 2006 article A Theory of Compatible Versions. It would have been helpful to those who enjoy this stuff to be able to delve into the topic more. Furthermore there are no footnotes nor references! For a “serious” book this size, this is rather shocking.

Another issue I had with the book was its lack of discussion of REST and REST-ian approaches to contract versioning. Considering how widespread REST services are today, this is rather puzzling. I would have enjoyed hearing a serious “non-religious” discussion as to when a SOAP or REST approach is more appropriate. For example, REST better suits public consumer-oriented APIs (flickr, AWS) whereas WS* might be more appropriate for a complex B2B integration scenario with functionality that cannot be easily shoe-horned into a resource model with only four HTTP verbs.

There seemed to be an implicit equating of SOA with WS-* and no shedding of light on more general problems of contract versioning. REST services whose data payloads are defined by an XSD face the same problems that SOAP XSD data formats. And what about popular data formats that do not use XSD such as Atom? The Atom and AtomPub approach, with built-in extensibility, is certainly something that should be on the radar screen of service designers. Google is using Atom as the basis for many of their web APIs – see Google Data. However, the service operation layer – WSDL and resource model – face quite different versioning problems. I would have loved to hear what some of the éminence grise authors had to say about that!

For more information, see two good preview excerpts by the authors:

There is also an excellent article that talks about real-life trade-offs and issues in contract versioning: