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, Part 3: Web services software repository, Part 2

A Web service for content updating

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:  Continuing their example of a Web service for storing and managing software, Uche Ogbuji and Mike Olson illustrate how to update the repository using SOAP messages and how to advertise it as a Web service.

Date:  01 May 2001
Level:  Introductory
Also available in:   Japanese

Activity:  9073 views
Comments:  

We began presenting an example of a software repository in part 2 of this column, illustrating how a lot of the heavy lifting of data and metadata management could be made much simpler by using available Web tools and open Web standards such as XML, XSLT, and RDF. Since building the core of the software repository was so simple, we now have time to contemplate how to represent this in a Web service.

In this article, we will look at ways of adding content to the software repository using HTTP POST and SOAP. Also, we'll look at a SD description of the resulting Web service and how 4Suite Server can help expose this. You will want to be familiar with the work from part 2 as well as with HTML forms and the Hypertext Transport Protocol (HTTP) protocol (see Resources).

Software by post

To begin with we should look at updates using simple HTTP POST. This can serve as a means for both human contributors and software agents to provide updates, the former by way of a browser form.

Start by making sure that the software repository core is set up using the steps we explained in part 2. Unfortunately, there's a twist. The last article was based on 4Suite Server version 0.10.2, but since then we released version 0.11.0, with significant improvements. See Resources for an update to the last article that covers the 0.11.0 release.

Let's say the form for contributors to use in adding entries to the repository is as in Figure 1. This corresponds to the HTML in Listing 1.


Figure 1: Form for adding new software to the repository
Form for adding new software to the repository

4Suite Server allows us to set up an XSL transform to handle POST requests such as this form generates, creating a new document that is added to the XML repository. The XSL transform we use for the purpose of adding an entry to the software repository is in Listing 2.

The action attribute of the form element in our HTML source is interpreted with the document at the path in the URI as the source, and the template-xslt argument is interpreted as the XSL transform to use for generating the new document.


Listing 2: XSLT transform to turn HTTP POST data into a new XML document

<?xml version="1.0"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:ftext="http://xmlns.4suite.org/ext"
  extension-element-prefixes="ftext"
  version="1.0"
>
  <xsl:param name='title'/>
  <xsl:param name='creator'/>
  <xsl:param name='home'/>
  <xsl:param name='version'/>
  <xsl:param name='description'/>
  <xsl:template match="/">
<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="{$title}">
    <dc:Title><xsl:value-of select='$title'/></dc:Title>
    <dc:Creator><xsl:value-of select='$creator'/></dc:Creator>
    <dc:Description><xsl:value-of select='$description'/></dc:Description>
    <CurrentVersion><xsl:value-of select='$version'/></CurrentVersion>
    <Home rdf:resource="{$home}"/>
  </Software>
</rdf:RDF>
    <ftext:set-post-template-params
      new-doc-uri="incoming/{$title}-{$version}.xml"
      response-uri="thanks.xhtml"
      docdef="dublin_core"
    />
  </xsl:template>
</xsl:stylesheet>

The first thing to note is the group of parameters such as title and creator. These are automatically set by the server to the values from the form elements of the same name, which become HTTP POST query arguments. These parameters can then be used to craft the output using all the tools XSLT places at our disposal. As you can see, the transform is creating a software description document in the form we introduced in the first part of this series. We omitted some optional fields for simplicity.

Finally, observe the ftext:set-post-template-params extension element at the end of the transform. This is a special extension set up by the server which allows you to set such important parameters as the URI of the document to be added, its document definition and the URI to be used by the server to generate the HTML to be sent in response to the HTTP POST (this is, for instance, the HTML that would appear in the browser after the "Submit" button was clicked to submit an entry).

The steps involved are briefly outlined here:

  1. Create a container and give universal read access to it.
  2. Create a document for the HTTP POST operation.
  3. Create the XSLT template.
  4. Create the submission response document.
  5. Create the container to store the output.

To try this yourself, first create an appropriate container and grand universal read access to it:


Listing 3a

$ 4ss create container /softrepo
$ 4ss set acl --world-read /softrepo

Then create a simple dummy document (just "<null/>") as the HTTP POST target. For example:


Listing 3b

$ 4ss create document - BASE_XML /softrepo/submit-new-software-entry
<null/>
$ 4ss set acl --world-read /softrepo/submit-new-software-entry

If you specify "-" as the source for the XML document, the command will read the XML source from standard input. Next, create the template XSLT document, as shown below:


Listing 3c

$ 4ss create document submit-entry.xslt BASE_XSLT /softrepo/submit-entry.xslt
$ 4ss set acl --world-read softrepo/submit-entry.xslt

Now create the submission response document as follows:


Listing 3d

$ 4ss create document - BASE_XML softrepo/thanks.xhtml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
<html xmlns='http://www.w3.org/1999/xhtml'>
<head>
<title>Thanks for your submission</title>
</head>
<body>
  <p>Thanks for your submission to the software repository.</p>
</body>
$ 4ss set acl --world-read softrepo/thanks.xhtml

Finally, create the container where submitted software records will go. This one must be world-writable in order for the documents to be added by anonymous users. See listing 3e.


Listing 3e

$ 4ss create container softrepo/incoming
$ 4ss set acl --world-write softrepo/incoming

Once this is set up, people can enter the data into a form, or software agents can enter the data using HTTP libraries in the language of choice. There is, however, an alternative growing in popularity for software-to-software access of data, without involving humans.


Software on a rope

