views:

389

answers:

4

I offer a small Web Services API to my clients which I plan to evolve over time. So I need some sort of versioning, but I can't find any information about how you do something like that.

Is there a best practice?

How can I keep adding new functionality without breaking compatibility with the web services consumers?

A: 

Add the "API version number" as parameter in all your API's then implement strategy pattern in your web service code where version number dictates what strategy to use.

ian
This would work only if the versioned web services take *exactly* the same arguments, so the same WSDL applies. If in a new version requires the addition of a new attribute what do you do?
Stella Peristeraki
+1  A: 

I generally add the version string to the web service URL, giving me "versioned endpoints". The code implementing those endpoints can either be shared, if the differences are trivial and can be handled by the same code, or the code can be cloned, or somewhere in between.

The different versioned endpoints could also use versioned XML Schemas, if that's what you need.

skaffman
+4  A: 

Versioning is a complex topic, so first, you need to define your goals in a more descriptive manner. It would be great to say that you have an interface insures you'll never break compatibility, but depending on what the new functionality is, that might not even be possible. So there are different situations and different trade-offs.

If your intent is to only provide new functionality to new consumers, and all of your consumers are direct consumers (no intermediaries, frameworks, etc.), then a discrete endpoint approach is the best choice. Each time you add a feature that risks a break, create a new endpoint, give it a new version number and then let the consumers know to validate against it and switch their configurations. This strategy is pretty tried and true, but it has the drawbacks of putting the burden on consumers to keep up to date. Also, if there are dependencies between services it can become a chore to track. The upside being if code breaks it's not (directly) your fault.

The other main strategy is the extensible interface. There's three different varieties here that I'm aware of. First, is the type of interface that tries to so well describe the service domain that every possible feature you might add is somehow possible given the existing interface. If that sounds hard, it is. You might call this the perfect interface. Everything is completely described, but the entire domain is also completely described. The "perfect" is really only on paper though.

The second variety is the type that looks like a normal interface but add generic extension points. In WSDLs this means xs:any, name-value pairs or something similar. You might call this the basic extensible interface. It's not too hard to do, but it's not without it's complications. The extension points may make the interface harder to work with in certain tooling (xs:any), or explicitly lose some of your ability to validate inputs and outputs (name-value pairs). It's also pretty easy to abuse those extension points in a way that makes the version 3 or 4 pretty hard to use.

The third variety is the type that converts your interface into a byte-stream. You might call these god interfaces. They aren't without their justifications, but if you're using one, you may want to ask why you're using web-services at all. Maybe you should be thinking about raw TCP/IP, or basic HTTP GET/POST. But maybe you're fed up with the complexity of WSDLs and XSDs and you just want to start from scratch but you're tied to web-services for some infrastructure reason. Realize however that once you start down this path, you're going to need a whole new way of describing to your consumers how to/not to use your service, and if you use XSD for that.. well you're basically back where you started.

Your best bet is to know all these options and approach your service design by first trying for the "perfect interface", then giving up and adding generic extensibility points. Trying to design the perfect interface will force you to learn things which will make your service better, not just your interface, but it will take time, and if you don't limit that time somehow, it'll take forever.

A little bit short of a true god interface, there is the wrapper interface. If you're system has layers, you want your interface to be in layers too. When you change layer B, you only want to change layer B, not all the instances in layer C.

nedruod
A: 

One of the possibilities is to design all web service operations to have only one parameter of a type that inherits from some abstract type that holds version number. This approach is implemented by eBay web services platform. Something like the following:

<xsd:complexType name="AbstractRequestType">
  <xsd:attribute name="version" type="string" />
  ....

<xsd:complexType name="AddCustomerRequestType">
  <xsd:complexContent>
   <xsd:extension base="AbstractRequestType">
   ....

then use AddCustomerRequestType as a type of only parameter 
in addCustomer web service operation.

Additionally if you work over http you may require to add version as a http GET parameter to web service endpoint url, so you'll be able to detect requested version easily http://server/service?version=1

Gennady Shumakher