web400 loose coupling & serialization patterns clemens vasters newtelligence ag...
Post on 18-Dec-2015
223 views
TRANSCRIPT
Definition: Loose Coupling
Macro: Varying implementationsJ2EE .Net, .Net v1 .Net v1.1, etc.
SOA is the solution
Micro: Flexible/Resilient implementationOptional data & unions
New messages
New operations
Smart contract & schema design is the solution
Definition: Serialization
The transformation of a graph of objects to a stream and back again
Roll your own
System.Xml.Serialization
System.Runtime.Serialization
The transformation of a CLR type into an XSD schema and back again
Roll your own
System.Xml.Serialization
Definition: Pattern
“Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing the same thing twice.”
-- Christopher Alexander
Objectives
Learn the best mechanisms to achieve “micro” loose coupling for data
Learn how to make messages flexible & resilient to change
Learn how loose coupling manifests itself in the programming model
Disclaimer: Some of the code/schema has been cut to fit on slides
Development Approaches
Two options for developing messages Code first: “I like the CLR” Schema first: “I like XSD” We love both of them
Code first is more familiar but implicit
Schema first is explicit but less familiar
We map from schema code
To achieve loose coupling you must understand XSD – code or schema first
Code First Development
The best way to avoid unsupported schema constructs
If you can do it in code – it is supported
Use the [SoapDocumentMethod]Controls the contract that is emitted
Useful settingsParameterStyle=SoapParameterStyle.Bare
Use=SoapBindingUse.Literal
Examine the induced contract often
Schema First Development
Some schemas cannot be mappedWe are working on documenting this
Develop schema & contract separately Use WSDL import to associate them
Do not use “parameters” message part You want “bare” semantics
Always, always, always use doc/literal Encoding – what is that?
Schema First Development
Use disco.exe to retrieve documents
Use wsdl.exe /server to create stub
Modify stub to make it all workStrip abstract class & method modifiers
Add Location to [WebServiceBinding]
Add Binding to [SoapDocumentMethod]
Add your implementation
This is easier than creating a subclass
Designing Messages
Each message part resolves to an element (doc/literal)
You have a lot of options with varying degrees of “coupledness” for the element types
xsd:anyType aka System.Object
xsd:string aka System.Object
User-defined types (UDTs hereafter)
You must choose wisely…
Object xsd:anyType
Send anything you wantIf the serializer supports & knows about it
Very open – lots of flexibility
Very open – shoot yourself in the foot
Must negotiate semantics out of band<schema xmlns="http://www.w3.org/2001/XMLSchema" <schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://people">targetNamespace="http://people"><element name="person" type="anyType"/><element name="person" type="anyType"/>
</schema></schema>
public string AddPerson( [XmlElement(Namespace="http://people")]public string AddPerson( [XmlElement(Namespace="http://people")]object person) {...}object person) {...}
String xsd:string
Better know as “XML as string”
Slightly less open than anyType, but has many of the same issues
Just about anything can be represented as a string
<schema xmlns="http://www.w3.org/2001/XMLSchema" <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://people">targetNamespace="http://people"><element name="person" type="string"/><element name="person" type="string"/>
</schema></schema>
public string AddPerson( [XmlElement(Namespace="http://people")] public string AddPerson( [XmlElement(Namespace="http://people")] string person) {...}string person) {...}
User-defined Types (UDTs)
Most commonly used
Not resilient to change by default
<schema targetNamespace="http://people" xmlns="..." ><schema targetNamespace="http://people" xmlns="..." > <element name="person"><element name="person"> <complexType><complexType> <sequence><sequence> <element name="name" type="string"/><element name="name" type="string"/> </sequence></sequence> </complexType></complexType> </element></element></schema></schema>
public string AddPerson( [XmlElement(Namespace="http://people")] public string AddPerson( [XmlElement(Namespace="http://people")] Person person) {...}Person person) {...}
UDTs and optional data
Elements can be optional
Defines must-haves & nice-to-haves<schema targetNamespace="http://people" xmlns="..." ><schema targetNamespace="http://people" xmlns="..." > <element name="person"><element name="person"> <complexType name="Person"><complexType name="Person"> <sequence><sequence>
<element name="name" type="string"/><element name="name" type="string"/><element name="ssn" type="string"/><element name="ssn" type="string"/><element name="age" type="int" minOccurs="0"/><element name="age" type="int" minOccurs="0"/>
</sequence></sequence> </complexType></complexType> </element></element></schema></schema>
UDTs and optional data
UDT contains xxxSpecified “buddy” member
Value determines element presence[XmlType(Namespace="http://people")][XmlType(Namespace="http://people")]public class Person {public class Person { public string name;public string name; public string ssn;public string ssn; public int age;public int age; [XmlIgnore()][XmlIgnore()] public bool ageSpecified;public bool ageSpecified;
}}
UDTs and unions
XSD supports a choice between elements
<schema targetNamespace="http://people" xmlns="..." ><schema targetNamespace="http://people" xmlns="..." > <element name="person"><element name="person"> <complexType name="Person"><complexType name="Person"> <sequence><sequence>
<element name="name" type="string"/><element name="name" type="string"/> <choice><choice> <element name="ssn" type="string"/><element name="ssn" type="string"/> <element name="driverslicence" type="string"/><element name="driverslicence" type="string"/> <element name="passportnumber" type="string"/><element name="passportnumber" type="string"/> </choice></choice>
</sequence></sequence> </complexType></complexType> </element></element></schema></schema>
UDTs and unions
UDT contains choice “buddy” member
[XmlType(Namespace="http://people")][XmlType(Namespace="http://people")]public class person {public class person { public string name;public string name; [XmlElement("driverslicence", typeof(string))][XmlElement("driverslicence", typeof(string))] [XmlElement("passportnumber", typeof(string))][XmlElement("passportnumber", typeof(string))] [XmlElement("ssn", typeof(string))][XmlElement("ssn", typeof(string))] [XmlChoiceIdentifier("ItemElementName")][XmlChoiceIdentifier("ItemElementName")] public string Item;public string Item; [XmlIgnore()][XmlIgnore()] public ItemChoiceType ItemElementName;public ItemChoiceType ItemElementName;
}}
Enabling resiliency
Changing without breakingClients work without recompileData is not lost on roundtrip
Requires forethoughtThere is no magic for this -- yet
Most mechanisms for UDTsxsd:anyType & xsd:string don’t need help
Namespace versioning is not versioningNew namespace != new versionNew namespace == new elements & types
Element/Attribute wildcards
Better know as open content model
Substitution with some restrictions
Very resilient user-defined type ;-)<schema targetNamespace="http://people" xmlns="..."><schema targetNamespace="http://people" xmlns="..."> <element name="person"><element name="person"> <complexType><complexType> <xs:sequence><xs:sequence>
<xs:any processContents="lax" maxOccurs="unbounded"/><xs:any processContents="lax" maxOccurs="unbounded"/> </xs:sequence></xs:sequence>
<xs:anyAttribute processContents="lax"/><xs:anyAttribute processContents="lax"/> </complexType></complexType> </element></element></schema></schema>
Element/Attribute wildcards
Use XmlElement & XmlAttribute as programming model
You process the XML directly[XmlType(Namespace="http://people")][XmlType(Namespace="http://people")]public class person {public class person { [XmlAnyElement()][XmlAnyElement()] public XmlElement[] Any;public XmlElement[] Any; [XmlAnyAttribute()][XmlAnyAttribute()] public XmlAttribute[] AnyAttr;public XmlAttribute[] AnyAttr;}}
Wildcards and UDTs
Need resiliency for your UDT?
Wildcards to the rescue<schema targetNamespace="http://people" xmlns="..."><schema targetNamespace="http://people" xmlns="..."> <element name="person"><element name="person"> <complexType><complexType>
<sequence><sequence> <element name="name" type="string"/><element name="name" type="string"/> <element name="ssn" type="string"/><element name="ssn" type="string"/> <any processContents="lax" minOccurs="0" <any processContents="lax" minOccurs="0"
maxOccurs="unbounded"/>maxOccurs="unbounded"/></sequence></sequence><anyAttribute processContents="lax"/><anyAttribute processContents="lax"/>
</complexType></complexType> </element></element></schema></schema>
Wildcards and UDTs
Use your fields as you always would
Optionally add more data in the future[XmlType(Namespace="http://people")][XmlType(Namespace="http://people")]public class person {public class person {
public string name;public string name; public string ssn;public string ssn; [XmlAnyElement()][XmlAnyElement()] public XmlElement[] Any;public XmlElement[] Any; [XmlAnyAttribute()][XmlAnyAttribute()] public XmlAttribute[] AnyAttr;public XmlAttribute[] AnyAttr;}}
Processing wildcards
A version attribute is useful, especially with wildcards
<schema targetNamespace="http://people" xmlns="..."><schema targetNamespace="http://people" xmlns="..."> <element name="person"><element name="person"> <complexType><complexType>
<sequence><sequence> <element name="name" type="string"/><element name="name" type="string"/> <any processContents="lax" minOccurs="0" <any processContents="lax" minOccurs="0"
maxOccurs="unbounded" />maxOccurs="unbounded" /></sequence></sequence><anyAttribute processContents="lax"/><anyAttribute processContents="lax"/><attribute name="version" type="string" use="required"/><attribute name="version" type="string" use="required"/>
</complexType></complexType> </element></element></schema></schema>
Processing wildcards
Switching for proper processingpublic string AddPerson([XmlElement(Namespace="http://people")] public string AddPerson([XmlElement(Namespace="http://people")]
Person person) {Person person) {
switch (person.version) {switch (person.version) { case "1.0":case "1.0":
return DoAddPersonV1(person);return DoAddPersonV1(person); default:default: return DoAddPersonV2(person);return DoAddPersonV2(person); }}}}
XmlElement Parameters
Code first only
Generates an fairly open content model[WebMethod][WebMethod]public void AddPerson(System.Xml.XmlElement person) {...} public void AddPerson(System.Xml.XmlElement person) {...}
<schema targetNamespace="http://people" xmlns="..."><schema targetNamespace="http://people" xmlns="..."> <element name="person"><element name="person"> <complexType><complexType> <sequence><sequence> <any /> <any /> </sequence></sequence> </complexType></complexType> </element></element><schema><schema>
Summary
Think hard about loose couplingIf you think it is going to change, it will
This is similar to security – you need to design it in
SOA & WS enable loose coupling, but they don’t guarantee it
There are many tools to achieve thisBoth code first & schema first are valid
Choose which mechanism is right for you
ResourcesResourcesWeb sites
http://msdn.microsoft.com/webserviceshttp://www.w3.org/XMLSchema
Newsgroupsmicrosoft.public.dotnet.xmlmicrosoft.public.dotnet.framework.aspnet.webservices
Contactshttp://radio.weblogs.com/[email protected]@microsoft.comhttp://www.douglasp.com
Community Resources
Community Resourceshttp://www.microsoft.com/communities/default.mspx
Most Valuable Professional (MVP)http://www.mvp.support.microsoft.com/
NewsgroupsConverse online with Microsoft Newsgroups, including Worldwidehttp://www.microsoft.com/communities/newsgroups/default.mspx
User GroupsMeet and learn with your peershttp://www.microsoft.com/communities/usergroups/default.mspx
© 2003 Microsoft Corporation. All rights reserved.© 2003 Microsoft Corporation. All rights reserved.This presentation is for informational purposes only. MICROSOFT MAKES NO WARRANTIES, EXPRESS OR IMPLIED, IN THIS SUMMARY.This presentation is for informational purposes only. MICROSOFT MAKES NO WARRANTIES, EXPRESS OR IMPLIED, IN THIS SUMMARY.