contract versioning

20
1 Contract Versioning, Compatibility and Composability Kjell-Sverre Jerijærvi, Jean-Jacques Dubray In the recent weeks, many industry analysts have been prompt to point out fears, uncertainties and doubts about SOA. Gartner, for instance, claims that companies with plans to start SOA initiatives are falling, while companies which plan no SOA initiatives have increased from 6 to 16% in the last 12 months. These notes and articles often sound as if companies no longer believe in building reusable IT assets which can be composed in different solutions. We believe that the explanation for this lower level of interest in SOA is quite different: one of the key failure of SOA initiatives has been precisely the inability to produce reusable and composable assets. It seems as if that every new consumer brings enough fresh requirements to mandate a service different from existing services. Since services are more expensive to design, build and operate when compared to more traditional solution architectures, SOA cannot realize a large part of its business case when these services can’t be reused. To our experience, few companies have been able to move beyond primitive reuse of services to achieve the promised effects of SOA. If you ever hope to reuse a service, it is imperative to have clear design guidelines for contracts that express what this service provides and how it can be consumed. You may be able start your SOA initiative without much SOA Governance, but it would be a mistake not to have contract design guidelines. Overtime, these design guidelines will of course become a central part of your SOA Governance design compliance policies. It seems, however, that the industry as a whole has put a heavy emphasis on SOA Governance processes as a way to successfully build reusable assets, often dismissing the “Just a Bunch of Web Services” (JaBoWS) approach , but this strategy has yet to prove that it is enough to accomplish this particular goal. We argue that SOA Governance is necessary but cannot generally deliver Service Specifications that are at the level required for reusing assets over long periods of time. SOA Governance is important, and as much governance as practical should be practiced when identifying, specifying and designing a service. However, because of limited resources, time and the inability to predict the future well beyond a 3-6 month horizon, Governance alone cannot create reusable assets. Inevitably, new and unforeseen service consumers will come with new requirements that will require an evolution of existing services. Without a proper versioning strategy, new versions of a service will result in a new service altogether, creating the need for similar, yet separate registry entries, code bases and lifecycles. Organizations without a proper versioning strategy often deploy, operate and maintain several “versions” of the same service in

Upload: kjell-sverre-jerijaervi

Post on 14-Jun-2015

856 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: Contract Versioning

1

Contract Versioning, Compatibility and Composability

Kjell-Sverre Jerijærvi, Jean-Jacques Dubray

In the recent weeks, many industry analysts have been prompt to point out fears, uncertainties and

doubts about SOA. Gartner, for instance, claims that companies with plans to start SOA initiatives are

falling, while companies which plan no SOA initiatives have increased from 6 to 16% in the last 12

months. These notes and articles often sound as if companies no longer believe in building reusable IT

assets which can be composed in different solutions.

We believe that the explanation for this lower level of interest in SOA is quite different: one of the key

failure of SOA initiatives has been precisely the inability to produce reusable and composable assets. It

seems as if that every new consumer brings enough fresh requirements to mandate a service different

from existing services. Since services are more expensive to design, build and operate when compared

to more traditional solution architectures, SOA cannot realize a large part of its business case when

these services can’t be reused. To our experience, few companies have been able to move beyond

primitive reuse of services to achieve the promised effects of SOA.

If you ever hope to reuse a service, it is imperative to have clear design guidelines for contracts that

express what this service provides and how it can be consumed. You may be able start your SOA

initiative without much SOA Governance, but it would be a mistake not to have contract design

guidelines. Overtime, these design guidelines will of course become a central part of your SOA

Governance design compliance policies. It seems, however, that the industry as a whole has put a heavy

emphasis on SOA Governance processes as a way to successfully build reusable assets, often dismissing

the “Just a Bunch of Web Services” (JaBoWS) approach, but this strategy has yet to prove that it is

enough to accomplish this particular goal.

We argue that SOA Governance is necessary but cannot generally deliver Service Specifications that are

at the level required for reusing assets over long periods of time. SOA Governance is important, and as

much governance as practical should be practiced when identifying, specifying and designing a service.

However, because of limited resources, time and the inability to predict the future well beyond a 3-6

month horizon, Governance alone cannot create reusable assets. Inevitably, new and unforeseen service

consumers will come with new requirements that will require an evolution of existing services. Without

a proper versioning strategy, new versions of a service will result in a new service altogether, creating

the need for similar, yet separate registry entries, code bases and lifecycles. Organizations without a

