Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JAXB / XJC parent-child-parent navigation

Tags:

java

jaxb

xjc

i would like to have bidirectional navigation methods in classes between child object and parent object. IDREF is not enough in my case because I don't want to specify le id of parent. to be clear, from an xsd like that:

<complexType name="A">
    <xs:sequence>
        <element name="b" type="B" minOccurs="0" maxOccurs="unbounded"></element>
    </xs:sequence>
    <attribute name="id" type="ID"></attribute>
</complexType>
<complexType name="B">
    <attribute name="id" type="ID"></attribute>
</complexType>

i would like classes looks like this:

class A {
    ...
    public List<B> getB() { ...}
    ...
   }
class B {
    ...
    public A getA() {
    ...
}

and my xml must looks like this:

<a id="a1">
    <b id="b1"/>
    <b id="b2"/>
    ...
</a>

After unmarshal, I would like to be able to navigate A to Bs AND from B to A (via b.getA()) !! It a very basic feature, but I don't find a simple way to achieve that ...

Any idea ??

Thanks in advance

like image 821
fedevo Avatar asked Jun 14 '11 11:06

fedevo


2 Answers

Note: I'm the EclipseLink JAXB (MOXy) lead, and a member of the JAXB (JSR-222) expert group.

Eclipse JAXB (MOXy) offers the @XmlInverseReference extension to handle this use case. Currently it can not be generated by XJC and must be applied to the domain model directly:

class A {
    ...
    public List<B> getB() { ...}
    ...
   }

class B {
    ...
    @XmlInverseReference(mappedBy="b")
    public A getA() {
    ...
}

For More Information

  • http://bdoughan.blogspot.com/2010/07/jpa-entities-to-xml-bidirectional.html
like image 112
bdoughan Avatar answered Sep 19 '22 17:09

bdoughan


In addition to musiKk answer in case you are using xjc to generate domain model classes from xsd. To add reference to parent class in all model classes you should:

  1. Create base class which extends Unmarshaller.Listener

    public abstract class BaseClass extends Unmarshaller.Listener {
        protected Object parent;
    
        public void afterUnmarshal(Unmarshaller unmarshaller, Object parent)     {
            this.parent = parent;
        }
    
        public Object getParent(){
            return parent;
        }
    }
    
  2. Tell xjc that all model classes should extend your BaseClass by creating global xjc binding configuration

    <jaxb:globalBindings>
        <xjc:superClass name="com.acme.BaseClass" />
    </jaxb:globalBindings>
    
like image 43
swarmshine Avatar answered Sep 21 '22 17:09

swarmshine