Client Application Developer's Guide

     Previous  Next    Open TOC in new window    View as PDF - New Window  Get Adobe Reader - New Window
Content starts here

Advanced Topics

This chapter describes miscellaneous features related to client programming with BEA AquaLogic Data Services Platform. It covers the following topics:

 


Accessing Metadata Using Catalog Services

BEA AquaLogic Data Services Platform maintains metadata about data services, application, functions, schemas through Catalog Services, which is a system catalog-type data service. Catalog services provide a convenient way for client-application developers to programmatically obtain information about any AquaLogic Data Services Platform application, data services, schemas, functions, and relationships. Catalog Services are also data services, therefore, you can view them using the AquaLogic Data Services Console, AquaLogic Data Services Platform Palette, and Data Service controls.

Some advantages of using Catalog Services are as follows:

This section provides details about installing and using Catalog Services to access metadata for any AquaLogic Data Services Platform application. It includes the following topics:

Installing Catalog Services

You can install Catalog Services as a project for an AquaLogic Data Services Platform application or as a JAR file that is added to the Library folder in WebLogic Workshop. The Catalog Services project (_catalogservices) contains data services that provide information about the application, folders, data services, functions, schemas, and relationships available with the application.

DataServiceRef and SchemaRef are additional data services, which consist of functions that retrieve the paths to the data services and schemas available with the AquaLogic Data Services Platform application. For more information about the data services and functions available with Catalog Services, refer to Using Catalog Services on page 11-3.

To install Catalog Services as a project:

  1. Right-click the AquaLogic Data Services Platform application in WebLogic Workshop.
  2. Select the Install Catalog Services (Expanded) option if you want to use the catalog services for development, as shown in Figure 11-1. If you need catalog services only during runtime then select Install Catalog Services (Jar) option.
  3. Figure 11-1 Installing Catalog Services

    Installing Catalog Services

Using Catalog Services

After installing Catalog Services, the catalog services project, _catalogservices, is created for the AquaLogic Data Services Platform application. All the data services associated with catalog services are available under this project. You can invoke the data service functions to access metadata. The client Mediator API is used to invoke the Catalog Service methods.

The data services available under _catalogservices include:

Note: To use data service functions available with Catalog services, refer to the code samples available at:
Note: http://dev2dev.bea.com/wiki/pub/CodeShare/Sample1/catalogsrv_output.zip

Application (application.ds)

The following table provides the declaration and description for the getApplication()function in Application.ds.

Table 11-2 Functions in Application.ds
Function Declaration
Description
getApplication() as schema-element(t1:Application) external;
This function returns the name of the AquaLogic Data Services Platform application. It does not take any parameters.

DataService (DataService.ds)

Table 11-3 provides declaration and description information for the functions available in DataService.ds.

Table 11-3 Functions in DataService.ds
Function Declaration
Description
Sample Input
getDataServiceRef($arg as element(md:DataService)) as element(md:DataServiceRef) {$arg/md:DataServiceRef}
This function returns the path of the data service associated with the function.
For this function, you need to specify the following:
  • Path of the data service
  • Path of the schema for the data service
  • Function ID of the function for which you need the data service reference
<urn:DataService kind="javaFunction" xmlns:acc="ld:RTLAppDataServices/CustomerDB/Customer" xmlns:urn="urn:metadata.ld.bea.com">
<urn:DataServiceRef>
<id>
ld:RTLAppDataServices/CustomerDB/Customer.ds</id>
</urn:DataServiceRef>
<returnType name="CUSTOMER" kind="read" quantifier="*" schemaId="ld:RTLAppDataServices/CustomerDB/schemas/CUSTOMER.xsd"/>
<!--Zero or more repetitions:-->
<key>
<!--1 or more repetitions:--> <path>ld:RTLAppDataServices/CustomerDB/Customer.ds</path>
</key>
<!--Zero or more repetitions:-->
<urn:FunctionId name="CUSTOMER" arity="0"/>
</urn:DataService>
getDataService($x1 as element(t1:DataServiceRef)) as schema-element(t1:DataService)? external
This function returns the attributes of the specified data service such as the schema path, functions, and relational data source.
Specify the path of the data service to retrieve the required result.
<DataServiceRef xmlns="urn:metadata.ld.bea.com">
<id xmlns="">ld:DataServices/CustomerDB/CUSTOMER.ds</id>
</DataServiceRef>

DataServiceRef (DataServiceRef.ds)

The following table provides the declaration and description for the functions available in DataServiceRef.ds.

