Writing Perform Documents

This practical session will teach you how to write perform documents. The exercises start by looking at a simple synchronous request, then move on to parameterisation, before taking a look at transformations and asynchronous delivery.

Solutions are provided at the bottom of the document.

Abbreviations

The following notational abbreviations are used within the instructions:

Preparation

Before starting the exercises, follow these steps:

Exercise 1 - Write a simple perform document

OGSA-DAI provides the xPathStatement activity for performing XPath queries against XML databases. XPath is a simple language for addressing parts of an XML document. OGSA-DAI includes the XPathStatement activity for performing XPath queries.

For this exercise you will write a simple perform document that queries the Xindice database on your local machine using the xPathStatement activity.

1.1

Copy the template below into a new file, named "exercise1.xml", within your exercises directory:

<?xml version="1.0" encoding="UTF-8"?>
<gridDataServicePerform
  xmlns="http://ogsadai.org.uk/namespaces/2003/07/gds/types"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://ogsadai.org.uk/namespaces/2003/07/gds/types ../../../../schema/ogsadai/xsd/activities/activities.xsd">

  <documentation>
    Performs a simple XPath statement against the
    test database and delivers the results in the
    response document.
  </documentation>

  <xPathStatement name="statement">
    <expression>XXXXX</expression>
    <resourceSetStream name="XXXXX"/>
  </xPathStatement>

</gridDataServicePerform>

1.2

Complete the parts marked XXXXX by providing the following XPath expression:

/entry[@id&lt;100]

NOTE: in order to encode '<' and '>' characters into XPath expressions, you must use the HTML form, '&lt;' and '&gt;'. This is because '<' and '>' are special characters that indicate the beginning and end of an XML elements.

and giving the <resourceSetStream> element a unique name. This is the name of the output of the xPathStatement activity. Later on, you will see this name referenced in the response document.

1.3

Use the OGSA-DAI Client to send this perform document to a Grid Data Service:

#> cd <OGSA-DAI>
#> ./setenv.sh
#> java uk.org.ogsadai.client.Client -test http://localhost:8080/ogsa/services/ogsadai/DAIServiceGroupRegistry exercises/exercise1.xml

When the client runs, select the factory for Xindice Grid Data Services. The client will then use the factory to create a GDS, send the perform document, process the query and return a response document. The results of the query should be contained in the response document. Refer to the solutions to verify your results.

Exercise 2 - Parameterising a perform document

OGSA-DAI provides the sqlQueryStatement activity for performing SQL queries against relational databases. This activity supports parameterisation using a notation similar to a JDBC prepared statement. '?' characters can be inserted into SQL expressions to indicate parameters.

For example, a simple SQL statement expression could be written as follows:

select * from littleblackbook where id=?

The value of the '?' can then set using an <sqlParameter> element, as shown below. Note that the position attribute refers to the position of the '?' within the expression, starting from 1. If there was a second '?' then this would have a position of 2.

<sqlParameter position="1" from="someOutput"/>

The 'from' attribute should reference the output of another activity. It is from this output that the value for the parameter is read. OGSA-DAI provides the dataStore activity for this purpose.

For this exercise you will write a second perform document to perform a parameterised query against a MySQL database on the workshop server.

2.1

Copy the perform document, "exercise1.xml" into a new document called "exercise2.xml", within the exercises directory.

#> cd <OGSA-DAI>/exercises
#> cp exercise1.xml exercise2.xml

Now replace the xPathStatement activity XML contained in "exercise2.xml" with an sqlQueryStatement activity. Shown below is an example of a basic (non-parameterised) sqlQueryActivity. This will make a good starting point.

<sqlQueryStatement name="statement">
  <expression>select * from littleblackbook where id=10</expression>
  <webRowSetStream name="statementOutput"/>
</sqlQueryStatement>

2.2

Now modify the expression to select all the data from littleblackbook where the id is between two values. Use '?'s to represent these values. These will be set later using parameterisation.

NOTE: in order to encode '<' and '>' characters into the expression, you must use the HTML form, '&lt;' and '&gt;'. This is because '<' and '>' are special characters that indicate the beginning and end of an XML elements.

