users@jaxb.java.net

Getting JAXB to instanciate your subclasses

From: David Halonen <david.halonen_at_compuware.com>
Date: Wed, 26 Mar 2003 09:47:31 -0700

We have a somewhat complex tree of objects that includes data that needs to be persisted to XML and user interface data that is needed for proper presentation.

The hope is to use JAXB to persist the non-UI data to an XML stream, but while unmarshalling the UI fields are set. One alternative would be to simply walk the tree once its done, but that's percieved as being especially difficult.

At any rate, I have found a possible solution and would like to have a critical review.

Assume one schema and using the vendor specfic extension such that all generated implementation classes derive from one base class. This class needs a name, DataModelBase. Lets give DataModelBase the methods setParent( Object obj ) & setIcon( ImageIcon icn ).

Use the JAXB RI Vendor Extension to extend all JAXB implementation classes from DataModelBase. Runing the xjc jar, we get the JAXB interface & implementation classes.

Assume we have an XML element CONNECTION that maps to the JAXB Connection & ConnectionImpl classes. We need a class that extends ConnectionImpl, so we'll call it OurConnection class. It does all sorts of wonderful things, including everything in DataModelBase and ConnectionImpl. The question is, then how to get JAXB to return OurConnection class when unmarshalling an XML stream?

Its actually very easy. Simply go back to your original schema document and use the Class Binding Declarations. Include <class implClass="OurConnection"> and re-run xjc. All marshalling & unmarshalling code will now work w/ OurConnection class.

  +---------------------+
       DataModelBase
  +---------------------+
            /\
           / \
           ----
            |
            |
  +---------------------+
       ConnectionImpl
  +---------------------+
            /\
           / \
           ----
            |
            |
  +---------------------+
       OurConnection
  +---------------------+

In summary, xjc needs to be run twice: once to generate the standard JAXB classes and a second time to tweak the context and/or generated code to build the correct objects. The <class implClass="foo"> will get commented out and un-commmented via Perl or perhaps even Java. This can all handled with an Ant script.

  1. xjc w/ implClass commented out in schema
  2. script to uncomment implClass
  3. xjc schema
  4. script to comment implClass

This does work, by the way. I can get the unmarshaller to return OurConnection from XML, which is kinda useful. I've just started to test it out, so issues may abound.

At any rate, what do you think of this bright idea?

How fragile is this from the perspective that the next release of JAXB will have me crying in my milk?

What gotcha's do I have to worry about as far as marshalling/unmarshalling fields? ie, if OurConnection has a field named _mySpecialField that is not in the XML will it cause problems?

Regards,
David Halonen
Compuware
248.737.7300 ext 13578