Skip to main content

Service Data Objects (SDO) 2.0: Create and read an XML document based on XML Schema

Fuhwei Lwo (fuhwei@us.ibm.com), Developer, IBM Software Group, Application and Integration Middleware Software, IBM, Software Group
Fuhwei Lwo photo
Fuhwei Lwo is the team leader of WebSphere Service Data Objects (SDO) in IBM Software Group. His main focus is to drive the success of SDO adoption as data model programming APIs in Service Oriented Architecture (SOA).

Summary:  Learn about the advantages of the SDO 2.0 API by following a simple example. (Updated to correct Listing 1--Ed.)

Date:  03 Jul 2007 (Published 07 Apr 2006)
Level:  Introductory
Activity:  5276 views
Comments:  

Introduction: What is SDO?

Service Data Object (SDO) 2.0 is an open standard data model programming API that allows the developer to easily manipulate data at a high level. Although SDO 1.0 aims at the same data abstraction goal, it has several major drawbacks, the main one being a lack of helper classes, such as XSDHelper, XMLHelper, and so on. The end result is that the developer is forced to utilize the SDO 1.0 implementation APIs, which come from Eclipse Modeling Framework (EMF) SDK.

The current implementation, SDO 2.0, uses EMF 2.2 SDK, but that is an SDO 2.0 implementation detail that does not impact the developer writing to the new API. In the future, the open source community, through the Apache Software Foundation, may decide to provide a different implementation of SDO 2.0., but that should not affect the applications built upon SDO 2.0 APIs.

The most basic way to see the advantages of the new API is to use SDO 2.0 to create and then read an XML document compliant to XML Schema (XSD). To accomplish the same goal without using the SDO 2.0 would require the developer to understand how the XML parser works and tightly integrate the data parsing logic with the application. Later, if the XSD needs to change, the application would need to be touched everywhere, which would jeopardize the quality of the code.

It's difficult for new users of SDO 2.0 APIs to comprehend the concept by simply studying the specification. To help, I created an example from the XML Schema Primer (see Resources) to explain how SDO 2.0 APIs are used to:

  • Write an XML document to the disk, and
  • Read it back.

Scenario: purchase order information collection and delivery

Here's the usage scenario we will try to realize with our example. First, the company determines the requirements for purchase order (PO) information. Once that is done, we start creating a static form to structure the information. In the database, that static form is the table schema. In XML, that static form is the XML Schema (XSD). Later on, if additional customer information needs to be collected, we will need to redesign the form/table schema/XSD.

When placing an order, the customer needs to fill out a PO form or give the same information to the operator for filling out the form. The information in the form will then be used by the company to deliver the order.

After the company receives the PO information, it would most likely save it and then read it for the purpose of, say, customer support. In this example, we can save the information in XML format and then read it using SDO APIs.

Figure 1 shows a sample of PO information collected from customer Robert Smith. An XSD file will be created to structure this sample purchase order. A sample program called CreatePurchaseOrder.java is used to create the sample PO in XML format called po.xml. Finally, ReadPurchaseOrder.java is used to demonstrate how to read order information from the po.xml.


Figure 1. Sample purchase order information from Robert Smith
Order date: 1999-10-20

Shipping information:
Name: Alice Smith
Street: 123 Maple Street
City: Mill Valley
State: CA
Zip code: 90952
Country: US

Billing information:
Name: Robert Smith
Street: 8 Oak Avenue
City: Mill Valley
State: PA
Zip code: 95819
Country: US

Order Items:
1. Part number: 872-AA
Product name: Lawnmower
Quantity: 1
Price: 148.95
Comment: Confirm this is electric

2. Part number: 926-AA
Product name: Baby Monitor
Quantity: 1
Price: 39.98
Ship date: 1999-05-21

Comment: Hurry, my lawn is going wild!


Purchase order’s XML schema

Based on the sample purchase order shown in Figure 1, a PO type can be used to represent the order. Let’s call it PurchaseOrderType. The instance of PurchaseOrderType may contain four major data, as follows:

  1. shipping information
  2. billing information
  3. order items information
  4. comment

The shipping and billing information may contain more data, such as name, street, city, state, zip, and country. Order items information may contain many information about items purchased by the customer. Each item may contain part number, product name, quantity, price, ship date, and comment. The comment area of the PO accommodates a string value without requiring more structured information.

