# Presentation: 045460

## Python Web/Grid Services

- Presenter: Joshua Boverhof
- Lawrence Berkeley National Lab.

## Project links

- Webpage:
-     http://pywebsvcs.sourceforge.net/
-     http://dsd.lbl.gov/gtg/projects/download/download_info.html
- Demo:
-     http://dsd.lbl.gov/~boverhof
- Email:
-     JRBoverhof@lbl.gov
-     Pywebsvcs-talk@lists.sourceforge.net

## Overview

- ZSI -- Zolera SOAP implementation
- wsdl2python -- WSDL/XML Schema
- Generate Client:  Locators, Ports, Messages
- Generate Service: ServiceSOAPBinding
- pyGridWare -- WS-Resource Framework
- New Directions: Basic Profile, WS-Addressing, WS-Resource, XML Message Security

## WSDL Info Items

- <service>

- <binding>

- <portType>

- <input>

- <output>

- <messsage>

- <types>

- <operation>

- <port>

- <operation>

- <input>

- <output>

## WSDL to Python

- <service>

- <binding>

- <portType>

- <messsage>

- <types>

- <operation>

- <port>

- <operation>

- Locator

- SOAPPort

- messages

- Types

- elements

- <part>

- <schema>

## TypeCodes: Describing the data

- ZSI.TypeCode “aname”: specifies python attribute name TypeCode will access for element value when parsing and serializing.
- 	--wsdl2py convention specify aname as “_name”
- Facets: minOccurs, maxOccurs, nillable
- 	--ZSI TypeCodes expects repeatable (maxOccurs>1) elements to be specified 	in sequences.

## Elements, Types, and TypeCodes

-  <wsdl:message name='FreeDBService_searchByTrack_Response'>
-         <wsdl:part name='response' element='ns0:ArrayOfCDInfo_Response'/>
-     </wsdl:message>
-  <xsd:element name="**ArrayOfCDInfo_Response**” nillable="true” type="xns4:ArrayOfCDInfo"/>
-  <xsd:complexType name="ArrayOfCDInfo">
-                 <xsd:sequence>
-                     <xsd:element maxOccurs="unbounded" minOccurs="0"
-                         name="**CDInfo**" nillable="true" type="tns:CDInfo"/>
-                 </xsd:sequence>
-             </xsd:complexType>
-  <xsd:complexType name="CDInfo">
-                 <xsd:sequence>
-                     <xsd:element name="**artist**" nillable="true” type="xsd:string"/>
-                     <xsd:element name="**category**" nillable="true” type="xsd:string"/>
-                     <xsd:element name="**discId**" nillable="true” type="xsd:string"/>
-                     <xsd:element name="**title**" nillable="true” type="xsd:string"/>
-                 </xsd:sequence>
- </xsd:complexType>

- WSDL from http://soap.systinet.net/demos/FreeDB/wsdl

## Elements --> XML Instance

- <e:Envelope xmlns:e="http://schemas.xmlsoap.org/soap/envelope/"
-     xmlns:d="http://www.w3.org/2001/XMLSchema"
-     xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
-     xmlns:wn0="http://systinet.com/wsdl/com/systinet/demo/freedb/"
-     xmlns:wn1="http://systinet.com/xsd/SchemaTypes/"
-     xmlns:wn2="http://idoox.com/interface">
-   <e:Body>
-     <wn1:**ArrayOfCDInfo_Response** i:type="wn0:ArrayOfCDInfo">
-       <wn0:**CDInfo** i:type="wn0:CDInfo">
-         <wn0:**artist** i:type="d:string">Deftones et Slipknot</wn0:artist>
-         <wn0:**category** i:type="d:string">rock</wn0:category>
-         <wn0:**discId** i:type="d:string">23110313</wn0:discId>
-         <wn0:**title** i:type="d:string">Personnalisé</wn0:title>
-       </wn0:CDInfo>
-     ...
-  </e:Body>
- </e:Envelope>

## Generated Client Modules 

- Locator

- SOAPPort

- messages

- Types

- elements

- _services.py

- _types.py

