This is a guide that explains how to begin using the Client Toolkit (CTk) to develop clients for OGSA-DAI 3.0. The CTk is a Java API which contains the building blocks from which a range of clients can be developed all the way from simple clients that submit queries to OGSA-DAI services to more sophisticated clients that can do data integration and transformation. The purpose of the CTk is to aid developers by allowing them to focus on the core logic of their process rather than the lower level details of interacting with OGSA-DAI servers. The CTk also removes the need for a client developer to deal with server-side implementation issues.
The guide shows how to develop a simple SQL query client which submits an OGSA-DAI workflow composed of three activities to an OGSA-DAI web service and gets the result.
This guide assumes you have an OGSA-DAI binary distribution and have deployed OGSA-DAI or have access to an OGSA-DAI server.
The basic notion is that the client will build a workflow of activities which will be executed on the OGSA-DAI server. There are two key elements here, the activities and the workflow.
Activities are the basic building blocks of OGSA-DAI workflows, they are discrete packages which do one logical step in a process. Activities are broken into several different categories, some of which are resource specific and others which are not. The categories types of activity are:
Input data delivery - activities that retrieve input from remote OGSA-DAI data sources.
Data access and collection - activities that access data typically held in resources such as databases.
Data write - activities that write data to resources such as databases.
Data transform - activities that transform data from one format to another. Data processing and data aggregation can be considered to be data transforms.
Output data delivery - activities that send data to remote OGSA-DAI data sinks.
Management and control - activities that manage the OGSA-DAI server.
Each category contains activities which are focussed around a specific task and are only concerned with doing that task, for instance, the SQLQuery activity deals with the task of querying an SQL database and getting a set of results.
The client toolkit provides support for specifying the activities in a workflow. The OGSA-DAI server actually contains the activity implementations i.e. the functionality of the activities to be executed.
For this simple SQL query client, the main stages which will need to be addressed through activities are:
Querying the database.
Transforming the results to a more useable format.
Transforming the results to a more efficient format.
Delivering the results back to the client.
Each of these stages is a discrete step in the process and forms an activity which is part of the workflow.
OGSA-DAI workflows are made up of activities that can be connected together such that an output of one activity becomes the input of another activity. A set of connected activities are known as a pipeline.
Pipelines can be executed in parallel or sequentially as parts of a larger workflow. The example here uses a contains just a single pipeline.
A detailed implementation-independant overview of activities, workflows and pipelines is given in Section 6.4, “Data-centric workflows”.
You first need to set your
CLASSPATH. You can do this as follows
(or alternatively see Section C.1.21, “
What do I need in my CLASSPATH to be
able to run OGSA-DAI clients or compile OGSA-DAI client examples?
”).
To set the CLASSPATH in an OGSA-DAI
binary distribution:
If running under Solaris or Linux run:
$ source setenv.sh
If running under Windows run:
$ setenv.bat
The FAQ "Section C.1.21, “
What do I need in my CLASSPATH to be
able to run OGSA-DAI clients or compile OGSA-DAI client examples?
”" describes what is needed in
the CLASSPATH to run OGSA-DAI clients
if the above are not used.
The code examples assume that the OGSA-DAI server is setup with a default URL prefix (or base services URL) of:
OGSA-DAI Axis Default:
http://localhost:8080/dai/services/
This URL is used in the example client code below, and should be changed in your code to reflect the actual setup of the OGSA-DAI server you are using.
It is also assumed that the OGSA-DAI server you are using exposes a
relational data resource called
MySQLDataResource and that this is
associated with a database which contains a
littleblackbook table. If this is
not the case then replace the resource ID and queries in the code
examples with the resource ID and a query compliant with your
data resource and database.
If you want to create a
littleblackbook please see Chapter 11, Creating test databases.
The example will be a Java client built using components from the
CTk. The example will be in a class called
SQLClient. Each step will give
example code, and conclude with the overall code at that stage. The
example client is split into a number of methods, some of which could
be replaced in a more advanced case or the method could be added
to. The reason for splitting up what could be a single method into a
set of methods is to make explanation of the various steps in
developing the example client easier to follow. It also will help when
dealing with exceptions and their sources.
This example will execute the following query
SELECT * FROM littleblackbook WHERE id <10;
on a database table littleblackbook
held in a database known to an OGSA_DAI server.
It will return the results of the query and output the results as a table.
The first step in any client is to connect to an OGSA-DAI server. To
facilitate this, the CTk provides a
ServerProxy which implements a
Server interface. The requirement is
that known OGSA-DAI URLs are provided to the
Server.
Server mServer;
public void setupServer(String serverURLStr) throws ClientToolkitException, MalformedURLException
{
mServer = new ServerProxy();
mServer.setDefaultBaseServicesURL(new URL(serverURLStr));
}
This proxy is a client-side representation of an OGSA-DAI server. Through it can be obtained proxies to each web service, and so each resource, deployed on the OGSA-DAI server. The base services URL is the prefix for all OGSA-DAI services available.
The Server class provides methods
for an instance to access proxies representing the different resources
available on the OGSA-DAI server. The proxies, which correspond to
the six types of OGSA-DAI resource, include:
DataRequestExecutionResource DataSinkResource DataSourceResource DataResource RequestResource SessionResource
This example will use some of these resources to carry out its
operation. The first of these is a
DataRequestExecutionResource proxy
for a DRER. A Data Request Execution Resource is an OGSA-DAI resource
that accepts workflows from clients, executes these and possibly
returns results. A DRER can be viewed as a workflow management and
execution resource. It is typically the first point of contact for
clients. The DRER proxy can be obtained by the following code:
DataRequestExecutionResource mDRER;
public void setupDRER(ResourceID drerID)
throws ServerException, ClientToolkitException
{
mDRER = mServer.getDataRequestExecutionResource(drerID);
}
This resource is what will execute the workflows, building a request from the client and instructing the server on what to do. This will be expanded upon when the example deals with workflows and execution.
The code is split into different methods, so that the exceptions which can be thrown at each stage are explicitly shown.
Now that the basic connection has been prepared, the activities can be created for the task at hand. In this example, four activities are needed:
SQLQuery TupleToWebRowSetCharArrays CharArraysResize DeliverToRequestStatus
When creating a workflow, all of the inputs and outputs of the activities must be properly connected. If this is not done, then an error concerning an unconnected pipe will be generated. (see Section C.1.9, “When using the client toolkit I get an error about an unconnected pipe”).
The first activity to create is the
SQLQuery activity. This activity acts
on a relational data resource, issuing an SQL query and receiving a
result from the resource. The following code is a method for
creating an SQLQuery activity for a
SQL query and a data resource. In OGSA-DAI a Data Resource is an
OGSA-DAI abstraction of a database or other type of data
resource which resides on the OGSA-DAI server. Resource-specific
activities - such as those that execute SQL queries - can be targeted
at these.
public SQLQuery makeSQLQuery(ResourceID dataResourceID, String sqlStr)
{
SQLQuery tempQuery = new SQLQuery();
tempQuery.setResourceID(dataResourceID);
tempQuery.addExpression(sqlStr);
return tempQuery;
}
The parameters of the method are the
ResourceID for the data resource that
is to be targeted, e.g. a MySQL database exposed by the OGSA-DAI
server, and the SQL query represented by the string
sqlStr.
![]() | Note |
|---|---|
The
This activity requires that the
|
In this example the transformation activity we shall use is the
TupleToWebRowSetCharArrays. This
activity converts tuples, such as those output from a query activity
to a web row set format. This activity does not have to be targeted at
a resource. It requires that another activity provides the input. At this
stage, only the instance is created using a similar method to that for
SQLQuery.
public TupleToWebRowSetCharArrays makeTupleToWebRowSetCharArrays()
{
return new TupleToWebRowSetCharArrays();
}
In this example we shall add another transformation activity.
TupleToWebRowSetCharArrays outputs
character arrays which can cause efficiency problems when used with
SOAP over HTTP - the medium used for server-client communications
in OGSA-DAI.
The CharArraysResize activity
can restructure the arrays into a size that results in improved
efficiency when transporting them via SOAP over HTTP. The
size of the restructured arrays can be specified by the client and,
if necessary, tuned.
This activity does not have to be targeted at
a resource. It requires that another activity provides the input. At this
stage, only the instance is created using a similar method to that for
SQLQuery.
public CharArraysResize makeCharArraysResize()
{
CharArraysResize resize = new CharArraysResize();
resize.addArraySizeInput(5000);
return resize;
}
Delivery from OGSA-DAI can be carried out in a number of ways, through FTP, GridFTP, SMTP or, like in this example, via a DeliverToRequestStatus activity. This activity ensures that any data it receives are placed in the request status which is returned to a client by a DRER when their workflow completes execution. Again, note that like the transformation activity above, this activity does not need to be explicitly targeted at a resource.
public DeliverToRequestStatus makeDeliverToRequestStatus()
{
return new DeliverToRequestStatus();
}
All of the above code fragments focus on generating instances of activities and do not connect them together or place them into a workflow. The transform and delivery activities could be instantiated inline in a main listing but for this example splitting them into methods allows for easier integration into the main code.
Now we can build our workflow using a
PipelineWorkflow object.
A workflow is a sequence of activities which are related to each other, these activities form a path through which data and control will flow. In this example, a sequential pipeline workflow will be used. There are parallel workflows available and also the ability to have workflows with child workflows (for full details see Section 6.4.8, “Activities and workflows execution order”).
The following method takes as parameters the activities already
discussed and connected their input and outputs appropriately and adds
them to a PipelineWorkflow. The
SQLQuery output is connected to the
input of the
TupleToWebRowSetCharArrays which in
turn has its output connected to the
CharArraysResize which in turn
has its output connected to the
DeliverToRequestStatus. These
activities are then all added to the workflow using the
add method.
![]() | Note |
|---|---|
The order in which the activities are added does not matter as long as the pipes from activity to activity are connected correctly. Otherwise an unconnected pipe error will occur (see Section C.1.9, “When using the client toolkit I get an error about an unconnected pipe”). |
public PipelineWorkflow makePipelineWorkflow(SQLQuery query,
TupleToWebRowSetCharArrays transform,
CharArraysResize resize,
DeliverToRequestStatus delivery)
{
// Create a new pipeline.
PipelineWorkflow tempFlow = new PipelineWorkflow();
// Connect the query output to the transform input.
transform.connectDataInput(query.getDataOutput());
// Connect the transform output to the transform input.
resize.connectDataInput(transform.getResultOutput());
// Connect the transform output to the delivery input.
delivery.connectInput(resize.getOutput());
// Add the activities to the pipeline.
tempFlow.add(query);
tempFlow.add(transform);
tempFlow.add(resize);
tempFlow.add(delivery);
return tempFlow;
}
Once a workflow pipeline has been created the next step is to execute
the pipeline using the
DataRequestExecutionResource.
public RequestResource executePipeline(PipelineWorkflow pipe)
throws ServerCommsException,
ServerException,
ResourceUnknownException,
ClientException,
RequestException,
ClientToolkitException
{
return mDRER.execute(pipe, RequestExecutionType.SYNCHRONOUS);
}
The CTk basically takes the workflow and sends this across to an OGSA-DAI data request execution service, a web service that exposes the DRER. The DRER executes the workflow and returns a request status. The use of a DeliverToRequestStatus activity means the query data returns in the request.
This method returns a RequestResource
into which the CTk will deposit the request status from the OGSA-DAI
server. Things to note in this method are the exceptions which can be
thrown and the type of
RequestExecutionType. The
RequestExecutionType can be either
ynchronous, where the
execute method does not return until
the DRER on the OGSA-DAI server has completed the workflow execution
or asynchronous where the method returns
immediately but the DRER on the OGSA-DAI server will continue on with
the workflow execution. In such cases the DRER server-side will create
a request resource which the client can poll via the
RequestResource object returned by
this method.
The DeliverToRequestStatus activity
will return the status of the workflow and the results from its
connected input to the RequestStatus
object. This is obtained by using the following code:
RequestResource rr = sqlClient.executePipeline(pipeline); RequestStatus rs = rr.getRequestStatus();
In this example, the results should contain the output of
the TupleToWebRowSetCharArrays
(the effects of CharArraysResize are
transparent in terms of the content of the data) which
should look like this:
Request id="ogsadai-113440d0c59" Request status="uk.org.ogsadai.resource.request.status.COMPLETED" Result activityInstanceName="ogsadai-1134428a47d" resultName="result" Data: --DataItem--->[ --DataItem---><webRowSet xmlns="http://java.sun.com/xml/ns/jdbc" xmlns:xsi="http://www.w3. org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/jdbc http://java.sun.com/xml/ns/jdbc/webrow set.xsd"> <properties> <command></command> <concurrency></concurrency> <datasource></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>0</max-field-size> <max-rows>0</max-rows> <query-timeout>0</query-timeout> <read-only>true</read-only> <rowset-type>1003</rowset-type> <show-deleted>false</show-deleted> <table-name></table-name> <url></url> <sync-provider> <sync-provider-name/> <sync-provider-vendor/> <sync-provider-version/> <sync-provider-grade/> <data-source-lock/> </sync-provider> </properties> <metadata> <column-count>4</column-count> <column-definition> <column-index>1</column-index> <auto-increment></auto-increment> <case-sensitive></case-sensitive> <currency></currency> <nullable>1</nullable> <signed></signed> <searchable></searchable> <column-display-size>11</column-display-size> <column-label>id</column-label> <column-name>id</column-name> <schema-name></schema-name> <column-precision>11</column-precision> <column-scale>0</column-scale> <table-name></table-name> <catalog-name></catalog-name> <column-type>4</column-type> <column-type-name>INTEGER</column-type-name> </column-definition> <column-definition> <column-index>2</column-index> <auto-increment></auto-increment> <case-sensitive></case-sensitive> <currency></currency> <nullable>1</nullable> <signed></signed> <searchable></searchable> <column-display-size>64</column-display-size> <column-label>name</column-label> <column-name>name</column-name> <schema-name></schema-name> <column-precision>64</column-precision> <column-scale>0</column-scale> <table-name></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></auto-increment> <case-sensitive></case-sensitive> <currency></currency> <nullable>1</nullable> <signed></signed> <searchable></searchable> <column-display-size>128</column-display-size> <column-label>address</column-label> <column-name>address</column-name> <schema-name></schema-name> <column-precision>128</column-precision> <column-scale>0</column-scale> <table-name></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></auto-increment> <case-sensitive></case-sensitive> <currency></currency> <nullable>1</nullable> <signed></signed> <searchable></searchable> <column-display-size>20</column-display-size> <column-label>phone</column-label> <column-name>phone</column-name> <schema-name></schema-name> <column-precision>20</column-precision> <column-scale>0</column-scale> <table-name></table-name> <catalog-name></catalog-name> <column-type>12</column-type> <column-type-name>VARCHAR</column-type-name> </column-definition> </metadata> <data> --DataItem---><currentRow> <columnValue>1</columnValue> <columnValue>Ally Antonioletti</columnValue> <columnValue>101 Antonioletti Road, San Jose</columnValue> <columnValue>087192027</columnValue> </currentRow> --DataItem---><currentRow> <columnValue>2</columnValue> <columnValue>Amy Atkinson</columnValue> <columnValue>70 Atkinson Crescent, Southampton</columnValue> <columnValue>0105931111</columnValue> </currentRow> --DataItem---></data> </webRowSet> --DataItem--->] Activity instanceName="ogsadai-1134428a47e" status="COMPLETED" Activity instanceName="ogsadai-1134428a47b" status="COMPLETED" Activity instanceName="ogsadai-1134428a47d" status="COMPLETED" Activity instanceName="ogsadai-1134428a47f" status="COMPLETED" </output>
This output is quite unwieldy for someone to look at but in applications
it would be passed from the
TupleToWebRowSetCharArrays activity
to another client, or to a method, for formatting the output in a
more usable format.
The status of the execution of the request can be checked by calling
the getExecutionStatus method on the
RequestStatus object. This code will
simply print out the execution status,
RequestStatus rs = rr.getRequestStatus(); System.out.println(rs.getExecutionStatus());
and in most cases this should output:
uk.org.ogsadai.resource.request.status.COMPLETED
If an error has occurred then the status can return as
COMPLETED_WITH_ERROR.
As a simple example of using all of the above code, a
main method can be added and used
with the query stated before. Remember that,
as explained in Section 20.4, “Assumptions”,
you may have to change the base services URL on line 3, the
SQL statement on line 5 and data resource ID on line 6 depending on
your server setup and relational data resource.
public static void main(String[] args) throws Exception
{
String serverURL = "http://localhost:8080/dai/services/";
ResourceID drerID = new ResourceID("DataRequestExecutionResource");
String sqlStr = "SELECT * FROM littleblackbook WHERE id<3;";
ResourceID dataResourceID = new ResourceID("MySQLDataResource");
SQLClient iSQLClient = new SQLClient();
iSQLClient.setupServer(serverURL);
iSQLClient.setupDRER(drerID);
SQLQuery sqlQ = iSQLClient.makeSQLQuery(dataResourceID, sqlStr);
DeliverToRequestStatus dtrs = iSQLClient.makeDeliverToRequestStatus();
TupleToWebRowSetCharArrays ttwrsca = iSQLClient.makeTupleToWebRowSetCharArrays();
CharArraysResize car = iSQLClient.makeCharArraysResize();
PipelineWorkflow pwf = iSQLClient.makePipelineWorkflow(sqlQ, ttwrsca, car, dtrs);
RequestResource rr = iSQLClient.executePipeline(pwf);
RequestStatus rs = rr.getRequestStatus();
System.out.println(rs.getExecutionStatus());
}
The above code does not take into account exceptions at this point. The first few lines set up the SQL query string and the resource IDs. The first of these is the string for the base services URL for the OGSA-DAI server.
The client can be run from your working directory:
$ java SQLClient
Before moving on to consider the exceptions, the output from the
TupleToWebRowSetCharArrays can be
used in a number of ways and, to finish off this example client, a way
to obtain a tabular output will be shown. This can access the activity
output directly and get access to the metadata for resultant output to
format the table.
First a small method that gives
TupleToWebRowSetCharArrays a direct
reference to the request status so it can parse it. This is a
consequence of using CharArraysResize
for improving efficiency:
private static void setRequestStatus(TupleToWebRowSetCharArrays
tupleToWebRowSet,
DeliverToRequestStatus
deliverToRequestStatus)
{
tupleToWebRowSet.getResultOutput().setDeliverToRequestStatusActivity(deliverToRequestStatus);
}
Then a small method to assist in padding out strings:
private static String pad(String base, int width)
{
StringBuffer baseBuffer = new StringBuffer(base);
int padLength = width - base.length();
for (int i = 0; i < padLength; i++)
{
baseBuffer.append(" ");
}
return baseBuffer.toString();
}
This method will pad any string out to the stated width in the parameters.
Then to write out the table of results, the
TupleToWebRowSetCharArrays is
accessed directly after the request has finished executing and written
out as a table using the metadata and results. The following method
will use the pad method and write the table to output.
public void printTable(TupleToWebRowSetCharArrays tupleToWebRowSet)
throws SQLException,
DataStreamErrorException,
UnexpectedDataValueException,
WebRowSetResultSetParseException,
DataSourceUsageException
{
if (tupleToWebRowSet.hasNextResult())
{
// Get ResultSet.
ResultSet rs = tupleToWebRowSet.nextResultAsResultSet();
// Get ResultSet metadata.
ResultSetMetaData md = rs.getMetaData();
// Get column names and initial column widths.
int numColumns = md.getColumnCount();
String[] columns = new String[numColumns];
int[] widths = new int[numColumns];
for (int i = 0; i < numColumns; i++)
{
String column = md.getColumnLabel(i + 1);
columns[i] = column;
widths[i] = column.length();
}
// Get ResultSet rows and update column widths also.
Vector rows = new Vector();
while (rs.next())
{
String[] fields = new String[numColumns];
for (int i = 0; i < numColumns; i++)
{
fields[i] = rs.getString(i + 1);
if (fields[i] == null)
{
fields[i] = "null";
}
widths[i] = Math.max(widths[i], fields[i].length());
}
rows.add(fields);
}
rs.close();
// Print column names.
String tableHeading = "| ";
for (int i = 0; i < numColumns; i++)
{
tableHeading += (pad(columns[i], widths[i]) + " | ");
}
System.out.println(tableHeading);
// Print rows.
for (int j = 0; j < rows.size(); j++)
{
String[] row = (String[])rows.get(j);
String rowString = "| ";
for (int i = 0; i < numColumns; i++)
{
rowString += (pad(row[i], widths[i]) + " | ");
}
System.out.println(rowString);
}
}
}
The output from a short query should look similar to this:
| id | name | address | phone | | 1 | Ally Antonioletti | 101 Antonioletti Road, San Jose | 087192027 | | 2 | Amy Atkinson | 70 Atkinson Crescent, Southampton | 0105931111 |
The final code without exception handling should look like this.
Remember that, as explained in Section 20.4, “Assumptions”,
you may have to change the base services URL, the SQL statement
and data resource ID in the main
method depending on your server setup and relational data resource.
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Vector;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import uk.org.ogsadai.client.toolkit.DataRequestExecutionResource;
import uk.org.ogsadai.client.toolkit.DataValueIterator;
import uk.org.ogsadai.client.toolkit.PipelineWorkflow;
import uk.org.ogsadai.client.toolkit.RequestExecutionType;
import uk.org.ogsadai.client.toolkit.RequestResource;
import uk.org.ogsadai.client.toolkit.Server;
import uk.org.ogsadai.client.toolkit.ServerProxy;
import uk.org.ogsadai.client.toolkit.activities.block.CharArraysResize;
import uk.org.ogsadai.client.toolkit.activities.delivery.DeliverToRequestStatus;
import uk.org.ogsadai.client.toolkit.activities.sql.SQLQuery;
import uk.org.ogsadai.client.toolkit.activities.transform.TupleToWebRowSetCharArrays;
import uk.org.ogsadai.client.toolkit.exception.ClientException;
import uk.org.ogsadai.client.toolkit.exception.ClientToolkitException;
import uk.org.ogsadai.client.toolkit.exception.RequestException;
import uk.org.ogsadai.client.toolkit.exception.ResourceUnknownException;
import uk.org.ogsadai.client.toolkit.exception.ServerCommsException;
import uk.org.ogsadai.client.toolkit.exception.ServerException;
import uk.org.ogsadai.client.toolkit.exception.DataSourceUsageException;
import uk.org.ogsadai.client.toolkit.exception.DataStreamErrorException;
import uk.org.ogsadai.client.toolkit.exception.UnexpectedDataValueException;
import uk.org.ogsadai.converters.webrowset.WebRowSetResultSetParseException;
import uk.org.ogsadai.resource.ResourceID;
import uk.org.ogsadai.resource.request.RequestStatus;
/**
* Example SQL Client
*/
public class SQLClient
{
private Server mServer;
private DataRequestExecutionResource mDRER;
/**
* Constructor
*/
public SQLClient()
{
mServer = null;
mDRER = null;
}
/**
* Method will retrieve an OGSA-DAI server from the parameter
* serverURLstr.
*
* @param serverURLStr
* @throws ClientToolkitException
* @throws MalformedURLException
*/
public void setupServer(String serverURLStr)
throws ClientToolkitException, MalformedURLException
{
mServer = new ServerProxy();
mServer.setDefaultBaseServicesURL(new URL(serverURLStr));
}
/**
* Method will get the DRER identified by the ResourceID from the server.
*
* @param drerID
* @throws ClientToolkitException
*/
public void setupDRER(ResourceID drerID)
throws ServerException, ClientToolkitException
{
mDRER = mServer.getDataRequestExecutionResource(drerID);
}
/**
* Method creates a SQLQuery activity for the identified resource
* and given query
* @param dataResourceID
* @param sqlStr
* @return SQLQuery
*/
public SQLQuery makeSQLQuery(ResourceID dataResourceID, String sqlStr)
{
SQLQuery tempQuery = new SQLQuery();
tempQuery.setResourceID(dataResourceID);
tempQuery.addExpression(sqlStr);
return tempQuery;
}
/**
* Creates a new DeliverToRequestStatus activity
* @return DeliverToRequestStatus
*/
public DeliverToRequestStatus makeDeliverToRequestStatus()
{
return new DeliverToRequestStatus();
}
/**
* Creates a new TupleToWebRowSetCharArrays activity
* @return TupleToWebRowSetCharArrays
*/
public TupleToWebRowSetCharArrays makeTupleToWebRowSetCharArrays()
{
return new TupleToWebRowSetCharArrays();
}
/**
* Creates a new CharArraysResize activity
* @return CharArraysResize
*/
public CharArraysResize makeCharArraysResize()
{
CharArraysResize resize = new CharArraysResize();
resize.addArraySizeInput(5000);
return resize;
}
/**
*
* Creates a new pipelineworkflow for the three activities.
* Connects the activities, query-transform-delivery
* @param query
* @param transform
* @param delivery
* @return PipelineWorkflow
*/
public PipelineWorkflow makePipelineWorkflow(SQLQuery query,
TupleToWebRowSetCharArrays transform,
CharArraysResize resize,
DeliverToRequestStatus delivery)
{
PipelineWorkflow tempFlow = new PipelineWorkflow();
transform.connectDataInput(query.getDataOutput());
resize.connectDataInput(transform.getResultOutput());
delivery.connectInput(resize.getOutput());
tempFlow.add(query);
tempFlow.add(transform);
tempFlow.add(resize);
tempFlow.add(delivery);
return tempFlow;
}
/**
* Executes a pipelineworkflow in a synchronous mode and returns
* a requestResource
*
* @param pipe
* @return RequestResource
* @throws ServerCommsException
* @throws ServerException
* @throws ResourceUnknownException
* @throws ClientException
* @throws RequestException
* @throws ClientToolkitException
*/
public RequestResource executePipeline(PipelineWorkflow pipe)
throws ServerCommsException,
ServerException,
ResourceUnknownException,
ClientException,
RequestException,
ClientToolkitException
{
return mDRER.execute(pipe, RequestExecutionType.SYNCHRONOUS);
}
/**
* Prints a table format to standard output using the data from the
* transform activity passed in as parameter.
*
* @param tupleToWebRowSet
* @throws SQLException
* @throws DataStreamErrorException
* @throws UnexpectedDataValueException
* @throws WebRowSetResultSetParseException
* @throws DataSourceUsageException
*/
public void printTable(TupleToWebRowSetCharArrays tupleToWebRowSet)
throws SQLException,
DataStreamErrorException,
UnexpectedDataValueException,
WebRowSetResultSetParseException,
DataSourceUsageException
{
if (tupleToWebRowSet.hasNextResult())
{
// Get ResultSet.
ResultSet rs = tupleToWebRowSet.nextResultAsResultSet();
// Get ResultSet meta data.
ResultSetMetaData md = rs.getMetaData();
// Get column names and initial column widths.
int numColumns = md.getColumnCount();
String[] columns = new String[numColumns];
int[] widths = new int[numColumns];
for (int i = 0; i < numColumns; i++)
{
String column = md.getColumnLabel(i + 1);
columns[i] = column;
widths[i] = column.length();
}
// Get ResultSet rows and update column widths also.
Vector rows = new Vector();
while (rs.next())
{
String[] fields = new String[numColumns];
for (int i = 0; i < numColumns; i++)
{
fields[i] = rs.getString(i + 1);
widths[i] = Math.max(widths[i], fields[i].length());
}
rows.add(fields);
}
rs.close();
// Print column names.
String tableHeading = "| ";
for (int i = 0; i < numColumns; i++)
{
tableHeading += (pad(columns[i], widths[i]) + " | ");
}
System.out.println(tableHeading);
// Print rows.
for (int j = 0; j < rows.size(); j++)
{
String[] row = (String[])rows.get(j);
String rowString = "| ";
for (int i = 0; i < numColumns; i++)
{
rowString += (pad(row[i], widths[i]) + " | ");
}
System.out.println(rowString);
}
}
}
/**
* Pads out a string to the width given as parameter
* @param base
* @param width
* @return String
*/
private static String pad(String base, int width)
{
StringBuffer baseBuffer = new StringBuffer(base);
int padLength = width - base.length();
for (int i = 0; i < padLength; i++)
{
baseBuffer.append(" ");
}
return baseBuffer.toString();
}
/**
* Allow TupleToWebRowSetCharArrays access to the request status.
*
* @param transform
* @param delivery
*/
private static void setRequestStatus(TupleToWebRowSetCharArrays
tupleToWebRowSet,
DeliverToRequestStatus
deliverToRequestStatus)
{
tupleToWebRowSet.getResultOutput().setDeliverToRequestStatusActivity(deliverToRequestStatus);
}
public static void main(String[] args) throws Exception
{
// Setup
String serverURL = "http://localhost:8080/dai/services/";
ResourceID drerID = new ResourceID("DataRequestExecutionResource");
SQLClient iSQLClient = new SQLClient();
ResourceID dataResourceID = new ResourceID("MySQLDataResource");
String sqlStr = "SELECT * FROM littleblackbook WHERE id<3;";
// Server
iSQLClient.setupServer(serverURL);
iSQLClient.setupDRER(drerID);
// Activities Creation
SQLQuery sqlQ = iSQLClient.makeSQLQuery(dataResourceID, sqlStr);
DeliverToRequestStatus dtrs = iSQLClient.makeDeliverToRequestStatus();
TupleToWebRowSetCharArrays ttwrsca = iSQLClient.makeTupleToWebRowSetCharArrays();
CharArraysResize car = iSQLClient.makeCharArraysResize();
// Workflow and Execution
PipelineWorkflow pwf = iSQLClient.makePipelineWorkflow(sqlQ, ttwrsca, car, dtrs);
RequestResource rr = iSQLClient.executePipeline(pwf);
RequestStatus rs = rr.getRequestStatus();
// outputs
System.out.println(rs.getExecutionStatus());
iSQLClient.setRequestStatus(ttwrsca, dtrs);
iSQLClient.printTable(ttwrsca);
}
}
The last line of the main method will print the results table to standard output.
That is the outline of constructing a basic SQL client to OGSA-DAI.