Listing 1 shows all the purchase order information in a file structured in XSD format.


Listing 1. PO.xsd

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns="http://www.example.com/PO" targetNamespace="http://www.example.com/PO">

    <xsd:element name="purchaseOrder" type="PurchaseOrderType"/>
    <xsd:element name="comment" type="xsd:string"/>

    <xsd:complexType name="PurchaseOrderType">
        <xsd:sequence>
            <xsd:element name="shipTo" type="USAddress"/>
            <xsd:element name="billTo" type="USAddress"/>
            <xsd:element ref="comment" minOccurs="0"/>
            <xsd:element name="items"  type="Items"/>
        </xsd:sequence>
        <xsd:attribute name="orderDate" type="xsd:date"/>
    </xsd:complexType>

    <xsd:complexType name="USAddress">
        <xsd:sequence>
            <xsd:element name="name"   type="xsd:string"/>
            <xsd:element name="street" type="xsd:string"/>
            <xsd:element name="city"   type="xsd:string"/>
            <xsd:element name="state"  type="xsd:string"/>
            <xsd:element name="zip"    type="xsd:decimal"/>
        </xsd:sequence>
        <xsd:attribute name="country" type="xsd:NMTOKEN" fixed="US"/>
    </xsd:complexType>

    <xsd:complexType name="Items">
        <xsd:sequence>
            <xsd:element name="item" minOccurs="0" maxOccurs="unbounded">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:element name="productName" type="xsd:string"/>
                        <xsd:element name="quantity">
                            <xsd:simpleType>
                                <xsd:restriction base="xsd:positiveInteger">
                                    <xsd:maxExclusive value="100"/>
                                </xsd:restriction>
                            </xsd:simpleType>
                        </xsd:element>
                        <xsd:element name="USPrice"  type="xsd:decimal"/>
                        <xsd:element ref="comment"   minOccurs="0"/>
                        <xsd:element name="shipDate" type="xsd:date" minOccurs="0"/>
                    </xsd:sequence>
                    <xsd:attribute name="partNum" type="SKU" use="required"/>
                </xsd:complexType>
            </xsd:element>
        </xsd:sequence>
    </xsd:complexType>
    <xsd:simpleType name="SKU">
        <xsd:restriction base="xsd:string">
            <xsd:pattern value="\d{3}-[A-Z]{2}"/>
        </xsd:restriction>
    </xsd:simpleType>
</xsd:schema>


You can also use the Unified Modeling Language (UML) class diagram to structure the purchase order information, as shown in Figure 2.


Figure 2. UML class diagram of purchase order
UML class diagram of purchase order

The XSD po.xsd file and the UML class diagram differ in the following ways:

  1. The class diagram defines ItemType, which is not defined in po.xsd.diagram. Although po.xsd didn’t define ItemType specifically, the XSD specification handles ItemType as an anonymous type.
  2. All xsd:<type> in XSD has been abbreviated to become <type> in the class diagram. In XSD, the xsd in the pattern of xsd:<type> is used to indicate the namespace to which the type belongs. In the class diagram, it was taken out for simplicity.
  3. SKU type is not defined in the class diagram. SKU type is in fact a normalized string type defined in the po namespace. In the class diagram, it is represented by string type.

Create sample PO in XML

The sample program CreatePurchaseOrder.java shown in Listing 2 creates a PO in XML format called po.xml, shown in Listing 3.


Listing 2. CreatePurchaseOrder.java
/**
 * Author:	Fuhwei Lwo
 */
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.OutputStream;

import commonj.sdo.DataObject;
import commonj.sdo.helper.DataFactory;
import commonj.sdo.helper.XMLHelper;
import commonj.sdo.helper.XSDHelper;

public class CreatePurchaseOrder {
  private static final String PO_MODEL = "po.xsd";
  private static final String PO_NAMESPACE = "http://www.example.com/PO";
  private static final String PO_XML = "po.xml";

	private static void definePOTypes() throws Exception {
	 FileInputStream fis = new FileInputStream(PO_MODEL);
	 XSDHelper.INSTANCE.define(fis, null);
	 fis.close();
	}

