6.5 million software developers and still going strong

Java Developer Magazine

Subscribe to Java Developer Magazine: eMailAlertsEmail Alerts newslettersWeekly Newsletters
Get Java Developer Magazine: homepageHomepage mobileMobile rssRSS facebookFacebook twitterTwitter linkedinLinkedIn


Java Developer Authors: APM Blog, Stackify Blog, Pat Romanski, Hollis Tibbetts, Andreas Grabner

Related Topics: Apache Web Server Journal, XML Magazine, Java Developer Magazine

Apache Web Server: Article

The Perfect Database Round-Trip Using JAXB & JDO

The Perfect Database Round-Trip Using JAXB & JDO

Java Data Objects (JDO) enables Java developers to perform database transactions from within Java objects without writing database (SQL)- or JDBC-specific code. Java Architecture for XML Binding (JAXB) and JDO provide great APIs for performing complex XML- and database-oriented tasks. But what about using the two in tandem? This article is about combining these technologies to solve the complex tasks of data access and data persistence.

Java classes can be generated by compiling XML Schemas using JAXB technology. As long as a schema is a well-formed XML document with a definition of simple or complex types, JAXB can generate Java interfaces and classes for each data type defined in the schema. JAXB also provides methods to unmarshall an XML instance document into a Java content object tree. The reverse process is also supported by JAXB. It allows you to marshall the Java content tree back to the XML instance document. This article focuses on the unmarshalling techniques of JAXB.

The JDO API is a standard interface-based Java model abstraction of persistence. Java developers use JDO to store Java objects that hold data (they resemble JavaBeans) into the persistent store (database). When you use JDO, you just need to know Java - no other programming language is required.

This article shows you how to build a simple application that reads customer data from an XML file. We'll deploy JAXB to create a customer Java object model and will also use JDO to store these objects in the database. The example included here uses only the reference implementation released by JavaSoft and its partners.

The JAXB specifications and documentation can be downloaded from http://java.sun.com/xml/jaxb, and JDO specifications and documentation can be downloaded from http://java.sun.com/products/jdo. (You will need the latest version of JDO 1.0.1 to run the example http://access1.sun.com/jdo/private/index.html). Also, the example uses JAXB bundled with the Java Web Services Developer Pack (http://java.sun.com/webservices/downloads/ webservicespack.html). Complete installation steps are explained in the readme.txt.

Why JAXB and JDO?
Although a lot of work must done to explore the use of these two technologies working in tandem, because the JAXB generates Java objects that can be persisted using JDO they seem to complement one another. JDO imposes no constraints on the Java objects in processing them using JDO APIs. They don't need to have any prior knowledge of JDO-specific interfaces (such as PersistenceManager, Transaction, and Extent). Note: Care must be taken to ensure that the data types in the JAXB-generated classes fall within the data types defined by the JDO specification.

JAXB Architecture
JAXB enables developers to achieve a two-way data transformation in a platform-neutral fashion, without having to deal with or even know XML programming techniques. Moreover, developers can take advantage of XML strengths without having to rely on heavyweight, complex XML processing models like SAX or DOM. JAXB hides the details and gets rid of the extraneous relationships in SAX and DOM. From the developer's perspective, only the most useful relationships defined by the source schemas are transformed in the Java object model. The result is highly portable XML data joined with highly portable Java code that can be used to create flexible, lightweight applications. Since the Java object tree is based on the input XML Schema and auto-generated by the JAXB Binding Compiler, the tedious task of mapping XML elements to Java objects is completely automated and remains error free. Typically, developers have relied on standard programming techniques such as the Data Access Object (DAO) pattern to access data from the databases or XML instance documents. The development and the maintenance phases of the project where the schemas tend to change require minimal programming effort to keep up with the changes.

JDO Architecture
The two main goals of the JDO architecture are to provide developers with a transparent, Java-centric view of persistent information, such as enterprise data and locally stored data, and to enable pluggable implementations of data stores in application servers. The data stored in data stores is presented as instances of the persistence-capable classes. Such data objects are generally represented with getter and setter methods, although JDO doesn't enforce the existence of such methods in the data objects, and the properties defined in the data objects can be declared as private. I found an excellent read on JDO - Java Data Objects by David Jordan and Craig Russell (www.oreilly.com/catalog/jvadtaobj). I recommend that you go through at least the first three chapters of this book before deploying JDO. There are various other techniques, such as direct file I/O, serialization, JDBC, and Enterprise JavaBeans (EJB), to persist data but benefits such as portability (JDO is as portable as Java), database independence, ease of use (no need to worry about field-by-field storage of objects), and high performance make a compelling case for JDO.

Figure 1 shows specific components of JAXB and JDO used in building the example.

The process of transforming XML data into content object trees and persisting content objects in the database can be divided into roughly four steps:
1. Compile schema to generate Java classes (JAXB task)
2. Enhance classes (JDO task)
3. Build content objects (JAXB task)
4. Persist content objects (JDO task)