proper versioning strategy often deploy, operate and maintain several “versions” of the same service in

Page 2: Contract Versioning

2

production drastically limiting SOA’s benefits and Return-On-Investment fueling comments from some

analysts who have been prompt to claim that “reuse” should not be expected as part of a SOA initiative.

In this article, we provide a series of recommended practices for establishing a Service Contract

Versioning strategy geared towards service reuse, composability and compatibility with prior consumers

(or providers). We claim that such versioning strategy is essential to achieve satisfactory levels of service

reuse and in turn generate higher (and expected) ROI from SOA initiatives.

Elements of a contract “A contract is the most important metadata in SOA”, says Ron Schmelzer, analyst at ZapThink. There are

many parts to a contract between a service provider and a service consumer. Some of these elements

can be made machine readable, and even for some enforceable at runtime, using technologies such as

XML Schema, WSDL and WS-Policy specifications for instance, while other elements will remain mostly

for human consumption only.

The goal of this paper is not necessarily to look at every possible elements of a contract from the format

and sequence of the bits that travel on the wire, to service level agreements or legal statements (about

privacy for instance). Rather, we would like to focus on one simple problem: defining a strategy that

supports the evolution of a service provider or consumer while remaining compatible with existing

consumers or provider, respectively. We believe that this strategy is core to delivering the benefits of

SOA and can greatly reduce both the initial cost of building a service (because it reduces the need for

governance) as well as the ongoing service maintenance and operations costs.

The proposed versioning strategy is twofold:

a) Create machine readable contract elements that express all rules enforced at run-time by both

the service consumer and provider

b) Create or leverage a set of compatibility rules between the versions of the contract elements

agreed upon service consumers and providers

Machine readable contract elements are the foundation of versioning because this metadata can and

must be used by both the service consumer and provider to decide whether the current message sent to

and received at an endpoint will and can legitimately be processed. These elements define the lowest

bar for a potentially successful processing of a given message. Of course, business rules in the service

implementation can potentially return a contract exception.

One strategy could be to define no machine readable contract element and keep exchanging exceptions

each time the consumer or provider cannot process a message, until either the consumer or the

provider fixes the problem. For instance, members of the REST community have advocated the adoption

of a “uniform contract” dismissing the need for further machine readable elements which could have

otherwise provided unambiguous semantics while assisting in the implementation, validation or

configuration of a service. Yet, the REST community does not provide evidence that RESTful Web

Services can be evolved in a compatible way.

Page 3: Contract Versioning

3

The problem is less about which contract elements one needs, but how to facilitate the expression of

compatibility between two versions of a service provider (or consumer). In other words if a consumer

interacts with a new version of service provider, are we expecting a behavior equivalent to the prior

version or not? Adopting a “uniform contract” such as agreeing simply on sending and receiving

messages at a particular location is not going to help answer the compatibility question.

In this article we will focus on the metadata necessary to validate whether an incoming SOAP message is

legitimate or not. So we will focus on the contract elements defined in a WSDL document. Since the

usage of WSDL 2.0 is not yet widespread, we will be using WSDL 1.1. We do not believe that there would

be any significant changes when applying this strategy to WSDL 2.0. The elements of WSDL 1.1 include:

Service definition target namespace

Message types

Message definitions

Port types

Bindings

Service definitions

Optional policies expressed using WS-Policies

Fig 1. Elements of a WSDL 1.1. Contract

Versioning guidelines Service and Schema Versioning can lead to these types of compatibility scenarios (Fig 2):

No compatibility

Forwards Compatible

Backwards Compatible

Page 4: Contract Versioning

4

A new version of a contract that continues to support consumers designed to work with the old version

of the contract is considered to be Backwards Compatible.

A contract that is designed to support unknown future consumers is considered to be Forwards

Compatible. Such a contract anticipates that consumers will evolve over time by supporting extensibility

through XML Schema wildcards. This type of compatibility is often found in B2B scenarios where a

consumer works with multiple service providers which may evolve at a slower pace. In the enterprise,

the most common scenario is backwards compatibility.

Backwards compatibility is what is typically meant by “compatible” and is possible when non-breaking

changes are made to a contract. Making breaking changes to a contract will always lead to no

compatibility. These scenarios have been extensively described in the literature by John Evdemon or

Dave Orchard for instance.

Note that contracts can be both backwards and forwards compatible (more on this later).

