Python SOAP Tutorial - Creating a WEB Service with ZSI

From PeformIQ Upgrade
Revision as of 12:02, 13 January 2009 by PeterHarding (talk | contribs) (New page: Table of Contents <pre> 1 Foreword 3 1.1 Lizens 3 2 Einfuhrung ...)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search


Table of Contents


1       Foreword                                                 3
1.1     Lizens                                                   3
2       Einf?uhrung                                             3
3       Einfache Datentypen: Ein rpc/literal MatheService        4
3.1     Die MatheService WSDL                                    4
3.2     Der Python ZSI Server f?ur den MatheService             5
3.2.1   Methodenstubs aus der WSDL generieren                    5
3.2.2   Implementation des MatheService Web- Servers             6
3.2.3   Die Service Implementation einf?ugen                    7
3.3     Der Python ZSI Client f?ur den MatheService            10
4       Komplexe Datentypen                                     12
4.1     Erweitern der WSDL mit Eclipse                          12
4.2     Den Erweiterten Server erstellen                        16
4.3     Der erweiterte Client                                   20
5       Deutsche Zusammenfassung des ZSI user manual            22
5.1    ?Ubersicht                                              22
5.1.1   SOAP Bindings                                           22
5.1.2   Python Werkzeuge                                        22
5.2     Von der WSDL zum Python Code                            22
5.2.1   wsdl2py - Die Grundlagen der Codeerstellung             23
5.2.2   Typecode Erweiterungen                                  24
6       Links 25

Index of Diagrams 


1 Workspace in Eclipse                                          12
2 Design View of the  MatheServicewsdl                          13
3 Design View with new Operation                                13
4 Design View with new Operation and assigned elements          13
5 Element ModuloRequest                                         14
6 Complex Data Type                                             14


1. Foreword

Although Web Services an increasingly gr?oere spread�reasons, the production from clients and servers are nowhere as simple as at many places promised. This is probably not least because little easy on the theme Einf?uhrungen exist. Just englischsprachige ?auerst instructions are rare. This is the Step Tutorial f?ur step entry into the subject of Web Services f?ur Anf?anger (like me) easier. The Python Implementation is being used.

2. Licence

Copyright c 2007 Richard Mutschler. All rights reserved. Sources copied from other authors are labeled with a copyright note. Redistribution and use in source (LYX, LATEX) and 'compiled' forms (SGML, HTML, PDF, Post- Script, RTF and so forth) with or without modification, are permitted provided that the following conditions are met:

1. Redistributions of source code (LYX, LATEX) must retain the above copyright notice, this list of conditions and the following disclaimer as the �rst lines of this �le unmodi�ed. 2. Redistributions in compiled form (transformed to other DTDs, converted to PDF, PostScript, RTF and other formats) must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

THIS DOCUMENTATION IS PROVIDED 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANYWAY OUT OF THE USE OF THIS DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE


Einf?uhrung

It is in this tutorial from a certain Grundkentnis in Python. Some basic concepts of WSDL, SOAP and HTTP servers are beil?au�g presented. It does not mention n?aher, since the network is a lot of information dar?uber verf?ugbar. With this software was to prepare this Tutorials worked

* Python 2.4
* PyXML 0.8.3
* ZSI 2.0 rc3
* soapUI 1.6
* Eclipse 3.2
* PyDev for Eclipse 1.2.5
* Web Standard Tools (WST) for Eclipse 1.5.2


The point of departure shown here f?ur example, a WSDL file. A major collection of WSDL files f?ur further projects�unfounded http://www.xmethods.com. under: A major m?oglichst Interoperabilit?at gew?ahrleisten to be here only Web Service 1 battery WSDL files in rpc/literal and document/literal Style.


3. Simple Datatypes: An RPC/literal MathService

A simple example, which initially implemented only offering a function, which is a double as receives argument and square the number zur?uckgibt. This example Sp?ater functions to the Modolodivision f?ur expanded. Here are just a simple initially scalar datatypes used a single argument and a R?uckgabewert.


