Content starts here Building Logical Entity Data Services
This page last changed on Mar 11, 2008.

eDocs Home > BEA AquaLogic Data Services Platform Documentation > Data Services Developer's Guide > Contents

Building Logical Entity Data Services

This topic introduces you to logical entity data services.

The Benefits of Logical Services

The benefit of data services is the ability to combine multiple data sources of different types into service-oriented architectures. Enterprise data is often stored in relational databases, non-relational databases, packaged applications (such as SAP, PeopleSoft, Siebel, and others), custom applications, or files of various types. You might also be accessing data from web services.

The goal is to create a new loosely coupled architecture by piecing together the data assets you already have. In a practical sense, this means combining data from relational data sources, web services, XML files, other files, or Java functions. Logical data services are of two types, entity and library.

Logical entity services allow you to design, model, and create a data view from many underlying data sources. Logical library services are simply a collection of related functions and procedures within a data service container. This topic introduces logical entity services.

On a tangible level, a logical entity service is an XQuery source file with functions and procedures that act on data. A logical entity service has:

  • Exactly one XML schema that represents the data the service returns (its return type).
  • Any number of create, update, or delete procedures, where up to one of each type is primary.
  • Any number of library functions and procedures.
  • Any number of relationships with other entity services.

In addition, a logical entity service must have a primary read function if you want the service to have an update map.

Design View

Logical data services have their foundation in XML web services. The backbone of a logical data service is its return type, which is a combination of data you design expressed as an XML schema.

You can see the return type in the Overview tab in Studio.

Design View of a Logical Data Service

The logical service's return type is shown in the center. You can right-click it to see the XML schema source. On the left, you see the defined for the service. On the right, you see other data services that underly the logical data service.

ALDSP Functions and Procedures

The underlying data services can be physical or logical.

The beauty of a logical data service is that a return type is a model. Logical models capture the complexity of data integration once, and allow you to write clients that remain the same even when underlying physical data sources change.

The structure of a return type does not need to match the structure of the underlying data sources. Here, the CUSTOMER element has a 1-to-many relationship with its child element ADDRESS, and a 1-to-1 relationship with its other child element, CREDITRATING. Each complex element represents a separate physical data source.

The Return Type Schema
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema targetNamespace="ld:logical/CustomerProfile" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="CUSTOMER_PROFILE">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="CUSTOMER">
          <xs:complexType>
	    <xs:sequence>
		<xs:element name="CUSTOMER_ID" type="xs:string"/>
		<xs:element name="FIRST_NAME" type="xs:string"/>
		<xs:element name="LAST_NAME" type="xs:string"/>
		<xs:element name="EMAIL_ADDRESS" type="xs:string"/>
		<xs:element name="ADDRESS" maxOccurs="unbounded">
		  <xs:complexType>
		    <xs:sequence>
			<xs:element name="ADDR_ID" type="xs:string"/>
			<xs:element name="CUSTOMER_ID" type="xs:string"/>
			<xs:element name="STREET_ADDRESS1" type="xs:string"/>
			<xs:element name="STREET_ADDRESS2" type="xs:string" minOccurs="0"/>
			<xs:element name="CITY" type="xs:string"/>
			<xs:element name="STATE" type="xs:string"/>
			<xs:element name="ZIPCODE" type="xs:string"/>
			<xs:element name="COUNTRY" type="xs:string"/>
		    </xs:sequence>
		  </xs:complexType>
		</xs:element>
		<xs:element name="CREDITRATING" maxOccurs="1">
		  <xs:complexType>
		    <xs:sequence>
			<xs:element name="CUSTOMER_ID" type="xs:string"/>
			<xs:element name="RATING" type="xs:int" minOccurs="0"/>
		    </xs:sequence>
		  </xs:complexType>
		</xs:element>
	      </xs:sequence>
      	    </xs:complexType>
          </xs:element>
        </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

However, this structure is only by design. You could also have designed the return type with fewer elements, or in a flat structure, depending on how you want the service to return data.

The Primary Read Function

The functions and procedures in a logical entity service are implemented in XQuery, which queries XML data much as SQL queries relational data. You can get information about any function or procedure by right-clicking it in the Overview tab.

A read function, for example, often takes no parameters and returns an instance of the return type.

Viewing the Signature of a Read Function

In a logical entity service, you can designate one read function as primary. A primary read function captures the main data integration logic in the service. ALDSP generates the create, update, and delete procedures and the update map from the primary read function.

You can see the source code of the primary read function in the Source tab.