Fig 2. Service Operations Compatibility Scenarios

The degree of support of Web Services technologies for both forwards and backwards scenarios is

unmatched in the distributed computing technologies world. Neither RPC, CORBA, DCOM or JEE have

been able to support these scenarios out of the box, simply by applying specific design constrains. As a

matter of fact the ability to support these scenarios is a key to achieving loose-coupling and reuse.

When a service is evolved in a backwards compatible manner, it can be reused by more consumers,

without requiring existing consumers’ implementation or configuration to change. When Governance

has failed to predict the needs of future consumers or when the budget prevented to get all the features

needed in V+0, compatible service versioning is what enables updates without impacting existing

consumers’ operations. In particular, this is how “JaBoWS” can slowly but surely evolve into Enterprise

Class services, serving a wide range of consumers.

Page 5: Contract Versioning

5

Compatibility is defined by a stated versioning scheme:

Major versions: incompatible (breaking change)

Minor versions: compatible (non-breaking change)

Breaking changes are modifications, for instance, to existing schema types that will cause processing of

incoming messages to fail, such as changing an existing optional element to be mandatory or adding

new required elements. Non-breaking changes are e.g. adding a new optional element. Non-breaking

changes to schemas or services are registered as minor versions, while breaking will always be

registered as a new major version.

All the versionable artifacts of a service will be affected by changes, and these changes will ripple

through the artifacts from bottom to top, and eventually the ripple effect will impact your consumers.

This ripple effect is detailed in table 1 and illustrated in figure 3. While versioning lets you control the

effects of changes, compatibility helps you alleviate some of the negative effects of versioning.

Fig 3. The ripple effect of changes

In the following, we will state that a service version is incompatible using a major version and a

compatible version (forwards or backwards) using a minor version. Point version should be used to

denote versions that did not involve contract changes and were limited to implementation, deployment

or configuration changes (for instance a bug correction, a new service container release, etc). Point

versions are always compatible by definition (again this is a statement not a guaranty).

Artifact Change Major Minor Point

Service Breaking X

Service Non-Breaking X

Page 6: Contract Versioning

6

Composite Service Incompatible Schema Service X

Composite Service Compatible Service X

Service Incompatible Schema X

Service Compatible Schema X

Schema Breaking X

Schema Non-breaking X

Schema Aggregate Incompatible Schema X

Schema Aggregate Compatible Schema X

Code Bug fix / maintenance X

Code Safe modifications X

Code Semantic / Unsafe modifications X

Other service

artifacts

Any X

Table 1. The versioning ripple effect of changes to code, schemas and services

Two message types can be stated to be compatible using these simple rules when designing Message

Type Schemas:

XML Namespace values must be constant for a given message type and a given major version

Message type schemas must include mandatory minor and point version custom attribute on

the message type root element, using for instance a type xsd:int.

Whether XML validation is used or not, each message consumer must verify that the major

version of an incoming message is matching its own implementation version. An exception

should be returned when the major versions of the message sender and receiver do not match.

In the .Net world, Message Type artifacts are also known as data contracts.

Page 7: Contract Versioning

7

Web Services Extensibility Guidelines The principles of forwards compatibility have been well documented (see also this reference), yet they

are rarely applied. For the sake of clarity we are detailing them here.

Service definition target namespace

WSDL target namespace can be different from Message types XML Schema namespaces. WSDL target namespace must be different each time the service contract or implementation is modified, be it for a point, minor or major version This namespace is not used at runtime, provided that SOAP actions are defined manually instead of automatically by the runtime. Therefore, all WSDL definitions MUST include manually defined SOAP actions1

Message types Message type schemas must be designed with the utilization of XML Schema extensibility mechanisms (we provide a detailed discussion of these mechanisms below) Message type namespaces must only refer to a major version of the service contract, indicating an incompatible service version. Minor version may be specified as an attribute to the root element

Message definitions Parts can potentially be added to message definitions, we however recommend to use a single part which contains a message envelope in which content can be extended using XML Schema’s extensibility rules

Port types Port types can be extended with new operations No changes can be made to the operation’s signature nor the order in which the operations are called (which is not specified in WSDL)

Bindings New bindings can be defined, however, existing bindings cannot be modified, including the endpoint of the service

Service definitions Services definitions can only be extended with new ports, existing ports cannot be altered

Optional policies expressed using WS-Policies

There are no general framework available to assess compatibility scenarios for policies

