- From: David Orchard <dorchard@bea.com>
- Date: Wed, 9 Jun 2004 17:11:43 -0700
- To: <www-ws-desc@w3.org>
This is potential primer material that explores how to use the WSDL http binding to describe interactions with an HTTP service. This is an example of music information and purchasing Web service. It is styled after the CDDB database http://www.gracenote.com/gn_products/cddb.html and allmusic.com sites. It has generated a number of questions where I don't think the WSDL as exists can express certain things. I'm grateful for any reviews or comments on this. It could be put into the primer as well. An Artist has: - ID - Name - Biography - Genre - Image - Web site Clients have 3 types of interactions: retrieve all/specific information, change/add/delete information, and search based upon a subset of the Artist fields. - Get Artist complete information for a given Artist - Get Artist field contents (Name, Biography, etc.) for a given Artist - Add Artist - Update Artist - Get Artist list by Artist name, genre Schema <?xml version="1.0" encoding="UTF-8"?> <xs:schema targetNamespace="http://www.w3.org/2002/ws/music/2004/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.w3.org/2002/ws/music/2004/" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xs:element name="Music"> <xs:complexType name="Music"> <xs:sequence> <xs:element ref="tns:Artist" maxOccurs="unbounded"/> <xs:element ref="tns:ArtistRef" maxOccurs="unbounded"/> <xs:any namespace="##other" processContents="lax"/> </xs:sequence> </xs:complexType> </xs:element> <!-- To do a /Music/Artist/5, need to have a type with only 1 child --> <xs:complexType name="ArtistIDBase"> <xs:sequence> <xs:element name="id" type="xs:ID"/> </xs:sequence> </xs:complexType> <!-- When Adding an artist, the ID isn't known --> <xs:element name="ArtistWithoutID"> <xs:complexType name="ArtistWithoutId"> <xs:sequence> <xs:element name="Name" type="xs:string"/> <xs:element name="Biography" type="xs:string"/> <xs:element name="Genre" type="xs:string"/> <xs:element name="Image" type="xs:anyURI"/> <xs:element name="Site" type="xs:anyURI"/> <xs:any namespace="##other" processContents="lax"/> </xs:sequence> </xs:complexType> </xs:element> <!-- Need to have ID + all of the fields for <artist> returns --> <!-- probably better modelling in schema to combine the id with the non-id fields --> <xs:element name="Artist"> <xs:complexType name="Artist"> <xs:complexContent> <xs:extension base="tns:ArtistIDBase"> <xs:sequence> <xs:element name="Name" type="xs:string"/> <xs:element name="Biography" type="xs:string"/> <xs:element name="Genre" type="xs:string"/> <xs:element name="Image" type="xs:anyURI"/> <xs:element name="Site" type="xs:anyURI"/> <xs:any namespace="##other" processContents="lax"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> </xs:element> <!-- Need a query structure to do queries, ie &name=thieverycorp --> <xs:element name="ArtistQuery"> <xs:complexType name="ArtistQuery"> <xs:complexContent> <xs:extension base="tns:ArtistIDBase"> <xs:sequence> <xs:element name="Name" type="xs:string" minOccurs="0"/> <xs:element name="Genre" type="xs:string" minOccurs="0"/> <xs:element name="Rating" type="xs:decimal" minOccurs="0"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> </xs:element> <!-- ID + REF structure for getting back list of IDs that can be used to create URI --> <xs:element name="ArtistIDRef"> <xs:complexType name="ArtistIDRef"> <xs:complexContent> <xs:extension base="tns:ArtistIDBase"> <xs:sequence> <xs:element name="Name" type="xs:string"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> </xs:element> <!-- Artist Field names for doing field queries --> <xs:element name="ArtistIDFieldName" type="tns:ArtistField"/> <xs:complexType name="ArtistField"> <xs:complexContent> <xs:extension base="tns:ArtistIDBase"> <xs:sequence> <xs:element name="Field" type="tns:ArtistFieldNames"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <!-- Artist Field Name + Value for setting field --> <xs:element name="ArtistFieldNameAndValue"> <xs:complexType name="ArtistFieldNameAndValue"> <xs:complexContent> <xs:extension base="tns:ArtistField"> <xs:sequence> <xs:element name="Value"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> </xs:element> <!-- List of field names --> <xs:simpleType name="ArtistFieldNames"> <xs:restriction base="xs:string"> <xs:enumeration value="Name"/> <xs:enumeration value="Biography"/> <xs:enumeration value="Genre"/> <xs:enumeration value="Image"/> <xs:enumeration value="Site"/> </xs:restriction> </xs:simpleType> <!-- URI for getting back opaque URIs --> <xs:complexType name="uri"> <xs:sequence> <xs:element name="uri" type="xs:anyURI"/> </xs:sequence> </xs:complexType> </xs:schema> Interacting using the x-www-form-uriencoded style WSDL <?xml version="1.0" encoding="UTF-8"?> <wsdl:definitions xmlns:musicw="http://example.com/Artist" xmlns:wsdl=""> <xs:import href="Music-Artist.xsd"/> <wsdl:interface name="Artist"> <wsdl:operation name="ArtistSearch" method="GET"> <wsdl:input ref="music:ArtistQuery"/> <wsdl:output ref="music:Music"/> </wsdl:operation> <wsdl:operation name="ArtistRefSearch" method="GET"> <wsdl:input ref="music:ArtistQuery"/> <wsdl:output ref="music:Music"/> </wsdl:operation> <wsdl:operation name="GetArtist" method="GET"> <wsdl:input ref="music:ArtistID"/> <wsdl:output ref="music:Artist"/> </wsdl:operation> <!-- Given a uri in a field for an artist, simply dereference the URI --> <wsdl:operation name="GetArtistOpaqueURI" method="GET"> <wsdl:input ref="music:uri"/> <wsdl:output ref="music:ArtistWithoutURI"/> </wsdl:operation> <wsdl:operation name="GetFieldByFieldName" method="GET"> <wsdl:input ref="music:ArtistFieldName"/> <wsdl:output ref="xsd:any"/> </wsdl:operation> <wsdl:operation name="AddArtistServerID" method="POST"> <wsdl:input ref="music:ArtistWithoutID"/> <wsdl:output ref="music:ArtistRef"/> </wsdl:operation> <wsdl:operation name="AddArtistClientID" method="POST"> <wsdl:input ref="music:Artist"/> <wsdl:output ref="music:ArtistRef"/> </wsdl:operation> <wsdl:operation name="DeleteArtist" method="DELETE"> <wsdl:input ref="music:ArtistID"/> </wsdl:operation> <wsdl:operation name="UpdateArtist" method="PUT"> <wsdl:input ref="music:Artist"/> <wsdl:output ref="music:Artist"/> </wsdl:operation> <wsdl:operation name="UpdateField" method="PUT"> <wsdl:input ref="music:ArtistFieldNameAndValue"/> </wsdl:operation> </wsdl:interface> <wsdl:binding name="Artist" interface="Artist" http:defaultMethod="GET"> <wsdl:operation ref="ArtistSearch" location="Artist/{Name}"/> <wsdl:operation ref="ArtistRefSearch" location="ArtistRef/{Name}"/> <wsdl:operation ref="GetArtist" location="Artist/{ID}"/> <wsdl:operation ref="GetArtistOpaqueURI" location="{uri}"/> <wsdl:operation ref="GetFieldByFieldname" location="Artist/{ID}/"/> <wsdl:operation ref="AddArtistServerID" location="Artist" method="POST"/> <wsdl:operation ref="AddArtistClientID" location="Artist" method="POST"/> <wsdl:operation ref="DeleteArtist" location="Artist/{ID}" method="DELETE"/> <wsdl:operation ref="UpdateArtist" location="Artist/{ID}" method="PUT"/> <wsdl:operation ref="UpdateArtistField" location="Artist/{ID}" method="PUT"/> </wsdl:binding> </wsdl:definitions> Message Examples Example: ArtistSearch GET /Music/Artist?genre="electronica" Return: <Music> <Artist> <ID>5</ID> <Name>Thievery Corp</Name> <Genre>Electronica</Genre> <site>http://thievery.com</site> </Artist> </Music> Example: GetAllArtists GET /Music/Artist Returns: <Music> <Artist> <ID>5</ID> <Name>Thievery Corp</Name> <Genre>Electronica</Genre> <site>http://thievery.com</site> </Artist> </Music> Example: GetArtistReferences GET /Music/ArtistRef?genre="electronica" Return: <Music> <ArtistRef> <ID>5</ID> <Name>Thievery Corp</Name> </ArtistRef> </Music> Example: GetArtist GET /Music/Artist/5 Return: <Artist> <ID>5</ID> <Name>Thievery Corp</Name> <Genre>Electronica</Genre> <site>http://thievery.com</site> </Artist> Example: GetArtistOpaqueURI * This assumes the URI="id/xyz" GET /Music/Artist/id/zyz Return: <Artist> <Name>Thievery Corp</Name> <Genre>Electronica</Genre> <site>http://thievery.com</site> </Artist> Example: GetFieldByFieldName GET /Music/Artist/5?field="site" Return: <site>http://thievery.com</site> Example: AddArtistServerId POST /Music/Artist <Artist> <Name>Thievery Corp version 2</Name> <Genre>Electronica</Genre> <site>http://newbetterthievery.com</site> </Artist> Returns: Content-Location: /Music/Artist/6 * How is the HTTP Content-location mapped to xml in this case? Is it dropped? Should there be XML returned? Example: AddArtistClientID * I don't think this works in the current WSDL http binding POST /Music/Artist/7 <Artist> <ID>7</ID> <Name>Thievery Corp version 3</Name> <Genre>Electronica</Genre> <site>http://newwaybetterthievery.com</site> </Artist> Returns: Content-Location: /Music/Artist/7 Example: DeleteArtist DELETE /Music/Artist/5 Example: UpdateArtist * I don't think this works in the current WSDL http binding PUT /Music/Artist/5 <Artist> <ID>5</ID> <Name>Thievery Corp</Name> <Genre>Electronica</Genre> <site>http://newbetterthievery.com</site> </Artist> Example: UpdateArtistField * I don't think this works in the wsdl as is PUT /Music/Artist/5/site <site>http://newbetterthievery.com</site>
Received on Wednesday, 9 June 2004 20:11:45 UTC