HELP: If you are unfamiliar with writing SQL statements, refer to the solutions at the end of this document.

2.3

Next add the appropriate <sqlParameter> sub-elements to the <sqlQueryStatement> element. Use the value "myDataStore" for the 'from' attribute values.

2.4

Finally add a dataStore activity to the perform document, above the sqlQueryStatement activity. You can copy and paste from the example below, then complete the part marked XXXXX with the name of the dataStore output. This name must be referenced by the from attributes of the <sqlParameter> elements specified in example 2.3.

      <dataStore name="parameter">
        <item>50</item>
        <item>100</item>
        <itemCursor name="XXXXX"/>
      </dataStore>

2.5

Now use the OGSA-DAI Client to process this perform document. Select the Grid Data Service Factory for the MySQL database. All the data with id values between 50 and 100 should be returned in the response document. Compare your results with the solution.

2.6

Modify the perform document to return the data within a different id range.

Exercise 3 - Transformations

For this exercise, you will be returning to the local Xindice database. Starting with the perform document created in exercise 1, you will add transformation and delivery activities in order to transform the results from an arbitrary XML structure into HTML.

3.1

Copy "exercise1.xml" into a new file named "exercise3.xml", within the exercises directory.

#> cd <OGSA-DAI>/exercises
#> cp exercise1.xml exercise3.xml

3.2

Next you will transform the results into HTML using an XSL Transform. XSLT (XML Stylesheet Language Transformations) is a language for transforming XML documents into other XML documents. OGSA-DAI includes the xslTransform activity for performing XSL Transformations.

First have a look at the example XSLT perform document provided in the examples directory:

      <OGSA_DAI>\examples\GDSPerform\Transform\xslTransform.xml

Notice that the xslTransform activity has two inputs:

The from attributes of each of these inputs must refer to outputs from other activities. In the example, a deliverFromURL activity is being used to generate one input, and an xPathStatement activity to generate the other.

Modify your "exercise3.xml" perform document to include a deliverFromURL activity and an XSLTranform activity. Position both of these after the xPathStatement. You can copy and paste from the examples below.

<deliverFromURL name="deliverXSLT">

  <fromURL>file://XXXXX/examples/GDSPerform/Transform/transform.xsl</fromURL>
  <toLocal name="XXXXX"/>

</deliverFromURL>

<xslTransform name="transform">

  <inputXSLT from="XXXXX"/>
  <inputXML from="XXXXX"/>
  <output name="transformedOutput"/>

</xslTransform>

Complete the parts marked XXXXX by specifying the full path to the "transform.xsl" transform file, and adding the appropriate values to the 'name' and 'from' attributes.

3.3

Use the OGSA-DAI Client to perform this document against the Xindice database. Compare the results with the solutions. You should see that the results from exercise 1 have been tranformed into HTML.

Further Exercises

Examine the example perform documents provided in the examples directory of the OGSA-DAI distribution. Experiment with the various delivery and database management activities - but don't delete the collections on the workshop server, Xindice 1.0 has no security policy!

Solutions

1.2

  <xPathStatement name="statement">
    <expression>/entry[@id<100]</expression>
    <resourceSetStream name="statementOutput"/>
  </xPathStatement>

1.3

<gridDataServiceResponse xmlns="http://ogsadai.org.uk/namespaces/2003/07/gds/types"><result name="st
atementOutput" status="COMPLETE"><![CDATA[<resourceSet>
  <resource>

<entry id="1" xmlns:src="http://xml.apache.org/xindice/Query" src:col="/db/littleblackbook" src:key=
"1">
  <name>Ally Antonioletti</name>
  <address>826 Hume Crescent, Southampton</address>
  <phone>01670061244</phone>
</entry>
  </resource>
  <resource>

<entry id="10" xmlns:src="http://xml.apache.org/xindice/Query" src:col="/db/littleblackbook" src:key
="10">
  <name>Martin Laws</name>
  <address>224 Palansuriya Lane, Winchester</address>
  <phone>06686142062</phone>