Table 11-4 Functions in DataService
Function Declaration
Description
Sample Input
getDataServiceRefsByFolder($x1 as xsd:string, $x2 as xsd:boolean) as schema-element(t1:DataServiceRef)* external
This function returns the data services that exist within a folder in the project. You need to specify the path of the project folder and set the boolean value to true for this function.
String parameter = ld:RTLAppDataServices/CustomerDB/
Boolean = true
getDataServiceRefs() as schema-element(t1:DataServiceRef)* external
This function returns the path to all the data services in the project. It does not require any parameters.
No input required.
getDependents($x1 as element(t1:DataServiceRef), $x2 as xsd:boolean) as schema-element(t1:DataServicRef)* external
This function returns the path of the data services on which the specified data service depends.
For this function, you need to specify the path of the data service whose dependents you need to determine. For example, if you need to find out the dependents for CUSTOMER.ds then specify the path of the data service as:
ld:DataServices/CustomerDB/CUSTOMER.ds
<urn:DataServiceRefdat xmlns:urn="urn:metadata.ld.bea.com"> <id>ld:DataServices/CustomerDB/CUSTOMER.ds</id>
</urn:DataServiceRef>
getDependencies($x1 as element(t1:DataServiceRef), $x2 as xsd:boolean) as schema-element(t1:DataServiceRef)* external
This function returns the dependencies for the specified data service.
For this function, you need to specify the path of the data service whose dependencies you need to determine.
<urn:DataServiceRef xmlns:urn="urn:metadata.ld.bea.com"> <id>ld:DataServices/Demo/CustomerProfile.ds</id>
</urn:DataServiceRef>
getFunctions($x1 as element(t1:DataServiceRef)) as schema-element(t1:Function)* external
This function returns the list of data service functions and their attributes such as function kind, arity, and schema path.
For this function, specify the path of the data service as input.
<DataServiceRef xmlns="urn:metadata.ld.bea.com">
<id xmlns="">ld:RTLAppDataServices/CustomerDB/CUSTOMER.ds</id>
</DataServiceRef>
getRelationships($x1 as element(t1:DataServiceRef)) as schema-element(t1:Relationship)* external
This function retrieves the path of data services which have any relationship with the specified data service. You need to specify the path of the data service, such as ld:RTLAppDataServices/CustomerDB/CUSTOMER.ds
DataServiceRef xmlns="urn:metadata.ld.bea.com">
<id xmlns="">ld:RTLAppDataServices/CustomerDB/CUSTOMER.ds</id>
</DataServiceRef>
getSchemaRefs($arg as element(t1:DataServiceRef), $transitive as xs:boolean) as element(t1:SchemaRef)* external
For this function, enter the path of the data service and set the boolean value to true for retrieving the list of associated schemas. This function also lists the paths of schemas for data services, which have a relationship with the specified data service.
<urn:DataServiceRef xmlns:urn="urn:metadata.ld.bea.com"> <id>ld:RTLAppDataServices/CustomerDB/CUSTOMER.ds</id>
</urn:DataServiceRef>
Enter true as the boolean parameter.
getDataService($x1 as element(t1:DataServiceRef)) as schema-element(t1:DataService)? external
This function returns the attributes of the specified data service such as the schema path, functions, and relational data source.
Specify the path of the data service to retrieve the required result.
<urn:DataServiceRef xmlns:urn="urn:metadata.ld.bea.com">
<id xmlns="">ld:RTLAppDataServices/CustomerDB/CUSTOMER.ds</id>
</urn:DataServiceRef>

Folder (folder.ds)

The following table provides the declaration and description for the functions available in Folder.ds.

Table 11-5 Functions in Folder.ds
Function Declaration
Description
Sample Input
getFolder() as schema-element(t1:Folder)* external
This function provides a list of paths of folders and data services that exist within the AquaLogic Data Services Platform project. It does not require any parameters.
No input required.
getFolder($x1 as xsd:string, $x2 as xsd:boolean) as schema-element(t1:Folder)* external
This folder returns the paths of all the data services that exists within a specified folder. You need to specify two parameters for this function, which include:
  • Path of the folder such as ld:RTLAppDataServices/CustomerDB
  • Boolean value (usually set to true)
  • Parameter 1 (string) = ld:RTLAppDataServices/CustomerDB
  • Parameter 2 (boolean) = true
getDataServiceRefs($x1 as element(t1:Folder)) as schema-element(t1:DataServiceRef)* external
This function also provides the paths of the data services that exist within a folder. To retrieve this information, specify the path of the folder as input.
<Folder xmlns="urn:metadata.ld.bea.com">
<id xmlns="">ld:RTLAppDataServices/CustomerDB</id>
</Folder>

Function (Function.ds)

The following table provides the declaration and description for the functions in Function.ds.

Table 11-6 Functions in Function.ds
Function Declaration
Description
Sample Input
getFunctionById($x1 as element(t1:FunctionId)) as schema-element(t1:Function) external
This function returns the path of the data service and schema along with function arity, function kind and return type information about the specified function.
For this function, specify the function ID and arity as input.
<FunctionId name=" cus:CUSTOMER " arity="0" xmlns:cus="ld:RTLAppDataServices/CustomerDB/CUSTOMER" xmlns="urn:metadata.ld.bea.com"/>
getDataService($arg as element(md:Function)) as element(md:DataService)
This function returns the function arity and physical data source information for the specified function.
For this function, you need to specify the function ID, path of the data service and schema.
<?xml version="1.0" encoding="UTF-8" ?>
<urn:Function kind="read" xmlns:acc="ld:RTLAppDataServices/CustomerDB/CUSTOMER"
xmlns:urn="urn:metadata.ld.bea.com">
<urn:FunctionId arity="0" name="acc:getAll"></urn:FunctionId>
<returnType kind="element" name="urn:Account" quantifier="1" schemaId="ld:RTLAppDataServices/CustomerDB/schemas/CUSTOMER.xsd">
</returnType>
<urn:DataServiceRef> <id>ld:RTLAppDataServices/CustomerDB/CUSTOMER.ds</id>
</urn:DataServiceRef>
</urn:Function>
getRelationship($arg as element(md:Function)) as element(md:Relationship) external
This function returns the relationship target and path of the data services with which the navigation function has a relationship.
Specify the function ID, path of the data service and schema as input.

