WSDL Extension Changes (WODEN-47)
JIRA WODEN-47 introduces some changes to the Woden API for handling component extensions. It does not change the API for extension elements and attributes. This page describes these changes. The new source code is in the 'woden47' branch in the Woden SVN repository. The pre-woden47 WSDL extensions programming model is described on the "WSDL Extensions" wiki page.
Summary of the original Component extensions model
Prior to WODEN-47, the API programming model provided read-access to component extension properties by component by namespace. The ComponentExtensions interface defined a minimal super-type (just a getNamespace() method), which was sub-typed for each WSDL component that had extension properties from a particular namespace. For example, SOAPBindingExtensions or HTTPBindingFaultExtensions. These subtypes would declare accessor methods specific to the extension properties of those components. For example, the getSoapVersion() and getSoapMepDefault() methods of SOAPBindingExtensions. These subtypes declared a static, compile-time extension property API for each extension namespace by component.
The implementation classes for these ComponentExtensions subtypes would need to be registered with the ExtensionRegistry via the registerComponentExtension method. For example, SOAPBindingExtensionsImpl or HTTPBindingFaultExtensionsImpl. This was done automatically for the WSDL 2.0-defined extensions implemented by Woden (WSDLX, RPC, SOAP, HTTP). At runtime, Woden would create an instance of the registered implementation class for each occurrence of the extension namespace and component in the WSDL.
WSDLComponent, the super-type of all WSDL 2.0 components, declared the method: getComponentExtensionsForNamespace(NSuri), which returned the ComponentExtensions implementation object for the specified extension namespace. The client application could then use its extension-specific API to access the relevant extension properties.
The WODEN-47 Requirements
The only way that Woden's client applications can access extension properties is via these statically-defined, compile-time extension property APIs declared by the ComponentExtensions subtypes. Some applications need a more flexible approach that provides a more generic API for accessing extension properties, without requiring detailed knowledge of each ComponentExtensions subtype API. For example, WSDL editors or GUI tools should be able to display any WSDL, including it's extensions, without predefined knowledge of all possible extension-types and their specific APIs. They need to be able to retrieve these properties as generic extension properties, via a common programming model.
Summary of the Solution
A new type ExtensionProperty has been introduced which provides a generic representation of an extension property (name, namespace and content as a java.lang.Object). ExtensionProperty accessor methods have been declared in a new type PropertyExtensible, for retrieving extension properties. WSDLComponent now extends PropertyExtensible. These accessor methods retrieve extension properties by namespace or by namespace and name. The namespaces and property names for the extensions defined by WSDL 2.0 are declared in extension constants classes like SOAPConstants and HTTPConstants. These constants classes are now public on the API, instead of being in 'internal' packages.
The ComponentExtensions interface has been renamed to ComponentExtensionContext to better reflect its role as an accessor for retrieving extensions in a particular context (that is, for a component and an extension namespace) and to avoid giving the impression that it is the collection of extension properties for that component and namespace. Furthermore, to avoid API confusion with new PropertyExtensible methods like getExtensionProperties, the WSDLComponent method getComponentExtensionsForNamespace(NSuri) has been renamed to getComponentExtensionContext(NSuri) (and that now returns a ComponentExtensionContext).
The ExtensionRegistry methods that handled the ComponentExtensions type have been changed to use ComponentExtensionContext instead. These are the registerComponentExtension and createComponentExtension methods.
NOTE: Extension properties cannot be treated entirely generically. They can be accessed in a generic way and wrapped as generic ExtensionProperty objects, but the caller will still need to know what to do with the java.lang.Object returned by the ExtensionProperty.getContent() method - what to cast it to or whether it implements a useful toString() method. Woden should possibly provide some guidance here, like "extension implementors should define a suitable toString() method for their extension properties, or for items in an extension property based on a set.". Then, client applications like GUI tools can at least display extension property content without needing to know what type of object it is. As the Woden API convention is to return typed-arrays for a set property, applications could just check for an Array type, then call toString() on each element.
API change impact
Most of the API changes in WODEN-47 are additions to the API. Changes to the existing API have been minimized to keep the new extension model largely backward-compatible.
The necessary changes to the existing API are:
calls to WSDLComponent.getComponentExtensionsForNamespace(NSuri) must be replaced with WSDLComponent.getComponentExtensionContext(NSuri) (the extension subtypes like SOAPBindingExtensions have been changed to the new super-type, so those APIs will not be affected)
calls to ExtensionRegistry.createComponentExtension will now return ComponentExtensionContext instead of ComponentExtensions, but this method is typically called by Woden anyway, not by user code.
The extension constants classes like SOAPConstants have been moved from the internal packages like org.apache.woden.internal.wsdl20.extensions.soap to the public API packages like org.apache.woden.wsdl20.extensions.soap. Existing client code should not have been using the 'internal' constants classes, but if any code was it will need to be changed.
Overview of the new Component extensions model
The following UML class diagram and the notes that follow it provide an overview of the new Component extensions model:
The org.apache.woden.wsdl20.extensions API package contains:
ExtensionProperty - this interface represents a generic abstraction of a component extension property. The getContent() method returns a java.lang.Object. The caller must know what to cast this to or whether it provides a useful toString() method.
GenericExtensionProperty - this class implements the ExtensionProperty interface and is used by the Woden implementation. It is in a public API package because it should be available to other implementors of WSDL extensions to reuse or extend.
ComponentExtensionContext - this interface replaces the ComponentExtensions interface. It declares new ExtensionProperty accessor methods which must be defined by WSDL extension implementors. The original subtypes of ComponentExtensions such as SOAPBindingExtenions, HTTPBindingFaultExtensions, etc, still have the same names and extension-specific APIs, but they now extend ComponentExtensionContext.
BaseComponentExtensionContext - this class implements common behaviour for ComponentExtensionContext, leaving the ExtensionProperty accessor methods abstract, for concrete subclasses to implement. It is used by the WSDL 2.0-defined extensions implemented by Woden and it is in a public API package because it is available for implementors of other WSDL extensions to subclass.
PropertyExtensible - this interface declares accessor methods for ExtensionProperty which are common to all WSDL components, so it is extended by WSDLComponent.
The org.apache.woden.wsdl20 API package contains:
WSDLComponent - this inherits the generic ExtensionProperty accessor methods from PropertyExtensible. It also provides access to ComponentExtensionContext objects by extension namespace via the getComponentExtensionContext(NSuri) method.
The implementation classes for the ComponentExtensionContext subtypes (like SOAPBindingExtensionsImpl and HTTPBindingFaultExtensionsImpl) now extend BaseComponentExtensionContext. User-defined extensions may subclass this too (it's in an API package for this purpose).
In WSDLComponentImpl, the PropertyExtensible methods are implemented by forwarding the calls to the appropriate ComponentExtensionContext object(s).