Caused by: javax.xml.bind.MarshalException
- with linked exception:
[com.sun.istack.SAXException2: A cycle is detected in the object graph. This will cause infinitely deep XML: org.test.data.Business[id=1] -> org.test.data.BusinessType[id=1] -> org.test.data.Business[id=1]]
at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:269)
at com.sun.xml.bind.v2.runtime.BridgeImpl.marshal(BridgeImpl.java:100)
at com.sun.xml.bind.api.Bridge.marshal(Bridge.java:141)
at com.sun.xml.ws.message.jaxb.JAXBMessage.writePayloadTo(JAXBMessage.java:317)
... 35 more
Caused by: com.sun.istack.SAXException2: A cycle is detected in the object graph. This will cause infinitely deep XML: org.test.data.Business[id=1] -> org.test.data.BusinessType[id=1] -> org.test.data.Business[id=1]
at com.sun.xml.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:248)
at com.sun.xml.bind.v2.runtime.XMLSerializer.pushObject(XMLSerializer.java:537)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:631)
at com.sun.xml.bind.v2.runtime.property.ArrayElementNodeProperty.serializeItem(ArrayElementNodeProperty.java:65)
at com.sun.xml.bind.v2.runtime.property.ArrayElementProperty.serializeListBody(ArrayElementProperty.java:168)
at com.sun.xml.bind.v2.runtime.property.ArrayERProperty.serializeBody(ArrayERProperty.java:155)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:340)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:696)
at com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:152)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:340)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:696)
at com.sun.xml.bind.v2.runtime.property.ArrayElementNodeProperty.serializeItem(ArrayElementNodeProperty.java:65)
at com.sun.xml.bind.v2.runtime.property.ArrayElementProperty.serializeListBody(ArrayElementProperty.java:168)
at com.sun.xml.bind.v2.runtime.property.ArrayERProperty.serializeBody(ArrayERProperty.java:155)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:340)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:696)
at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:264)
... 38 more
To this error above you can found solutions saying to use this interface:
- com.sun.xml.internal.bind.CycleRecoverable
NetBeans recognize this package and not mark like an error. But on compile time this package does not exist to compiler side. Perhaps you will receive this error when compiles:
/home/eduveks/project/wstest/src/org/test/data/Business.java:8: package com.sun.xml.internal.bind does not exist
import com.sun.xml.internal.bind.CycleRecoverable;
On my view this error is a bug of NetBeans that recognizes this package when isn't a valid package to Java compiler. To test this bug you only need put this "import com.sun.xml.internal.bind.CycleRecoverable;" into any Java file and you will see that NetBeans don't says nothing and accept as well, but if you "Clean and Build" the error will show up.
The correct package is (without .internal):
import com.sun.xml.bind.CycleRecoverable;
To uses that package path above you need add it:
Project Properties -> Libraries -> "Add Library...", select JAXB 2.2 and "Add Library".
A sample how to implements the com.sun.xml.bind.CycleRecoverable:
> Business.java
package org.test.data;
import com.sun.xml.bind.CycleRecoverable;
import java.io.Serializable;
import java.util.Collection;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlID;
import javax.xml.bind.annotation.XmlIDREF;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import org.test.data.adapter.IntegerAdapter;
@Entity
@Table(name = "Business")
@NamedQueries({
@NamedQuery(name = "Business.findAll", query = "SELECT b FROM Business b"),
@NamedQuery(name = "Business.findById", query = "SELECT b FROM Business b WHERE b.id = :id"),
@NamedQuery(name = "Business.findByNome", query = "SELECT b FROM Business b WHERE b.name = :name"),
public class Business implements Serializable, CycleRecoverable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "Id")
private Integer id;
@Basic(optional = false)
@Column(name = "Name")
private String name;
@JoinColumn(name = "BusinessTypeId", referencedColumnName = "Id")
@ManyToOne(optional = false)
private BusinessType businessType;
public Business() {
}
public Business(Integer id) {
this.id = id;
}
public Business(Integer id, String name) {
this.id = id;
this.name = name;
}
@XmlID
@XmlJavaTypeAdapter(value = IntegerAdapter.class, type = String.class)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@XmlIDREF
public BusinessType getBusinessType() {
return businessType;
}
public void setBusinessType(BusinessType businessType) {
this.businessType = businessType;
}
@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Business)) {
return false;
}
Business other = (Business) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
@Override
public String toString() {
return "org.test.data.Business[id=" + id + "]";
}
@Override
public Object onCycleDetected(Context cntxt) {
System.out.println("CycleRecoverable.onCycleDetected # ".concat(this.toString()));
Business n = new Business();
n.setId(this.getId());
return n;
}
}
> BusinessType.java
package org.test.data;
import com.sun.xml.bind.CycleRecoverable;
import java.io.Serializable;
import java.util.Collection;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlID;
import javax.xml.bind.annotation.XmlIDREF;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import org.test.data.adapter.IntegerAdapter;
@Entity
@Table(name = "BusinessType")
@NamedQueries({
@NamedQuery(name = "BusinessType.findAll", query = "SELECT bt FROM BusinessType bt"),
@NamedQuery(name = "BusinessType.findById", query = "SELECT bt FROM BusinessType bt WHERE bt.id = :id"),
@NamedQuery(name = "BusinessType.findByName", query = "SELECT bt FROM BusinessType bt WHERE bt.name = :name")})
public class BusinessType implements Serializable, CycleRecoverable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "Id")
private Integer id;
@Basic(optional = false)
@Column(name = "Name")
private String name;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "BusinessType")
private Collection businessCollection;
public BusinessType() {
}
public BusinessType(Integer id) {
this.id = id;
}
public BusinessType(Integer id, String name) {
this.id = id;
this.name = name;
}
@XmlID
@XmlJavaTypeAdapter(value = IntegerAdapter.class, type = String.class)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@XmlIDREF
public Collection getBusinessCollection() {
return businessCollection;
}
public void setBusinessCollection(Collection businessCollection) {
this.businessCollection = businessCollection;
}
@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof BusinessType)) {
return false;
}
BusinessType other = (BusinessType) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
@Override
public String toString() {
return "org.test.data.BusinessType[id=" + id + "]";
}
@Override
public Object onCycleDetected(Context cntxt) {
System.out.println("CycleRecoverable.onCycleDetected # ".concat(this.toString()));
BusinessType n = new BusinessType();
n.setId(this.getId());
return n;
}
}
You need mark the IDs with @XmlID(only before the get method, before the variable declaration don't works):
@XmlID
@XmlJavaTypeAdapter(value = IntegerAdapter.class, type = String.class)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
And mark all Collection relationships methods with @XmlIDREF(only before the get method, before the variable declaration don't works):
> BusinessType.java
@XmlIDREF
public Collection getBusinessCollection() {
return businessCollection;
}
public void setBusinessCollection(Collection businessCollection) {
this.businessCollection = businessCollection;
}
Sample of the IntegerAdapter.java:
package org.test.data.adapter;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class IntegerAdapter extends XmlAdapter {
@Override
public Integer unmarshal(String v) {
return Integer.parseInt(v);
}
@Override
public String marshal(Integer v) {
return v.toString();
}
}
Thanks this was great help but my code is breaking at web service client side, i m getting following error
ReplyDeleteUnmarshalling Error: Undefined ID
I am also facing the same issue? Were you able to resolve this?(I admit you got this issue long time back :))
DeleteGreat! now i finally got ride of the problem with the @XmlTransient field that were auto generated that i wanted to send back with my webservice :) without the cycle error.
ReplyDeleteThis comment has been removed by a blog administrator.
ReplyDeleteThis comment has been removed by a blog administrator.
ReplyDeleteThis comment has been removed by a blog administrator.
ReplyDeleteThis comment has been removed by a blog administrator.
ReplyDelete