Note: This function is applicable to navigation functions only.

<?xml version="1.0" encoding="UTF-8" ?>
<urn:Function kind="navigate" xmlns:acc="ld:RTLAppDataServices/CustomerDB/Customer" xmlns:urn="urn:metadata.ld.bea.com">
<urn:FunctionId arity="1" name="acc:getDISCOUNT">
</urn:FunctionId>
<returnType kind="element" name="urn:getDISCOUNT" quantifier="1" schemaId="ld:RTLAppDataServices/CustomerDB/schemas/CUSTOMER.xsd">
</returnType>
<parameter name="arg">
<type kind="navigate" name="urn:DISCOUNT" quantifier="*" schemaId="ld:RTLAppDataServices/CustomerDB/CUSTOMER.xsd">
</type>
</parameter>
<urn:DataServiceRef>
<id>ld:RTLAppDataServices/CustomerDB/CUSTOMER.ds</id>
</urn:DataServiceRef>
<roleName>DISCOUNT</roleName>
</urn:Function>
getSchemaRefs($x1 as element(t1:Function), $x2 as xsd:boolean) as schema-element(t1:SchemaRef)* external
For this function, specify the function ID and path of the data service to retrieve the path of the schemas associated with the data service.
<urn:Function kind="navigate" xmlns:acc="ld:RTLAppDataServices/CustomerDB/CUSTOMER" xmlns:urn="urn:metadata.ld.bea.com">
<urn:FunctionId name="acc:getDISCOUNT" arity="1"/>
<returnType name="DISCOUNT" kind="element" quantifier="*" schemaId="ld:RTLAppDataServices/CustomerDB/schemas/CUSTOMER.xsd"/>
<!--Zero or more repetitions:-->
<parameter name="arg">
<type name="DISCOUNT" kind="element" quantifier="*" schemaId="ld:RTLAppDataServices/CustomerDB/schemas/CUSTOMER.xsd"/>
</parameter>
<urn:DataServiceRef>
<id>ld:RTLAppDataServices/CustomerDB/Customer.ds</id>
</urn:DataServiceRef>
<!--Optional:-->
<roleName>DISCOUNT</roleName>
</urn:Function>

Relationship (Relationship.ds)

The following table provides the declaration and description for the functions available in Relationship.ds.

Note: The functions in Relationship.ds can be used to access metadata only for navigation functions.

Table 11-7 Functions in Relationship.ds
Function Declaration
Description
Sample Input
getFunctions($arg as element(md:Relationship)) as element(md:Function)
This function returns the attributes of the function that you specify as input. You need to specify the following parameters for this function:
  • String parameter = Path of the data service
  • Function ID
  • Values for minOccurs and maxOccurs
<urn:Relationship xmlns:acc="ld:RTLAppDataServices/CustomerDB/CUSTOMER" xmlns:urn="urn:metadata.ld.bea.com">
<!--1 to 2 repetitions:-->
<relationshipTarget roleName="DISCOUNT" minOccurs="1" maxOccurs="1" description="">
<urn:DataServiceRef>
<id>ld:RTLAppDataServices/CustomerDB/CUSTOMER.ds</id>
</urn:DataServiceRef>
<!--Zero or more repetitions:-->
<urn:FunctionId name="acc:getDISCOUNT" arity="1"/>
</relationshipTarget>
</urn:Relationship>
getDataServiceRefs($x1 as element(t1:Relationship)) as schema-element(t1:DataServiceRef)
You need to specify the following parameters for this function:
  • String parameter = Path of the data service
  • Function ID
  • Values for minOccurs and maxOccurs
<urn:Relationship xmlns:acc="ld:RTLAppDataServices/CustomerDB/CUSTOMER" xmlns:urn="urn:metadata.ld.bea.com">
<!--1 to 2 repetitions:-->
<relationshipTarget roleName="DISCOUNT" minOccurs="1" maxOccurs="1" description="">
<urn:DataServiceRef>
<id>ld:RTLAppDataServices/CustomerDB/CUSTOMER.ds</id>
</urn:DataServiceRef>
<!--Zero or more repetitions:-->
<urn:FunctionId name="acc:getDISCOUNT" arity="1"/>
</relationshipTarget>
</urn:Relationship>
getDataServices($arg as element(md:Relationship)) as element(md:DataService)
This function returns the attributes, such as relational datasource and function arity, of the navigation function of the data service. For this function, you need to specify the following parameters:
  • String parameter = Path of the data service
  • String parameter = Path of the schema
  • Values for maxOccurs and minOccurs
  • FunctionID