3.1 The MathService WSDL

This WSDL forms the interface to MatheService:

<?xml version="1.0"?>
<definitions name="MatheService"
targetNamespace="http://MyNs:8080/MatheService"
xmlns:tns="http://MyNs:8080/MatheService"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<message name="getSquareRequest">
<part name="x" type="xsd:double"/>
</message>
<message name="getSquareResponse">
<part name="return" type="xsd:double"/>
</message>
<portType name="SquarePortType">
<operation name="getSquare">
<documentation>the square method
</documentation>
<input message="tns:getSquareRequest"/>
<output message="tns:getSquareResponse"/>
</operation>
</portType>
<binding name="SquareBinding" type="tns:SquarePortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="getSquare">
<soap:operation soapAction="http://127.0.0.1:8080/MatheService/getSquare"/>
<input>
<soap:body use="literal" namespace="http://MyNS:8080/MatheService"/>
Returns x^2 (x**2, square(x)) for a given float x
</documentation>
<port name="SquarePort" binding="tns:SquareBinding">
<soap:address location="http://127.0.0.1:8080/MatheService"/>
</port>
</service>
</definitions>
 1  Original by Holger Joukl, modified by Richard Mutschler

3.2 The Python ZSI Server for the MatheService

The ZSI Web service package is a tool for top-down development of Web-Services. This means that an existing WSDL used to client and server applications. In the context this document describes a Webservice a WSDL file that describes the Service Interface.


3.2.1 Method Stubs Generated from the WSDL

ZSI provides two Python scripts for Verf?ugung which Quellcodeger?uste f?ur Server and Client from the WSDL generated k?onnen:

*  wsdl2py will be used to the Python Bindings f?ur Service can evolve.
*  Wsdl2dispatch creates a Serverger?ust, at the service auszuf?uhren. The processing, with us, so SquareService tabled here. 


If ZSI installed, ?o net now top the console and changes in the provided, in which our MatheService.wsdl. Now the two scripts ausgef?uhrt:

*  wsdl2py -f MatheService.wsdl
*  wsdl2dispatch -f MatheService.wsdl 


The option -f spezi�is styled the input, so our WSDL file. If a WSDL from the network will be used, for example of http://www.xmethods.com, can here by -u instead of -f the URL. It should not be in the directory three new files be�reasons:

MatheService services.py - Die durch wsdl2py generierten Bindings, MatheService services types.py - Durch wsdl2py generierten Typde�nitionen, MatheService services server.py - Das durch wsdl2dispatch generiertes Server Ger?ust.

What to do now? We have the Server skeleton and the Python bindings to use the Service to communicate. What we need now is:

* The main program, the (HTTP-) Server and the Request Handler and
* the Methods,  the practices questions.

ZSI includes the module ZSI.ServiceContainer, which the server for us implemented.


3.2.2 Implementation of the MatheService Web-Servers

We create a Python file called MyMatheService.py . I use the Python programming Eclipse with PyDev Plugin, however, there is any free dasWerkzeug seinerWahl . MyMatheService.py is the main program. It is a request Handler, combines the Verf?ugung our Service with the ServiceContainer and starts HTTP Server.

MyMatheService.py

from ZSI.ServiceContainer import ServiceContainer, SOAPRequestHandler
from MatheService_services_server import MatheService

import os

class MySOAPRequestHandler(SOAPRequestHandler):

    def do_GET(self):
    #Return the WSDL file. We expect to get the location from the
    #invocation URL ("path").
        wsdlfile = os.path.join('.', self.path.replace('/', "", 1) + ".wsdl")
        print ">>>>> using wsdl file", wsdlfile
        wsdl = open(wsdlfile).read()
        self.send_xml(wsdl)
        
# Copied from ZSI.ServiceContainer, extended to instantiate with a custom
# request handler

