2 Data Programming Model and Update Framework

Oracle Data Service Integrator implements Service Data Objects (SDO) as its data client-application programming model. This chapter discusses SDO concepts and APIs that are of interest to Oracle Data Service Integrator client application developers.

2.1 Introduction

SDO is an architecture and set of APIs for working with data objects while disconnected from their source. In Oracle Data Service Integrator, SDO-compliant data objects— whether typed or untyped data objects — are obtained from data services through Mediator APIs or through Data Service controls. (See also Section 1.5, "Introducing Service Data Objects (SDO).")

Client applications manipulate the data objects as required for the business process at hand, and then submit changed objects to the data service, for propagation to the underlying data sources. Although the SDO specification does not define one, it does discuss the need for mediator services, in general, that can send and receive data objects; the specification also discusses the need for handling updates to data sources, again, without specifying an implementation. The SDO specification leaves the details up to implementors as to how mediator services are implemented, and how they should handle updates to data objects.

As discussed in Section 1.6, "Introducing the Data Service Mediator API," the Oracle Data Service Integrator Data Service Mediator is the process that not only handles the back-and-forth communication between client applications and data services, it also facilitates updates to the various data sources that comprise any data service.

This chapter includes information about the Oracle Data Service Integrator implementation of the SDO data programming model, as well as its update framework.

2.2 Oracle Data Service Integrator and SDO

When you invoke a data service's read operation through the Data Service Mediator API, a data object is returned. Data objects are the fundamental artifacts of the SDO data programming model.

Note:

For information on the Mediator API, see Chapter 3, "Invoking Data Services from Java Clients."

Data objects represent the contents of a complex type. A data object contains properties, which represent elements and attributes. The properties can be of simple or complex types. In SDO, a simple type property is called a datatype property, while a complex type property contains a data object (which in turn has properties).

Data objects can be defined to contain a special kind of property called a change summary. A change summary is used to track changes to the data object. As changes are made to the properties (or properties of nested descendant data objects), the changes are captured in the change summary.

The change summary is used by the Mediator to derive the update plan and ultimately, to update data sources. The change summary submitted with each changed SDO remains intact, regardless of whether or not the update function succeeds, so it can support rollbacks when necessary.

A datagraph is a built-in data object type that is defined to have a change summary property. Thus it is convenient to use a datagraph to encapsulate change tracking. The datagraph has one immediate data object child, and a change summary that can track changes to this data object. Figure 2-1 shows the structure of a datagraph.

Figure 2-1 Structure of a DataGraph

Structure of a DataGraph
Description of "Figure 2-1 Structure of a DataGraph"

2.2.1 Static and Dynamic Data Object APIs

SDO specifies both static (typed) and dynamic (untyped) interfaces for data objects:

  • Static. The static data object API is an XML-to-Java API binding that contains methods that correspond to each element of the data object returned by the data service. These generated interfaces provide both getters and setters: getCustomer( ) and setCustomer( ). For examples see Table 2-2.

  • Dynamic. The dynamic data object API provides generic getters and setters for working with data objects. Elements are passed as arguments to the generic methods. For example, get("Customer") or set("Customer").

The dynamic data object API can be used with data types that have not yet been deployed at development time.

Table 2-1 summarizes the advantages of each approach.

Table 2-1 Static and Dynamic Data Object APIs

Data Model Advantages...

Static Data Object API

  • Easy-to-implement interface; code is easy to read and maintain.

  • Compile-time type checking.

  • Enables code-completion in Workshop for WebLogic Source View.

Dynamic Data Object API

  • Dynamic; allows discovery.

  • Runtime type checking.

  • Allows for a general-purpose coding style.


2.2.1.1 Static Data Object API

SDO's static data object API is a typed Java interface generated from a data service's XML schema definition. It is similar to JAXB or XMLBean static interfaces. The interface files, packaged in a JAR, are typically generated by the data service developer using WebLogic Workshop, or by using one of the provided tools.

The generated interfaces extend the commonj.sdo.DataObject interface and provide typed getters and setters for all properties of the XML datatype.

An interface is also generated for each complex property (such as CREDIT and ORDER shown in Figure 2-2), with getters and setters for each of the properties that comprise the complex type.

For many-valued properties, a get method is generated that returns a java.util.List object. A many-valued property corresponds to an XML schema element that has maxOccurs greater than one. The List returned by a get method for a many-valued property is "live." This means that if you modify the List object, the changes are reflected directly and immediately in the containing data object.

