Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

The Python Web services developer: Web services software repository, Part 3

Mike Olson (molson@fourthought.com) and Uche Ogbuji (uche@fourthought.com) are co-founders of and principal consultants at Fourthought Inc., where they develop the open-source tools 4Suite and 4Suite Server , and provide commercial consulting, training, and 4Suite customization for clients working with XML and Web services. They reside in Boulder, Colorado.
Uche Ogbuji (uche@ogbuji.net), Principal Consultant, Fourthought, Inc.
Uche Ogbuji
Mike Olson (molson@fourthought.com) and Uche Ogbuji (uche@ogbuji.net) are co-founders of and principal consultants at Fourthought Inc., where they develop the open-source tools 4Suite and 4Suite Server , and provide commercial consulting, training, and 4Suite customization for clients working with XML and Web services. They reside in Boulder, Colorado.

Summary:  In this third and final article about building a software repository implemented as a Web service, Mike Olson and Uche Ogbuji extend the software repository to broadcast its presence using WSDL.

Date:  10 Jul 2001
Level:  Introductory
Also available in:   Japanese

Activity:  8101 views
Comments:  

At the end of the second part of this series on creating the repository, we stopped at providing a means to upload software to the repository using the HTTP Post method and SOAP. In this, the third of a three part series on building a software repository, we will show how to extend the software repository to broadcast its presence using WSDL, and then provide an example program that brings all of the pieces together.

Before you begin

Before you go on with this article, you should know a few things about the protocols and the latest changes to the software. First, you should be familiar with the workings of the Web Services Description Language (WSDL) (see Resources for articles that explain how WSDL works).

The examples in this column require Python 1.5.2 or later (though Python 2.1 is recommended), 4Suite version 0.11.1 or later, 4Suite Server version 0.11.1 or later, and WSDL lib. The Resources section of this column has all the necessary information about downloading and installing all of the prerequisites.

A new feature in 4Suite Server 0.11.1 is a set of extensions to Python's distutils package that let you bootstrap a 4Suite Server installation directly from a product's setup.py file. The setup.py file that is downloadable from this article contains examples of how to do this. The end result is that to install and bootstrap our example application, all you need to do is run setup.py.


Using WSDL

WSDL is an XML format used to describe the technical characteristics of a Web service. It is used in conjunction with UDDI (Universal Description, Discovery, and Integration) to let Web services announce their presence and capabilities. Using these technologies, it is possible for an application to query a UDDI repository, find information about a desired Web service, and make a request to that Web service.

Since UDDI by itself would take an entire series of articles (keep an eye on this column for just that, though), we will focus only on the WSDL aspect. To add WSDL to our software repository we will create a simple document definition that will be used make simple statements about the presence of WSDL documents. Listing 1 shows the WSDL document definition.

<DocDef xmlns='http://namespaces.4suite.org/4ss' name='WSDL'>
  <RdfMapping>
    <Subject>$uri</Subject>
    <Predicate>'http://schema.4suite.org#wsdl'</Predicate>
    <Object>/wsdl:definitions/@name</Object>
  </RdfMapping>
  <NsMapping>
    <Prefix>wsdl</Prefix>
    <Uri>http://schemas.xmlsoap.org/wsdl/</Uri>
  </NsMapping>
</DocDef>


This document definition will add a statement to the Resource Description Framework (RDF) model for every WSDL document added to the repository. The statement will be used by our WSDL POST handler to keep track of all of the WSDL documents in the system.


A WSDL handler

We spent a fair amount of time in the previous installment of this series (see Resources) explaining how to use the 4Suite Server POST handler to add new content to the system. We will build on this knowledge to write a set of WSDL registration pages that will let you add, edit, and delete WSDL descriptions.

With the code installed, bring up the 4Suite Server HTTP server so we can walk through the example application together. Listing 2 shows the RDF descriptions you will need to make sure are in your 4Suite Server configuration file.

<rdf:Description ID='SoftRepoSoapHandler'>
  <rdf:type resource='http://xmlns.4Suite.org/4ss/properties#HttpHandler'/>    
  <Priority>30</Priority>
  <Module>WebServices4.SoftRepoSoapHandler</Module>