Table 2. Service Definition Compatibility Design Rules

The design of Message Types using XML Schema must be carefully planned to achieve forwards

compatibility, also known as XSD extensibility.

John Evdemon explains:

The XML Schema standard introduces <xsd:any> as a wildcarding element.

<xsd:any> enables schemas to be extended in a well-defined manner. <xsd:any>

includes a namespace attribute that either constrains or extends the range of

elements that might appear within the wildcard. The namespace attribute can be

set to any of the following:

##any enables the use of elements from any Namespace to extend the schema.

##targetnamespace restricts wildcards to the elements that appear within the

targetNamespace.

Page 8: Contract Versioning

8

##other makes it illegal to extend the schema using elements from the

targetNamespace.

The processContents attribute dictates how schema extensions should be

validated by the parser:

strict requires the parser to validate all schema extensions.

skip turns off validation for schema extensions.

lax validates elements from supported namespaces and ignores unknown or

unexpected elements (most Web services specifications use lax).

Regarding XSD extensibility, there is a snag in the XML Schema’s 1.0 specification. Because of the

unique particle attribution (UPA) rule there is an ambiguity during the validation of XML Schema types

that have an optional or unbounded number of elements as their last element in the type definition. For

that reason, when the last element of the type has a variable cardinality, we have to add a specific

element with a cardinality of exactly one, before using the <xs:any

namespace=“##targetNamespace”…/> element.

For instance, you may want to choose an element such as this one:

<eovMxmy> where x and y are the major, minor version numbers (eov stands for end-of-version)

In XML Schema 1.1 this ambiguity will be removed and this additional element will not be needed.

Using XML Schema extensibility features is one thing, but we still need to define and agree on a set of

rules when an older version of a message consumer encounters a new version of a message. It is likely

that this new message will have elements that fall in the some of the extensibility sections. The question

becomes then, what should we do with these elements? We recommend applying the following rules

which result in Forwards Compatibility requiring no consumer side changes:

The behavior of a service when it encounters an unknown element must be clearly defined by

an extensibility handling rule as part of the contract

New elements added to a new version of a message type designed to be forwards compatible

must not invalidate the prior version of the message type

Consumers of a message must accept and remove from processing any element that they do not

recognize

Responses generated from a request that contains the same types as their corresponding

request must add the corresponding elements they removed prior to processing the request

Page 9: Contract Versioning

9

These rules ensure that every consumer is in the position to use XML schema validation for the elements

that it is bound to process in its implementation. In no way, we are recommending to use of XML and

XML schema extensibility in a sloppy and forego validation (Figure 4). Contrary to a widespread belief in

the industry, XML and XML Schema extensibility is essential to a compatibility-based versioning

strategy, and hence essential to achieve reuse.

Consumers and providers’ implementations are asymmetric when it comes to their implementations:

If the consumer validates the incoming messages sent by the provider, they will pass validation

(because of the implementation rules defined)

However, -and of course- the service provider implementation must in general keep track of the

schemas for all the minor versions for incoming messages and validate each incoming message

based on its minor version number for a given major version, even possibly route the call to

variants of the implementation

The reason for that is because an upper minor version schema cannot validate a lower version schema

(in general). The upper minor version will most likely have required elements in the same target

namespace that cannot be validated with a lower minor version schema.

Consumer Variations There is also a need for “extension areas” in an XML Schema that are different from versioning (Figure

4). For instance, extensions are common when consumer specific variations are needed, i.e. when

specialized relationships between consumers and providers (independently of other consumers) are

necessary. These extensions can be viewed as a private contract between a particular consumer and the

service provider, embedded in the contract common to all consumers. Again, having a strategy to enable

these extensions is essential to achieve a good level of reuse of services.

Extensions must be treated separately from the general versioning patterns. We recommend

implementing extensions using a single element under the root element of the message type.

Extensions must not be processed by the message consumer, unless they are explicitly defined

in its message type or unless specified with a mustUnderstand=’true’ attribute. The message

consumer’s implementation must generate an exception when it cannot process the required

elements.

It is advised to have extensions belong to a different namespace from the root of the message

type.

Page 10: Contract Versioning

10

Fig 4. Versioning and User Extension Compatibility

With Web Services technologies, the fact that one may use different endpoints to access the same

information via different versions of the business logic simplifies greatly the maintenance and

operations of the corresponding services. Overall, Web Services technologies, XML and XML Schema

