Topic: Data Binding Object Pattern (DBO) [zt]

  Print this page

1.Data Binding Object Pattern (DBO) [zt] Copy to clipboard
Posted by: ditty
Posted on: 2003-06-10 10:43

Context

Data needs to be exchanged across tiers. In Java, binary serialization of Transfer Objects is essentially free. However, if we want text over HTTP, i.e. XML, then several possibilities exist. Accessing data from Transfer Objects varies depending on the Transfer Object. Serializing Transfer Objects to XML varies greatly depending on the approach (document model, code generated data binding, mapping based data binding, and so forth) and further complicated by the API chosen.

Problem

Text serialization using XML over HTTP is often a consideration if your J2EE application is concerned with interoperability with other applications, among other reasons. Much like there are many different persistent storage mechanisms, there are also many different mechanisms for working with XML and marked differences in the way these APIs are utilized.

The way your application will work with XML will vary depending on the approach chosen. For example, if you take a document model approach, then your application will be very concerned about the structure of the XML document. To get to the data you want you’ll need to navigate parent-child and sibling relationships up and down the document tree.

If you take an XML binding approach then you are much less concerned about, and less tightly coupled to, document structure. Generally, the XML document is transparent in a conversation with this approach.

Examples of APIs for a document model approach are the W3C standard interfaces like DOM, and simpler Java centric solutions such as JDOM. For XML data binding we have even greater possibilities, which further complicate the issue. We can take a code generated approach such as JAXB and JBind or a mapping style based approach such as Castor XML Mapping.

The many approaches and APIs to choose from offer challenges to the application and, as is often the case, potentially creates a dependency between the Transfer Object that is concerned with serialization and the XML serialization mechanism. If a Transfer Object needs to serialize or deserialize in XML, they can use the appropriate API. However, once we begin including the serialization code inside the Transfer Object then we establish a tight coupling between the application and the serialization mechanism.

Forces

• Transfer Objects (or Value Objects) want XML text serialization in addition to binary serialization.
• Several approaches exist for working with XML such as data binding and document model.
• APIs differ greatly depending on the approach taken to work with XML.
• These APIs are not uniform.
• Transfer Objects typically use proprietary APIs to perform serialization tasks.
• Transfer Objects need to be transparent to the actual approach and API implementation to provide easy migration to other approaches and APIs.

Solution

Use a Data Binding Object (DBO) to abstract and encapsulate working with XML and handle the serialization tasks. The DBO manages working with the XML API to perform serialization and deserialization.

The DBO implements the XML serialization (toXML) and deserialization (fromXML) tasks required to work with the XML API. This API could be a document model approach API such as JDOM, an XML Binding code generated approach such as JAXB, or an XML Binding mapping style approach such as Castor.

The Transfer Object that relies on the DBO uses a simpler DBO interface that is exposed to its clients. The DBO will completely hide the implementation details from its clients since the interface exposed to the clients will not change when the underlying implementation changes. This pattern allows the DBO to adapt to different approaches and APIs without directly effecting the Transfer Object. The DBO is basically an adapter between Transfer Objects that need serialization and the XML API used to perform this serialization.

(People generally haven’t been using UML, I suppose I could provide a link to some in the future)

Structure

A Transfer Object ‘uses’ a Data Binding Object that ‘encapsulates’ an XML Serialization API.

Participants and Responsibilities

Transfer Object: Also known as Value Object. This represents a Transfer Object used as a data carrier. It is the object, that for some useful purpose, we are concerned with serializing in XML text.

Data Binding Object: The primary object in this pattern. Abstracts away the XML serialization approach and API utilized.

XML Serialization API: Represents XML Serialization implementation. This could be JDOM, Castor, JAXB, or a host of others.

Strategies
Factory for Data Binding Objects strategy

I tend to use the Abstract Factory pattern [Gang of Four] to make this pattern extremely sinuous to the application. Create a base DBO factory that is implemented by concrete DBO factories each supporting a different XML Serialization implementation. For example a Transfer Object could obtain a JDOMDBOFactory and use it to obtain the concrete DBO for that object which works with JDOM.

Consequences

• Text serialization transparency: TransferObjects can use the XML serialization API without knowing specific implementation details.
• Easy migration to other APIs.
• Reduces code complexity of Transfer Objects: All XML serialization is handled inside the implementing DBO.
• Text serialization is centralized into another layer. If you’ve worked with some of the more complex serialization APIs you’ll appreciate this.
• Adds extra layer. C’mon this is J2EE we’re in love with layers.

Sample Code

Finally some code… I’ll skip the DBO Factory stuff and assume you are familiar with Abstract Factories.

