Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@XmlInverseReference annotation not working

i found similar questions, but none of answers helped me.

So, i have 2 objects with a back-pointer relationship. Parent :

@XmlRootElement
public class A {

    private B b;

    @XmlElement(name = "Element B")
    public B getB() {
        return b;
    }

    public void setB(B b) {
        this.b = b;
    }

}

and B :

@XmlRootElement
public class B {

    private A a;

    @XmlInverseReference(mappedBy = "b")
    public A getA() {
        return a;
    }

    public void setA(A a) {
        this.a = a;
    }

}

I've put the jaxb.properties in the same package as models. (javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory)

And after this snippet :

A a = new A();
a.setB(new B());
a.getB().setA(a);

Json representation of "a" is cyclic "see below" :

{"Element B":{"a":{"Element B":{"a":{"Element B":{"a":{"Element B":{"a":{"Element B":{"a":{"Element B":{"a":{"Element B":{"a":{"Element B":{"a":{"Element B":{"a":{".........

and the stacktrace is also cyclic :

at org.codehaus.jackson.map.ser.BeanSerializer.serializeFields(BeanSerializer.java:245) at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:212) at org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:428) at org.codehaus.jackson.map.ser.BeanSerializer.serializeFields(BeanSerializer.java:245) at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:212) at org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:428) at org.codehaus.jackson.map.ser.BeanSerializer.serializeFields(BeanSerializer.java:245)

i quess that i've not corectly added MOXy extension to my project...(a just added to project eclipselink.jar)

like image 763
Eugen Halca Avatar asked Jun 02 '26 14:06

Eugen Halca


1 Answers

The following should help:

DEMO CODE

Your mappings are correct. You can verify this with the following demo code.

package forum14031963;

import java.util.*;
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.JAXBContextProperties;

public class Demo {

    public static void main(String[] args) throws Exception {
        Map<String, Object> properties = new HashMap<String, Object>(2);
        properties.put(JAXBContextProperties.MEDIA_TYPE, "application/json");
        properties.put(JAXBContextProperties.JSON_INCLUDE_ROOT, false);
        JAXBContext jc = JAXBContext.newInstance(new Class[] {A.class}, properties);

        A a = new A();
        a.setB(new B());
        a.getB().setA(a);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(a, System.out);
    }

}

OUTPUT

Below is the output fro running the demo code.

{
   "Element B" : {
   }
}

JAVA MODEL

In your example the @XmlRootElement annotations are not required and I have removed them. The demo code will also work the same way if they are there.

A

package forum14031963;

import javax.xml.bind.annotation.XmlElement;

public class A {

    private B b;

    @XmlElement(name = "Element B")
    public B getB() {
        return b;
    }

    public void setB(B b) {
        this.b = b;
    }

}

B

package forum14031963;

import org.eclipse.persistence.oxm.annotations.XmlInverseReference;

public class B {

    private A a;

    @XmlInverseReference(mappedBy = "b")
    public A getA() {
        return a;
    }

    public void setA(A a) {
        this.a = a;
    }

}

jaxb.properties

To specify MOXy as your JAXB provider you need to include a file called jaxb.properties in the same package as your domain model with the following entry (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html).

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

JAX-RS

If you are using JAX-RS, in your current configuration Jackson is being picked up as the JSON provider. The easiest way to get MOXy as your JSON provider is to use the MOXyJsonProvider class.

package org.example;

import java.util.*;
import javax.ws.rs.core.Application;
import org.eclipse.persistence.jaxb.rs.MOXyJsonProvider;

public class CustomerApplication  extends Application {

    @Override
    public Set<Class<?>> getClasses() {
        HashSet<Class<?>> set = new HashSet<Class<?>>(2);
        set.add(MOXyJsonProvider.class);
        set.add(CustomerService.class);
        return set;
    }

}

For More Information

  • http://blog.bdoughan.com/2011/08/json-binding-with-eclipselink-moxy.html
  • http://blog.bdoughan.com/2012/05/moxy-as-your-jax-rs-json-provider.html
  • http://blog.bdoughan.com/2010/07/jpa-entities-to-xml-bidirectional.html
like image 64
bdoughan Avatar answered Jun 04 '26 11:06

bdoughan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!