Java Data Objects and Service Data Objects in SOA


Java Data Objects (JDO) is a complementing standard of accessing data from your data store using a standard interface-based abstraction model of persistence in java. The original JDO (JDO 1.0) specification is quite old and is based on Java Specification Request 12 (JSR 12). The current major version of JDO (JDO 2.0) is based on JSR 243. The original specifications were done under the supervision of Sun and starting from 2.0, the development of the API and the reference implementation happens as an Apache open-source project.

Why JDO?

We have been happily programming to retrieve data from relational stores using JDBC, and now the big question is do we need yet another standard, JDO? If you think that as software programmers you need to provide solutions to your business problems, it makes sense for you to start with the business use cases and then do a business analysis at the end of which you will come out with a Business Domain Object Model (BDOM). The BDOM will drive the design of your entity classes, which are to be persisted to a suitable data store. Once you design your entity classes and their relationship, the next question is should you be writing code to create tables, and persist or query data from these tables (or data stores, if there are no tables). I would like to answer 'No' for this question, since the more code you write, the more are the chances of making errors, and further, developer time is costly. Moreover, today you may write JDBC for doing the above mentioned "technical functionalities", and tomorrow you may want to change all your JDBC to some other standard since you want to port your data from a relational store to a different persistence mechanism. To sum up, let us list down a few of the features of JDO which distinguishes itself from other similar frameworks.

  • Separation of Concerns: Application developers can focus on the BDOM and leave the persistence details (storage and retrieval) to the JDO implementation.
  • API-based: JDO is based on a java interface-based programming model. Hence all persistence behavior including most commonly used features of OR mapping is available as metadata, external to your BDOM source code. We can also Plug and Play (PnP) multiple JDO implementations, which know how to interact well with the underlying data store.
  • Data store portability: Irrespective of whether the persistent store is a relational or object-based file, or just an XML DB or a flat file, JDO implementations can still support the code. Hence, JDO applications are independent of the underlying database.
  • Performance: A specific JDO implementation knows how to interact better with its specific data store, which will improve performance as compared to developer written code.
  • J2EE integration: JDO applications can take advantage of J2EE features like EJB and thus the enterprise features such as remote message processing, automatic distributed transaction coordination, security, and so on.

JPOX—Java Persistent Objects

JPOX is an Apache open-source project, which aims at a heterogeneous persistence solution for Java using JDO. By heterogeneous we mean, JPOX JDO will support any combination of the following four main aspects of persistence:

  • Persistence Definition: The mechanism of defining how your BDOM classes are to be persisted to the data store.
  • Persistence API: The programming API used to persist your BDOM objects.
  • Query Language: The language used to find objects due to certain criteria.
  • Data store: The underlying persistent store you are persisting your objects to.

JDO Sample Using JPOX

In this sample, we will take the familiar Order and LineItems scenario, and expand it to have a JDO implementation. It is assumed that you have already downloaded and extracted the JPOX libraries to your local hard drive.

BDOM for the Sample

We will limit our BDOM for the sample discussion to just two entity classes, that is, OrderList and LineItem. The class attributes and relationships are shown in the following screenshot:

Java Data Objects and Service Data Objects in SOA

The BDOM illustrates that an Order can contain multiple line items. Conversely, each line item is related to one and only one Order.

Code BDOM Entities for JDO

The BDOM classes are simple entity classes with getter and setter methods for each attribute. These classes are then required to be wired for JDO persistence capability in a JDO specific configuration file, which is completely external to the core entity classes.

OrderList is the class representing the Order, and is having a primary key attribute that is number.

