270 likes | 392 Views
Web service and XML Extensibility and Versioning. David Orchard W3C Lead BEA Systems. Distributed Architectures. Description Registry. Description. Contains. Describes. Uses. Client. Service. Message. Examples: Registry: UDDI, Google, Email Description: WSDL, Sample msgs, word
E N D
Web service and XML Extensibility and Versioning David Orchard W3C Lead BEA Systems
Distributed Architectures Description Registry Description Contains Describes Uses Client Service Message Examples: Registry: UDDI, Google, Email Description: WSDL, Sample msgs, word Message formats: SOAP, XML, HTML
Loosely Coupled • Various definitions of Loose Coupling • #1: Interface to Programming environment • Changes in programs affect interface? • XML helps with this problem • Need to bind XML to language • #2: Interface changes breaking application • If the data structure changes, then client breaks • The “version” problem, new version of interface
Program change • Software Indirection from Address • Insulates client from sender • In Distributed Objects, client connects directly to object • Use only the data needed • Validate only the data needed, ignore the rest • Other portions of the message can change • Pipeline aka Handler chains • Modularize the places that change • Massage the data if possible to older interface • Mapping layers • Map Data into programming language • Can provide multiple mappings of data into the same service
Handler Chains • Handler chains (aka Pipelines) are chains of processing steps • Handler A -> Handler B -> Application • Allow loose coupling between the components • And can add the handlers in without changing the application • Example: • Handler A is a WS-Security handler • Decrypts an encrypted message • Verifies Signature • Handler B is a Reliability handler • Persistently stores message and sends an Acknowledgement • Handler chains work best with SOAP headers • Well defined framework for extensibility
Extension & Versioning • Perhaps the biggest goal of loose coupling is to allow distributed extension and evolution • Versioning a super hard problem • This introduces some rules to guide design • Achieve backwards and forwards compatible evolution of interface
Compatibility definitions • Backwards Compatible • Newer software can read older versions of documents • ie. Update Schema and older documents validate • Forwards Compatible • Older software can read newer versions of documents • Incompatible extensions mean that software must be upgraded
Web services ext & vers • WSDL perspective, what can change? • Add/change/delete message content • Add/delete operations • Add/delete bindings • Add/delete interfaces • In general, changing operations, bindings, interfaces is incompatible change • Though adding an input operation is compatible • Much can be done for message content
Rules for data versioning • #1: Allow Extensibility • any namespace • other namespaces • Extension element + other namespaces • #2: Ignore Unknown content • #3: Keep Namespace if compatible change • #4: Use version attribute for “minor” version • only if needed • #5: Use MustUnderstand Model
Rule #1: Allow Extensibility • Allow elements in other namespaces • Allow attributes in any namespace • Schema Wildcard element’s attributes: • ProcessContents is for schema validation • Lax allows WSDL to control validation • Namespace for which namespaces are allowed • Schema does not have a “default” extensibility model • sometimes called open content model
First Solution • <s:complexType name=“NameType"> <s:sequence> <s:element name=“first" type="s:string" minOccurs="1" maxOccurs="1"/> <s:any processContents="lax" namespace="##any“ minOccurs="0" maxOccurs="unbounded" /> </s:sequence> <s:anyAttribute/></s:complexType> • <ns:name> <ns:first>Dave</ns:first> <ns:last>Orchard</ns:last> </ns:name>
First Solution Problem • Problem: Can’t create new Schema for this • Illegal: • <s:complexType name=“NameType"> <s:sequence> <s:element name=“first" type="s:string" minOccurs="1" maxOccurs="1"/> <s:element name=“last" type="s:string" minOccurs=“0" maxOccurs="1"/> <s:any processContents="lax" namespace="##any“ minOccurs="0" maxOccurs="unbounded" /> </s:sequence> <s:anyAttribute/></s:complexType>
Why so complex? • XML DTDs and XML Schema require “deterministic content models”. • “the content model ((b, c) | (b, d)) is non-deterministic, because given an initial b the XML processor cannot know which b in the model is being matched without looking ahead to see which element follows the b.” • This means optional elements followed by <any targetNamespace=“ns”> are NOT allowed • <s:element name=“last" type="s:string" minOccurs=“0" maxOccurs="1"/><s:any processContents="lax" namespace="##any“ minOccurs="0" maxOccurs="unbounded" /> • <s:element ref=“ns2:last” minOccurs=“0" maxOccurs="1"/><s:any processContents="lax" namespace="##other” minOccurs="0" maxOccurs="unbounded" />
Second Solution • <s:complexType name=“NameType"> <s:sequence> <s:element name=“first" type="s:string" minOccurs="1" maxOccurs="1"/> <s:any processContents="lax" namespace="##other“ minOccurs="0" maxOccurs="unbounded" /> </s:sequence> <s:anyAttribute/></s:complexType> • <ns:name> <ns:first>Dave</ns:first> <ns2:last>Orchard</ns2:last> </ns:name>
Second Solution Problem • Problem: Can’t create new Schema for this • Illegal: • <s:complexType name=“NameType"> <s:sequence> <s:element name=“first" type="s:string" minOccurs="1" maxOccurs="1"/> <s:element ref=“ns2:last” minOccurs=“0" maxOccurs="1"/> <s:any processContents="lax" namespace="##other“ minOccurs="0" maxOccurs="unbounded" /> </s:sequence> <s:anyAttribute/></s:complexType>
Extension schema choices • extension is required - incompatible • extension is optional, either: • Lose the extensibility point • This means only 1 new version • Do not add the extension into the schema • Validate any extensions found if you can • Can’t validate the “right” extensions are in the “right” place • <name><first/><areacode/>….. <phone><last/>
Extension element • There is another, though more complex, way to do this • Extension element for same namespace • This element has only a wildcard • This does the “swap” extensibility for element content trick
Third solution • <s:complexType name=“name"> <s:sequence> <s:element name=“first" type="s:string" minOccurs="1" maxOccurs="1"/> <s:element name="Extension" type=“ns:ExtensionType" minOccurs="0" maxOccurs="1"/> <s:any processContents="lax" namespace="##other“ minOccurs="0" maxOccurs="unbounded" /> </s:sequence> <s:anyAttribute/></s:complexType><s:complexType name="ExtensionType"><s:sequence> <s:any processContents="lax" namespace="##targetnamespace“ minOccurs="0"maxOccurs="unbounded" /></s:sequence><s:anyAttribute/></s:complexType>
Sample • <ns:name> <ns:first>Dave</ns:first> <ns:extension> <ns:last>Orchard</ns:last> </ns:extension> </ns:name> • Another revision • <ns:name> <ns:first>Dave</ns:first> <ns:extension> <ns:last>Orchard</ns:last> <ns:extension> <ns:middle>Bryce</ns:middle> </ns:extension> </ns:extension> </ns:name>
Schema V2 <s:complexType name=“name"><s:sequence> <s:element name=“first" type="s:string" minOccurs="1" maxOccurs="1"/> <s:element name="Extension" type=“ns:LastExtensionType" minOccurs="0" maxOccurs="1"/> <s:any processContents="lax" namespace="##other“ minOccurs="0" maxOccurs="unbounded" /> </s:sequence> <s:anyAttribute/></s:complexType><s:complexType name="LastExtensionType"><s:sequence> <s:element name=“last" type="s:string" minOccurs=“0" maxOccurs="1"/> <s:element name="Extension" type=“ns:ExtensionType" minOccurs="0" maxOccurs="1"/> <s:any processContents="lax" namespace="##other“ minOccurs="0" maxOccurs="unbounded" /></s:sequence><s:anyAttribute/></s:complexType> <s:complexType name="ExtensionType">
#2: Must Ignore unknowns • Receivers must ignore content they don’t understand • This is critical for compatible changes • Sender can put new information in without breaking receiver • example, receiver must ignore ns2:last • <ns:name xmlns:ns=“myns” xmlns:ns2=“extns”> <ns:first>Dave</ns:first> <ns2:last>Orchard</ns2:last></ns:name>
#3: Preserve NS if possible • Change a Namespace ONLY if a non-compatible change is done • A required element is added • Semantics of existing elements change • Optional last name • <ns:name xmlns:ns=“myns” xmlns:ns2=“extns”> <ns:first>Dave</ns:first> <ns2:last>Orchard</ns2:last></ns:name> • Required last name • <ns2:name xmlns:ns2=“extns”> <ns2:first>Dave</ns2:first> <ns2:last>Orchard</ns2:last></ns2:name>
#4: Version attribute • Use version attribute for minor version • Identify a version of a particular namespace • Software can “know” whether an extension is supported or not • can choose to use or not • ie, client knows <last> isn’t supported • Client doesn’t send
#5: Use MustUnderstand • When adding required functionality • Extension authors may not “own” namespace • Provide or use Must Understand rule • Overrides the Must Ignore rule • Example: add required ns2:last as SOAP header • <soap:header> <ns2:last xmlns:ns2=“extns” soap:mustUnderstand=“1”>Orchard</ns2:last> </soap:header> <soap:body> <ns:name xmlns:ns=“myns”> <ns:first>Dave</ns:first> </ns:name> … • Another solution: provide a mustUnderstand model • <ns:name xmlns:ns=“myns” xmlns:ns2=“extns”> <ns:first>Dave</ns:first> <ns2:last ns:mustUnderstand=“1”>Orchard</ns2:last></ns:name>
Versioning architecture • Very difficult to have multiple versions of service • Typically the data model changes and requires new data • Easier to try for compatible evolution of interface and data
Versioning activities • W3C TAG work • Web architecture doc, finding • WSDL 2.0 • version attribute • primer • XML Schema 1.1 • 1.0 doesn’t make extensibility easy • explicit wildcards and determinism constraints • 1.1 may relax determinism • RelaxNG has open content model