<?xml version="1.0" encoding="UTF-8" ?>
<urn:Relationship xmlns:acc="ld:RTLAppDataServices/CustomerDB/CUSTOMER" xmlns:urn="urn:metadata.ld.bea.com">
<relationshipTarget description="" maxOccurs="1" minOccurs="1" roleName="DISCOUNT">
<urn:DataServiceRef>
<id>
ld:RTLAppDataServices/CustomerDB/CUSTOMER.ds</id>
</urn:DataServiceRef>
<urn:FunctionId arity="1" name="acc:getDISCOUNT">
</urn:FunctionId>
</relationshipTarget>
<relationshipTarget description="" maxOccurs="1" minOccurs="1" roleName="DISCOUNT" xmlns:acc="ld:RTLAppDataServices/CustomerDB/CUSTOMER">
<urn:DataServiceRef>
<id>ld:RTLAppDataServices/CustomerDB/CUSTOMER.ds</id>
</urn:DataServiceRef>
<urn:FunctionId arity="1" name="acc:getDISCOUNT">
</urn:FunctionId>
</relationshipTarget>
</urn:Relationship>

Schema (Schema.ds)

The following table provides the declaration and description for the functions available in Schema.ds.

Table 11-8 Functions in Schema.ds
Function Declaration
Description
Sample Input
getSchema($x1 as element(t1:SchemaRef)) as schema-element(t1:Schema)* external
This functions returns the schema attributes of the schema associated with the data service. You need to specify the path of the schema which you need to access as string parameter. For example:
ld:RTLAppDataServices/CustomerDB/schemas/CUSTOMER.xsd
<urn:SchemaRef xmlns:urn="urn:metadata.ld.bea.com">
<id>ld:RTLAppDataServices/CustomerDB/schemas/CUSTOMER.xsd</id>
</urn:SchemaRef>
getSchemaRef($x1 as element(t1:Schema)) as schema-element(t1:SchemaRef)
This function returns the path of the schema of the data service.
Specify the schema path to get the reference to the schema. For example:
ld:RTLAppDataServices/CustomerDB/schemas/CUSTOMER_TABLE.xsd
<urn:Schema xmlns:urn="urn:metadata.ld.bea.com">
<urn:SchemaRef>
<id>ld:RTLAppDataServices/CustomerDB/schemas/CUSTOMER_TABLE.xsd</id>
</urn:SchemaRef>
</urn:Schema>

SchemaRef (SchemaRef.ds)

The following table provides the declaration and description for the functions available in SchemaRef.ds.

Table 11-9 Functions in SchemaRef.ds
Function Declaration
Description
Sample Input
getDependencies($x1 as element(t1:SchemaRef), $x2 as xs:boolean) as schema-element(t1:SchemaRef)* external
This function returns the dependencies of the specified data service.
You need to specify the path of the schema for the data service as a string parameter. For example:
ld:DataServices/Demo/schemas/CustomerProfile.xsd
<urn:SchemaRef xmlns:urn="urn:metadata.ld.bea.com">
<id xmlns="">ld:DataServices/Demo/schemas/CustomerProfile.xsd</id>
</urn:SchemaRef>
The second parameter is boolean and the value can be either true or false.
getSchema($x1 as element(md:SchemaRef)) as schema-element(md:Schema)* external
This functions returns the schemas associated with the data service.
You need to specify the path of the schema for the data service as a string parameter. For example:
ld:RTLAppDataServices/CustomerDB/schemas/CUSTOMER.xsd
<urn:SchemaRef xmlns:urn="urn:metadata.ld.bea.com">
<id>ld:RTLAppDataServices/CustomerDB/schemas/CUSTOMER.xsd</id>
</urn:SchemaRef>

 


Filtering, Sorting, and Fine-tuning Query Results

The Filter API enables client applications to apply filtering conditions to the information returned by data service functions. In a sense, filtering allows client applications to extend a data service interface by allowing them to specify more about how data objects are to be instantiated and returned by functions.

The Filter API alleviates data service designers from having to anticipate every possible data view that their clients may require and to implement a data service function for each view. Instead, the designer may choose to specify a broader, more generic interface for accessing a business entity and allow client applications to control views as desired through filters.

Only objects in the function return set that meet the condition are returned to the client. (The evaluation occurs at the server, so objects that are filtered are not passed over the network. Often, objects that are filtered out are not even retrieved from the underlying sources.) A filter is similar to a WHERE clause in an XQuery or SQL statement—it applies conditions to a possible result set. You can apply multiple filter conditions using AND and OR operators. Other operators that be applied to filter conditions are listed in Table 11-10.

Table 11-10 Filter Operators
Operator
Usage Note or Example
LESS_THAN
Can also use "<". For example: myFilter.addFilter("CUST/CUST_ORDER/ORDER", "CUST/CUST_ORDER/ORDER/ORDER_AMOUNT", ">", "1000");
myFilter.addFilter("CUST/CUST_ORDER/ORDER", "CUST/CUST_ORDER/ORDER/ORDER_AMOUNT", FilterXQuery.GREATER_THAN, "1000");
GREATER_THAN
Can also use ">".
LESS_THAN_EQUAL
Can also use "<=".
GREATER_THAN_EQUAL
Can also use ">=".
EQUAL
Can also use "=".
NOT_EQUAL
Can also use "!=".
matches
Tests for string equality.
sql-like
Tests whether a string contains a specified pattern.
OR
Compound operator that can apply to more than one filter.
NOT
Compound operator that can apply to more than one filter.
AND
Compound operator that can apply to more than one filter.