Compile schema
When a schema is compiled to generate Java classes, JAXB generates interfaces for global elements and complex types. For details on how JAXB generates interfaces for complex types and complex types that use other complex types, see the user guide included with the JAXB distribution package. JAXB also generates concrete implementation of the interfaces it generates for the complex types. JAXB does not promote direct instantiation of such classes; rather, it provides an ObjectFactory to get instances of these classes.

Enhance classes
Before a JDO persistence manager can process any of the content classes, the classes must be enhanced. Enhancement of a class is a unique step required by the JDO. It processes the class files (overwrites) and adds JDO-specific code to them (you can explore what is modified by the enhancer by reading the log included in readme.txt). The JDO reference implementation comes with the Enhancer com.sun.jdori.enhancer. Main, which reads JDO metadata for each class that must be run within the JDO environment. In our architecture, this step is a main connection between JAXB and JDO.

Build content objects
Generally, when JAXB is used independently, content objects can be built using JAXB-generated implementations of interfaces. This step is also called "unmarshalling." When you need to process these classes using JDO, you use the class files that are enhanced in the previous step. To build the content tree, first create a new instance of JAXBContext by providing a contextPath parameter that contains a list of Java package names that contain schema-derived interfaces, specifically the interfaces generated by the JAXBbinding compiler (in this case it is just the "customer"), then create an unmarshaller using JAXBContext; finally, you get a root content object (based on the XML tree) using the unmarshaller by passing it an input instance XML document. After that, you can simply navigate the content object tree using various accessor methods.

Persist content objects
There are various architectures proposed by JDO to persist content objects in the data store (please refer to the previously mentioned book on JDO). The example presented here uses the simplest model for using single PersistenceManager. To be able to persist content objects, you also need to build the JDO-aware classes that make direct use of the JDO API, generally called transient classes. In our example, DBManager, CreateCustomer, and PrintCustomer are JDO-aware classes. On the other hand, CustomerTypeImpl is a JDO-transparent class that makes no direct references to the JDO API. That's where JDO is much more powerful than other technologies such as JDBC.

This discussion can be a bit overwhelming initially, but once you work through the example code it should be much easier to comprehend. The example will show you that most of the code is generated using JAXB and JDO and not much is being built manually.

Example
Let's take a look at a very simple application based on the above architecture. We start with customer information presented in an XML file. An associated schema is also built for the XML data file to be able to generate the class files. From this point on we really don't have to build any Java code to represent the data in a Java content object tree. The only code we'll build will process these objects to store them in the database and fetch them from the database. JDO-aware classes will be used to perform these operations.

