Architect: Web Services
by Gabriel Bechara
Web services are bound to change and evolve over time. The loose coupling principles of service-oriented architecture (SOA) imply that service providers can release a new version of a shared service without waiting for consumers to adapt, and that service consumers should test and certify on a new shared service version before switching. Consequently, you might need to have multiple versions of a shared service running concurrently and simultaneously accessible by different service consumers. Some service consumers might need to continue using an old version of a service until migration of the consumer code occurs. Therefore, Web services versioning is an important subject that should be considered carefully in all enterprise SOA approaches.
Current standards for Web services have no explicit support for versioning, requiring architects and developers to solve the problem through the application of patterns. This article will:
By the end of this article, you should have a good understanding of the main aspects that should be dealt with when building your own enterprise Web services versioning strategy.
A change in a Web services implementation may affect its consumers depending on a number of factors:
Therefore, a typology of change in Web services can be created in relation to the impact on the current consumers of those services. One approach is to qualify a change that will not affect the current consumers as a minor release and a change that will affect the current consumers as a major release.
A minor release can be one of two types. The first is a correction of a bug or a performance enhancement. This type will not affect the Web Services Description Language (WSDL) of the Web service. The second type consists of adding new methods to a Web service, wherein the WSDL is changed with no impact on service consumers. A distinction can be made between these two types when labeling those versions. For example, for the first type you can change the second decimal place of the version number (1.0X), while for the second type you change the first decimal place of the version number (1.Y0).
A major release involves a change that will break backwards compatibility. In this case the consumers must be modified. A release that only affects the functionalities of a Web service, without affecting the WSDL, is also considered a major release. This is because the current consumers cannot invoke the new version without considering the Web service's modified functionalities. Now that we have identified the various types of changes and their impact on current consumers, let's take a look at different patterns for Web services versioning.
When a new version of a Web service is released -- whether a major or minor release -- the consumers are notified about the change, and are responsible for changing the code to access the new version. The new WSDL is published -- in a UDDI registry, for example -- and a notification is sent to the consumers so that they can find the new service and establish binding with the new service provider. One practice for using a UDDI registry involves associating a given version of a portType to a unique tModel. One WSDL is associated with one tModel. This tModel should contain a reference to the version number for a major release because two major versions will imply two different WSDLs. The tModel may contain a reference to the minor version if two minor versions need to be accessed at one time. A consumer of that portType/version could do a green-pages UDDI search for services that advertise compliance by associating themselves with the tModel of the corresponding version.
This method may impose changes in the consumers' code, at least in the search performed on the registry for accessing a version (major or minor) of a service, even for minor releases. And what if you need to have two minor versions running at the same time? For instance, you might want to deploy a new minor release on a test site to be used by a limited number of consumers, while maintaining the old version for the rest. The consumers of the service deployed on the test site will need to change the end point of the service even if the WSDL is not modified (because it's a minor version). In this specific case, it may be useful to have a layer of indirection between the consumers and the providers, to drive the migration of different consumers in a graceful way.
Figure 1. Consumer Binding Pattern
Note: The consumer binding pattern does not imply the use of UDDI; it refers to the fact that the binding decision is made on the consumer side. We'll discuss interesting uses of this pattern in a moment.
When a new minor version of a Web service is released, the consumer can transparently migrate to the new release. This ability is provided by the layer of indirection through a routing mechanism that ensures content-based routing or user-based routing (based on the IP of the requester, for instance, or on the principal of the requester when propagating security roles) to call the different versions of a Web service.
The use of a layer of indirection allows two minor releases to coexist without changing the consumers' code, and helps to ensure a graceful migration to a new release.
Figure 2. Layer of Indirection Pattern
But in the case of a major release, the consumers will need to change their code. And what if, for some organizational reason, we need to migrate to a new major release without changing the current consumers' code, calling the new service with the old client? This might happen if, for example, some regulatory reason implies a change accessible only through the use of the new major release of a service, provided by a business partner external to your organization. This leads to using an adapter to enable the use of a new major release for current consumers until all the consumers' code is modified.
The adapter pattern consists of adapting the client request and response to be able to consume a new major release of a service. Using this pattern offers a smoother migration, in case the use of a new major version of a service is mandatory for some business, regulatory, or organizational reason.
Figure 3. Adapter Pattern
The different patterns can be applied in different ways. This can be done in the consumers' code, but that is rarely the case because it can cause coding delays and increase the complexity of the code handling versioning. An alternative is to use a mediation layer for decoupling the consumer from the provider and to apply those patterns in the mediation layer. Using Oracle Service Bus as a mediation layer will provide the functionalities of the Layer of Indirection pattern associated with the Adapter Pattern, relieving the consumers' code from those concerns. See Figure 4.
Figure 4. Applying the patterns using Oracle Service Bus
Using this approach based on Oracle Service Bus offers these advantages:
Mediation in Oracle Service Bus is mainly configured using proxies to access business services. In between there are pipelines, consisting of stages, actions, branches, and routing nodes. The message is adapted within those pipelines, routing the requests in the routing nodes. The configuration of the proxies and the business services can be organized with a reference to the version numbers. The proxies in Oracle Service Bus may include in their path a reference to the major release, and the business service may include the major and minor release. For example, for a major v1.XX, we will have one proxy, one or more business services (one per minor release), and one WSDL:
functional_block/module/proxies/v1_XX/
functional_block/module/businessservices/v1_00/
functional_block/module/businessservices/v1_01/
functional_block/module/wsdls/v1_XX
...and for major V2.XX:
functional_block/module/proxies/v2_XX
functional_block/module/businessservices/v2_00
functional_block/module/wsdls/v2_XX
Note: Because the proxies and the WSDL are the same for minor releases, the path containing those does not need to include a reference to the minor version.
We have addressed the access to different services through Oracle Service Bus. But there are other issues to deal with, such as the deployment of two different versions of a service provider coming from the same development environment. Those services might have the same Java Platform, Enterprise Edition (Java EE) Web module context path, because they may have been developed using the same development tools. Therefore, unless you provide a build script that adds version reference in the context of the Java EE Web module, you might want to consider deploying different versions of the same service on different targets. (A target is a cluster or a managed server.) See Figure 5.
Figure 5. Deploying service providers on different Targets
Note: Some frameworks and development tools, including Oracle JDeveloper, automate the versioning of some service providers. That capability has been extended in Oracle JDeveloper 11 Technical Preview 4 to deal with the versioning of Service Component Architecture (SCA) composites (multiple services in one composite).
Presentation services and orchestration services (business process services) will benefit from the transparency of this approach when consuming other services belonging to the business services layer or the data access services layer. But what about consumers of presentation services? A composite portal can consume presentation services using Web Services for Remote Portlets (WSRP) to consume remote portlets. The Layer of Indirection pattern, coupled with the Adapter Pattern using Oracle Service Bus, can also be applied in this case, but we may use a more adapted approach based on the portal capabilities. Portals usually come with administration tools for configuring access to portlets (reusable presentation services). Using users' role-based rules and entitlements to display some part of the composite portal, depending on the user properties, may be more appropriate for the presentation services. This is more of a concern with a composite portal engine than with Oracle Service Bus.
Therefore, presentation services layer versioning is better accommodated using the Consumer Binding pattern. In this context, the pattern is not applied by using a UDDI registry to choose the service. In this case, applying this pattern relies on the entitlements or personalization engine provided by the composite portal. An important aspect of this particular use of this pattern is that the choice of the version is made through configuration, in the portal administration tool. Thus, it will not imply any code modification or maintenance.
The figure below shows how a composite portal can consume portlets through WSRP in different versions of the same application. The selection of the portlet version to be exposed is made in the composite portal engine.
Figure 6. The Consumer Binding Pattern applied to presentation services.
Doing this allows two versions of the same application to run simultaneously, exposing new functionalities only to selected end users based on user profile attributes.
Web services versioning can be handled in a variety of ways, depending on business constraints and the layer to which the service belongs. In this article we've covered practices that can be applied to a variety of versioning tasks:
Some additional factors should be taken into consideration, including XML Schemas versioning and managing dependencies between services and the XML Schemas used by those services. At the organizational level, this will become very difficult to handle without the proper tools for managing dependencies and for driving the changes properly and holistically.
Gabriel Bechara has worked with Oracle-BEA presales and consulting services since 2003. A 15-year veteran of the software industry, Gabriel has served as an architect and advisor on large projects, providing practical experience and feedback on concepts that can provide a foundation for building new information systems. His interests include methodologies for defining software and enterprise architectures, with a strong focus on business integration and SOA.