Garden of Eden
2.4 Versioning Schemas
Problem
There are lots of different ways to indicate versions for schemas, and you’re not sure which, if any, is most appropriate in an SOA context.
Solution
Strongly consider using some part of the namespace to indicate the schema version.
This supports the canonical data model pattern. You must do so in a way that does not disrupt tools that perform code generation, however.
Discussion
Your XML schemas will evolve over time, even those in your canonical model that you hope to change only infrequently, so you need a strategy for versioning your schemas
that will support your work on a practical level within an SOA. There are a few options, which we’ll discuss here.
Use the version attribute
The most straightforward way to version a schema is to use the built-in attribute that exists just for this purpose. It looks like this:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
version="1.0.0">
The chief benefit of versioning this way is that it’s easy and doesn’t require any addi-tional work. It is also advantageous because if the existing schema or WSDL that im-ports the versioned schema is compatible with the new version, it doesn’t need to change.
But, as with so many easy things, it doesn’t really get us what we want. The downside is that it is not enforceable by tools. Moreover, it is not clear from an importing artifact (such as a WSDL or another schema) what version you are using unless you also rep-resent the version in the location of the physical document. This becomes a mainte-nance issue,because it violates the DRY (Don’t Repeat Yourself) rule. It also begs the question why you’d bother asserting the version in this attribute if it alone is not sufficient.
Hack the root element
You could define the root element in your schema to carry a version attribute of its own. This would allow validation to be enforceable with tools, but this is not really a solution. The enforced validation requires additional and custom preprocessing. You do not want to pollute your data model with implementation-specific items (such as a schema version number). This is altogether inappropriate within web service usage.
Change the name or URI of the schema document
You could simply change the name of the file or its location. This would allow importing schema documents or WSDLs to clearly represent what version they are using, as shown below:
<customer
xmlns="http://www.soacookbook.com/Customer"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.soacookbook.com/Customer http://www.soacookbook.com/Customer-v1.0.0.xsd">
This is similar to the previous choice. The schemaLocation attribute is not authoritative, meaning that it is a hint to processors, and can be ignored. This would work for WSDL documents because they do explicitly import based on physical location. However, this could create considerable inconsistencies and difficulties with tools because the name-space has not changed, though the version has. That advertises to consumers that the
WSDL is compatible with the namespace in general, and not simply this specific ver-sion. Generated code used by clients out in the world will be out of sync.
Use the namespace and document name
The best solution is to use the namespace itself to indicate the version of the schema.
This is familiar from many of the specifications we work with in web services. Consider the following namespaces:
• The namespace for SOAP 1.2 is http://www.w3.org/2003/05/soap-envelope.
• The namespace for WS-Addressing 1.0 is http://www.w3.org/2005/08/addressing.
• The namespace for XML Schema 1.0 is http://www.w3.org/2001/XMLSchema, and it uses the namespace for instances of http://www.w3.org/2001/XMLSchema-instance. These namespaces, all of which are central to web services, indicate their version by including the year and month of their publication in the namespace itself. There is no confusion as to whether you are looking at a SOAP 1.1 or SOAP 1.2 envelope. However, you are not free to simply replicate this structure directly in the schemas you define for use in a WSDL. That’s because web services rely on code generated by tools. Tools such as wsimport and WSDL2Java generate package names for the client artifacts they create from a WSDL using the namespace. And in Java, it is illegal to begin a package name with a number.
This is easily remedied. You could do something like this:
<definitions name="MyService"
targetNamespace="http://ns.soacookbook.com/sales/v2009Q1"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://www.soacookbook.com/sales/v2009Q1"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
Using a prefix such as “v” to indicate “version” takes care of the client-side generation problem. You don’t have to use a date, of course, and can use a more standard version number.
This has the advantage of making clear in WSDLs, in importing schemas, and in gen-erated client code what exactly is being used. It also allows these items to continue using the version they’re compatible with until they’re ready to take the update.
Because you have changed the namespace, you should create a new document based on the new version, and keep both versions until you can update everybody. Not everything can or should be migrated to the new schema at once.
Make sure that you decide on a single convention up-front, publish it in your developer documentation and governance guidelines, and enforce the structure you’ve chosen.