解决CXF WebService使用Hibernate双向oneToMany引起的循环对象异常:com.sun.istack.SAXException2: 在对象图中检测到循环。这将产生无限深的 XM
2014-11-06 12:14
337 查看
异常:Caused by: com.sun.istack.SAXException2: 在对象图中检测到循环。这将产生无限深的 XML:
解决方法:使用注解:@XmlTransient,在one的getList方法上火many的parent的getter方法上添加 @XmlTransient,表示不生成这个对象的xml文档
循环引用:
Parent 和 Child是1:n的关系, Parent含有一个child的列表children,child对于parent有一个引用,那这两个对象之间就存在循环引用的关系.
java 代码
public class Parent {
private List children;
// setter / getter
}
java 代码
java 代码
import javax.xml.bind.annotation.XmlTransient;
public class Child {
private Parent parent;
@XmlTransient
public Parent getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
public void afterUnmarshal(Unmarshaller u, Object parent) {
this.parent = (Parent) parent;
}
}
这就是一个典型的环引用,而我们不能 直接将带有环的对象暴露给webservice,因为这会导致最终生成xml的时候会陷入死循环最后栈溢出,所以cxf检测出对象存在cycle会抛出一 个异常阻止进一步发布webservice.(以前的XFire可没这么聪明,它没有检测机制,直接就去序列化xml结果会导致
OutOfMemory).
如何解决呢?就是要破掉这个环,去某一端,如何在不破坏原有设计的情况下做到这一点,就是要使用@XmlTransient
这个annotation会标明这个字段不要解析成xml,所有你不想解析进webservice的都可以通过这个标签来标记
注:cxf默认采用JAXB做databindings,如果要用aegis,相应的就要用@IgnoreProperty这个元注释
像这种情况,我们一般要打破子对父的引用,就是要打破Child对于Parent的引用.注意要在parent的get方法上面加而不是在parent的声明处.
这样从生成的wsdl里面我们就看不到child里有对于parent的引用
虽然client能够拿到children列表了,但通过child得不到parent的信息,因为在client现在是单向的,那我也想访问parent怎么办?
这里有一个解决办法,在Parent下面加入如下代码:
public void afterUnmarshal(Unmarshaller u, Object parent) {
this.parent = (Parent) parent;
}
怎么做到的?背后的道理是这样的:
循环的双向关系,一端到另一端的关系确定了以后,反过来另一端也就确定了.
cxf在解析wsdl映射成对象的过程中(也就是unmarshal),处理Parent并处理它所包含的child,结果发现parent引 用的child有afterUnmarshal方法,然后把自己的引用通过该方法传递给child,这样child也具有了对于 parent的引用,这一切都是在客户端完成的.真的是很聪明的做法.
这些功能必须要cxf来做客户端才能实现,但我们可以利用这种技术来在其他客户端实现这个功能.比如flex,.net, php 等等.
上面的例子首先访问的是parent,cxf可以拿到两端的信息,但如果先访问child就拿不到parent了.
那么如果把@XmlTransient加到Parent, 同样道理, child可以得到parent的信息,但是这个parent的getChildren里恐怕就只有那一个child了.
所以还是看具体设计,如果parent需要经常访问child,第一种最好,如果child要经常访问parent,显然是第二种
解决方法:使用注解:@XmlTransient,在one的getList方法上火many的parent的getter方法上添加 @XmlTransient,表示不生成这个对象的xml文档
循环引用:
Parent 和 Child是1:n的关系, Parent含有一个child的列表children,child对于parent有一个引用,那这两个对象之间就存在循环引用的关系.
java 代码
public class Parent {
private List children;
// setter / getter
}
java 代码
java 代码
import javax.xml.bind.annotation.XmlTransient;
public class Child {
private Parent parent;
@XmlTransient
public Parent getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
public void afterUnmarshal(Unmarshaller u, Object parent) {
this.parent = (Parent) parent;
}
}
这就是一个典型的环引用,而我们不能 直接将带有环的对象暴露给webservice,因为这会导致最终生成xml的时候会陷入死循环最后栈溢出,所以cxf检测出对象存在cycle会抛出一 个异常阻止进一步发布webservice.(以前的XFire可没这么聪明,它没有检测机制,直接就去序列化xml结果会导致
OutOfMemory).
如何解决呢?就是要破掉这个环,去某一端,如何在不破坏原有设计的情况下做到这一点,就是要使用@XmlTransient
这个annotation会标明这个字段不要解析成xml,所有你不想解析进webservice的都可以通过这个标签来标记
注:cxf默认采用JAXB做databindings,如果要用aegis,相应的就要用@IgnoreProperty这个元注释
像这种情况,我们一般要打破子对父的引用,就是要打破Child对于Parent的引用.注意要在parent的get方法上面加而不是在parent的声明处.
这样从生成的wsdl里面我们就看不到child里有对于parent的引用
虽然client能够拿到children列表了,但通过child得不到parent的信息,因为在client现在是单向的,那我也想访问parent怎么办?
这里有一个解决办法,在Parent下面加入如下代码:
public void afterUnmarshal(Unmarshaller u, Object parent) {
this.parent = (Parent) parent;
}
怎么做到的?背后的道理是这样的:
循环的双向关系,一端到另一端的关系确定了以后,反过来另一端也就确定了.
cxf在解析wsdl映射成对象的过程中(也就是unmarshal),处理Parent并处理它所包含的child,结果发现parent引 用的child有afterUnmarshal方法,然后把自己的引用通过该方法传递给child,这样child也具有了对于 parent的引用,这一切都是在客户端完成的.真的是很聪明的做法.
这些功能必须要cxf来做客户端才能实现,但我们可以利用这种技术来在其他客户端实现这个功能.比如flex,.net, php 等等.
one more thing
上面的例子首先访问的是parent,cxf可以拿到两端的信息,但如果先访问child就拿不到parent了.那么如果把@XmlTransient加到Parent, 同样道理, child可以得到parent的信息,但是这个parent的getChildren里恐怕就只有那一个child了.
所以还是看具体设计,如果parent需要经常访问child,第一种最好,如果child要经常访问parent,显然是第二种
相关文章推荐
- 在使用Linq to SQL并序列化一个数据对象的时候报System.InvalidOperationException异常,序列化类型XXX的对象时检测到循环引用。
- com.sun.istack.SAXException2: 在对象图中检测到循环。这将产生无限深的 XML
- [com.sun.istack.SAXException2: 在对象图中检测到循环。这将产生无限深的 XML:
- 在使用Linq to SQL并序列化一个数据对象的时候报System.InvalidOperationException异常,序列化类型XXX的对象时检测到循环引用。
- 在对象图中检测到循环。这将产生无限深的 XML
- 关于在Webservice里使用LinqToSQL遇到一对多关系的父子表中子表需要ToList输出泛型而产生循环引用错误的解决办法!(转)
- eWebEditor在IE8中使用时候总是报错“没有对象”。解决办法如下:
- 如何使用Exchange Web Service获取日历(包含循环会议)
- CXF WebService中传递复杂类型对象
- Webservice里使用Linq遇到ToList输出泛型而产生循环引用错误的解决办法(转)
- 采用CXF解决webservice循环引用对象的问题
- 使用json序列化类型为“ajax学习.DataSetComment+T_CommentDataTable”的对象时检测到循环引用。
- 如何使用Exchange Web Service Managed API获取公共文件夹日历(包括循环会议)
- ADO.NET 实体数据模型 异常-“序列化类型为 XX 的对象时检测到循环引用”
- Web项目中使用java2word出现异常 解决方法
- 采用CXF解决webservice循环引用对象的问题
- 使用Filter时产生java.lang.IllegalStateException异常解决办法
- editor.js 缺少对象的解决方法(ewebeditor 使用)
- CXF WebService Notification(WS-N)使用简介
- tping一个好用的TCP检测工具,外加win7 x64下解决msvcr71.dll丢失引起tping无法使用的问题