The example comprises the following files (code listings can be found at www.sys-con.com/xml/sourcec.cfm):

  • Customer schema (see Listing 1)
  • Customer XML data file (see Listing 2)
  • JDO properties file - database definition (see Listing 3)
  • JDO metadata file - class and package definition (see Listing 4)
  • JDO-aware classes (see Listings 5 and 6)
  • Main class (see Listing 7)

    Using the schema as described in Listing 1, the JAXB compiler generates the packages "customer" and "customer.impl." The root package name can be different than "customer" as it can be passed to the XJC compiler. Please see the "build.xml" Ant build file for details. Among all the generated interfaces and classes, we're most interested in CustomerTypeImpl class, not the CustomerType class. This is very important! We must not include the class generated based on the document root element. Only the classes generated based on the data types must be included when enhancing classes using JDO enhancer.

    The example makes use of the file-based data store included in the reference implementation (JDORI). The directory "database" must exist before you try to initialize the database using the InitDatabase class.

    The metadata in Listing 4 has a definition for just one class to be enhanced. The metadata can be defined on a class or package basis and in one or more XML files. These files must have a .jdo suffix. For more efficient mapping declare the element type for each collection in the model.

    The first four lines in the Main class (see Listing 7) are JAXB-related. We create the JAXBContext and then obtain an unmarshaller. Using the unmarshaller, we create an instance of root element Customer, which is used to navigate the tree to display the customer information. The rest of the lines in this class are JDO-related. The objects obtained by navigating the root class tree cannot be used to pass to the JDO-aware classes for persistence since they're not the enhanced classes. The only class we enhanced is the CustomerTypeImpl class. JAXB does not recommend creating a direct instance of the generated *Impl classes; instead, it provides an ObjectFactory class to create instances of these classes. Once we create an instance of CustomerTypeImpl class, we can copy data from the content tree to the instance of CustomerTypeImpl and then pass it to the CreateCustomer class, where we invoke a makePersistent() method to save it in the database. This example also includes a utility class, PrintCustomer, that fetches customer information from the database and prints it.

    Running the Application
    The example includes a simple Ant build file to run the complete application. Please run it in the following order:

  • ant compileSchema: Generates Java interfaces and classes from the schema.
  • ant compileSource: Compiles all Java classes, including the the above classes.
  • ant genDocs: Generates Javadocs for all the classes.
  • ant enhance: Enhances specific Java classes as defined in the JDO metadata file.
  • ant initDb: Creates a sample database.
  • ant run: Runs the Main class. Prints XML info, saves it in the database, and then fetches the same information from the database and prints it again.

    Please follow the instructions in the readme.txt before building and running the application.

    As you can see, the only programming effort needed for building the application is creating the JDO-aware classes. Moreover, those classes do not contain any SQL- or JDBC-specific code. The only language you need to know is Java! This example is tested using only the JDO reference implementation. A very simplistic persistence capability has been achieved and more complex data elements must be tested before you decide to deploy such an architecture in your project. Nonetheless, the idea of combining JAXB and JDO technologies is quite promising.

    Conclusion
    Although JAXB and JDO technologies are relatively new, they solve a great deal of problems in a uniform programming model confined to just one programming language - Java. These two technologies complement each other and reduce the amount of programming effort needed.

    Resources

  • Code for this article: www.sys-con.com/xml/sourcec.cfm
  • JAXB: http://java.sun.com/xml/jaxb/
  • JWSDP-1.2: http://java.sun.com/webservices/webservicespack.html
  • JDO 1.0.0: http://java.sun.com/products/jdo/
  • JDO 1.0.1: http://access1.sun.com/jdo/private/index.html
  • JTA (Java Transaction API): http://java.sun.com/products/jta/
  • Antlr for JDOQL: www.antlr.org
  • Xerces Parser: http://xml.apache.org/xerces-j
  • Java Data Objects (O'Reilly): www.oreilly.com/catalog/jvadtaobj/
  • More Stories By Rajesh Zade

    Rajesh Zade has more than 13 years of experience in the computing field and has been working in various Java and e-Commerce technologies since 1996. He is currently chief technical architect for NetCliff, Inc., based in Santa Clara, CA.

    Comments (6) View Comments

    Share your thoughts on this story.

    Add your comment
    You must be signed in to add a comment. Sign-in | Register

    In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.


    Most Recent Comments
    Ivano 10/29/03 07:18:44 AM EST

    I have a feeling that perhaps the castor xml binding could integrate with castor jdo implementation with less problem that the JAXB.
    Have you tried it?

    Rajesh Zade 09/11/03 01:51:31 PM EDT

    Ives Landrieu,

    My main ojective behind writing this article was to drive more minds in the direction of combining these two technologies. This article does demonstrates that this can be done (with examples) albiet with some limitations. The very fact that the JAXB generated classes can be fed in as input to JDO is quite promising. Imagine when you can export database tables to XML, unmarshall to Java Object Trees and persist using JDO - without any limitations! That would be nice.

    But this is certainly a step in the right direction.

    Ives Landrieu 09/11/03 09:40:08 AM EDT

    Hi,

    I have been playing with the combination JAXB and JDO a couple of weeks ago too, and the author forgets to mention one big thing: you cannot easily persist relationships. The JAXB classes use a custom list implementation for relationships (e.g. an Order class with LineItems would store them in such a list), and most JDO implementations will not know how to handle this custom List implementation because they only support plain ArrayList or LinkedList (support for other List implementations is a very optional feature I believe).

    I did file this in the bug database on the website of Sun, and it is currently a RFE for which you can vote:

    http://developer.java.sun.com/developer/bugParade/bugs/4897443.html

    Ives Landrieu

    Ives Landrieu 09/11/03 09:37:56 AM EDT

    Hi,

    I have been playing with the combination JAXB and JDO a couple of weeks ago too, and the author forgets to mention one big thing: you cannot easily persist relationships. The JAXB classes use a custom list implementation for relationships (e.g. an Order class with LineItems would store them in such a list), and most JDO implementations will not know how to handle this custom List implementation because they only support plain ArrayList or LinkedList (support for other List implementations is a very optional feature I believe).

    I did file this in the bug database on the website of Sun, and it is currently a RFE for which you can vote:

    http://developer.java.sun.com/developer/bugParade/bugs/4897443.html

    Ives Landrieu

    Ives Landrieu 09/11/03 09:37:29 AM EDT

    Hi,

    I have been playing with the combination JAXB and JDO a couple of weeks ago too, and the author forgets to mention one big thing: you cannot easily persist relationships. The JAXB classes use a custom list implementation for relationships (e.g. an Order class with LineItems would store them in such a list), and most JDO implementations will not know how to handle this custom List implementation because they only support plain ArrayList or LinkedList (support for other List implementations is a very optional feature I believe).

    I did file this in the bug database on the website of Sun, and it is currently a RFE for which you can vote:

    http://developer.java.sun.com/developer/bugParade/bugs/4897443.html

    Ives Landrieu

    Ives Landrieu 09/11/03 09:33:38 AM EDT

    Hi,

    I have been playing with the combination JAXB and JDO a couple of weeks ago too, and the author forgets to mention one big thing: you cannot easily persist relationships. The JAXB classes use a custom list implementation for relationships (e.g. an Order class with LineItems would store them in such a list), and most JDO implementations will not know how to handle this custom List implementation because they only support plain ArrayList or LinkedList (support for other List implementations is a very optional feature I believe).

    I did file this in the bug database on the website of Sun, and it is currently a RFE for which you can vote:

    http://developer.java.sun.com/developer/bugParade/bugs/4897443.html

    Ives Landrieu