def AsServer(port=80, services=(), RequestHandlerClass=SOAPRequestHandler):
    address = ('127.0.0.1', port)
    sc = ServiceContainer(address, RequestHandlerClass=RequestHandlerClass)
    for service in services:
        path = service.getPost()
        sc.setNode(service, path)
    sc.serve_forever()
    
AsServer(port=8080, services=[MatheService()], RequestHandlerClass=MySOAPRequestHandler)


W?are n?otig it not been his own Request Handler to implement MySOAPRequestHandler, both Python ZSI Clients, which the ServiceProxy class and MS Visual Basic SOAP Clients, expect a HTTP GET, the WSDL file ?ubermittelt. This is now a widespread behavior. This was the AsServer(..) function will be extended to his own Request handler. We k?onnen Service now test.


In line 3 response=getSquareResponse(), we reject the Variable Response the type getSquareResponse().

In line 4 is now our getSquare method is called. The parameter is the x value of the inquiry (the '_' is important!!!) method. The result, we then the Variable return our response variable.

At the end we give the with a value gef?ullte Response Variable zur?uck. We are testing our server now come back with SOAPUI:


         ----- SOAPUI Request -----
  <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:mat="http://MyNS:8080/MatheService">
    <soapenv:Body>
      <mat :getSquare>
        <x>6</x>
      </mat :getSquare>
    </soapenv:Body>
  </soapenv:Envelope>
         ----- SOAPUI Response -----


         -----  -----


Congratulations, our Server works!

The server because we have no function yet wrote that request, we as a result : return xsi:nile=1. That was so far is also expected. We see in particular, however, that the server l?auft and our request receives. For now meaningful results we implement the getSquare function.

3.2.3 The Service Implementation Einflugen

The only thing we do now m?ussen, is the implementation of the services in the by wsdl2dispatch produced Serverger?ust einzuf?ugen. The following steps are necessary:

*  Forwarding the request of the correct method, 
*  the method the parameters of the SOAP- request ?ubergeben,
*  the result of the method in the SOAP- response letter.

We first ?o nen MatheService services server.py file :


   >>>> Stuff in here <<<<<



3.3 The Python ZSI Client for MatheService

At the Client to implement, we create a new Python file, in this example My- MathServiceClient.py:


MyMatheServiceClient.py

from MatheService_services import *
from MatheService_services_types import *
import sys
from optparse import OptionParser

parser= OptionParser()

parser.add_option("-s", "--square", dest="square", type="string", help="A number calculate Square ")
parser.add_option("-a", "--arg1", dest="arg1", type="string", help="The first Modulodivision parameter ")
parser.add_option("-b", "--arg2", dest="arg2", type="string", help="The second Modulodivision parameter")

(options, args)=parser.parse_args()

loc = MatheServiceLocator()

proxy = loc.getMathePortType(tracefile = sys.stdout)

if options.square:
    response= proxy.getSquare((float)(options.square))
    print "The square of ", options.square, "is: ", response
    
elif options.Zahl1 and options.Zahl2:
    response = proxy.getModulo((int)(options.arg1),(int)(options.srg2))
    print "The result of the modulodivision of ", options.Zahl1, "and", options.Zahl2, "is", response


We recognize quickly that the client pretty simple. The relevant lines of code will now be explained :

* Line 1:   The wsdl2py created bindings are imported.
* Line 14:  an instance of Locator class is created. The Locator MatheService_services.py class is defined. Of the locate represents the Bindings at the given Web Service and the Port class, which is used to the Remote operations involve Web Services. In addition, several classes defined message to the SOAP, XML Schema datatypes locations. The name of this class depending, of course the name of the WSDL defined Services.  This means that if any other WSDL used the name changes also. You will find the class of wsdl2py generated _services.py file is quite simple (it is the first class, who in the file is always on and ends ServiceLocator).
* Line 15:  the variables proxy, the port of Locator- class assigned. Through this port will be the operations of the Web Services. The specified parameters tracefile = sys.stdout there for debugging the SOAP messages on the standard output.
* Line 22:  as well as the Server we need the instance of class, the type of data from the SOAP message represents.
* Line 23:  similar to the server we fill our request with a value. Note: In Eclipse, the possible variables that are in the request can be set by the code (Strg Space) displayed.
* Line 24:  here is now the Operation getSquare called and the result of the Variable response.


