Latest Version: 0.9.6.2
  Dashboard > Pylons Cookbook > ... > Controllers > Making a SOAP Controller with Optio's Soaplib
  Pylons Cookbook Log In | Sign Up   View a printable version of the current page.  
  Making a SOAP Controller with Optio's Soaplib
Added by Ben Bangert, last edited by Lysander David on Mar 18, 2008  (view change) show comment
Labels: 

Name Space Section Page Version Status Reviewed Author(s)
Making a SOAP Controller with Optio's Soaplib Pylons Cookbook Controllers Making a SOAP Controller with Optio's Soaplib 1.0 Draft False Ben Bangert

Reading Attaching WSGI apps under Pylons helps understand how Pylons treats controllers as WSGI applications which provides a good foundation for this recipe.

Introduction

Implementing SOAP in an application used to be hard work but now, thanks to Optio's Soaplib WSGI app, the hard work has been done for you.

Install soaplib

You will need to install Routes 1.7 version for soaplib to function properly behind Pylons.

1
sudo easy_install -U Routes

1
sudo easy_install soaplib

Soaplib should now be installed and ready to use.

Create a SOAP Controller

Next, create a basic controller to get started with:

1
paster controller soapy

Now that we have the controller stub file we need to modify it to use soaplib. In this example, we'll use the basic HelloWorld SOAP service. The Pylons application in this example is named 'wsgitest', make sure to change that line to reflect the name of your Pylons app.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
from wsgitest.lib.base import *

from soaplib.wsgi_soap import SimpleWSGISoapApp
from soaplib.service import soapmethod
from soaplib.serializers.primitive import String, Integer, Array

class HelloWorldService(SimpleWSGISoapApp):

    @soapmethod(String,Integer,_returns=Array(String))
    def say_hello(self,name,times):
        results = []
        for i in range(0,times):
            results.append('Hello, %s'%name)
        return results

SoapyController = HelloWorldService()

Modify Routes To Download WSDL

Insert the following line

1
map.connect(':(controller).wsdl')

before

1
map.connect(':controller/:action/:id')

in config/routing.py so that make_map looks like

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
def make_map():
    """Create, configure and return the routes Mapper"""
    map = Mapper(directory=config['pylons.paths']['controllers'],
                 always_scan=config['debug'])

    # The ErrorController route (handles 404/500 error pages); it should
    # likely stay at the top, ensuring it can always be resolved
    map.connect('error/:action/:id', controller='error')

    # CUSTOM ROUTES HERE
    map.connect(':(controller).wsdl')
    map.connect(':controller/:action/:id')

    return map

This will allow the wsdl to be downloaded using the url
http://localhost:5000/soapy.wsdl

Test the SOAP Service

Open a python prompt in your projects directory, and run the following code (replacing wsgitest with the name of your project):

1
2
3
4
5
>>> from soaplib.client import make_service_client
>>> from wsgitest.controllers.soapy import HelloWorldService
>>> client = make_service_client('http://localhost:5000/soapy',HelloWorldService())
>>> print client.say_hello("Dave",5)
['Hello, Dave', 'Hello, Dave', 'Hello, Dave', 'Hello, Dave', 'Hello, Dave']

Testing the built-in WSDL facility

As above, run the following code (replacing wsgitest with the name of your project):

1
2
3
4
>>> from soaplib.client import make_service_client
>>> from wsgitest.controllers.soapy import HelloWorldService
>>> client = make_service_client('http://localhost:5000/soapy',HelloWorldService())
>>> client.server.wsdl('')

The result is pretty-printed below:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<?xml version='1.0' encoding='utf-8'?>
<definitions 
    name="HelloWorldService" 
    targetNamespace="wsgitest.controllers.soapy.HelloWorldService" 
    xmlns="http://schemas.xmlsoap.org/wsdl/" 
    xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
    xmlns:plnk="http://schemas.xmlsoap.org/ws/2003/05/partner-link/" 
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
    xmlns:tns="wsgitest.controllers.soapy.HelloWorldService" 
    xmlns:typens="wsgitest.controllers.soapy.HelloWorldService" 
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <types>
        <schema 
            targetNamespace="wsgitest.controllers.soapy.HelloWorldService" 
            xmlns="http://www.w3.org/2001/XMLSchema">
            <xs:element name="say_hello" type="tns:say_hello" />
            <xs:complexType name="say_hello">
                <xs:sequence>
                    <xs:element name="name" type="xs:string" />
                    <xs:element name="times" type="xs:int" />
                </xs:sequence>
            </xs:complexType>
            <xs:element name="stringArray" type="tns:stringArray" />
            <xs:complexType name="say_helloResponse">
                <xs:sequence>
                    <xs:element name="retval" type="tns:stringArray" />
                </xs:sequence>
            </xs:complexType>
            <xs:complexType name="stringArray">
                <xs:sequence>
                    <xs:element maxOccurs="unbounded" 
                                minOccurs="0" name="string" type="xs:string" />
                </xs:sequence>
            </xs:complexType>
            <xs:element name="say_helloResponse" type="tns:say_helloResponse" />
        </schema>
    </types>
    <message name="say_hello">
        <part element="tns:say_hello" name="say_hello" />
    </message>
    <message name="say_helloResponse">
        <part element="tns:say_helloResponse" name="say_helloResponse" />
    </message>
    <portType name="HelloWorldService">
        <operation name="say_hello" parameterOrder="say_hello">
            <documentation>
                Docstrings for service methods appear in the wsdl output.
            </documentation>
            <input message="tns:say_hello" name="say_hello" />
            <output message="tns:say_helloResponse" name="say_helloResponse" />
        </operation>
    </portType>
    <plnk:partnerLinkType name="HelloWorldService">
        <plnk:role name="HelloWorldService">
            <plnk:portType name="tns:HelloWorldService" />
        </plnk:role>
    </plnk:partnerLinkType>
    <binding name="HelloWorldService" type="tns:HelloWorldService">
        <soap:binding 
            style="document" 
            transport="http://schemas.xmlsoap.org/soap/http" />
        <operation name="say_hello">
            <soap:operation soapAction="say_hello" style="document" />
            <input name="say_hello">
                <soap:body use="literal" />
            </input>
            <output name="say_helloResponse">
                <soap:body use="literal" />
            </output>
        </operation>
    </binding>
    <service name="HelloWorldService">
        <port binding="tns:HelloWorldService" name="HelloWorldService">
            <soap:address location="" />
        </port>
    </service>
</definitions>

Server-side example fragment

The rest of the work consists of adding functionality to the controller. As a simple illustration, here is a fragment from one of the soaplib examples:

1
2
3
4
5
6
7
8
@soapmethod(User,_returns=Integer)
def add_user(self,user):
    global user_database
    global userid_seq
    user.userid = userid_seq
    userid_seq = userid_seq+1
    user_database[user.userid] = user
    return user.userid

Conclusion

Adding additional SOAP controllers, or increasing the complexity of the existing one is rather easy and can be done as the examples on the optio website show. In addition, it's rather trivial to use the existing database functions and other Pylons features you might desire in your SOAP services.

Site running on a free Atlassian Confluence Open Source Project License granted to Pylons. Evaluate Confluence today.
Powered by Atlassian Confluence, the Enterprise Wiki. (Version: 2.3.3 Build:#645 Feb 13, 2007) - Bug/feature request - Contact Administrators
Top