users@jaxb.java.net

Re: Mixing custom/manual marshalling with JAXB

From: Kohsuke Kawaguchi <Kohsuke.Kawaguchi_at_Sun.COM>
Date: Tue, 11 Jul 2006 12:55:58 -0700

I wonder if you can adapt your DataObject class to DOM element by using
XmlJavaTypeAdapter.

Nick Minutello wrote:
> Hi, thanks Dim.
>
> I will explain it as briefly and clearly as I can :-)
>
> (I have had an attempt at doing that previously, here
> http://forums.java.net/jive/thread.jspa?threadID=16615&tstart=0 so feel
> free to use that as further info)
>
> The business problem at hand is that we want people to be able to define
> some metadata in some storage somewhere (they would create a meta-model
> of concepts, their properties & relationships to each other). From this
> metamodel, an xml schema representation could be generated dynamically.
> We want people to be able to send/receive XML conforming to that xml
> schema to/from the server - but we don't want to have to change anything
> on the server. The server has a generic data object it works with - and
> the xml would get marshalled into and out of that.
>
> Basically, at a technical level, my problem is this:
> I have a bunch of classes that I want to map using JAXB - and I can do
> that fine.
>
> But I have 1 class where the class and the XML are going to be very very
> different.
> The class is called DataObject which is just a property bag and some
> Type information (The type information/metadata tells it what
> properties it can have (property name and property type - where one of
> the property types might be DataObject)
> But basically you can think about it as a Map of Maps.
>
> The thing is I don't want the DataObject graph to look like a map of
> maps when its serialised to XML.
> I want it to be readable. I want the xml to look like the domain
> concepts defined in the metamodel.
>
> So, imagine I have the following code to create a small DataObject
> graph:
>
> =====================
> // defining the metadata (in my case its stored somewhere centrally)
> Type personType = new Type("Person");
> personType.addProperty("name", Type.STRING);
>
> Type petType = new Type("Cat")
> petType.addProperty("weight", Type.DECIMAL);
> petType.addProperty("name", Type.STRING);
> petType.addProperty("owner", personType);
>
> // now create some instances
> DataObject john = new DataObject(personType, new Guid())
> john.setProperty("name", "John");
>
> DataObject sooty= new DataObject(petType, new Guid());
> sooty.setProperty("weight", 5.5);
> sooty.setProperty("name", "sooty");
> sooty.setProperty("owner", john)
> =====================
>
> I want sooty to look like this as XML:
>
> <pet xsi:type="Cat" name="sooty" weight="5.5" guid="32l2-k3-43j...">
> <owner xsi:type="Person" name="John" />
> </pet>
>
> And you can imagine for Fluffy, its like this:
> <pet xsi:type="Cat" name="fluffy" weight="15.5" guid="2433-sd9-243...">
> <owner xsi:type="Person" name="Billy" />
> </pet>
>
> So, you see the XML looks like it would come from a classes like this:
> class Person {
> String name;
> }
> class Cat {
> String name;
> Double weight;
> Person owner;
> }
>
> But these classes don't ever exist.
> Effectively, we want to map a bunch of different schema complexType's to
> one generic DataObject.
> We want people to be able to add a new concept to the metamodel - and
> the server handle it with no code change.
> The metadata (which would come from some storage) would tell us:
> A) what the xml schema would effectively look like (so clients know what
> to send/receive)
> B) how the server marshals conforming XML to/from our generic DataObject
> graph
>
> So, all the other static classes (like Type & Property, the
> ActionCommand's and their Envelopes, etc - a bunch of other stuff) I can
> map with JAXB no problem. However, its not clear to me if (let alone
> how) I can get JAXB to do the Marshalling/unmarshalling of DataObject
> to/from readable XML like you see above.
>
> What I *don't* want is XML that looks like this:
>
> <dataobject guid="2433-sd9-243..." doType="Cat" >
> <property name="name" xsi:type="xs:string" value="fluffy" />
> <property name="weight" xsi:type="xs:double" value="15.5" />
> <property name="owner" doType="Person">
> <dataobject guid="2433-sd9-243..." doType="Person" >
> <property name="name" xsi:type="xs:string" value="Billy" />
> </dataobject>
> </property>
> </dataobject>
>
> The XML schema in this case would tell me nothing about the domain.
>
> So, if indeed its not possible to get JAXB to do the marshalling &
> unmarshalling, I need to find a way I can get JAXB to delegate the
> marshalling/unmarshalling to me whenever it hits a DataObject.
>
> Can I do this? Does this mechanism exist?
> I think I can use a SAX Filter to switch unmarshalling delegation
> between JAXB and my own custom SAX DatObject unmarshaller.
> I don't see a way I can plug into JAXB's marshalling though.
>
> I thought I could be cunning and use an XmlJavaTypeAdapter to convert
> between DataObject and String - but of course it escapes the String
> contents - so marshalling my DataObject into an xml string wasn't the
> droid I was looking for...


-- 
Kohsuke Kawaguchi
Sun Microsystems                   kohsuke.kawaguchi_at_sun.com