Note: Filter API Javadoc, as well as other AquaLogic Data Services Platform APIs, is described at AquaLogic Data Services Platform Mediator API Javadoc on page 1-13.

 


Using Filters

Filtering capabilities are available to Mediator and Data Service control client applications. You use filter conditions to specify the data you want returned, sort the data, or limit the number of records returned. To use filters in a mediator client application, import the appropriate package and use the supplied interfaces for creating and applying filter conditions. Data service control clients get the interface automatically. When a function is added to a control, a corresponding "WithFilter" function is added as well.

The filter package is named as follows:

	com.bea.ld.filter.FilterXQuery; 

To use a filter, perform the following steps:

  1. Create an FilterXQuery object, such as:
  2. FilterXQuery myFilter = new FilterXQuery();
  3. Add a condition to the filter object using the addFilter() method. With this method you can specify what node your filter condition will apply to and specify the number of records to be returned based on a limit; for example, you can specify the filter will apply to customer orders where only orders with an amount over a specified value will be returned.
  4. The addFilter() method has several signatures with different parameters, including the following:

    public void addFilter(java.lang.String appliesTo, 
    java.lang.String field,
    java.lang.String operator,
    java.lang.String value,
    java.lang.Boolean everyChild)

    This version of the method takes the following arguments:

    • appliesTo indicates the node that filtering affects. That is, if a node specified by the field argument does not meet the condition, appliesTo nodes are filtered out.
    • field is the node against which the filtering condition is tested.
    • operator and value together compose the condition statement. The operator parameter specifies the type of comparison to be made against the specified value. See Table 11-10, Filter Operators, on page 11-16 for information about available operators.
    • everyChild is an optional parameter. It is set to false by default. Specifying true for this parameter indicates that only those child elements that meet the filter criteria will be returned. For example, by specifying an operator of GREATER_THAN (or ">") and a value of 1000, only records for customers where all orders are over 1000 will be returned. A customer that has an order amount less than 1000 will not be returned, although other order amounts might be greater than 1000.
    • The following is an example of an add filter method where those orders with an order amount greater than 1000 will be returned (note that everyChild is not specified, so order amounts below 1000 will be returned):

           myFilter.addFilter("CUSTOMERS/CUSTOMER/ORDER",
      "CUSTOMERS/CUSTOMER/ORDER/ORDER_AMOUNT",
      ">",
      "1000");
  5. Use the Mediator API call setFilterCondition() to add the filter to a data service, passing the FilterXQuery instance as an argument. For example,
  6. CUSTOMER custDS = CUSTOMER.getInstance(ctx, "RTLApp");
    custDS.setFilterCondition(myFilter);
  7. Invoke the data service function. (For more information on invoking data service functions, see Accessing Data Services from Java Clients.)

Specifying Filter Effects

If a filter condition applied to a specified element value resolves to false, an element is not included in the result set. The element that is filtered out is specified as the first argument to the addFilter() function.

The effects of a filter can vary, depending on the desired results. For example, consider the CUSTOMERS data object shown in Figure 11-1. It contains several complex elements (CUSTOMER and ORDERS) and several simple elements, including ORDER_AMOUNT. You can apply a filter to any elements in this hierarchy.

Figure 11-11 Nested Value Filtering

In general, with nested XML data, a condition such as "CUSTOMER/ORDER/ORDER_AMOUNT > 1000" can affect what objects are returned in several ways. For example, it can cause all CUSTOMER objects to be returned, but filter ORDERS that have an amount less than 1000.

Alternatively, it can cause only CUSTOMER objects to be returned that have at least one large order, and all ORDER objects are returned for every CUSTOMER. Further, it can cause only CUSTOMER objects to be returned for which every ORDER is greater than 1000. For example,

	FilterXQuery myFilter = new FilterXQuery();
myFilter.addFilter( "CUSTOMERS/CUSTOMER",
"CUSTOMERS/CUSTOMER/ORDER/ORDER_AMOUNT",
FilterXQuery.GREATER_THAN,"1000",true);

Note that in the optional fourth parameter everyChild = true, by default this attribute is false. By setting this parameter to true, only those CUSTOMER objects for which every ORDER is greater than 1000 will be returned.

The following examples show how filters can be applied in several different ways:

The last example is a compound filter; that is, a filter with two conditions. Listing 11-1 uses the AND operator to apply a combination of filters to a result set, given a data service instance customerDS.

Listing 11-1 Example of Combining Filters by Using Logical Operators
FilterXQuery myFilter = new FilterXQuery();
Filter f1 = myFilter.createFilter("CUSTOMER_PROFILE/ADDRESS/ISDEFAULT",
FilterXQuery.NOT_EQUAL,"0");
Filter f2 = myFilter.createFilter("CUSTOMER/ADDRESS/STATUS",
FilterXQuery.EQUAL,
"\"ACTIVE\"");
Filter f3 = myFilter.createFilter(f1,f2, FilterXQuery.AND);
Customer customerDS = Customer.getInstance(ctx, "RTLApp");
CustomerDS.setFilterCondition(myFilter);

Ordering and Truncating Data Service Results