The following Listing shows the console output from running our Client:

 ----- Running MyMatheServiceClient.py -----
   >>>> Stuff in here <<<<<


Congratulations, our client also works!







NCName in AName transformieren:

1. Vorangestellter Unterstrich ' ' Preceded stressed 2. Zeichen, die nicht in dem Zeichensatz(Buchstabe, Zir, ' ') vorkommen, werden durch ' ' ersetzt. Characters that are not in the characterset(, Zir, ' '), occur, ' ' replaced

Attribut Deklarationen:

attrs aname: Attrs aname ist ein Attribut einer TypeCode Instanz. is an attribute of a order instance

Sein Wert ist eine Zeichenkette, die den Attributnamen darstellt, der verwendet wird, um auf ein Dictionary zu verweisen. Dieses enth?alt Daten, welche die Attributdeklaration darstellen.

Die Schl?ussel dieses dictionary sind die (namespace, Name) Tupel. Der Wert jedes Schl?ussels stellt den Wert des Attributes dar.


5.2.2 Typecode Extensions

The option {complexType, -b: the Option {complexType when invoking wsdl2py provides the programr many simplifications to Verf?ugung. This option is tested and the use of the authors recommended.


Low-level Description :

If the Option {complexType set all the attribute generated pyclasses metaclass hinzugef?ugt. The Metaklasse pr?uft the order attributes of pyclass and created a set of Hilfsmethoden f?ur each Element and attribute that in the De �economic of the ComplexType specified. This option f?ugt Wrapper f?ur the handling of the content added, without the generation of ?andern.

Getter/Setter:

A getter and a setters method is f?ur each element of a complex types de�and. These methods will get element ANAME ANAME and set element.

Factory Method:

If an element of complex type himself a complex type, it is for easier handling a factory method creates an instance of the holder class of type zur?uckgibt. The factory method is called 'newANAME'.

Attributes:

Four Python classes are four each element of a complex type properties (properties) creates. These are on the appropriate getter and setter methods of the element illustrated. Namens?uberschneidungen order to avoid these properties 'PNAME',, the first letter of the pname attribute a large type written

fromm ZSI.ServiceContainer import ServiceContainer, SOAPRequestHandler
from MatheService_services_server import MatheService

import os

class MySOAPRequestHandler(SOAPRequestHandler):

    def do_GET(self):
    #Return the WSDL file. We expect to get the location from the
    #invocation URL ("path").
        wsdlfile = os.path.join('.', self.path.replace('/', "", 1) + ".wsdl")
        print ">>>>> using wsdl file", wsdlfile
        wsdl = open(wsdlfile).read()
        self.send_xml(wsdl)
        
# Copied from ZSI.ServiceContainer, extended to instantiate with a custom
# request handler

def AsServer(port=80, services=(), RequestHandlerClass=SOAPRequestHandler):
    address = ('127.0.0.1', port)
    sc = ServiceContainer(address, RequestHandlerClass=RequestHandlerClass)
    for service in services:
        path = service.getPost()
        sc.setNode(service, path)
    sc.serve_forever()
    
AsServer(port=8080, services=[MatheService()], RequestHandlerClass=MySOAPRequestHandler)







6. Links

Here are the Links to download the tools used:

* EntwicklungsIDE Eclipse: http://www.eclipse.org
* Zolera SOAP Infrastructure (ZSI) http://pywebsvcs.sourceforge.net/
* Python 2.5 http://www.python.org/download/releases/2.5/
* PyXML http://sourceforge.net/projects/pyxml/
* soapUI 1.5 http://www.soapui.org/