</rdf:Description>  

<rdf:Description ID='SoftRepoWsdlHandler'>
  <rdf:type resource='http://xmlns.4Suite.org/4ss/properties#HttpHandler'/>    
  <Module>WebServices4.WsdlHandler</Module>
</rdf:Description>  

<rdf:Description ID='SoftRepoGetHandler'>
  <rdf:type resource='http://xmlns.4Suite.org/4ss/properties#HttpHandler'/>
  <Module>FtServer.Protocols.Http.GetHandler</Module>
  <DocumentRoot>/WebServices-4</DocumentRoot>
</rdf:Description>

<rdf:Description ID='SoftRepoPostHandler'>
  <rdf:type resource='http://xmlns.4Suite.org/4ss/properties#HttpHandler'/>
  <Module>FtServer.Protocols.Http.PostHandler</Module>
  <DocumentRoot>/WebServices-4</DocumentRoot>
</rdf:Description>

<rdf:Description ID='SoftRepoDeleteHandler'>
  <rdf:type resource='http://xmlns.4Suite.org/4ss/properties#HttpHandler'/>
  <Module>FtServer.Protocols.Http.DeleteHandler</Module>
  <DocumentRoot>/WebServices-4</DocumentRoot>
</rdf:Description>

<rdf:Description ID='PythonSoftRepoServer'>
  <rdf:type resource='http://xmlns.4Suite.org/4ss/properties#PythonServer'/>
  <StartMode>MANUAL</StartMode>
  <Port>8080</Port>
  <PidFile>/tmp/PyHttp.pid</PidFile>
  <ErrorLog>/tmp/PyHttp.all</ErrorLog>
  <TransferLog>/tmp/PyHttp.all</TransferLog>
  <Handler resource='#SoftRepoGetHandler'/>
  <Handler resource='#SoftRepoWsdlHandler'/>
  <Handler resource='#SoftRepoPostHandler'/>
  <Handler resource='#SoftRepoDeleteHandler'/>
  <Handler resource='#SoftRepoSoapHandler'/>
</rdf:Description>


Then, bring up the server with the following command line:

[molson@penny molson]$ 4ss_manager start PythonSoftRepoServer
PythonSoftRepoServer started (pid 6045)

With 4Suite Server configured and running, you should be able to point your browser to http://localhost:8080/index.html to see the index page of our WSDL manager. From the index page, shown in Figure 1, we can either view existing WSDL descriptions or add a new WSDL description to the system.


Figure 1: WSDL Manager index page
Figure 1: WSDL Manager index page

Since there are no WSDL descriptions in the system initially, we will add one. Follow the add new WSDL description link. A new page will ask that a new WSDL description be entered. Listing 3 (also in the example file data/softrepo.wsdl) shows a WSDL description example for our software repository.

<?xml version="1.0"?>
<definitions name="Software Repository"
             xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
             xmlns:tns="http://4Suite.org/webservices-4.wsdl"
             xmlns="http://schemas.xmlsoap.org/wsdl/">
  
  <message name="AddSoftwareInput">
    <part name="title"/>
    <part name="creator"/>
    <part name="home"/>
    <part name="version"/>
    <part name="description"/>
  </message>

  <portType name="AddSoftwarePortType">
    <operation name="AddSoftware">
      <input message="tns:AddSoftwareInput"/>
    </operation>
  </portType>
                          
  <binding name="SoftwareRepoBinding"
           type="tns:AddSoftwarePortType">
    <soap:binding style="document"
                  transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="Add">
      <soap:operation soapAction="http://localhost/Add"/> 
      <input>
        <soap:body use="literal" 
                   namespace="http://spam.com/softrepo"/>
      </input>             
    </operation>
  </binding>

  <service name="SoftwareRepoService">
    <documentation>Example Software Repository Service</documentation>
    <port name="SoftwareRepoPort" binding="tns:SoftwareRepoBinding"> 
      <soap:address location="http://localhost/Add"/>
    </port>
  </service>
                         
</definitions>