Another type of filter you can use in client application code is an ordering condition—you specify the order (descending, ascending) in which results should be returned from the data service. The method (addOrderBy(), in the FilterXQuery class), takes a property name as the criterion upon which the ascending or descending decision is based. Listing 11-2 provides an example of creating a filter that will return customer profiles in ascending order, based on the date each person became a customer.

Listing 11-2 Example of Applying an Ordering Filter
FilterXQuery myFilter = new FilterXQuery();
myFilter.addOrderBy("CUSTOMER_PROFILE",
"CustomerSince" ,FilterXQuery.ASCENDING);
ds.setFilterCondition(myFilter);
DataObject objArrayOfCust = (DataObject) ds.invoke("getCustomer", null);

Similarly, you can set the maximum number of results that can be returned from a function. The setLimit() function limits the number of elements in an array element to the specified number. And on a repeating node, it makes sense to specify a limit on the results to be returned. (Setting the limits on non-repeating nodes does not truncate the results.)

Listing 11-3 shows how to use the setLimit() method. It limits the number of active address in the result set (filtering out active addresses) to 10 given a data service instance ds.

Listing 11-3 Example of Applying a Filter that Truncates (Limits) Results
FilterXQuery myFilter = new FilterXQuery();
Filter f2 = myFilter.createFilter("CUSTOMER_PROFILE/ADDRESS",
FilterXQuery.EQUAL,"\"INACTIVE\"");
myFilter.addFilter("CUSTOMER_PROFILE", f2);
myFilter.setLimit("CUSTOMER_PROFILE", "10");
ds.setFilterCondition(myFilter);

Using Ad Hoc Queries to Fine-tune Results from the Client

An ad hoc query is an XQuery function that is not defined as part of a data service, but is instead defined in the context of a client application. Ad hoc queries are typically used in client applications to invoke data service functions and refine the results in some way. You can use an ad hoc query to execute any valid XQuery expression against a data service. The expression can target the actual data sources that underlie the data service, or can use the functions and procedures hosted by the data service.

To execute an XQuery expression, use the PreparedExpression interface, available in the Mediator API. Similar to JDBC's PreparedStatement interface, the PreparedExpression interface takes the XQuery expression as a string in its constructor, along with the JNDI server context and application name. After constructing the prepared expression object in this way, you can call the executeQuery( ) method on it. If the ad hoc query invokes data service functions or procedures, the data service's namespace must be imported into query string before you can reference the methods in your ad hoc query.

Listing 11-4 shows a complete example; the code returns the results of a data service function named getCustomers( ), which is in the namespace:

ld:DataServices/RTLServices/Customer
Listing 11-4 Invoking Data Service Functions using an Ad Hoc Query
import com.bea.ld.dsmediator.client.PreparedExpression;
String queryStr = 
"declare namespace ns0=\"ld:DataServices/RTLServices/Customer\";" +
"<Results>" +
" { for $customer_profile in ns0:getCustomer()" +
" return $customer_profile }" +
"</Results>";
PreparedExpression adHocQuery =
DataServiceFactory.prepareExpression(context,"RTLApp",queryStr );
XmlObject objResult = (XmlObject) adHocQuery.executeQuery();

AquaLogic Data Services Platform passes information back to the ad hoc query caller as an XMLObject data type. Once you have the XMLObject, you can downcast to the data type of the deployed XML schema. Since XMLObject has only a single root type, if the data service function returns an array, your ad hoc query should include a root element as a container for the array.

For example, the ad hoc query shown in Listing 11-4 specifies a <Results> container object to hold the array of CUSTOMER_PROFILE elements that will be returned by the getCustomer() data service function.

Security policies defined for a data service apply to the data service calls in an ad hoc query as well. If an ad hoc query uses secured resources, the appropriate credentials must be passed when creating the JNDI initial context. (For more information, see Obtaining a WebLogic JNDI Context for AquaLogic Data Services Platform.)

As with the PreparedStatement interface of JDBC, the PreparedExpression interface supports dynamically binding variables in ad hoc query expressions. PreparedExpression provides several methods (bindType( ) methods; see Table 11-12), for binding values of various data types.

Table 11-12 PreparedExpression Methods for Bind Variables
To bind data type of...
Use bind method...
Binary
bindBinary(javax.xml.namespace.QName qname, byte[] abyte0)
BinaryXML
bindBinaryXML(javax.xml.namespace.QName qname, byte[] abyte0)
Boolean
bindBoolean(javax.xml.namespace.QName qname, boolean flag)
Byte
bindByte(javax.xml.namespace.QName qname, byte byte0)
Date
bindDate(javax.xml.namespace.QName qname, java.sql.Date date)
Calendar
bindDateTime(javax.xml.namespace.QName qname, java.util.Calendar calendar)
DateTime
bindDateTime(javax.xml.namespace.QName qname, java.util.Date date)
DateTime
bindDateTime(javax.xml.namespace.QName qname, java.sql.Timestamp timestamp)
BigDecimal
bindDecimal(javax.xml.namespace.QName qname, java.math.BigDecimal bigdecimal)
double
bindDouble(javax.xml.namespace.QName qname, double d)
Element
bindElement(javax.xml.namespace.QName qname, org.w3c.dom.Element element)
Object
bindElement(javax.xml.namespace.QName qname, java.lang.String s)
float
bindFloat(javax.xml.namespace.QName qname, float f)
int
bindInt(javax.xml.namespace.QName qname, int i)
long
bindLong(javax.xml.namespace.QName qname, long l)
Object
bindObject(javax.xml.namespace.QName qname, java.lang.Object obj)
short
bindShort(javax.xml.namespace.QName qname, short word0)
String
bindString(javax.xml.namespace.QName qname, java.lang.String s)
Time
bindTime(javax.xml.namespace.QName qname, java.sql.Time time)
URI
bindURI(javax.xml.namespace.QName qname, java.net.URI uri)