public class OrderList{ 
private int number;
private Date orderDate;
private Set lineItems;
// other getter & setter methods go here
// Inner class for composite PK
public static class Oid implements Serializable{
public int number;
public Oid(){
public Oid(int param){
this.number = param;
public String toString(){
return String.valueOf(number);
public int hashCode(){
return number;
public boolean equals(Object other){
if (other != null && (other instanceof Oid)){
Oid k = (Oid)other;
return k.number == this.number;
return false;

LineItem represents each item container in the Order. We don't explicitly define a primary key for LineItem even though JDO will have its own mechanism to do that.

public class LineItem{ 
private String productId;
private int numberOfItems;
private OrderList orderList;
// other getter & setter methods go here


JDO requires an XML configuration file, which defines the fields that are to be persisted and to what JDBC or JDO wrapper constructs should be mapped to. For this, we can create an XML file called package.jdo with the following content and put it in the same directory where we have the entities.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jdo SYSTEM "file:/javax/jdo/jdo.dtd">
<package name="com.binildas.jdo.jpox.order">
<class name="OrderList" identity-type="application"
objectid-class="OrderList$Oid" table="ORDERLIST">
<field name="number" primary-key="true">
<column name="ORDERLIST_ID"/>
<field name="orderDate">
<column name="ORDER_DATE"/>
<field name="lineItems" persistence-modifier="persistent" mapped-by="orderList">
<collection element-type="LineItem">
<class name="LineItem" table="LINEITEM">
<field name="productId">
<column name="PRODUCT_ID"/>
<field name="numberOfItems">
<column name="NUMBER_OF_ITEMS"/>
<field name="orderList" persistence-modifier="persistent">
<column name="LINEITEM_ORDERLIST_ID"/>


In this sample, we will persist our entities to a relational database, Oracle. We specify the main connection parameters in jpox.PROPERTIES file.


This class contains the code to test the JDO functionalities. As shown here, it creates two Orders and adds few line items to each order. First it persists these entities and then queries back these entities using the id.

public class Main{ 
static public void main(String[] args){
Properties props = new Properties();
props.load(new FileInputStream(""));
catch (Exception e){
PersistenceManagerFactory pmf =
PersistenceManager pm = pmf.getPersistenceManager();
Transaction tx = pm.currentTransaction();
Object id = null;
LineItem lineItem1 = new LineItem("CD011", 1);
LineItem lineItem2 = new LineItem("CD022", 2);
OrderList orderList = new OrderList(1, new Date());
LineItem lineItem3 = new LineItem("CD033", 3);
LineItem lineItem4 = new LineItem("CD044", 4);
OrderList orderList2 = new OrderList(2, new Date());
id = pm.getObjectId(orderList);
System.out.println("Persisted id : "+ id);
id = pm.getObjectId(orderList2);
System.out.println("Persisted id : "+ id);
orderList = (OrderList) pm.getObjectById(id);
System.out.println("Retreived orderList : " + orderList);
catch (Exception e){
if (tx.isActive()){

Build and Run the JDO Sample

You can download the required code for this article from Unzip the file and the code of our interest is in the folder 3216_04_Code. There is also a README.txt file, which gives detailed steps to build and run the samples.

Since we use Oracle to persist entities, we need the following two libraries in the classpath:

  • jpox-rdbms*.jar
  • classes12.jar

We require a couple of other libraries too which are specified in the build.xml file. Download these libraries and change the path in examples.PROPERTIES accordingly.

To build the sample, first bring up your database server. Then to build the sample in a single command, it is easy for you to go to ch04jdo folder and execute the following command.

cd ch04jdo

The above command will execute the following steps:

  • First it compiles the java source files
  • Then for every class you persist, use JPOX libraries to enhance the byte code.
  • As the last step, we create the required schema in the data store.

Java Data Objects and Service Data Objects in SOA

To run the sample, execute:

ant run

You can now cross check whether the entities are persisted to your data store. This is as shown in the following screenshot where you can see that each line item is related to the parent order by the foreign key.

Java Data Objects and Service Data Objects in SOA


Data Services

Good that you now know how to manage the basic data operations in a generic way using JDO and other techniques. By now, you also have good hands-on experience in defining and deploying web services. We all appreciate that web services are functionalities exposed in standard, platform, and technology neutral way. When we say functionality we mean the business use cases translated in the form of useful information. Information is always processed out of data. So, once we retrieve data, we need to process it to translate them into information.

When we define SOA strategies at an enterprise level, we deal with multiple Line of Business (LOB) systems; some of them will be dealing with the same kind of business entity. For example, a customer entity is required for a CRM system as well as for a sales or marketing system. This necessitates a Common Data Model (CDM), which is often referred to as the Canonical Data Model or Information Model. In such a model, you will often have entities that represent "domain" concepts, for example, customer, account, address, order, and so on. So, multiple LOB systems will make use of these domain entities in different ways, seeking different information-based on the business context. OK, now we are in a position to introduce the next concept in SOA, which is "Data Services".

Data Services are specialization of web services which are data and information oriented. They need to manage the traditional CRUD (Create, Read, Update, and Delete) operations as well as a few other data functionalities such as search and information modeling. The Create operation will give you back a unique ID whereas Read, Update, and Delete operations are performed on a specific unique ID. Search will usually be done with some form of search criteria and information modeling, or retrieval happens when we pull useful information out of the CDM, for example, retrieving the address for a customer.

The next important thing is that no assumptions should be made that the data will be in a java resultset form or in a collection of transfer object form. Instead, you are now dealing with data in SOA context and it makes sense to visualize data in XML format. Hence, XML Schema Definition (XSDs) can be used to define the format of your requests and responses for each of these canonical data definitions. You may also want to use ad hoc queries using XQuery or XPath expressions, similar to SQL capabilities on relational data. In other words, your data retrieval and data recreation for information processing at your middle tier should support XML tools and mechanisms, and should also support the above six basic data operations. If so, higher level of abstractions in the processing tier can make use of the above data services to provide Application Specialization capabilities, specialized for the LOB systems. To make the concept clear, let us assume that we need to get the order status for a particular customer (getCustomerOrderStatus()) which will take the customer ID argument. The data services layer will have a retrieve operation passing the customer ID and the XQuery or the XPath statement will obtain the requested order information from the retrieved customer data. High level processing layers (such as LOB service tiers) can use high-level interface (for example, our getCustomerOrderStatus operation) of the Application Specialization using a web services (data services) interface and need not know or use XQuery or XPath directly. The underlying XQuery or XPath can be encapsulated, reused, and optimized.

Service Data Objects

Data abstraction and unified data access are the two main concerns that any SOA-based architecture has to address. In the data services discussion, we talked a bit about data abstraction, by first defining data around domain entities and then decorating it with useful methods for data operations. Equally important is the issue of accessing heterogeneous data in a uniform way.

Why SDO?

One of the main problems Service Data Objects (SDO) tries to solve is the issue of heterogeneous manner of data management. By data management, we mean data storage as well as operations on data lifecycle. SDO simplifies J2EE data programming model thus giving application developers more time to focus on the business problems.

SDO provides developers an API, the SDO API, and a programming model to access data. This API lets you to work with data from heterogeneous data sources, including RDBMS, entity EJBs, XML sources, web services, EIS data sources using the Java Connector Architecture, and so on. Hence you as a developer need not be familiar with a technology-specific API such as JDBC or XQuery in order to access and utilize data. Instead, you can just use SDO API.

SDO Architecture

In SDO, data is organized as a graph of objects, called DataObject. A DataObject is the fundamental component which is a representation of some structured data, with some properties. These properties have either a single value or multiple values, and their values can be even other data objects. Each data objects also maintains a change summary, which represents the alterations made to it.

SDO clients or consumers always use SDO programming model and API. This is generic of technology and framework, and hence the developers need not know how the underlying data they are working with is persisted. A Data Mediator Service (DMS) is responsible for creating a data graph from data source(s), and also for updating the data source(s) based on any changes made to a data graph. SDO clients are disconnected from both the DMS and the data source.

A DMS will create a Data Graph, which is a container for a tree of data objects. Another interesting fact is that a single data graph can represent data from different data sources. This is actually a design model to deal with data aggregation scenarios from multiple data sources. The data graphs form the basics of the disconnected architecture of SDO, since they can be passed across layers and tiers in an application. When doing so, they are serialized to the XML format.

A Change Summary contains any change information related to the data in the data object. Change summaries are initially empty and are populated as and when the data graph is modified.

Java Data Objects and Service Data Objects in SOA

Apache Tuscany SDO

Apache Tuscany SDO is a sub-project within open-source Apache Tuscany.

Apache Tuscany aims at defining an infrastructure that simplifies the development of Service-Oriented application networks, addressing real business problems. It is based on specifications defined by the OASIS Open Composite Services Architecture (CSA) Member Section, which advances open standards that simplify SOA application development. Tuscany SDO mainly provides implementations in Java and C++. Both are available for download at:

SDO Sample Using Tuscany SDO

SDO can handle heterogeneous data sources, but for the sample here, we will make use of an XML file as a data source. The sample will read as well as write an XML file, when the client program makes use of SDO API to do data operations.

Code the Sample Artifacts

The main artifacts for running the samples in SDO include an XSD schema file and an XML instance file. Then we have two java programs, one which reads the XML and another which creates an XML. We will look into these files first.


The hr.xsd restricts the structure of an employee XML file, which can contain multiple employees. Each employee can have a name, address, organization, and office elements. Each of these elements can have sub-elements, which are as shown here:

<?xml version="1.0"?>
<xsd:schema xmlns:xsd=""
xmlns="" targetNamespace="">
<xsd:element name="employees">
<xsd:element ref="employee" maxOccurs="unbounded" />
<xsd:element name="employee">
<xsd:documentation>Employee representation</xsd:documentation>
<xsd:element name="name" type="xsd:string" />
<xsd:element ref="address" maxOccurs="2" />
<xsd:element ref="organization" />
<xsd:element ref="office" />
<xsd:attribute name="id" type="xsd:integer" />
<xsd:element name="organization">
<xsd:element name="name" type="xsd:string"/>
<xsd:attribute name="id" type="xsd:integer" />
<xsd:element name="office">
<xsd:element ref="address"/>
<xsd:attribute name="id" type="xsd:integer" />
<xsd:element name="address">
<xsd:element name="street1" type="xsd:string"/>
<xsd:element name="street2" type="xsd:string" minOccurs="0"/>
<xsd:element name="city" type="xsd:string"/>
<xsd:element name="state" type="stateAbbreviation"/>
<xsd:element ref="zip-code"/>
<xsd:element name="zip-code">
<xsd:restriction base="xsd:string">
<xsd:pattern value="[0-9]{5}(-[0-9]{4})?"/>
<xsd:simpleType name="stateAbbreviation">
<xsd:restriction base="xsd:string">
<xsd:pattern value="[A-Z]{2}"/>


The hr.xml provided is fully constrained as per the above schema. For our sample demonstration this XML file contains data on two employees as shown here:

<?xml version="1.0"?>
<employees xmlns="">
<employee id="30379">
<name>Binildas C. A.</name>
<street1>45 Bains Compound Nanthencode</street1>
<organization id="08">
<office id="31">
<street1>101 Camarino Ruiz</street1>
<street2>Apt 2 Camarillo</street2>
<employee id="30380">
<name>Rajesh R V</name>
<street1>1400 Salt Lake Road</street1>
<street2>Appartment 5E</street2>
<organization id="15">
<office id="21">
<street1>2700 Cambridge Drive</street1>

Now, we are going to see SDO in action. In the ReadEmployees class shown below, we first read the XML file, mentioned previously, and load it into a root DataObject. A DataObject is a graph of other DataObjects. Hence, we can iterate over the graph and get each item DataObject.

public class ReadEmployees extends SampleBase{ 
private static final String HR_XML_RESOURCE = "hr.xml";
public static final String HR_XSD_RESOURCE = "hr.xsd";
public ReadEmployees(Integer commentaryLevel) {
super(commentaryLevel, SampleInfrastructure.SAMPLE_LEVEL_BASIC);
public static void main(String[] args)throws Exception{
ReadEmployees sample = new ReadEmployees(COMMENTARY_FOR_NOVICE);
public void runSample () throws Exception{
InputStream inputStream = ClassLoader.getSystemResourceAsStream(HR_XML_RESOURCE);
byte[] bytes = new byte[inputStream.available()];;
HelperContext scope = createScopeForTypes();
loadTypesFromXMLSchemaFile(scope, HR_XSD_RESOURCE);
XMLDocument xmlDoc = getXMLDocumentFromString(scope,
new String(bytes));
DataObject purchaseOrder = xmlDoc.getRootObject();
List itemList = purchaseOrder.getList("employee");
DataObject item = null;
for (int i = 0; i < itemList.size(); i++) {
item = (DataObject) itemList.get(i);
System.out.println("id: " + item.get("id"));
System.out.println("name: " + item.get("name"));

In the CreateEmployees class, we do the reverse process—we define DataObjects in code and build the SDO graph. At the end, the root DataObject is persisted to a file and also to the system output stream as shown in the following code.

public class CreateEmployees extends SampleBase { 
private static final String HR_XML_RESOURCE_NEW = "hr_new.xml";
public static final String HR_XSD_RESOURCE = "hr.xsd";
public static final String HR_NAMESPACE = "";
public CreateEmployees(Integer commentaryLevel) {
super(commentaryLevel, SAMPLE_LEVEL_BASIC);
public static void main(String[] args) throws Exception{
CreateEmployees sample = new CreateEmployees(COMMENTARY_FOR_NOVICE);
public void runSample() throws Exception{
HelperContext scope = createScopeForTypes();
loadTypesFromXMLSchemaFile(scope, HR_XSD_RESOURCE);
DataFactory factory = scope.getDataFactory();
DataObject purchaseOrder = factory.create(HR_NAMESPACE, "employees");
DataObject employee1 = purchaseOrder.createDataObject( "employee");
employee1.setString("id", "3457");
employee1.set("name", "Cindy Jones");
DataObject homeAddress1 = employee1.createDataObject("address");
homeAddress1.set("street1", "Cindy Jones");
homeAddress1.set("city", "Stanchion");
homeAddress1.set("state", "TX");
homeAddress1.set("zip-code", "79021");
DataObject organization1 = employee1.createDataObject("organization");
organization1.setString("id", "78");
organization1.set("name", "Sales");
DataObject office1 = employee1.createDataObject("office");
office1.setString("id", "43");
DataObject officeAddress1 = office1.createDataObject("address");
officeAddress1.set("street1", "567 Murdock");
officeAddress1.set("street2", "Suite 543");
officeAddress1.set("city", "Millford");
officeAddress1.set("state", "TX");
officeAddress1.set("zip-code", "79025");
DataObject employee2 = purchaseOrder.createDataObject( "employee");
employee2.setString("id", "30376");
employee2.set("name", "Linda Mendez");
DataObject homeAddress2 = employee1.createDataObject("address");
homeAddress2.set("street1", "423 Black Lake Road");
homeAddress2.set("street2", "Appartment 7A");
homeAddress2.set("city", "Boston");
homeAddress2.set("state", "MA");
homeAddress2.set("zip-code", "20967");
DataObject organization2 =
organization2.setString("id", "78");
organization2.set("name", "HR");
DataObject office2 = employee2.createDataObject("office");
office2.setString("id", "48");
DataObject officeAddress2 = office2.createDataObject("address");
officeAddress2.set("street1", "5666 Cambridge Drive");
officeAddress2.set("city", "Boston");
officeAddress2.set("state", "MA");
officeAddress2.set("zip-code", "20968");
OutputStream stream = new FileOutputStream(HR_XML_RESOURCE_NEW);
scope.getXMLHelper().save(purchaseOrder, HR_NAMESPACE, "employees", stream);
XMLDocument doc =
scope.getXMLHelper().createDocument(purchaseOrder, HR_NAMESPACE, "employees");
scope.getXMLHelper().save(doc, System.out, null);

Build and Run the SDO Sample

To build the sample in a single command, it is easy for you to go to ch04sdo folder and execute the following command:

cd ch04sdo

Now, you can execute the ReadEmployees class by executing:

ant read

Java Data Objects and Service Data Objects in SOA

Now, you can execute the CreateEmployees class by executing:

ant create

Java Data Objects and Service Data Objects in SOA


Standards and frameworks play a greater role in enabling easy and widespread industry adoption of SOA. In this article we discussed about Java Data Objects (JDO) and Service Data Objects (SDO) in SOA.

You've been reading an excerpt of:

Service Oriented Architecture with Java

Explore Title