offer unprecedented opportunities to support compatibility scenarios unlike distributed computing

technologies before them, including REST which cannot rely on a stable contract to specify a versioning

strategy. In REST, the fact that each resource exposes an endpoint is creating a strong coupling between

the endpoint and the resource and makes it difficult to operationally manage multiple major versions of

the implementation of the business logic as REST offers no room to introduce a layer of indirection. This

coupling between resource and endpoint makes it difficult to assign a version to a resource type. In REST

each resource (instance) can potentially implement its own version of the business logic associated to a

particular version of HTTP verb and arbitrary noun.

Page 11: Contract Versioning

11

Compatibility & Composability The compatibility scenarios defined earlier can be combined into these strategies as defined in the latest

Thomas Erl series book Web Service Contract Design and Versioning for SOA:

Strict: Any change is considered unsafe and must cause a new version. Non-breaking changes

cause a new minor version. Breaking changes will require a new major version. Both backwards

and forwards compatibility is intentionally disregarded.

Flexible: Non-breaking changes will only result in a new point version. Breaking changes will of

course require a new major version. This strategy uses backwards compatible contracts, but not

forwards compatible contracts.

Loose: Use both backwards and forwards compatible contracts. Breaking changes will of course

require a new major version.

“Strict” is a very common approach to handling schema versioning. It is a safe approach that will give

you no surprises when changing contracts. In fact, the schema artifact versioning table shown above is

based on the “Strict” strategy. However, it will lead to an explosion of contract versions as your services

evolve, and this will hurt discoverability and especially governance not to mention reuse. In addition,

operations will need to keep your multitude of service versions up and running. Changes to schemas

that are used in aggregate schemas (schema compositions) will ripple through all involved aggregates

and cause a domino effect of new schema versions. And of course, when a schema used in a service gets

a new version, the service must also get a new version. Composite services that involve these services

will then also be affected and must also get a new version. Thus, the ripple effect is much bigger than

you think.

This versioning domino effect soon has caused a little change to ripple through all versionable artifacts

in your system. And it doesn’t stop there; in the end it will affect your consumers.

Composability will suffer when you have poor service discoverability and a proliferation of service

versions. Which services should an unfortunate consumer use and which services will work together as

composite services? Having standardized service contracts including a common information model for

your domain might not be enough when there are thousands of versions of the standardized services

and schemas.

“Flexible” tries to alleviate the version explosion effect of Strict, by treating all non-breaking changes as

safe and backwards compatible. As backwards compatible contract changes by design continues to

support consumers designed to work with the old version of the contract, a new version is not needed –

i.e. it is just a point version. Services can easily be composed together as all the contracts within a major

version are backwards compatible and only one minor service version – the latest – needs to be

considered for every major version. Add “Loose” to get forwards compatible contracts, and all your

compatibility & composability issues are history.

In theory this seems to be the perfect solution, only breaking changes will require a new version and

hence ripple through all versionable artifacts. In theory - had it not been for possible side-effects of

Page 12: Contract Versioning

12

“safe” changes, both functional and non-functional. As Nicolai M. Josuttis shows in the book SOA in

Practice even adding a new optional XML element can have non-functional side-effects such as

increasing the response time of a service, breaking the SLA of the service. It would be safer to provide a

new service version with the new schema, as if there is a problem, only the upgraded consumers that

required the change will be affected. Keep in mind though, that in our proposed recommendations, the

compatibility is stated, not implied, so if the SLA was changed by a single element, this would mandate

the definition of a new major version (and XML namespace), even though from an XML extensibility

perspective, this change is perfectly compatible.

A certain combination of these will work better to our experience:

Flexible/Strict: Use “Flexible” for all safe schema changes, while “Strict” must be used for any

unsafe modification to schemas. Breaking changes will require a new major version. Support

forwards compatibility.

The “Flexible/Strict” strategy combines the best from the three original strategies. It grades changes into

safe and unsafe even if they are theoretically backwards compatible (i.e. non-breaking). Safe changes

cause point versions, while unsafe changes cause at least a minor version. There are no absolute

classification schemes of which changes are safe and which are unsafe, but we suggest that adding to

schemas are considered safe while modifying existing schema components are considered unsafe.

Always judge if even a “safe” change may cause negative side-effects, remember to consider non-

functional aspects.

Strategy Change Major Minor Point FW

Strict Breaking X

Strict Non-Breaking X

Flexible Breaking X

Flexible Non-Breaking X