<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0"
>
  <xsl:output method='text'/>
  <xsl:param name='wsdl'/>
  <xsl:template match='/'>
    <xsl:value-of select='$wsdl'/>
  </xsl:template>
</xsl:stylesheet>

To add the new WSDL to the system, copy the sample description into the text entry box. We post the message to the file add.doc and add.xslt for the generation of the WSDL in the system. Because we want to add the WSDL exactly as it is entered, our XSLT simply copies the value of the XSLT variable wsdl to the output. Notice that we had to set the output method to text so that it is properly formatted (and the character entities are not escaped). Listing 4 shows the contents of add.xslt.

After adding the WSDL, we are presented with the view screen as shown in Figure 2. This is the same screen we would have gone to had we chosen "View WSDL Definitions" from the index page. From here we have the ability to edit and delete WSDL definitions from our repository. (The edit and delete functions work in a relatively straightforward way and should not need additional explanation.)


Figure 2: WSDL Manager view page
Figure 2: WSDL Manager view page

Bringing it all together

We now have a neat little software repository, we know how to connect to it using SOAP, and we can even set and get a description of it using WSDL. Now we will write a small program that uses all of this to add software to the system. The program will be an extension of the application written in the last column, but here it will query the repository for available software repository services. From the results of the query, it will prompt the user for the needed input and add a new software entry to the system.

In the world of Web services, a UDDI registry is where the WSDL of a Web service is stored. Unfortunately, it would take a year's worth of columns to write and describe a proper UDDI example, so we will use our own method of discovery for Web services in our repository.

The proper way to do this is to extend our SOAP handler to accept a new message that lets us query for available Web services. However, we've already shown you how to write a SOAP handler in 4Suite Server, so for this example we will extend the allowed methods in a HTTP 1.1 request to include a request type of "WSDL." This request will require a header field of name which will be the name of the Web service we are inquiring about. Listing 5 shows the code for a custom 4Suite Server WSDL handler.

