web400 loose coupling & serialization patterns clemens vasters newtelligence ag...

33
WEB400 Loose Coupling & Serialization Patterns Clemens Vasters newtelligence AG ([email protected])

Post on 18-Dec-2015

223 views

Category:

Documents


0 download

TRANSCRIPT

WEB400

Loose Coupling & Serialization Patterns

Clemens Vastersnewtelligence AG([email protected])

Agenda

Definitions

Objectives

Development Approaches

Designing Messages

Enabling resiliency

Q&A

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;

}}

Designing MessagesDesigning Messages

CodeCode

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>

Enabling resiliencyEnabling resiliency

CodeCode

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

evaluationsevaluations

© 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.