To use the bindType methods, pass the variable name as an XML qualified name (QName) along with its value; for example:

adHocQuery.bindInt(new QName("i"),94133);

Listing 11-5 shows an example of using a bindInt() method in the context of an ad hoc query.

Listing 11-5 Binding a Variable to a QName (Qualified Name) for use in an Ad Hoc Query
PreparedExpression adHocQuery = DataServiceFactory.preparedExpression(
context, "RTLApp",
"declare variable $i as xs:int external;
<result><zip>{fn:data($i)}</zip></result>");
adHocQuery.bindInt(new QName("i"),94133);
XmlObject adHocResult = adHocQuery.executeQuery();
Note: For more information on QNames, see:

http://www.w3.org/TR/xmlschema-2/#QName

Listing 11-6 shows a complete ad hoc query example, using the PreparedExpression interface and QNames to pass values in bind methods.

Listing 11-6 Sample Ad Hoc Query
import com.bea.ld.dsmediator.client.DataServiceFactory;
import com.bea.ld.dsmediator.client.PreparedExpression;
import com.bea.xml.XmlObject;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.xml.namespace.QName;
import weblogic.jndi.Environment;

public class AdHocQuery
{
public static InitialContext getInitialContext() throws NamingException {
Environment env = new Environment();
env.setProviderUrl("t3://localhost:7001");
env.setInitialContextFactory("weblogic.jndi.WLInitialContextFactory");
env.setSecurityPrincipal("weblogic");
env.setSecurityCredentials("weblogic");
return new InitialContext(env.getInitialContext().getEnvironment());
}

public static void main (String args[]) {
System.out.println("========== Ad Hoc Client ==========");
try {
StringBuffer xquery = new StringBuffer();
xquery.append("declare variable $p_firstname as xs:string external; \n");
xquery.append("declare variable $p_lastname as xs:string external; \n");

xquery.append(
"declare namespace ns1=\"ld:DataServices/MyQueries/XQueries\"; \n");
xquery.append(
"declare namespace ns0=\"ld:DataServices/CustomerDB/CUSTOMER\"; \n\n");

xquery.append("<ns1:RESULTS> \n");
xquery.append("{ \n");
xquery.append(" for $customer in ns0:CUSTOMER() \n");
xquery.append(" where ($customer/FIRST_NAME eq $p_firstname \n");
xquery.append(" and $customer/LAST_NAME eq $p_lastname) \n");
xquery.append(" return \n");
xquery.append(" $customer \n");
xquery.append(" } \n");
xquery.append("</ns1:RESULTS> \n");

PreparedExpression pe = DataServiceFactory.prepareExpression(
getInitialContext(), "RTLApp", xquery.toString());
pe.bindString(new QName("p_firstname"), "Jack");
pe.bindString(new QName("p_lastname"), "Black");
XmlObject results = pe.executeQuery();
System.out.println(results);

} catch (Exception e) {
e.printStackTrace();
}
}

 


Handling Large Result Sets with Streaming APIs

This section discusses further programming topics related to client programming with the Data Service Mediator API. It includes the following topics:

Using the Streaming Interface

When a function in the standard data service interface is called, the requested data is first materialized in the system memory of the server machine. If the function is intended to return a large amount of data, in-memory materialization of the data may be impractical. This may be the case, for example, for administrative functions that generate "inventory reports" of the data exposed by AquaLogic Data Services Platform. For such cases, AquaLogic Data Services Platform can serve information as an output stream.

AquaLogic Data Services Platform leverages the WebLogic XML Streaming API for its streaming interface. The WebLogic Streaming API is similar to the standard SAX (Streaming API for XML) interface. However, instead of contending with the complexity of the event handlers used by SAX, the WebLogic Streaming API lets you use stream-based (or pull-based) handling of XML documents in which you step through the data object elements. As such, the WebLogic Streaming API affords more control than the SAX interface, in that the consuming application initiates events, such as iterating over attributes or skipping ahead to the next element, instead of reacting to them.

Note: The streaming API is intended to be used when large result sets are needed and cannot be easily materialized in memory. It may be advisable to run your data service queries on different servers in order to simultaneously support both real-time queries and large, batch-oriented queries.

However, if two servers are not possible, then consider running the streaming API queries during off-peak times.

In AquaLogic Data Services Platform only server-side steaming is supported. Thus a JSP, which is hosted on the server, can leverage the streaming API. However, an external Java application could not.

You can get AquaLogic Data Services Platform information as a stream by using either an ad hoc or an untyped data service interface.

Note: Streaming is not supported through static interfaces. For more information on the WebLogic Streaming API, see "Using the WebLogic XML Streaming API" at:

http://download.oracle.com/docs/cd/E13222_01/wls/docs81/xml/xml_stream.html.

The streaming interface can be found in the following classes in the com.bea.ld.dsmediator.client package:

Using these interfaces is very similar to using their SDO mediator client API equivalents. However, instead of a document object, they return data as an XMLInputStream. For functions that take complex elements (possibly with a large amount of data) as input parameters, XMLInputStream is supported as an input argument as well. The following is a example:

StreamingDataService ds = DataServiceFactory.newStreamingDataService(
context,
"ld:DataServices/RTLServices/Customer");
XMLInputStream stream = ds.invoke("getCustomerByCustID", "CUSTOMER0");

The previous example shows the dynamic streaming interface. The following example uses an ad hoc query:

String adhocQuery = 
"declare namespace ns0=\"ld:DataServices/RTLServices/Customer\";\n" +
"declare variable $cust_id as xs:string external;\n" +
"for $customer in ns0:getCustomerByCustID($cust_id)\n" +
"return\n" +
" $customer\n";
StreamingPreparedExression expr =
DataServiceFactory.prepareExpression(context, adhocQuery);

If you have external variables in the query string (adhocQuery in the above example), you will also need to do the following:

	expr.bindString("$cust_id","CUSOMER0");
XMLInputStream xml = expr.executeQuery();
Note: For more information on using the dynamic and ad hoc interfaces, see Using a Dynamic Mediator API in Accessing Data Services from Java Clients.
Note: Javadoc for the StreamingDataService interface and other AquaLogic Data Services Platform APIs is described at: AquaLogic Data Services Platform Mediator API Javadoc on page 1-13.

Listing 11-7 shows an example of a method that reads the XML input stream. This method uses an attribute iterator to print out attributes and namespaces in an XML event and throws an XMLStream exception if an error occurs.

Listing 11-7 Sample Streaming Application
import weblogic.xml.stream.Attribute;
import weblogic.xml.stream.AttributeIterator;
import weblogic.xml.stream.ChangePrefixMapping;
import weblogic.xml.stream.CharacterData;
import weblogic.xml.stream.XMLEvent;
import weblogic.xml.stream.EndDocument;
import weblogic.xml.stream.EndElement;
import weblogic.xml.stream.EntityReference;
import weblogic.xml.stream.Space;
import weblogic.xml.stream.StartDocument;
import weblogic.xml.stream.XMLInputStream;
import weblogic.xml.stream.XMLInputStreamFactory;
import weblogic.xml.stream.XMLName;
import weblogic.xml.stream.XMLStreamException;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class ComplexParse {

public void parse(XMLEvent event)throws XMLStreamException
{
switch(event.getType()) {
case XMLEvent.START_ELEMENT:
StartElement startElement = (StartElement) event;
System.out.print("<" + startElement.getName().getQualifiedName() );
AttributeIterator attributes = startElement.getAttributesAndNamespaces();
while(attributes.hasNext()){
Attribute attribute = attributes.next();
System.out.print(" " + attribute.getName().getQualifiedName() +
"='" + attribute.getValue() + "'");
}
System.out.print(">");
break;
case XMLEvent.END_ELEMENT:
System.out.print("</" + event.getName().getQualifiedName() +">");
break;
case XMLEvent.SPACE:
case XMLEvent.CHARACTER_DATA:
CharacterData characterData = (CharacterData) event;
System.out.print(characterData.getContent());
break;
case XMLEvent.COMMENT:
// Print comment
break;
case XMLEvent.PROCESSING_INSTRUCTION:
// Print ProcessingInstruction
break;
case XMLEvent.START_DOCUMENT:
// Print StartDocument
break;
case XMLEvent.END_DOCUMENT:
// Print EndDocument
break;
case XMLEvent.START_PREFIX_MAPPING:
// Print StartPrefixMapping
break;
case XMLEvent.END_PREFIX_MAPPING:
// Print EndPrefixMapping
break;
case XMLEvent.CHANGE_PREFIX_MAPPING:
// Print ChangePrefixMapping
break;
case XMLEvent.ENTITY_REFERENCE:
// Print EntityReference
break;
case XMLEvent.NULL_ELEMENT:
throw new XMLStreamException("Attempt to write a null event.");
default:
throw new XMLStreamException("Attempt to write unknown event["
+event.getType()+"]");
}
}

Writing Data Service Function Results to a File

You can write serialized results of a data service function to a file using a WriteOutputToFile method. Such a function is generated automatically for each function defined in the data service. For security reasons it writes only to a file on the server's file system.

These functions provide services that are similar to streaming APIs. They are intended for creating reports or an inventory of data service information. However, the writeOutputToFile method can be invoked from a remote mediator API (in contrast with the streaming API described in Using the Streaming Interface on page 11-26).

The following example shows how to write to a file from the untyped interface.

 StreamingDataService sds =
DataServiceFactory.newStreamingDataService(
context,"RTLApp","ld:DataServices/RTLServices/Customer"");
sds.writeOutputToFile("getCustomer", null, "streamContent.txt");
sds.closeStream();
Note: No attempt to create folders is made. In the above example, if you want to write data inside a folder named myData that folder should be present in the server domain root prior to the write operation.

  Back to Top       Previous  Next