4Suite Server implements the basic SOAP API, which we can use as the basis of our software repository Web service.

Listing 4 is a simple Python command-line program that adds a software entry file using the direct SOAP API. Note the special encoding style http://4suite.org/4ss/direct used in the direct 4Suite Server API. This encoding basically consists of an element representing the method invocation and attributes representing the parameters, and in some cases a body containing a document that serves as a parameter. Other than that, Listing 4 is pretty straightforward code to construct an XML representing a SOAP request document from command-line parameters -- put this into an HTTP request, send it off and listen for the response.


Listing 4: A Python program to send a SOAP request according to the core API

import sys, string, httplib, base64, mimetools
SERVER_ADDR = '127.0.0.1'
SERVER_PORT = 8080
BODY_TEMPLATE = """<SOAP-ENV:Envelope
  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:ft="http://xmlns.4suite.org/services"
  SOAP-ENV:encodingStyle="http://4suite.org/4ss/direct"
>
  <SOAP-ENV:Body>
    <ft:Create doc-def-name="%s" uri="%s">
%s
    </ft:Create>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>"""
#define the function
def AddSoftwareFromFile(entry, docdef, uri):
    body = BODY_TEMPLATE%(docdef, uri, base64.encodestring(entry))
    blen = len(body)
    requestor = httplib.HTTP(SERVER_ADDR, SERVER_PORT)
    requestor.putrequest('POST', '/soap-handler')
    requestor.putheader('Host', SERVER_ADDR)
    requestor.putheader('Content-Type', 'text/plain; charset="iso-8859-1"')
    requestor.putheader('Content-Length', str(blen))
    requestor.putheader('SOAPAction', "")
    requestor.endheaders()
    requestor.send(body)
    (status_code, message, reply_headers) = requestor.getreply()
    reply_body = requestor.getfile().read()
    print status_code
    print message
    print reply_body
if __name__ == "__main__":
    fname = sys.argv[1]
    docdef = sys.argv[2]
    uri = sys.argv[3]
    entry = open(fname, 'r').read()
    AddSoftwareFromFile(entry, docdef, uri)

A sample session running this program is shown in Listing 4b.

As you can see, the server merely echoes back the document added to the repository.

But what if we simply want to pass the server a few bits of relevant information for us and have it construct the software repository entry, as we did in the above HTTP POST example? 4Suite Server allows you to write your own specialized SOAP handler as shown in the example in Listing 5. This example handles SOAP messages consisting of the various fields describing the software, composes the description file on the server side, and then, adds it to the repository.

The most important part of this module is the SoftRepoSoapHandler class that is subclassed from the 4Suite Server SoapHandler. All the customized class has to do is define a mapping, NS_TO_HANDLER_MAPPING, which for each namespace defines another mapping from SOAP body element name to a handler function. In our case, we set up the AddEntry function to handle our intended requests.

In order to use this handler module, we must register it with 4Suite Server. This can be done by copying the Python file to a spot on the PYTHONPATH and appending a stanza such as the following to the configuration file.See listing 6a.


Listing 6a

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

You also need to add a line to the PythonServer or ApacheServer configuration stanza referring to the new handler we set up:


Listing 6b

    <Handler resource='#SoftRepoSoapHandler'/>

Once the handler is set up, you can make even simpler SOAP calls to add an entry to the software repository. Listing 7 is example client code for the purpose.


Listing 7: An example client to the software repository

import sys, httplib
SERVER_ADDR = '127.0.0.1'
SERVER_PORT = 8080
BODY_TEMPLATE = """<SOAP-ENV:Envelope
  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:s="http://spam.com/softrepo"
  SOAP-ENV:encodingStyle="http://spam.com/softrepo/encoding"
>
  <SOAP-ENV:Body>
    <s:Add>
      <s:Title><![CDATA[%s</s:Title>
      <s:Creator><![CDATA[%s</s:Creator>
      <s:Home><![CDATA[%s</s:Home>
      <s:Version><![CDATA[%s</s:Version>
      <s:Description><![CDATA[%s</s:Description>
    </s:Add>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>"""
#define the function
def AddEntry(title, version):
    creator = raw_input("Creator: ")
    home = raw_input("Home: ")
    desc = raw_input("Description: ")
    body = BODY_TEMPLATE%(title, creator, home, version, desc)
    blen = len(body)
    requestor = httplib.HTTP(SERVER_ADDR, SERVER_PORT)
    requestor.putrequest('POST', '/softrepo/soap-handler')
    requestor.putheader('Host', SERVER_ADDR)
    requestor.putheader('Content-Type', 'text/plain; charset="iso-8859-1"')
    requestor.putheader('Content-Length', str(blen))
    requestor.putheader('SOAPAction', "")
    requestor.endheaders()
    requestor.send(body)
    (status_code, message, reply_headers) = requestor.getreply()
    reply_body = requestor.getfile().read()
    print status_code
    print message
    print reply_body
if __name__ == "__main__":
    title = sys.argv[1]
    version = sys.argv[2]
    AddEntry(title, version)

Save Listing 7 as add_software2.py and try it out as shown in Listing 7b.


Moving right along...

SOAP support allows integration of our software repository with the rapidly emerging Web services infrastructure, while basic HTTP POST support allows humans and more traditional HTTP-based automation. As we have shown it is fairly simple to build both those interfaces into the same application using Python based services. In the next installment we shall round out the techniques for development of our software repository as a Web Service.


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=11531
ArticleTitle=The Python Web services developer, Part 3: Web services software repository, Part 2
publish-date=05012001
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