title: What are your WebService Versioning best practices?
body: <p>We have 2 separate products that need to communicate with each other via web services.
  What is the best-practice to support versioining of the API? </p>
  
  <p>I have <a href="http://www.ibm.com/developerworks/webservices/library/ws-version/" rel="noreferrer">this article</a> from 2004 claiming there is no actual standard, and only best practices. Any better solutions? How do you solve WS versioning?</p>
  
  <h1>Problem Description</h1>
  
  <h2>System A</h2>
  
  <h3>Client</h3>
  
  <pre><code>class SystemAClient{
      SystemBServiceStub systemB;
      public void consumeFromB(){
          SystemBObject bObject = systemB.getSomethingFromB(new SomethingFromBRequest("someKey"));
  
      }
  }
  </code></pre>
  
  <h3>Service</h3>
  
  <pre><code>class SystemAService{
      public SystemAObject getSomethingFromA(SomethingFromARequest req){
          return new SystemAObjectFactory.getObject(req);
      }
  }
  </code></pre>
  
  <h3>Transferable Object</h3>
  
  <p><em>Version 1</em></p>
  
  <pre><code>class SystemAObject{
       Integer id;
       String name;
       ... // getters and setters etc;
  }
  </code></pre>
  
  <p><em>Version 2</em></p>
  
  <pre><code>class SystemAObject{
       Long id;
       String name;
       String description;
       ... // getters and setters etc;
  }
  </code></pre>
  
  <h3>Request Object</h3>
  
  <p><em>Version 1</em></p>
  
  <pre><code>class SomethingFromARequest {
       Integer requestedId;
       ... // getters and setters etc;
  
  }
  </code></pre>
  
  <p><em>Version 2</em></p>
  
  <pre><code>class SomethingFromARequest {
       Long requestedId;
       ... // getters and setters etc;
  
  }
  </code></pre>
  
  <h2>System B</h2>
  
  <h3>Client</h3>
  
  <pre><code>class SystemBClient{
      SystemAServiceStub systemA;
      public void consumeFromA(){
          SystemAObject aObject = systemA.getSomethingFromA(new SomethingFromARequest(1));
          aObject.getDescription() // fail point
          // do something with it...
      }
  }
  </code></pre>
  
  <h3>Service</h3>
  
  <pre><code>class SystemBService{
      public SystemBObject getSomethingFromB(SomethingFromBRequest req){
          return new SystemBObjectFactory.getObject(req);
      }
  }
  </code></pre>
  
  <h3>Transferable Object</h3>
  
  <p><em>Version 1</em></p>
  
  <pre><code>class SystemBObject{
       String key;
       Integer year;
       Integer month;
       Integer day;
  
       ... // getters and setters etc;
  }
  </code></pre>
  
  <p><em>Version 2</em></p>
  
  <pre><code>class SystemBObject{
       String key;
       BDate date;
       ... // getters and setters etc;
  }
  
  class BDate{
       Integer year;
       Integer month;
       Integer day;
       ... // getters and setters etc;
  
  }
  </code></pre>
  
  <h3>Request Object</h3>
  
  <p><em>Version 1</em></p>
  
  <pre><code>class SomethingFromBRequest {
       String key;
       ... // getters and setters etc;
  }
  </code></pre>
  
  <p><em>Version 2</em></p>
  
  <pre><code>class SomethingFromBRequest {
       String key;
       BDate afterDate;
       BDate beforeDate;
       ... // getters and setters etc;
  }
  </code></pre>
  
  <h1>Fail Scenarios</h1>
  
  <p>If a <strong>System A</strong> <em>client</em> of <strong>version 1</strong> calls a <strong>System B</strong> <em>service</em> of <strong>version 2</strong> it can fail on: </p>
  
  <ul>
  <li>missing methods on <code>SystemBObject</code> (<code>getYear()</code>, <code>getMonth()</code>, <code>getDay()</code>)</li>
  <li>Unknown type <code>BDate</code></li>
  </ul>
  
  <p>If a <strong>System A</strong> <em>client</em> of <strong>version 2</strong> calls a <strong>System B</strong> <em>service</em> of <strong>version 1</strong> it can fail on:</p>
  
  <ul>
  <li>Unknown type <code>BDate</code> on the <code>SomethingFromBRequest</code> (A client uses a newer B request object that B version 1 doesn't recognize)</li>
  <li>If the System A client is smart enough to use version 1 of the request object, it can fail on missing methods on the <code>SystemBObject</code> object (<code>getDate()</code>)</li>
  </ul>
  
  <p>If a <strong>System B</strong> <em>client</em> of <strong>version 1</strong> calls a <strong>System A</strong> <em>service</em> of <strong>version 2</strong> it can fail on: </p>
  
  <ul>
  <li>Type missmatch or overflow on <code>SystemAObject</code> (returned <code>Long</code> but expected <code>Integer</code>)</li>
  </ul>
  
  <p>If a <strong>System B</strong> <em>client</em> of <strong>version 2</strong> calls a <strong>System A</strong> <em>service</em> of <strong>version 1</strong> it can fail on:</p>
  
  <ul>
  <li>Type missmatch or overflow on <code>SystemARequest</code> (request <code>Long</code> instead of <code>Integer</code>)</li>
  <li>If the request passed somehow, casting issues (the stub is <code>Long</code> but the service returns an <code>Integer</code> not nessecarily compatible in all WS implementations)</li>
  </ul>
  
  <h1>Possible solutions</h1>
  
  <ol>
  <li>Use numbers when advancing versions: e.g. <code>SystemAObject1</code>, <code>SystemBRequest2</code> etc but this is missing a an API for matching source / target version </li>
  <li>In the signature, pass XML and not objects (yuck, pass escaped XML in XML, double serialization, deserialization / parsing, unparsing)</li>
  <li>Other: e.g. does Document/literal / WS-I has a remedy? </li>
  </ol>