Loose Breaking X X

Loose Non-Breaking X X

Flexible/Strict Breaking X +

Flexible/Strict Non-Breaking, Safe X +

Flexible/Strict Non-Breaking, Unsafe X +

Table 3. Compatible changes classified as safe or unsafe

Using “Flexible/Strict” will impact the schema artifact versioning table as all changes that in the “Strict”

sense must be a new minor version now can become just a point version for safe changes. Unsafe non-

Page 13: Contract Versioning

13

breaking changes must still be a new minor version. Note that even if you judge a code change to be

safe, we still recommend this to be a new minor version.

Schemas are validated and routed based on their major and minor versions, thus aiming for point

version compatibility will also reduce the need for intricate versioning mechanisms in your services.

We recommend using the “Flexible/Strict” strategy for your published services, and also use forwards

compatibility in the form of planned extensibility. Avoid just throwing in schema wildcards everywhere

as this will lead to vague contracts, countering discoverability. John Evdemon advices that “schemas

should be designed for extensibility, not to avoid versioning”. Judicious use of unambiguous wildcards

can help minimize service versioning. We strongly recommend following these guidelines.

Use a combination of compatible contracts and multiple active service versions to ensure that you’re

system is flexible enough to accommodate the inevitable changes that will happen over time. Keep

things simple. Whatever you do, do not try to implement some implicit automagical handling of

versioning inside your services; instead expose your services at abstract endpoints and apply intelligent

routing to achieve service virtualization and apply schema duck-typing outside your services.

You should use the flexible strategy during development of the services due to the agility needed in that

phase. Wait until the services have been published (are in production) to apply strict versioning aspects,

otherwise you will just end up with a very frustrated bunch of consumer and provider developers.

Note that how platforms support forwards compatibility differs. Some require the use of schema

wildcards while others like WCF have implicit support for forwards compatibility. Always test that your

involved platforms work with your forwards compatible schemas. Don’t rely on this just working,

interoperability is important for composability.

Data Model and Message Type DSLs One of the core problems of distributed computing technologies is the combined handling of both

information and business logic. Some approaches are good at managing distributed information (REST /

HTTP) and some technologies are good at invoking business logic (Web Services). Technologies that have

tried to address both using a combination of remoting technologies and naming & identity services have

generally failed at delivering an environment where both information access and business logic

invocation coexist harmoniously. Most often, a pattern, such as the Data Transfer Object pattern, has

become the prevalent mode of interaction and information representations are simply conveyed back

and forth between endpoints representing services, i.e. business logic.

One of the fundamental reasons for the lack of solution for this difficult problem is the fact that

Enterprise Data is “relational” and utilizes most often bidirectional associations. By contrast, the Web is

built on a “navigational” data model and unidirectional links. In both cases (navigational and relational),

there is always the need to fetch data in a denormalized way via the same endpoint. This means that

when fetching a purchase order, one might also return some customer specific information (name,

address, telephone…) as well as shipping information. Whether you use a RESTful approach or a Web

Page 14: Contract Versioning

14

Services approach, the problem is exactly the same. REST is of course slightly better equipped to provide

a normalized solution to this problem since a link to the customer can be embedded within a purchase

order representation, but this is generally not practical as representations often need to embed related

data, to enhance user experience, limit navigations and network roundtrips.

The goal of this paper is not to solve this distributed information integration problem. We are going to

assume that somehow people can only deal with it behind endpoints in both REST and Web Services

world (this is the state of where we are today until more progress is made in distributed computing

technologies). In this environment, the problem people have to deal with is how to manage

denormalized message types, especially in the context of versioning, i.e. when the enterprise data

model needs a revision (Fig 5.).

Fig 5. How do we keep the enterprise data model and message types synchronized?

Up until this point, the industry has kept Enterprise Data Models, XML Schemas and Message types

relatively separate. At most, people defined an ontology with links to both.

In this article we argue that (Fig 6.)

XML Schema should not be used for creating and managing enterprise data models.

Enterprise Data Models should be created and managed based on a DSL (EDM-DSL)

Message types should be created and managed based on a DSL and using the Enterprise Data

Model elements as building blocks (MT-DSL)

XML Schemas should be generated from the Message Type DSL (itself referencing elements of

the Enterprise Data Model).

?????

Customer Order

1

0..n

PO

Customer

name

address

Shipment

Shipment0..n

0..n

POs

Customer

name

address

PO# POs

Customer