As an example of how static data object APIs are generated, given the CUSTOMER data type shown in Figure 2-2, generating typed client interfaces results in CUSTOMER, CREDIT, ORDER, and POITEM interfaces, each of which includes getters, setters, and factory classes (for instantiating static data objects and their properties).

Figure 2-2 CUSTOMER Return Type Displayed in Oracle Data Service Integrator Administration Console's Metadata Browser

CUSTOMER Return Type in ODSI
Description of "Figure 2-2 CUSTOMER Return Type Displayed in Oracle Data Service Integrator Administration Console's Metadata Browser"

When you develop Java client applications that use SDO's static data object APIs, you will import these typed interfaces into your Java client code. For example:

import appDataServices.AddressDocument;

Table 2-2 lists static data accessor and related API methods. These methods are generated using names that match the schema names with the first letter in the name forced to be upper-case. The generated names cannot conflict with standard Java naming rules.

Table 2-2 Static (Typed) Data Object API Getters and Setters

Static Data Object API (Generated) Description Examples

Type getPropertyName()

Returns the value of the property. Generated for boolean-valued properties.

String name = getLAST_NAME()

List<Type> getPropertyName()

For multiple occurrence elements, returns all PropertyName elements.

List<ORDER> orders = getORDER()

void setPropertyName(Type newValue)

Sets the value of the property to the newValue.

setLAST_NAME("Smith")

boolean isPropertyName()

Determines whether the PropertyName element or attribute exists in the data object.

isSPECIAL_DELIVERY()

void createPropertyName()

Generated only for non-datatype properties. Creates a data object for the specified property. The (created) data object is initialized with no values in its properties.

createORDER()

boolean isSetPropertyName()

Determines whether the property is set to some value.

isSetLAST_NAME()

void unsetPropertyName()

Unsets the property. The property is then considered not to be set.

unsetLAST_NAME()


2.2.1.2 XML Schema-to-Java Type Mapping Reference

Oracle Data Service Integrator client application developers can use the Oracle Data Service Integrator Administration Console to view the XML schema types associated with data services (see Figure 2-2). The Return Type tab indicates the data type of each element—string, int, or complex type, for example. The XML schema data types are mapped to corresponding Java types using the data type mappings shown in Table 2-3.

Note:

The following XQuery types are discussed by the SDO specification and are listed in Table 2-3 but are not supported for input or output from the Mediator API: xs:ENTITIES, xs:ENTITY, xs:ID, xs:IDREF, xs:IDREFS, xs:language, xs:Name, xs:NCName, xs:NMTOKEN, xs:NMTOKENS, xs:NOTATION. The Mediator API is discussed in Chapter 3, "Invoking Data Services from Java Clients."

Table 2-3 XML Schema to Java Data Type Mapping

XML Schema Type SDO Java Type

xs:anyType

commonj.sdo.DataObject

xs:anySimpleType

java.lang.Object

xs:anyURI

String

xs:base64Binary

byte[]

xs:boolean

boolean or java.lang.Boolean

xs:byte

byte or java.lang.Byte

xs:date

String

xs:dateTime

String

xs:decimal

java.math.BigDecimal

xs:double

double or java.lang.Double

xs:duration

String

xs:ENTITIES

List<String>

xs:ENTITY

String

xs:float

float or java.lang.Float

xs:gDay

String

xs:gMonth

String

xs:gMonthDay

String

xs:gYear

String

xs:gYearMonth

String

xs:hexBinary

byte[]

xs:ID

String

xs:IDREF

String

xs:IDREFS

List<String>

xs:int

int or java.lang.Integer

xs:integer

java.math.BigInteger

xs:language

String

xs:long

long or java.lang.Long

xs:Name

String

xs:NCName

String

xs:negativeInteger

java.math.BigInteger

xs:NMTOKEN

String

xs:NMTOKENS

List<String>

xs:nonNegativeInteger

java.math.BigInteger

xs:nonPositiveInteger

java.math.BigInteger

xs:normalizedString

String

xs:NOTATION

String

xs:positiveInteger

java.math.BigInteger

xs:QName

String

xs:short

short or java.lang.Short

xs:string

String

xs:time

String

xs:token

String

xs:unsignedByte

short or java.lang.Short

xs:unsignedInt

long or java.lang.Long

xs:unsignedLong