There are three things to notice about the handler. First, it inherits from CommonHandler. This is a base class that makes writing handler classes easier. It adds many common functions like _safeHandleRequest and _createErrorResponse, both used in our handler. _safeHandleRequest calls the function that is the second argument inside a try and except block. It catches many standard exceptions, such as "URI unknown" and "access denied," and turns them into the proper HTTP responses (in this case, 404 and 403, respectively.

from FtServer.Protocols.Http import CommonHandler
from FtServer import Core
class WsdlHandler(CommonHandler.CommonHandler):
    def handle(self, request):
        return self._safeHandleRequest(self._handle, request)
    def _handle(self,request):
        #See if the required name header is present
        if not request.headers.has_key('name'): return None
        name = request.headers['name']
        repo = Core.GetRepository()
        try:
            model = repo.getModel()
            #Get all of the statements from the model that define WSDL
            #documents with the requested name
            stmts = model.complete(None,"http://schema.4suite.org#wsdl",name)
            if not stmts:
                return self._createErrorResponse(request, 404, uri=name)
            #Fetch the document
            uri = stmts[0].subject
            body = repo.fetchDocument(uri).getContent()
        finally:
            repo.txRollback()
        headers = {'Content-type' : 'text/xml; charset=iso-8859-1',
                   'Content-length' : len(body),
                   }
        return CommonHandler.Response(200, headers, body)
        
def Register(properties):
    #Register are new handler to accept "WSDL" requests
    handler = WsdlHandler()
    return [(handler.handle, 'WSDL')]

The second thing to notice is the Register function at the bottom of the file. The server calls this Register function when it starts. Register takes a dictionary of properties from the configuration file and returns a list of tuples. The first item in each tuple is a callable object (in this case a method pointer) and the second is a HTTP request type that the method should be called for. In this case we want to be called for all WSDL request types.

Finally, in the beginning of the _handle function, we check to see if the headers have the name key. If they do not, then we return None. By returning None, we tell the server that we did not try to handle the request. The server will then look to see if there is any other registered handler listening for the WSDL request method. If there is, it will be called. If no handlers are found to handle the request, the server will return a 501 error.

Notice that there are three handlers defined for a POST request: the SoapHandler, the PostHandler, and the DeleteHandler. This mechanism is how all three of these can coexist. The SoapHandler first looks at the message. If there is not a SOAPAction header, it returns None. Then the PostHandler looks at the request. If there is not a template-xslt query argument, it returns None. Finally, the DeleteHandler looks at the request. If there is not a delete query argument, then it will return None. The idea is that eventually one of these handlers in the chain will handle the request, and no error is raised.

To test our sample handler, we will start building our sample application. In our application, we will connect to the repository, get the WSDL description about the Software Repository, query the user for a set of parameters to satisfy the interface defined in the WSDL, and, finally, make a request to add new software.

The first step is covered in Listing 6. This uses Python's standard httplib to connect to the server, make an HTTP request of type WSDL, and get the response.

Now that we have the WSDL of the software repository, we need to parse it and see what we can do. To do this we will use the Python wsdllib.py module. Instructions for downloading and installation are available in the resources section. Listing 7 shows the portion of our example script that parses the WSDL from the server.

    #now that we have gotten the WSDL, parse it in
    wsdl = wsdllib.ReadFromString(reply_body)

With the WSDL parsed, we will call the function CreateSOAPMessage. This function will use the WSDL to ask the user for the required inputs to the SOAP message, then build the body of the response. With this brief description and the comments in the code, you should be able to follow what is happening in the function.

Similar to the previous column, we send the SOAP request to the server and parse and display the response. Listing 8 shows the entire example program and Listing 9 shows an execution example of the completed program.

[molson@penny code]$ python src/example1.py 
Please enter a selection for 'Service'
  0.  SoftwareRepoService
Selection: 0
Please enter a selection for 'Service Port'
  0.  SoftwareRepoPort
Selection: 0
Please enter a selection for 'Operation'
  0.  AddSoftware
Selection: 0
Please enter value for 'title': New Software
Please enter value for 'description': This is a new software
Please enter value for 'version': 0.001
Please enter value for 'home': http://new-software.com
Please enter value for 'creator': Mike.Olson@fourthought.com
New Document (uri = /softrepo/incoming/New Software-0.001.xml)
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:dc="http://purl.org/dc/elements/1.1"
   xmlns="http://namespaces.4suite.org/www/software-map"
 >
   <Software rdf:ID="New Software">
     <dc:Title>New Software</dc:Title>
     <dc:Creator>Mike.Olson@fourthought.com</dc:Creator>
     <Home rdf:resource="http://new-software.com"/>
     <CurrentVersion>0.001</CurrentVersion>
     <dc:Description>This is a new software</dc:Description>
   </Software>
 </rdf:RDF>
[molson@penny code]$ 


A Conclusion to our software repository

We've now seen how to use 4Suite Server to implement a Web service. In the first column, we built a software repository that displayed and retrieved software packages using HTTP from a repository. In the second column, we extended the example to allow HTTP POSTs to create new entries in the software repository. We also showed how to add packages to the repository using SOAP. Lastly, in this column, we created a WSDL document that defined our software repository service, then connected to the repository and used the WSDL to create a SOAP message to add a new package to the repository.

In the next installment of the column, we will look at some other options for processing SOAP message in Python.


Resources

About the authors

Mike Olson (molson@fourthought.com) and Uche Ogbuji (uche@fourthought.com) are co-founders of and principal consultants at Fourthought Inc., where they develop the open-source tools 4Suite and 4Suite Server , and provide commercial consulting, training, and 4Suite customization for clients working with XML and Web services. They reside in Boulder, Colorado.

Uche Ogbuji

Mike Olson (molson@fourthought.com) and Uche Ogbuji (uche@ogbuji.net) are co-founders of and principal consultants at Fourthought Inc., where they develop the open-source tools 4Suite and 4Suite Server , and provide commercial consulting, training, and 4Suite customization for clients working with XML and Web services. They reside in Boulder, Colorado.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=SOA and Web services
ArticleID=11569
ArticleTitle=The Python Web services developer: Web services software repository, Part 3
publish-date=07102001
author1-email=molson@fourthought.com
author1-email-cc=
author2-email=uche@ogbuji.net
author2-email-cc=

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Special offers