For our sample we’ll examine a Transfer Object, Customer in Example 1 that wants to serialize itself into XML text. Barely more than a hello world type example, I’ll use some pretty trivial XML and Schema and some barely legal Java.

Example 1

public class Customer implements java.io.Serializable {
// member variables
String name;
//
// getter and setter methods...
...

// performs XML text serialization
public void toXmlString(Writer output) throws DataBindingException {
CustomerDBO dbo
= DBOFactory.getInstance().getCustomerDBO();
dbo.toXmlString(this, output);
}

// perofmrs XML deserialization into Customer object
public static Customer readXmlString(Reader input)
throws DataBindingException {
CustomerDBO dbo
= DBOFactory.getInstance().getCustomerDBO();
return dbo.readXmlString(input);
}
}

Simple sample customer.xml:

<?xml version="1.0" encoding="UTF-8"?>"
"<Customer name="Name"/>

Simple sample customer.xsd (cause we all like schemas):

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="Customer">
<xs:complexType>
<xs:attribute name="name" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
</xs:schema>

The CustomerDBO interface shown in Example 2 defines the XML serialization methods that are implemented by all concrete DBO implementations, such as JDOMCustomerDBO, CastorCustomerDBO, and JAXBCustomerDBO.

Example 2

// interface that all CustomerDBOs must support
public interface CustomerDBO {

public void toXmlString(Customer customer, Writer output)
throws DataBindingException;

public Customer readXmlString(Reader input)
throws DataBindingException;
}

The JDOMCustomerDBO implements the CustomerDBO as shown in Example 3.

Example 3

public class JDOMCustomerDBO implements CustomerDBO {
public void toXmlString(Customer customer, Writer output)
throws DataBindingException {
Element root = toXmlElement(customer);
Document doc = new Document(root);
XMLOutputter writer = new XMLOutputter();
try {
writer.output(doc, output);
} catch (IOException e) {
throw new DataBindingException("Error serializing " +
"customer", e);
}
}

public Customer readXmlString(Reader input)
throws DataBindingException {
try {
SAXBuilder builder = new SAXBuilder(
"org.apache.xerces.parsers.SAXParser", true );
builder.setFeature(
"http://apache.org/xml/features/validation/schema", true );
builder.setProperty(
"http://apache.org/xml/properties/schema/external-schemaLocation",
xsdURL );
Document doc = builder.build(input);
Element root = doc.getRootElement();
Customer result = readXml(root);
return result;
} catch (MalformedURLException mue) {
throw new DataBindingException("Could not get xsd url.", mue);
} catch (IOException ioe) {
throw new DataBindingException("Could not locate xsd.", ioe);
} catch (JDOMException je) {
je.printStackTrace();
throw new DataBindingException("Error deserializing xml.", je);
}
}

private Element toXmlElement(Customer customer) {
Element root = new Element("Customer");
root.setAttribute("name", customer.getName());
return root;
}

private static Customer readXml(Element source) {
Customer result = new Customer();
result.setName(source.getAttributeValue("name"));
}
}

Now let us take a look at an XML data binding mapping style approach using Castor in Example 4. We’ll omit the creation of the map here for simplicity.

Example 4

public class CastorCustomerDBO implements CustomerDBO {
Mapping mapping = new Mapping();

public void toXmlString(Customer customer, Writer output)
// Load the mapping information from the file
mapping.loadMapping( "customer_mapping.xml" );

// Marshal the data
Marshaller marshaller = new Marshaller(output);
marshaller.setMapping(mapping);
marshaller.marshal(customer);
}

public Customer readXmlString(Reader input)
throws DataBindingException {
// Load the mapping information from the file
mapping.loadMapping( "mapping.xml" );

// Unmarshal the data
Unmarshaller unmar = new Unmarshaller(mapping);
Customer customer = (Customer)unmar.unmarshal(new InputSource (input));
return customer;
}

Using the DBO is a snap. You’ll probably most likely do this in some business object. This could be a remote façade of some sort or even a session bean. Example 5 ignores your implementation choice and strictly deals with the code to use the DBO for serialization.

Example 5


String xmlData = null;

public String someMethodToGetXML(Customer customer) {
// serialize the customer and get the XML text.
Writer output = new StringWriter();
customer.toXmlString(output);
xmlData = output.toString();
return xmlData;
}



   Powered by Jute Powerful Forum® Version Jute 1.5.6 Ent
Copyright © 2002-2021 Cjsdn Team. All Righits Reserved. 闽ICP备05005120号-1
客服电话 18559299278    客服信箱 714923@qq.com    客服QQ 714923