java.math.BigInteger

xs:unsignedShort

int or java.lang.Integer

xs:keyref

String


2.2.1.3 Dynamic Data Object API

Every static (typed) data object implements the Data Object interface; therefore, you can use the DataObject (dynamic) methods as well as the static API. This API provides generic property getters and setters for specific Java data types (String, Date, List, BigInteger, and BigDecimal, for example). Table 2-4 lists representative APIs from SDO's dynamic Data Object API.

The propertyName argument indicates the name of the property whose value you want to get or set; propertyValue is the new value. The dynamic Data Object API also includes methods for setting and getting a DataObject's property by indexValue. This includes methods for getting and setting properties as primitive types, which include setInt( ), setDate( ), getString( ), and so on.

As an example, assuming that you have a reference to a CUSTOMER data object, you can use the dynamic Data Object API to get the LAST_NAME property as follows:

String lastName = customer.getString("LAST_NAME");

The SDO APIs are standard implementations. You can read the full SDO specification, "SDO for Java Specification V2.1" at http://www.osoa.org/display/Main/Service+Data+Objects+Specifications.

See also Service Data Objects at http://www.oracle.com/technology/pub/articles/dev2arch/2005/11/sdo.html.

Table 2-4 lists dynamic Data Object API getters and setters.

Table 2-4 Dynamic (Untyped) Data Object API Getters and Setters

Dynamic Data Object API Description Example

get(int PropertyIndex)

Returns the PropertyName child element at the specified index.

get(5)

set(int PropertyIndex, Object newValue)

Sets the value of the property to the newValue.

set(5, CUSTOMER3)

set(String PropertyName, Object newValue)

Sets the value of the PropertyName to the newValue.

set("LAST_NAME", "Nimble")

set(commonj.sdo.Property property, Object newValue)

Sets the value of Property object to the newValue.

set(LASTNAME, "Nimble")

getType(String PropertyName)

Returns the value of the PropertyName. Type indicates the specific data type to obtain.

getBigDecimal("CreditScore")

unset(int PropertyIndex)

Unsets the property. The property is then considered not to be set.

unset(5)

unset(commonj.sdo.Property property)

Unsets the property. The property is then considered not to be set.

unset(LASTNAME)

unset(String PropertyName)

Unsets the property. The property is then considered not to be set.

unset("LAST_NAME")

createDataObject(commonj.

sdo.Property property)

Returns a new DataObject for the specified containment Property.

createDataObject(LASTNAME)

createDataObject(String PropertyName)

Returns a new DataObject for the specified containment property.

createDataObject("LAST_NAME")

createDataObject(int PropertyIndex)

Returns a new DataObject for the specified containment property.

createDataObject(5)

createDataObject(String PropertyName, String namespaceURI, String typeName)

Returns a new DataObject for the specified containment property.

createDataObject("LAST_NAME","http://namespaceURI_here", "String")

delete()

Removes the object from its container and unsets all writeable properties.

delete(CUSTOMER)


XPath Expressions in the Dynamic Data Object API

Oracle Data Service Integrator supports a limited subset of XPath expressions called SDO path expressions. SDO path expressions offer flexibility in how you locate data objects and attributes in the dynamic Data Object API's accessors. For example, you can filter the results of a get( ) method invocation based on data elements and values:

company.get("CUSTOMER[1]/POITEMS/ORDER[ORDERID=3546353]")

The SDO path implementation augments XPath 1.0 support by adding zero-based array index notation (".index_from_0") to XPath's standard bracketed notation ([n]). As an example, Table 2-5 compares the XPath standard and SDO augmented notations to refer to the same element, the first ORDER child node under CUSTOMER (Table 2-5).

Table 2-5 XPath Standard and SDO Augmented Notation

XPath Standard Notation SDO Augmented Notation

get("CUSTOMER/ORDER[1]");

get("CUSTOMER/ORDER.0");


Zero-based indexing is convenient for Java programmers who are accustomed to zero-based counters, and may want to use counter values as index values without adding 1. Oracle Data Service Integrator fully supports both the traditional index notation and the augmented notation.