Checking the Primary Read Function Source
declare function tns:read() as element(tns:CUSTOMER_PROFILE)*{
for $CUSTOMER in cus1:CUSTOMER()
return
        <tns:CUSTOMER_PROFILE>
            <CUSTOMER>
                <CUSTOMER_ID>{fn:data($CUSTOMER/CUSTOMER_ID)}</CUSTOMER_ID>
                <FIRST_NAME>{fn:data($CUSTOMER/FIRST_NAME)}</FIRST_NAME>
                <LAST_NAME>{fn:data($CUSTOMER/LAST_NAME)}</LAST_NAME>
                <EMAIL_ADDRESS>{fn:data($CUSTOMER/EMAIL_ADDRESS)}</EMAIL_ADDRESS>
                {
                    for $ADDRESS in add:ADDRESS()
                    where $CUSTOMER/CUSTOMER_ID eq $ADDRESS/CUSTOMER_ID
                    return
                    <ADDRESS>
                        <ADDR_ID>{fn:data($ADDRESS/ADDR_ID)}</ADDR_ID>
                        <CUSTOMER_ID>{fn:data($ADDRESS/CUSTOMER_ID)}</CUSTOMER_ID>
                        <STREET_ADDRESS1>{fn:data($ADDRESS/STREET_ADDRESS1)}</STREET_ADDRESS1>
                        <STREET_ADDRESS2?>{fn:data($ADDRESS/STREET_ADDRESS2)}</STREET_ADDRESS2>
                        <CITY>{fn:data($ADDRESS/CITY)}</CITY>
                        <STATE>{fn:data($ADDRESS/STATE)}</STATE>
                        <ZIPCODE>{fn:data($ADDRESS/ZIPCODE)}</ZIPCODE>
                        <COUNTRY>{fn:data($ADDRESS/COUNTRY)}</COUNTRY>
                    </ADDRESS>
                }
                {
                	for $CREDITRATING in cre:CREDITRATING()
                	where $CUSTOMER/CUSTOMER_ID eq $CREDITRATING/CUSTOMER_ID
                	return
                	<CREDITRATING>
                    	   <CUSTOMER_ID>{fn:data($CREDITRATING/CUSTOMER_ID)}</CUSTOMER_ID>
                    	   <RATING?>{fn:data($CREDITRATING/RATING)}</RATING>
                	</CREDITRATING>
                }
            </CUSTOMER>
        </tns:CUSTOMER_PROFILE>
};

This read function returns a CUSTOMER_PROFILE element with a nested CUSTOMER element. Each CUSTOMER element has some number of ADDRESS elements and some number of CREDITRATING elements, where the CUSTOMER_ID in ADDRESS or CREDITRATING matches the CUSTOMER_ID in CUSTOMER. (The XQuery where clauses create table joins; see Add a Where Clause to a Query).

Create, Update, and Delete Procedures

A logical entity service also typically has create, update, and delete procedures that act on underlying data sources. (The difference between a function and a procedure is that a procedure can have side effects, while a function cannot; see Data Service Types and Functions).

The CustomerProfile service has one create procedure, one update procedure, and two delete procedures. It also has a library procedure named stringToShort, which casts between two data types.

Viewing Functions and Procedures

Query Map View

The Query Map view maps elements in data sources to the return type.

Mapping Data Sources to the Return Type

You can see the data sources on the left and the return type on the right. The blue lines map elements from the data sources to elements in the return type, showing how the return type receives data.

The green dashed lines between the data source blocks create joins, which become where clauses in the XQuery source, for example:

for $ADDRESS in add:ADDRESS()
where $CUSTOMER/CUSTOMER_ID eq $ADDRESS/CUSTOMER_ID
return

If you click a data element (not a container element) in the return type, you see its XQuery expression in the expression editor.

Mapping Data in an XQuery Expression

Notice that the mapping expressions use the built-in XQuery function fn:data, which extracts the data value from an XML element.

As you map elements visually in the Query Map, ALDSP creates XQuery source (for example, the read function shown above). The XQuery source is later converted to SQL queries, which you can see in Plan view.

Viewing a SQL Query in Plan View

In this query plan, you see the left outer join between the CUSTOMER and ADDRESS relational tables. This was created by the green dashed line drawn between the Customer and Address blocks in Query Map view.

When you build XQuery functions and procedures visually in Query Map view or by editing in Source view, you can test and run them on an ALDSP server. During server runtime, the functions and procedures are compiled into an executable query plan. Examine the query plan before you finalize the queries. Query Plan view gives you a peek into a query's execution logic and flags potential performance and memory problems. Building XQuery functions is an iterative process of test, view plan, and edit.

Update Map View

While Query Map view shows how a service reads from data sources, Update Map view shows how the service writes data to them.

Checking Update Map View

The data sources are on the left, with updates coming from the return type on the right. The return type is available to client applications, where users update data.

The blocks on the left are update blocks. Each mapped element in an update block has an XQuery expression that defines how the element is updated. You can see the expression in the expression editor below the mapping area.

Viewing an XQuery Update Expression

ALDSP generates the update map for you when you create a logical data service under these conditions:

  • Your service has a primary read function
  • You are using relational data sources

(If you are using other data source types, you must edit the update template.)

You can then customize the update map and test it in Test view, without programming.

An application client uses the Service Data Objects programming model to update data sources. SDO is an application framework that allows you to update data sources while disconnected from them, using a flexible, optimistic concurrency model. You use only one API, the SDO API, to update multiple data sources -- relational, web service, XML files, and so on. 

Test View

The Test view available in Studio works like a built-in client where you can easily test any function or procedure in the data service, before you build a custom client.

Choosing a Function or Procedure to Test

Testing a read function, for example, returns data as the service would to a client, in the shape of the return type.

Reading Customer Profile Data

To test a simple update, click the Edit button, edit some data in the result, then click Submit. When you test the read function again, the results show the change.

You can also test an SDO update by submitting a datagraph with a change summary (see Test an Update Procedure).

See Also

Concepts
How Tos
Reference
Other Sources
Document generated by Confluence on Apr 28, 2008 15:54