	public static void main(String[] args) throws Exception {
	 definePOTypes();
      
	 DataObject purchaseOrder = 
	   DataFactory.INSTANCE.create(PO_NAMESPACE, "PurchaseOrderType");
		
	 purchaseOrder.setString("orderDate", "1999-10-20");
		
	 DataObject shipTo = purchaseOrder.createDataObject("shipTo");
	 shipTo.set("country", "US");
	 shipTo.set("name", "Alice Smith");
	 shipTo.set("street", "123 Maple Street");
	 shipTo.set("city", "Mill Valley");
	 shipTo.set("state", "CA");
	 shipTo.setString("zip", "90952");
	 DataObject billTo = purchaseOrder.createDataObject("billTo");
	 billTo.set("country", "US");
	 billTo.set("name", "Robert Smith");
	 billTo.set("street", "8 Oak Avenue");
	 billTo.set("city", "Mill Valley");
	 billTo.set("state", "PA");
	 billTo.setString("zip", "95819");
	 purchaseOrder.set("comment", "Hurry, my lawn is going wild!");
		
	 DataObject items = purchaseOrder.createDataObject("items");
		
	 DataObject item1 = items.createDataObject("item");
	 item1.set("partNum", "872-AA");
	 item1.set("productName", "Lawnmower");
	 item1.setInt("quantity", 1);
	 item1.setString("USPrice", "148.95");
	 item1.set("comment", "Confirm this is electric");
		
	 DataObject item2 = items.createDataObject("item");
	 item2.set("partNum", "926-AA");
	 item2.set("productName", "Baby Monitor");
	 iteim2.setInt("quantity", 1);
	 item2.setString("USPrice", "39.98");
	 item2.setString("shipDate", "1999-05-21");
		
	 OutputStream stream = new FileOutputStream(PO_XML);
	 XMLHelper.INSTANCE.save(purchaseOrder, PO_NAMESPACE, "purchaseOrder", stream);
	}
}


Listing 3. Po.xml
<?xml version="1.0" encoding="ASCII"?>
<po:purchaseOrder xmlns:po="http://www.example.com/PO" orderDate="1999-10-20">
  <shipTo country="US">
    <name>Alice Smith</name>
    <street>123 Maple Street</street>
    <city>Mill Valley</city>
    <state>CA</state>
    <zip>90952</zip>
  </shipTo>
  <billTo country="US">
    <name>Robert Smith</name>
    <street>8 Oak Avenue</street>
    <city>Mill Valley</city>
    <state>PA</state>
    <zip>95819</zip>
  </billTo>
  <comment>Hurry, my lawn is going wild!</comment>
  <items>
    <item partNum="872-AA">
      <productName>Lawnmower</productName>
      <quantity>1</quantity>
      <USPrice>148.95</USPrice>
      <comment>Confirm this is electric</comment>
    </item>
    <item partNum="926-AA">
      <productName>Baby Monitor</productName>
      <quantity>1</quantity>
      <USPrice>39.98</USPrice>
      <shipDate>1999-05-21</shipDate>
    </item>
  </items>
</po:purchaseOrder>

The sample Java program first registers all types described in po.xsd with an SDO runtime by calling XSDHelper.INSTANCE.define() method. It then creates a root DataObject out of the PurchaseOrderType. From there, it uses DataObject APIs to build the DataObject tree representing the purchase order information, shown in Figure 3.


Figure 3. DataObject tree
DataObject tree

In Figure 3, each rectangular box has two compartments. The top compartment (with gray color) indicates the DataObject instance name and its real type; the bottom compartment indicates the contained properties. For example, the root object of the tree is the purchaseOrder DataObject instance; its real type is PurchaseOrderType, defined in PO.xsd in Listing 1. In this DataObject instance, it contains two property values – orderDate and comment.

After creating the DataObject tree, the program invokes the XMLHelper.INSTANCE.save() method to save the contents of the tree starting from the purchaseOrder DataObject instance to an XML document, in this case, po.xml. In fact, you can specify any DataObject instance from the tree as the first parameter of XMLHelper.INSTANCE.save() method and the save() method will save all DataObject instances from the one you specified.


Read sample PO

After CreatePurchaseOrder.java creates po.xml, we can compile and run ReadPurchaseOrder.java, shown in Listing 4 to demonstrate using SDO APIs to traverse the contents of po.xml. The application performs the following actions:

  1. Checks to be sure the types defined in po.xsd were registered with SDO runtime
  2. Invokes XMLHelper.load() method to load po.xml to the memory which is represented by the XMLDocument instance xmlDoc
  3. Invokes xmlDoc.getRootObject() method to retrieve the root object of the DataObject tree called purchaseOrder, which corresponds to the purchaseOrder DataObject in the DataObject tree diagram shown in Figure 3
  4. After the purchaseOrder DataObject is returned, traverses the DataObject tree to retrieve all the information about this PO

