Question

A java application I am working on has objects with a relationship similar to below. In the real application both objects are JPA entities.


class Underlying{}

class Thing
{
  private Underlying underlying;

  public Underlying getUnderlying()
  {
    return underlying;
  }

  public void setUnderlying(final Underlying underlying)
  {
    this.underlying = underlying;
  }
}

There is a requirement in the application to create xml of the form:

<template>
     <underlying>
        <thing/>
        <thing/>
        <thing/>
     </underlying>
</template>

So we have a situation where the object graph expresses the relationship between Thing and Underlying in the opposite direction to how it's expressed in the xml.

I expect to use JAXB to create the xml but ideally I don't want to have to create a new object hierarchy to reflect the associations in the xml. Is there any way to create xml of the form required from the entities in their current form (through the use of xml annotations or something)? I don't have any experience using JAXB but from the limited research I've done it doesn't seem like it's possible to reverse the direction of association in any straightforward way. Any help/advice would be greatly appreciated. One other option that has been suggested is to use XLST to transform the xml into the correct format. I have done no research on this topic as yet but I'll add to the question when I have some more info.

Thanks,

Matt.

Was it helpful?

Solution

The trick is making a instance of Underlying aware of the related instances of Thing. Below are a couple approaches you could leverate.

Option #1 - Make the Relationship Bidirectional

The easiest thing to do would be to make the relationship bidirectional. Then you could leverage the @XmlInverseReference extension in EclipseLink JAXB (MOXy). Note: I'm the MOXy tech lead:

Option #2 - Use an XmlAdapter

You could create an adapted version of Underlying. When building the adapted Underlying object the XmlAdapter could query the instances of Thing to populate the things property:

OTHER TIPS

JAXB may not the right approach in your case. JAXB is best when you need to round-trip the object model to XML and back, and you've got some latitude either with the XML or the object model. In this case, you seem to have no latitude. No JAXB for you, IMHO.

That's a non-trivial number of XML elements, too, considering you'll be sorting them somewhere. Probably on the expensive side to have the whole graph and a sorted copy in memory? So you'll want to fetch the Things from the JPA datastore ordered by Underlying (let the database do the sorting), and stream this to a javax.xml.stream.XMLStreamWriter for output.

On the input side, use a javax.xml.stream.XMLStreamReader.

Struggling with a similar issue, I just came across an additional possibility:

  • Add the parent reference property to your JAXB annotated classes
  • Annotate the property with @XmlTransient
  • Implement the method public void afterUnmarshal(Unmarshaller u, Object parent)
  • Implement the logic to set the parent pointer in this method like this: this.parent= (ParentType) parent; Of course you can to more stuff in that method.

The method is called by JAXB after unmarshalling, as the name implies.

References: (Rather old) discussion on forums.java.net, JAXB Guide

I cannot use @XmlInverseReference since we are using a different JAXB implementation than MOXy. While I came to appreciate @XmlAdapter, I find this approach simpler as it does not require additional classes.

While this does not match your problem description completely, I still think this could help future readers.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top