Access Keys:
Skip to content (Access Key - 0)

Data Services


Client API


Overview

caGrid Data Services provide a standard query method which all data services have in common. This query method is exposed to the grid via a uniform WSDL using request and response messages of a consistent namespace and type. This allows for a uniform client to invoke any arbitrary data service. Such a client is provided with the data services infrastructure, along with several helper classes. This is also true for data services which support WS-Enumeration or caGrid Bulk Data Transfer.

Creating a Query

Data services in caGrid use CQL to compose queries. A query can be produced programmatically, building up parts of the query using the supplied object model.

CQLQuery query = new CQLQuery();
Object target = new Object();
target.setName(Gene.class.getName());
Attribute symbolAttribute = new Attribute("symbol", Predicate.LIKE, "IL%");
target.setAttribute(symbolAttribute);
query.setTarget(target);

Alternatively, a CQL query can be loaded from a string of XML text, or an XML file and deserialized into the object model.

// from a string
CQLQuery query2 = (CQLQuery) Utils.deserializeObject(
new StringReader("<CQLQuery ... />"), CQLQuery.class);
// from a file
CQLQuery query3 = (CQLQuery) Utils.deserializeObject(
new FileReader(cqlFile), CQLQuery.class);

Standard Data Services

Initializing the Client

The generic data service client can be initialized simply by passing the URL of the remote data service service to the constructor:

String url = "http://localhost:8080/wsrf/services/cagrid/ExampleDataService";
DataServiceClient standardClient = new DataServiceClient(url);

The generic data service client has only the query method in its public API. To make use of any additional methods you may have added to your service, the specific client generated by Introduce for your service must be used.

Submitting a Query

A query can be submitted to the standard data service client, which will return the query results when processing is complete. The query method can throw two typed exceptions:

  • Query Processing Exception
    • Thrown when an error occurs in actually processing the query or formulating a result set. This might include database errors and misconfiguration of the query processor.
  • Malformed Query Exception
    • This is generally thrown from the query validation process, and indicates a query which violates the CQL schema, or attempts to reach parts of a domain model which are either excluded from queries or do not exist.
    • Query processor implementations may also throw this exception in response to queries which attempt to use features of CQL which are not supported by that particular implementation (eg. Attribute Results)
try {
CQLQueryResults results = standardClient.query(query);
} catch (QueryProcessingExceptionType ex) {
// handle processing exception
} catch (MalformedQueryExceptionType ex) {
// handle malformed query
} catch (RemoteException ex) {
// handle remote exception
}

Handling the Results

The results of a CQL query are returned in an object model which can hold one of either object results, attribute results, or a count result. These results can be iterated as single items using a specialized implementation of the standard Java Iterator interface.

Iterator iter = new CQLQueryResultsIterator(results,
InvocationExample.class.getResourceAsStream("client-config.wsdd"));
while (iter.hasNext()) {
Gene g = (Gene) iter.next();
System.out.println("Found a gene:");
System.out.println(g.getFullName() + " -- " + g.getSymbol());
}

Alternatively, the data service infrastructure provides a simplified handle class which hides the complexity of setting up an iterator to handle the query results.

try {
String url = "http://localhost:8080/wsrf/services/cagrid/ExampleDataService";
DataServiceClient standardClient = new DataServiceClient(url);
DataServiceHandle handle = new DataServiceHandle(standardClient);
Iterator i = handle.query(query);
// iterate
} catch (QueryProcessingExceptionType ex) {
// handle query processing exception
} catch (MalformedQueryExceptionType ex) {
// handle malformed query
} catch (MalformedURIException ex) {
// malformed URI
} catch (RemoteException ex) {
// handle remote exception
}

Enumeration Data Services

Initializing the Client

Just as the standard data service client, the enumeration data services client can be initialized with the URL of your grid service:

String url = "http://localhost:8080/wsrf/services/cagrid/ExampleDataService";
EnumerationDataServiceClient client = new EnumerationDataServiceClient(url);

Submitting a Query

The generic enumeration client supports a single method:

EnumerationResponseContainer responseContainer = client.enumerationQuery(query);

When this method is invoked, the service executes the CQL query as it would for a standard data service, but rather than returning the result directly, an enumeration resource is created to store the results, and an EnumerationResponseContainer instance is returned.

The EnumerationResponseContainer is a caGrid data type which encapsulates both the WS-Enumeration spec EnumerationContext and the endpoint reference (EPR) of the enumeration service context and the resource key of created enumeration resource. More information on caGrid's support for WS-Enumeration is provided here.

Handling the Results

The data service infrastructure provides tooling to assist in creating a ClientEnumIterator instance which can communicate with the remote enumeration service context.

EnumerationResponseContainer responseContainer = client.enumerationQuery(query);
InputStream wsddStream =
ClassUtils.getResourceAsStream(getClass(), "client-config.wsdd");
ClientEnumIterator iterator = EnumerationResponseHelper.createClientIterator(responseContainer, wsddStream);
// constraints to retrieve 10 results, no char limit, timeout of 5 sec
IterationConstraints cons = new IterationConstraints(10, \-1, DurationUtils.toDuration(5000));
iterator.setIterationConstraints(cons);
while (iterator.hasNext()) {
SOAPElement elem = (SOAPElement) iterator.next();
// process element
}

The contents of each SOAP Element are an XML representation CQLObjectResult instances, and can be deserialized as such.

Alternatively, the whole querying and result handling process can be condensed to a few lines using the supplied EnumDataServiceHandle class:

EnumDataServiceHandle handle = new EnumDataServiceHandle(client);
Iterator i = handle.query(query);
// iterate

BDT Data Services

Initializing the Client

As with all service clients, the generic BDT Data Service client can be initialized with the URL of the remote data service:

String url = "http://localhost:8080/wsrf/services/cagrid/ExampleDataService";
BDTDataServiceClient client = new BDTDataServiceClient(url);

Submitting a Query

The generic BDT data service client implementation exposes one public query method:

BulkDataHandlerClient bdtClient = client.bdtQuery(query);

The returned BulkDataHandlerClient can be used to invoke either the WS-Enumeration or WS-Transfer support methods.

// invoke WS-Enumeration
EnumerationResponseContainer enumResponse = bdtClient.createEnumeration();
// handle like an enumeration query

// invoke WS-Transfer
AnyXmlType transferResponse = bdtClient.get(new EmptyType());
// any type contains XML of CQLQueryResults instance

Handling the Results

In the case of using enumeration from BDT, the result handling is exactly the same as for a data service with enumeration.

For WS-Transfer's get method, the returned xsd AnyType contains the serialized XML of the CQLQueryResults, and can be handled as it is in a standard data service query.

Last edited by
William Stephens (1487 days ago) , ...
Adaptavist Theme Builder Powered by Atlassian Confluence