Listing 4. ReadPurchaseOrder.java
/**
/**
 * Author:	Fuhwei Lwo
 */
import java.io.FileInputStream;
import java.util.List;

import commonj.sdo.DataObject;
import commonj.sdo.helper.XMLDocument;
import commonj.sdo.helper.XMLHelper;
import commonj.sdo.helper.XSDHelper;


public class ReadPurchaseOrder {
 private static final String PO_MODEL = "po.xsd";
 private static final String PO_XML = "po.xml";

	private static void definePOTypes() throws Exception {
	  FileInputStream fis = new FileInputStream(PO_MODEL);
	  XSDHelper.INSTANCE.define(fis, null);
	  fis.close();
        }

	public static void main(String[] args) throws Exception {
 	  definePOTypes();

 	  FileInputStream fis = new FileInputStream(PO_XML);

 	  XMLDocument xmlDoc = XMLHelper.INSTANCE.load(fis);

 	  DataObject purchaseOrder = xmlDoc.getRootObject();
 	  
           System.out.println("Order date: " + purchaseOrder.get("orderDate"));
          System.out.println("Comment: " + purchaseOrder.get("comment"));

 	  DataObject shipTo = purchaseOrder.getDataObject("shipTo");
 	  System.out.println("Ship to name: " + shipTo.get("name"));

	  DataObject billTo = purchaseOrder.getDataObject("billTo");
           System.out.println("Bill to name: " + billTo.get("name"));
          System.out.println();

            DataObject items = purchaseOrder.getDataObject("items");
            List itemList = items.getList("item");
            for (int i=0; i<itemList.size(); i++) {
        
		       DataObject item = (DataObject)itemList.get(i);
			
		       System.out.println("Part num: " + item.get("partNum"));S
		      System.out.println("Product name: " + item.get("productName"));
    } // for
  }
}

System.out.println() in bold in Listing 4 displays the property values of various data objects including the following:

  • orderDate and comment properties of the purchaseOrder DataObject
  • name property of the shipTo DataObject
  • name property of the billTo DataObject
  • partNum and productName properties of various data objects

Figure 4. Console output of running ReadPurchaseOrder
Order date: 1999-10-20

Comment: Hurry, my lawn is going wild!
Ship to name: Alice Smith
Bill to name: Robert Smith

Part num: 872-AA
Product name: Lawnmower

Part num: 926-AA
Product name: Baby monitor

In figure 4, we can see the output of running the ReadPurchaseOrder Java code.


Conclusion: SDO to become de facto data model programming API

SDO 2.0 APIs provide a consistent way of creating and accessing data and shielding the developers from the underlined detailed implementation of parsing and maintaining data integrity. SDO 2.0 is currently an incubator subproject (called Tuscany) under the Apache Software Foundation that is intended become the de facto standard of data model programming APIs for SOA development. See the Resources section for a link.

As you can see from the examples above, the SDO 2.0 APIs completely shield you from knowing and using the XML parser APIs to read, write, and manipulate data. If you create the DataObject in Java representing the XML data in compliance with the XML Schema you define, SDO 2.0 gives you the convenience and flexibility to focus on how to use the data. As a result, it provides you the great benefits of increasing your development productivity and product quality.

In conclusion, using the data abstraction technology offered by SDO 2.0 allows you to treat your data according to whatever business logic you define to meet your business need. This helps you simplify your business application development and also increase your team's productivity and the quality of its work.


Resources

Learn

Discuss

About the author

Fuhwei Lwo photo

Fuhwei Lwo is the team leader of WebSphere Service Data Objects (SDO) in IBM Software Group. His main focus is to drive the success of SDO adoption as data model programming APIs in Service Oriented Architecture (SOA).

Comments



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=SOA and Web services, XML
ArticleID=107485
ArticleTitle=Service Data Objects (SDO) 2.0: Create and read an XML document based on XML Schema
publish-date=07032007
author1-email=fuhwei@us.ibm.com
author1-email-cc=

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Rate a product. Write a review.

Special offers