</entry>
  </resource>
  <resource>
...
...
...
<entry id="98" xmlns:src="http://xml.apache.org/xindice/Query" src:col="/db/littleblackbook" src:key
="98">
  <name>Norman Jackson</name>
  <address>033 Borley Avenue, San Jose</address>
  <phone>03480099767</phone>
</entry>
  </resource>
  <resource>

<entry id="99" xmlns:src="http://xml.apache.org/xindice/Query" src:col="/db/littleblackbook" src:key
="99">
  <name>Paul Krause</name>
  <address>100 Watson Crescent, Winchester</address>
  <phone>01908557297</phone>
</entry>
  </resource>
</resourceSet>
]]></result><result name="statement" status="COMPLETE"/>
</gridDataServiceResponse>

2.2

  <sqlQueryStatement name="statement">
    <expression>select * from littleblackbook where id > ? and id < ?</expression>
    <webRowSetStream name="statementOutput"/>
  </sqlQueryStatement>

2.3

  <sqlQueryStatement name="statement">
    <sqlParameter position="1" from="myDataStore"/>
    <sqlParameter position="2" from="myDataStore"/>
    <expression>select * from littleblackbook where id > ? and id < ?</expression>
    <webRowSetStream name="anyUniqueOutputName"/>
  </sqlQueryStatement>

2.4

 <dataStore name="parameter">
    <item>50</item>
    <item>100</item>
    <itemCursor name="myDataStore"/>
  </dataStore>

2.5

<gridDataServiceResponse xmlns="http://ogsadai.org.uk/namespaces/2003/07/gds/types"><result name="st
atementOutput" status="COMPLETE"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<!-- DOCTYPE RowSet PUBLIC '-//Sun Microsystems, Inc.//DTD RowSet//EN' 'http://java.sun.com/j2ee/dtd
s/RowSet.dtd' -->
<RowSet>
 <properties>
  <command><null/></command>
  <concurrency>1007</concurrency>
  <datasource><null/></datasource>
  <escape-processing>true</escape-processing>
  <fetch-direction>1000</fetch-direction>
  <fetch-size>0</fetch-size>
  <isolation-level>0</isolation-level>
  <key-columns>
  </key-columns>
  <map></map>
  <max-field-size>1048576</max-field-size>
  <max-rows>0</max-rows>
  <query-timeout>0</query-timeout>
  <read-only>1007</read-only>
  <rowset-type>1004</rowset-type>
  <show-deleted>false</show-deleted>
  <table-name><null/></table-name>
  <url><null/></url>
 </properties>
 <metadata>
  <column-count>4</column-count>
  <column-definition>
   <column-index>1</column-index>
   <auto-increment>false</auto-increment>
   <case-sensitive>false</case-sensitive>
   <currency>false</currency>
   <nullable>1</nullable>
   <signed>true</signed>
   <searchable>true</searchable>
   <column-display-size>11</column-display-size>
   <column-label>id</column-label>
   <column-name>id</column-name>
   <schema-name></schema-name>
   <column-precision>10</column-precision>
   <column-scale>1</column-scale>
   <table-name>littleblackbook</table-name>
   <catalog-name></catalog-name>
   <column-type>4</column-type>
   <column-type-name>LONG</column-type-name>
  </column-definition>
  <column-definition>
   <column-index>2</column-index>
   <auto-increment>false</auto-increment>
   <case-sensitive>true</case-sensitive>
   <currency>false</currency>
   <nullable>1</nullable>
   <signed>false</signed>
   <searchable>true</searchable>
   <column-display-size>64</column-display-size>
   <column-label>name</column-label>
   <column-name>name</column-name>
   <schema-name></schema-name>
   <column-precision>0</column-precision>
   <column-scale>0</column-scale>
   <table-name>littleblackbook</table-name>
   <catalog-name></catalog-name>
   <column-type>12</column-type>
   <column-type-name>VARCHAR</column-type-name>
  </column-definition>
  <column-definition>
   <column-index>3</column-index>
   <auto-increment>false</auto-increment>
   <case-sensitive>true</case-sensitive>
   <currency>false</currency>
   <nullable>1</nullable>
   <signed>false</signed>
   <searchable>true</searchable>
   <column-display-size>128</column-display-size>
   <column-label>address</column-label>
   <column-name>address</column-name>
   <schema-name></schema-name>
   <column-precision>0</column-precision>
   <column-scale>0</column-scale>
   <table-name>littleblackbook</table-name>
   <catalog-name></catalog-name>
   <column-type>12</column-type>
   <column-type-name>VARCHAR</column-type-name>
  </column-definition>
  <column-definition>
   <column-index>4</column-index>
   <auto-increment>false</auto-increment>
   <case-sensitive>true</case-sensitive>
   <currency>false</currency>
   <nullable>1</nullable>
   <signed>false</signed>
   <searchable>true</searchable>
   <column-display-size>10</column-display-size>
   <column-label>phone</column-label>
   <column-name>phone</column-name>
   <schema-name></schema-name>
   <column-precision>0</column-precision>
   <column-scale>0</column-scale>
   <table-name>littleblackbook</table-name>
   <catalog-name></catalog-name>
   <column-type>12</column-type>
   <column-type-name>VARCHAR</column-type-name>
  </column-definition>
 </metadata>
 <data>
  <row>
   <col>51</col>
   <col>Ali Sugden</col>
   <col>356 Hicken Drive, Winchester</col>
   <col>0274159427</col>
  </row>
  <row>
   <col>52</col>
   <col>Ally Watson</col>
   <col>827 Pearson Road, Winchester</col>
   <col>0961903504</col>
  </row>
  ...
  ...
  ...
    <row>
     <col>98</col>
     <col>Norman Jackson</col>
     <col>033 Borley Avenue, San Jose</col>
     <col>0348009976</col>
    </row>
    <row>
     <col>99</col>
     <col>Paul Krause</col>
     <col>100 Watson Crescent, Winchester</col>
     <col>0190855729</col>
    </row>
   </data>
  </RowSet>]]></result><result name="statement" status="PROCESSING"/><result name="parameter" status="