- %wsdl2py -u _[http://soap.systinet.net/demos/FreeDB/wsdl](http://soap.systinet.net/demos/FreeDB/wsdl)_
- %python
- >>>from com_systinet_demo_freedb_FreeDBService_services import *
- >>>loc = JavaServiceLocator()
- >>>port = loc.getFreeDBService()
- >>>msg = port.searchByArtist(’Slipknot')
- >>> msg
- <com_systinet_demo_freedb_FreeDBService_services_types.ArrayOfCDInfo_Response_Dec>
- >>> len(msg._CDInfo)
- 74
- >>> msg._CDInfo[49]._title
- u'My Plague (New Abuse Mix)'

## Generated Service Module 

- messages

- Types

- elements

- _types.py

- %wsdl2dispatch -u http://soap.systinet.net/demos/FreeDB/wsdl
- %python
- >>>from com_systinet_demo_freedb_FreeDBService_services_server import *
- >>>from ZSI.ServiceContainer import AsServer
- >>>AsServer(port=8080,services=(com_systinet_demo_freedb_FreeDBService(),))

- _services.py

- _services_server.py

- ServiceSOAP
- Binding

## Service Module 

- class com_systinet_demo_freedb_FreeDBService(ServiceSOAPBinding):
-     soapAction = {
-         'http://systinet.com/wsdl/com/systinet/demo/freedb/FreeDBService#getDetails#':'soap_getDetails',
-         'http://systinet.com/wsdl/com/systinet/demo/freedb/FreeDBService#search#':'soap_search',
-         'http://systinet.com/wsdl/com/systinet/demo/freedb/FreeDBService#searchByArtist#':'soap_searchByArtist',
-         'http://systinet.com/wsdl/com/systinet/demo/freedb/FreeDBService#searchByTitle#':'soap_searchByTitle',
-         'http://systinet.com/wsdl/com/systinet/demo/freedb/FreeDBService#searchByTrack#':'soap_searchByTrack',
-         }
-     def __init__(self, post='/FreeDB/', **kw):
-         ServiceSOAPBinding.__init__(self, post)
-     def soap_searchByArtist(self, ps):
-         # input vals in request object
-         args = ps.Parse( FreeDBService_searchByArtist_1_Request() )
-         # assign return values to response object
-         response = FreeDBService_searchByArtist_Response()
**        ****#User Adds some logic to do something**
**        ****if args == ‘Slipknot’:**
**            ****class Holder: pass**
**            ****response._CDInfo  = [Holder()]**
**            ****response._CDInfo[0]._title = ****'My Plague (New Abuse Mix)**** '**
**            ****response._CDInfo[0]._artist = ’SLIPKNOT'**
-         return response

## New Directions: pyGridWare

- WS-Resource: Stateless web services paradigm, implied factory pattern.
- WS-Address: Specify resource identity in SOAP Header.
- Message-Level Security

## Implied Resource Pattern

- create

- epr

- epr

- response

- operation

- epr

- epr

- client

- Soap:Header

- Service

- Body

- 1

- 2

- 3

- 4

- epr

- 5

- value

- Model State

## Client for WS-Resource

- $wsdl2py -f  counter_service.wsdl -a

- Client generated in same way... Just specify WS-Addressing
- Create operation -- receives an EndpointReference containing a
-     resource ID.  This is used to refer back to the stateful instance.
- Drop EndpointReference into a new port.
- New port refers to a stateful service

## Create XML Instance

- <SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
-     xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
-     xmlns:ZSI="http://www.zolera.com/schemas/ZSI/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
-     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-     SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
-   <SOAP-ENV:Header xmlns:ns1="http://schemas.xmlsoap.org/ws/2003/03/addressing">
-     <ns1:MessageID id="567080">uuid:1087253160.24</ns1:MessageID>
-     <ns1:Action id="54e808">http://counter.com/service/CounterPortType/createCounterRequest</ns1:Action>
-     <ns1:To id="73338">http://bundy.localdomain:8080/wsrf/services/CounterService</ns1:To>
-   </SOAP-ENV:Header>
- <SOAP-ENV:Body xmlns:ns1="http://counter.com">
-   <ns1:createCounter></ns1:createCounter>
- </SOAP-ENV:Body>
- </SOAP-ENV:Envelope>

- %python
- >>>import pyGridWare.generated.stubs.Counter_services as COUNTER
- >>>locator = COUNTER.CounterServiceLocator()
- >>>port = locator.getCounterPortType()
- >>>msg = port.createCounter(COUNTER.CreateCounterRequest())

## Create Response XML Instance

- <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
-   xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-   xmlns:wsa="http://schemas.xmlsoap.org/ws/2003/03/addressing">
-  <soapenv:Header>
-   <wsa:MessageID soapenv:mustUnderstand="0">uuid:E77B0490-BE5B-11D8-92A0</wsa:MessageID>
-   <wsa:To soapenv:mustUnderstand="0">http://schemas.xmlsoap.org/ws/2003/03/addressing/role/anonymous</wsa:To>
-   <wsa:Action soapenv:mustUnderstand="0">http://counter.com/service/CounterPortType/createCounterResponse
-   </wsa:Action>
- <wsa:From><wsa:Address>http://bundy.localdomain:8080/wsrf/services/CounterService</wsa:Address></wsa:From>
- <ns0:RelatesTo RelationshipType="wsa:Response" soapenv:mustUnderstand="0"
-     xmlns:ns0="http://schemas.xmlsoap.org/ws/2003/03/addressing">uuid:1087255976.97</ns0:RelatesTo>
-  </soapenv:Header>
-  <soapenv:Body>
-   <createCounterResponse xmlns="http://counter.com">
**   ****<wsa:EndpointReference>**
**    ****<wsa:Address>http://bundy.localdomain:8080/wsrf/services/CounterService</wsa:Address>**
**    ****<wsa:ReferenceProperties>**
**     ****<CounterKey>27378735</CounterKey>**
**    ****</wsa:ReferenceProperties>**
**   ****</wsa:EndpointReference>**
-   </createCounterResponse>
-  </soapenv:Body>
- </soapenv:Envelope>

## Add Operation 

- <SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
-     xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
-     xmlns:ZSI="http://www.zolera.com/schemas/ZSI/"
-     xmlns:xsd="http://www.w3.org/2001/XMLSchema"
-     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-     SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
- <SOAP-ENV:Header xmlns:ns1="http://schemas.xmlsoap.org/ws/2003/03/addressing" xmlns:ns2="http://counter.com">
-     <ns1:MessageID id="740980">uuid:1088447466.12</ns1:MessageID>
-     <ns1:Action id="55b610">http://counter.com/service/CounterPortType/addRequest</ns1:Action>
-     <ns1:To id="107a260">http://bundy.localdomain:8080/wsrf/services/CounterService</ns1:To>
-     **<ns2:CounterKey id="107a6b0">12399227</ns2:CounterKey>**
- </SOAP-ENV:Header>
- <SOAP-ENV:Body xmlns:ns1="http://counter.com">
-     <ns1:add id="18085d0">11</ns1:add>
- </SOAP-ENV:Body>
- </SOAP-ENV:Envelope>

- >>>msg = port.createCounter(COUNTER.CreateCounterRequest())
- >>>port = locator.getCounterPortType(endPointReference=msg._EndpointReference)
- >>>msg = port.add(11)