users@jaxb.java.net

Re: Using existing classes

From: Dmitri Colebatch <dim_at_colebatch.com>
Date: Tue, 28 Aug 2007 11:43:04 +1000

Hi Gary,

In general, what I like the idea of (and this isn't always easy to do)
is a class like this:

@Entity
@XmlRootElement
class Widget
{
  @Id
  @XmlTransient
  int id;

  @XmlElement
  @Column
  String name;

  @OneToMany(cascade = CascadeType.ALL, fetch=FetchType.LAZY)
  @JoinColumn(name="order_id", referencedColumnName = "id")
  @OrderBy("id")
  @XmlElementWrapper(name="Parts")
  @XmlElement(name="Part")
  List<Part> parts;

  void someBusinessMethod() { ... }
}

This gives three things:
1. O/R mapping using EJB3 annotations
2. O/XML mapping using JAXB
3. Business logic.

I dare say there are many arguments against this, but I think it gives
a nice set of benefits.

My real downside is that the JAXB design assumes that the object class
hierarchy is the same as the XSD hierarchy. EJB3 annotations have
their own set of restrictions as well... as a result this is only
really usable for greenfield development unless you're really lucky.

One of my main gripes on this approach is that it isn't possible
(afaik) to change the order of elements defined in a superclass. Eg,
I cant have this:

class PricedWidget extends Widget
{
  @Column
  @Element
  BigDecimal price;
}

and get XML like this:

<widget>
  <name>box</name>
  <price>13.99</price>
  <parts>
    <part> ... </part>
  </parts>
</widget>

There are many "errors" in the above example, but I hope it conveys
the problem. XML Schema doesn't let a subtype insert elements to a
sequence, you can only add to the end of the sequence. Thus instead
of the above you get:

<widget>
  <name>box</name>
  <parts>
    <part> ... </part>
  </parts>
  <price>13.99</price>
</widget>

Which irks me... Does anyone have any suggestions for how to best get
the price before parts? Obviously in this simple example it doesn't
matter, but in more complex scenarios it does matter.

cheers,
dim



On 8/28/07, Greg Scott <gptscott_at_googlemail.com> wrote:
>
>
> Hello,
>
>
>
> I have been searching the JAXB documentation for a discussion of a
> design-related problem I have with JAXB and incorporating it into an design
> (set of classes and interfaces). Reassuringly, I found this posting from
> this mailing list which almost completely captured my exact same problem (I
> have pasted it below):
> https://jaxb.dev.java.net/servlets/ReadMsg?listName=users&msgNo=150
>
>
>
> I noticed this was from 2002! Given the old age of this posting, could I
> raise this issue again, in the hope that, with the newer versions of JAXB or
> different thinking, someone could offer a better way around this problem
> than that suggested in (1).
>
>
>
> Many thanks for any advice.
>
>
>
> Greg Scott
>
>
>
>
>
>
>
>
>
> Date: Tue, 24 Dec 2002 11:39:00 -0500
>
> From: Gary Gregory <ggregory_at_seagullsw.com >
>
> Subject: Using existing classes
>
> Content-type: multipart/alternative;
>
> boundary="Boundary_(ID_58uuYtbp6qs51bz0CUtMnw)"
>
>
>
> 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