name

address

PO#

Shipment

name

address

PO#

PO#

Page 15: Contract Versioning

15

Fig. 6. Enterprise Data Model and Message Type DSLs

Let’s explore these points one by one. XML Schema should not be used for creating and managing

Enterprise Data Model because XML Schema was never designed for that. XML Schema cannot describe

efficiently the relational nature of enterprise data models. XML Schema is hierarchical in nature and

cannot model well bidirectional relationships between information entities. XML Schema is a technology

that is well suited to describe and validate the structure of self-standing “documents” be it message

types, web pages, office documents…

Enterprise Data Models should be created and Managed based on a DSL because no current modeling

technology, be it UML or Entity-Relationship diagrams (ERD) have the appropriate semantics to describe

Enterprise Data Models. The core semantic that is missing, and that makes it a non starter for any

existing technology, is paradoxically having the ability to describe a hierarchical structure of related

elements. In other words be it in UML or ERD, we do not have the semantic to define the boundary of a

purchase order or a customer. We can define classes or entities, but in reality a purchase order or a

customer is effectively “composed” of several classes. We need to be able to define a boundary to these

objects and no “standard” modeling language support this semantic because they themselves are too

close to the physical implementation model (Object Orientation in the case of UML and RDBMS in the

case of ERD). In the case of UML, we would have to define a UML profile to extend it with these

semantics. We recommend however to create a dedicated Data Model DSL instead of using a UML

profile because transformations are a lot easier, uncluttered by the UML metamodel.

Message types should be defined based on a dedicated message type DSL which references elements of

the Enterprise Data Model because, in essence, this is really how Message Types are constructed (or at

least should be constructed). When you create a service interface, be it RESTful or Web Services based,

EnterpriseData

ModelDSL

Message TypeDSL

EnterpriseData

Model

Message TypeMessage

TypeMessage

TypeDefinition

references references

Message TypeMessage

TypeWSDL

Message Type

Message TypeMessage

TypeMessage

TypeXML

Schema

Based on

Based on

referencesGenerate

Page 16: Contract Versioning

16

you really want to create a message type (or resource representation) that reflects the enterprise data

model both semantically and structurally, instead of reflecting the particularities of a given back end

system. This is in line with loose coupling practices which recommend to minimize the “contract-to-

implementation” coupling. An approach based on the semantics of an Enterprise Data Model is

expected to reduce the need for both Governance (or at least reuse Data Governance efforts) and

create service interfaces or resource representations that will be most likely reusable and composable.

Finally, flat XML Schemas should be generated from these Message Types definitions (based themselves

on the Enterprise Data Model). Flat schemas improve interoperability between Web Service stack as

some stack have difficulties to deal with complex nested schema files. XML Schema is a great technology

to validate the structure and (some of) the content of “documents”. It should remain the primary choice

for describing the structure and validating the content of incoming messages.

Active Service Versions It is important to implement service lifecycle management policies and procedures to help with

governing service versions. We recommended creating an “Active Service Versions” policy to keep the

number of service versions that you have to govern to a minimum. Alas, our experience shows that in

practice this will be hard to adhere to, thus implement the policy as a guideline rather than a law.

Such a policy typically states that there should be maximum three active versions of a service available

for consumers, plus a hidden active minor version of the latest major. The hidden minor version gives

current consumers a transition period for reverting to a compatible version, just in case the

compatibility statement made for the latest minor version was erroneous. In that case, the consumer

will manually point to the previous minor version endpoint.

Fig. 7. Service version classification

Page 17: Contract Versioning

17

You will typically end up with some services that require 5-6 major active service versions, especially for

popular services that are used by multiple consumers. There will always be some consumers that are

laggards in upgrading to newer service versions, and you might not be able to cut them off. However,

the approach that we are recommending ensure that for every major version available, we only need to

expose the respective latest minor version.

Ensure that new consumers always by default discover the published version of your services (i.e. the

latest major/minor version). The published version is what developers will get using the classic

http://url?WSDL “discovery” of the service. In addition, we recommend that three major versions of a

service can be discovered in your service registry. These must be the latest minor version of each.

Finally, you must monitor the usage of the services to know which are used and by whom. The service

lifecycle stewards must notify all consumers of deprecated versions and gently force them to upgrade to

an active service version. When no one (important) is using a deprecated version, you can decommission

it. This ends the lifecycle management of that service version. You can easily imagine how much harder

