Web services versioning

February 15th, 2009

Consider a scenario where you have a web service that you expose to consumers - and you want to make changes to the provided web service interface. What can you change without impacting existing consumers? And how do you handle changes that do impact existing consumers? I work on a project where we have to find a solution to this scenario and my investigation of the issue lead to the following.

Based on a develeoperWorks article on Best practices for Web services versioning I have created the following list of backwards compatible changes. These changes can be implemented without any impact to existing consumers of your web service:

  • Adding new operations to your web service
  • Adding new XML schema types that are not contained within previously existing types
  • Adding optional elements or attributes to existing request messages

However, the following are non-backwards compatible changes and require changes to be implemented by existing consumers in order to be able to use the changes web service:

  • Removing an operation
  • Renaming an operation
  • Changing the parameters (in data type or order) of an operation
  • Changing the structure of a complex data type
  • Adding new required elements to existing messages
  • Adding new optional elements to existing response messages
  • Removing required elements

Web services versioning is required to deploy changes that impact existing consumers (unless you are able to force the consumers to use the changed web service). For backwards compatible changes the developerWorks article recommends that XML comments are used to indicate unique version IDs or a version history. For non-backwards compatible changes the article recommends the use of web services versioning based on XML namespaces that clearly identify the version of the web service:

<schema targetNamespace="http://example.com/2009/02/15/webservice" xmlns="http://www.w3.org/2000/10/XMLSchema">

An article on Design Strategies for Web Services Versioning from SOA World Magazine recommends to enhance versioning by using a hybrid solution that combines XML namespaces and version ids where the targetNamespace is used for non-backwards compatible changes while the version id is used for backwards compatible changes:

<schema targetNamespace="http://example.com/2009/02/15/webservice" version="1.1" xmlns="http://www.w3.org/2000/10/XMLSchema">

For my particular project I find the combination of namespaces and version ids to be the most useful solution as the project will introduce both backwards and non-backwards compatible changes. It will be interesting to see how this will work in practice.

Update February 16: I have clarified that adding new elements to the response message will break existing web service consumers.

Tags: ,

3 Responses to “Web services versioning”

  1. Lars Ipsen Says:

    Hi Per

    Great overview of a subject that can be confusing. But I believe you need to point out the difference in the request and response, because if you add new elements to the response, then will the Web Service consumer also be forced to re-generate the Web Service client code

  2. Per Henrik Lausten Says:

    Hi Lars, good point - I have updated the post to reflect that adding new elements to the response will break existing consumers.

  3. Jenna Says:

    Thank you for putting this information together. Can you elaborate on the complex type? The situation that I'm facing may fall into changing the structure of the complex type, but I could be wrong.

    At my work place, I'm running into an issue where I need to decide whether to bump the major revision (publishing a new version of the web service) or bumping just the minor revision (hoping that the existing consumers don't notice the change).

    The change to the existing web service is as follow:

    1. existing web service has class A and an enumerated object B. I added a new property to A, and added a new enum value to B.
    before
    class A
    {
    int number;
    }

    enum B { Apple = 1, Oranges = 2}

    after
    Class A
    {
    int number;
    string name;
    }

    enum B { Grapes=3, Apple = 1, Oranges 2 }

    Does my change require to bump the major revision? Any advise is appreciated.

    Thanks