Gary, Thanks for sharing your experiences and thoughts.
I must not have been clear in my original post, that using inheritance to obtain JAXB benefits was pretty much out of the question. My hierarchies reflect my own detailed model, and I also considered the composite approach you ended up going with. I can live with a class that forwards a couple of method sends to a contained object, but more than that, and I start feeling ill.
When I made the reference to serialization, that really is the model I would like to see. By following a "contract" you can make sure that any object you create can be serialized. Many products have demonstrated that you can marshal and unmarshal virtually any object to and from XML generically given certain assumptions. If specialized classes must be generated for performance reasons, then let any class that wants to use JAXB, use this generated class to do that.
My need to have eighty percent of my objects unmarshaled repetitively may be unique today, but I see it become very common soon.
Leon
*********** REPLY SEPARATOR ***********
On 12/24/2002 at 11:39 AM Gary Gregory wrote:
We have been dealing with the same situation here. I will just share our current solution and thoughts (=ramblings). There are two main issues I think: (1) Integrating JAXB generated code and (2) Deciding on a per app basis what JAXB means to you.
(1) Clearly, being able to generate the JAXB model classes as a subclasses of custom classes would be quite practical at first. You would end up with, for example, a Customer class and an XMLCustomer subclass, where the latter was generated by JAXB. But, is this a proper use of inheritance? Do you really want "an XML kind of customer"? It seems (to me) that this looks too heavyweight of an architecture and also very brittle. You could end up with one XML subclass for every single class in your app model, possibly spread over many packages. In a general sense, adopting such an architecture would mean that for every encoding (XML, JDBC, or whatever) of such a model class would require a new subclass. Certainly, after a couple of encoding implementation, you would end up refactoring common behavior into... what? A CustomerMarshaller subclass which in turn has an XMLCustomer subclass? Nah... I claim that this is situation calls for composition, not inheritance. The Customer class can have an instance variable that holds on to it's "binding", the JAXB generated object. You can also add an "adaptor" layer to shield the model class from any changes to the underlying binding. This does not 'feel' like to best solution.
(2) The more general issue I have with JAXB can be subdivided into two areas: (a) Where do you start and (b) How much do you put into the XML Schema. I threw away a lot of my implementation when I ported our still-in-development app from object-based unit test fixtures to XML data file based unit test fixtures. Why? When you start with JAXB, you start with XML Schema. When you unmarshall, an XML data file with JAXB, you get a custom object tree based on the classes defined by the XML Schema. What did I have before? I already had a custom object tree in my unit tests. I already had a app model set of classes. Now I had both. What feels like a step back with JAXB is that the generated code defines state only. The app model I had contained both state and behavior of course, like in any decent OO design. But, to make things more complicated, the JAXB generated code does not have to be stateless, strictly speaking. XML Schema is pretty powerful stuff, and since you can specify all manners of restrictions and data validation on the data contained in attributes and elements, these specification do get translated into code. There can be (optionally), some amount of clever behavior in the JAXB model code. You can get behavior like data validation in your JAXB model classes. Now, I have two big conceptual piles: JAXB model class with some state and some behavior plus my app model with all of the state and all of the behavior. (I would say that most apps would have additional transient state in their model that do not get externalized.) Assuming that avoiding duplication is not acceptable, what to do?
For good or bad, here is what we did:
Start with XML-Schema. This forced us to decide what should really be persisted in the first place.
Use JAXB to generate code into a com.company.component.bind package. Since the general category of code generated belongs in the "XML data binding" category, we felt "bind" was a good name. The "bind" packages contains only JAXB generated code. Create a class called com.company.component.Bindings that hides JAXB details and provide type safe methods like unmarshalCustomer. A root model class is in com.company.component like com.company.component.Customer. Customer has an ivar called customerBinding (we postfix JAXB generated class names with "Binding"). Customer delegate to the binding getters and setters. Anything that requires binding data structure traversal is done in the Bindindgs class.
I am not 100% satisfied with this arrangement but I like delegating to a binding class instead of using inheritance as a hack to get my behavior for "free". Inheritance does not feel right to me: what if I want to save a Customer to a database? Do I have to create a JDBCCustomer subclass of... Customer? Not of XMLCustomer. But I have instances of XMLCustomer flying around my app... What if I had a "clean" Customer with all state and behavior, then I would just instantiate my XML or JDBS subclass just-in-time for that encoding/decoding task. But then I would need marshalling code to/from the XML/JDBC subclass, which seems to be redundant with what happens in JAXB already. Using an encoding subclass in a just-in-time manner also means that your app would not catch validation error until the last second, unless you where to duplicate code, which is not acceptable to me (in a perfect world). If the case of an app with a UI, if the model is backed by a binding object, you would be able the give feedback right away when an error is detected in data validation.
JAXB poses some interesting design issues and I wish Sun would at least talk about them in the JAXB docs/specs. BTW, I did not even mention subclassing the JAXB generated code which I consider would create the most brittle code and would be nasty. I think of all JAXB generated code as private to the "Bindings" helper class. Clearly, there has to be a better way, ot at least a cleaner way.
Gary
-----Original Message-----
From: Leon Smith [mailto:leon2000_at_pacbell.net]
Sent: Monday, December 23, 2002 2:44 PM
To: JAXB-INTEREST_at_JAVA.SUN.COM
Subject: Using existing classes
Sorry for the last HTML post, my email client is screwy:
Hello, I have been creating an application server for the past two years in which each of many classes gets loaded from an XML file. I am switching from my own proprietary binding scheme for performance reasons. My benchmark programs show JAXB to be very acceptable in terms of speed (roughly twice as fast as Castor for example), but I am a little mystified about the requirement to generate new classes from the schema.
Isn't this like requiring new classes for serialization ? Unmarshalling from XML is just one tiny part of the functionality of these classes. Wouldn't it make more sense to generate "helper" classes and pass a "target" class as an argument for unmarshalling ?
How do most people actually make this work in practice ? I have complex hierarchies established so I really can't subclass from the implementation classes, plus I don't see how to unmarshall into a subclass anyway.
If I add my behavior to the generated classes, I don't see that it will be preserved if I have to change the schema and generate again.
I really want to use JAXB, but right now I am at a loss for how I could. Any suggestiions would be very much appreciated.
Thanks
Leona