the steward’s job would be if he or she had to do the same thing for both the major and multiple minor

versions as well.

The active service versions should be accessible through a single virtual endpoint that the consumers

use to invoke the service. This will lessen the impact that versioning the service will have on its

consumers, as the virtual endpoint stays the same and handles the routing to the correct active service

version. Compatibility reduces the need for virtualization as the same endpoint can service several

generations of compatible consumers. Services are routed based on their major and minor versions,

thus aiming for point version compatibility will also reduce the need for complex virtual endpoint

mechanisms.

Service Virtualization is achieved by combining several ESB patterns such as abstract endpoints,

intelligent routing and schema transformations. Using service virtualization isolates the consumers from

the providers and it processes messages “in-flight” to route and mediate between the providers and

versions that make up a composite service that a consumer invokes or triggers through an event.

Using virtualization is not only for composite services, in fact all your published services at any

classification level would benefit from this seen from a governance perspective.

Page 18: Contract Versioning

18

Interoperability The economy is getting more and more globalized and outsourcing seems to be the standard these days.

The business processes of a company more often than not involve partners and suppliers mashed

together into what is called the extended enterprise

The constituents of an extended enterprise will have heterogeneous systems, just as the different

business units of a company most likely will have heterogeneous systems (figure 8). There is no end to

the diversity of legacy systems in use in companies today. A recent Gartner study shows that the

diversity of platforms used to deliver SOA is growing, even mainframe COBOL have had a surge the last

year.

Composability across these heterogeneous service providers in the extended enterprise will require

interoperability. This affects how you design your services and schemas, including which of the WS*

standards you choose to entail in your services. Our interoperability experience is summarized in the

below table.

Artifact Interoperability

SOAP Adhere to WS-I Basic Profile 1.1

SOAP 1.2 Most legacy platforms and tools require SOAP 1.1

WSDL style Prefer “Document/Literal Wrapped” (D/L-W)

WSDL design Avoid wsdl:import and xsd:import as many tools require a single flat WSDL. An

example is Flex.

Messages Use message exchange patters (MEP) e.g. as defined in WSDL 2.0

Message design Single part element for both request and response

Schema style Prefer “Venetian Blind” (complex types)

Schema style Do not use anonymous types (“Russian Doll”)

Schema design Support XSD extensibility, use marker element before schema wildcard; always

test support for schema wildcards across involved platforms

Schema design D/L-W schema components: allows only elements, prohibits use of attributes

Schema design Use of attributes for data or to annotate data elements might not be

supported by all platforms

Schema arrays Use wrapped arrays/collections

XSD types Not all XSD data types are supported by all platforms (e.g. xs:date,

xs:positiveInteger)

Page 19: Contract Versioning

19

XSD nillable Some nillable schema components might not be supported by a platform,

while other components might be required to be nillable

WS* standards The support varies wildly between platforms, always test and verify chosen

standard for interoperability

WS-Security Make sure to agree on version, token type, message or transport security,

order and level of encryption and signing, and establishment of secure

conversations (security sessions)

WS-Policy,

WS-SecurityPolicy

Some platforms and tools do not support these standard, thus policy metadata

have to be communicated out-of-band. An example is Java Spring-WS.

Table 4. Contract design guidelines

Fig. 8. Growing diversity in SOA platforms

The figure “Trends in Use of Development Languages are Related to SOA Adoption” is from the Gartner

report “2008 SOA User Survey: Adoption Trends and Characteristics” by Daniel Scholler.

Page 20: Contract Versioning

20

Conclusion

In this article we have defined a versioning strategy which focuses on reuse by enabling services to

evolve to meet new consumer requirements without breaking existing consumers of the service. In a

way this is a “forward” reuse strategy, as the “new version” of a service is reused by the older

consumers instead of the other way around, where a new consumer reuses a service designed for an

existing service consumer.

From our experience, we feel that compatible, versioned data models, messages and services have not

been a primary concern of SOA initiatives. In addition, of those that defined a versioning strategy, very

few have used XML and XML Schema extensibility. It is our strong belief that a compatibility-based

versioning strategy can increase service discoverability, composability and true reuse. It can also reduce,

albeit not eliminate, the need for service governance. Overall, it is expected that the cost of

construction, operation and maintenance of a service will greatly be reduced by such versioning

strategy. It is time to move beyond primitive reuse to reap the benefits of your service inventory.

1 Harmut Wilms, InnoQ, Private Communication