COMPLETE"/></gridDataServiceResponse>

3.2

<deliverFromURL name="deliverXSLT">

  <fromURL>full path to your transform.xsl file</fromURL>
  <toLocal name="deliverXSLTOutput"/>

</deliverFromURL>

<xslTransform name="transform">

  <inputXSLT from="deliverXSLTOutput"/>
  <inputXML from="statementOutput"/>
  <output name="transformedOutput"/>

</xslTransform>

3.3

<gridDataServiceResponse xmlns="http://ogsadai.org.uk/namespaces/2003/07/gds/types"><result name="transform" status="COMPLETE"/><result name="statement" status="COMPLETE"/><result name="deliverXSLT" status="COMPLETE"/><result name="transformedOutput" status="COMPLETE"><![CDATA[<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Little Black Book</title>
</head>
<body>
<h2>My Little Black Book</h2>
<table border="1">
<tr bgcolor="#99CCFF">
<th>Name</th><th>Address</th><th>Phone</th>
</tr>
<tr>
<td>Ally Antonioletti</td><td>826 Hume Crescent, Southampton</td><td>01670061244</td>
</tr>
<tr>
<td>Martin Laws</td><td>224 Palansuriya Lane, Winchester</td><td>06686142062</td>
</tr>
...
<td>Neil Hume</td><td>356 Atkinson Avenue, Southampton</td><td>07672577371</td>
</tr>
<tr>
<td>Norman Jackson</td><td>033 Borley Avenue, San Jose</td><td>03480099767</td>
</tr>
<tr>
<td>Paul Krause</td><td>100 Watson Crescent, Winchester</td><td>01908557297</td>
</tr>
</table>
</body>
</html>
]]></result></gridDataServiceResponse>

3.4


Further Reading

SQL - A gentle introduction can be found at http://sqlzoo.net/
XPath - See http://www.w3.org/TR/xpath for the XPath specification.
XSLT - See http://www.w3.org/TR/xslt for the XSLT specification.