Keep in mind these other points regarding Oracle Data Service Integrator XPath support:

  • Expressions with double adjacent slashes ("//") are not supported. As specified by XPath 1.0, you can use an empty step in a path to effect a wildcard. For example:

    ("CUSTOMER//POITEM")
    

    In this example, the wildcard matches all purchase order arrays below the CUSTOMER root, which includes either of the following:

    CUSTOMER/ORDERS/POITEM
    CUSTOMER/RETURNS/POITEM
    

    Because this notation introduces type ambiguity (types can be either ORDERS or RETURNS), it is not supported by the Oracle Data Service Integrator SDO implementation.

  • In SDO Path, "@" has no significance and is ignored. Elements and attributes in XML Schema both map to properties in SDO, and "@", the notation for denoting an attribute, can be used with any property; however, the "@" will be ignored. Moreover, attributes can be referenced in SDO Path simply with the attribute name, without an "@". For example, the ID attribute of the following element:

    <ORDER ID="3434">
    

    is accessed with the following path:

    ORDER/@ID, or with 
    Order/ID 
    

See also Section 3.9.4, "Specifying XPath Expressions as Arguments."

Obtaining Type Information about Data Objects

The dynamic Data Object API returns generic data objects. To obtain information about the properties of a data object, you can use methods available in SDO's Type interface. The Type interface (located in the commonj.sdo package) provides several methods for obtaining information, at runtime, about data objects, including a data object's type, its properties, and their respective types.

According to the SDO specification, the Type interface (see Table 2-6) and the Property interface (see Table 2-7) comprise a minimal metadata API that can be used for introspecting the model of data objects. For example, the following obtains a data object's type and prints a property's value:

DataObject o = ...; 
Type type = o.getType();
if (type.getName().equals("CUSTOMER") {
   System.out.println(o.getString("CUSTOMERNAME")); }

Once you have an object's data type, you can obtain all its properties (as a list) and access their values using the Type interface's get Properties() method, as shown in Example 2-1.

Example 2-1 Using SDO's Type Interface to Obtain Data Object Properties

public void printDataObject(DataObject dataObject, int indent) {
   Type type = dataObject.getType();
   List properties = type.getProperties();
   for (int p=0, size=properties.size(); p < size; p++) {
      if (dataObject.isSet(p)) {
         Property property = (Property) properties.get(p);
         // For many-valued properties, process a list of values 
         if (property.isMany()) {
            List values = dataObject.getList(p);
            for (int v=0; count=values.size(); v < count; v++) {
               printValue(values.get(v), property, indent);
            } 
         else { // For single-valued properties, print out the value
            printValue(dataObject.get(p), property, indent); 
            }
         }
      } 
   }

Table 2-6 lists other useful methods in the Type interface.

Table 2-6 Type Interface Methods

Method Description

java.lang.Class getInstanceClass()

Returns the Java class that this type represents.

java.lang.String getName()

Returns the name of the type.

java.lang.List getProperties

Returns a list of the properties of this type.

Property getProperty(

java.lang.String propertyName)

Returns from among all Property objects of the specified type the one with the specified name. For example, dataObject.get("name") or dataObject.get(dataObject.getType().getProperty("name"))

java.lang.String getURI()

Returns the namespace URI of the type.

boolean isInstance(

java.lang.Object object)

Returns True if the specified object is an instance of this type; otherwise, returns false.


Table 2-7 lists the methods of the Property interface.

Table 2-7 Property Interface Methods

Method Description

Type getContainingType()

Returns the containing type of this property.

java.lang.Object getDefault()

Returns the default value this property will have in a data object where the property has not been set

java.lang.String getName()

Returns the name of the property.

Type getType()

Returns the type of the property.

boolean isContainment()

Returns True if the property represents by-value composition.

boolean isMany()

Returns True if the property is many-valued.


2.3 Role of the Mediator API and SDO

In Oracle Data Service Integrator, data objects are passed between data services and client applications: when a client application invokes a read function on a data service, for example, a data object is sent to the client application.

The client application modifies the content as appropriate—adds an order to a customer order, for example—and then submits the changed data object to the data service. The Data Service Mediator is an API that receives the updated data objects and propagates changes to the underlying data sources.

The Data Service Mediator is the linchpin of the update process. It uses information from submitted data objects (change summary, for example) in conjunction with other artifacts to derive an update plan for changing underlying data sources. For relational data sources, updates are automatic.

The artifacts that comprise the Oracle Data Service Integrator update framework, including the Mediator, and how the default update process works, are described in more detail in "Managing Update Maps" in the Oracle Fusion Middleware Data Service Integrator Developer's Guide.

For detailed information on using the Mediator APIs for web services clients and Java clients, see: