gpt4 book ai didi

java - 解决jaxb中的循环引用

转载 作者:数据小太阳 更新时间:2023-10-29 02:02:12 28 4
gpt4 key购买 nike

我在实现项目的 Web 服务层时处理了一些循环引用。我正在使用 jaxb(最新版本,2.2.7),甚至我还查看了一些提示 herehere我无法让它工作。这是一个基本的 SSCCE关于我的问题:

/*
* The service interface
*/
@WebService
public interface IMyWS {

@WebMethod
public List<Class1> cyclicTest();

}

/*
* Interface implementation
*/
@WebService(endpointInterface = "com.mycompany.ws.interfaces.IMyWS")
public class MyWS implements IMyWS {

@XmlRootElement
public static class Class1 {

@XmlTransient
private Class2 class2;

public Class1() {

}

public Class1(Class2 refClass) {
class2 = refClass;
}

public Class2 getClass2() {
return class2;
}

public void setClass2(Class2 class2) {
this.class2 = class2;
}

@Override
public String toString() {
return this.getClass().getSimpleName();
}

}

@XmlRootElement
public static class Class2 {

private Class1 class1;

public Class2() {

}

public Class1 getClass1() {
return class1;
}

public void setClass1(Class1 class1) {
this.class1 = class1;
}

@Override
public String toString() {
return this.getClass().getSimpleName();
}
}

@Override
public List<Class1> cyclicTest() {
//I create an instance of each class, having them a cyclic reference to the other instance
Class2 class2 = new Class2();
Class1 class1 = new Class1(class2);
class2.setClass1(class1);
return Arrays.asList(class1);
}

}

调用 cyclicTest() 时我实际处理的异常:

Caused by: javax.xml.bind.MarshalException
- with linked exception:
[com.sun.istack.SAXException2: Se ha detectado un ciclo en el gráfico de objeto. Esto provocará un XML con profundidad infinita: Class1 -> Class2 -> Class1]
at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:326)
at com.sun.xml.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:178)
at org.apache.cxf.jaxb.JAXBEncoderDecoder.writeObject(JAXBEncoderDecoder.java:537)
at org.apache.cxf.jaxb.JAXBEncoderDecoder.marshall(JAXBEncoderDecoder.java:233)
... 50 more
Caused by: com.sun.istack.SAXException2: Se ha detectado un ciclo en el gráfico de objeto. Esto provocará un XML con profundidad infinita: Class1 -> Class2 -> Class1
at com.sun.xml.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:249)
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.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:158)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:361)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:696)
at com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:158)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:361)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:696)
at com.sun.xml.bind.v2.runtime.property.ArrayElementNodeProperty.serializeItem(ArrayElementNodeProperty.java:69)
at com.sun.xml.bind.v2.runtime.property.ArrayElementProperty.serializeListBody(ArrayElementProperty.java:172)
at com.sun.xml.bind.v2.runtime.property.ArrayERProperty.serializeBody(ArrayERProperty.java:159)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:361)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:696)
at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl$1.serializeBody(ElementBeanInfoImpl.java:156)
at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl$1.serializeBody(ElementBeanInfoImpl.java:131)
at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl.serializeBody(ElementBeanInfoImpl.java:333)
at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl.serializeRoot(ElementBeanInfoImpl.java:340)
at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl.serializeRoot(ElementBeanInfoImpl.java:76)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:494)
at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:323)
... 53 more

我认为我设置了正确的注释。我到底错过了什么?

最佳答案

使用@XmlID 和@XmlIDREF 应该可以解决您的问题。

这是我做的:

我在Class 1中添加了一个String字段作为id,并用@XmlID注解。然后,我用 @XmlIDREF 注释了 setClass1() 方法。我的测试在下面的主要方法中。

/*
* Interface implementation
*/
@WebService(endpointInterface = "com.mycompany.ws.interfaces.IMyWS")
public class MyWS implements IMyWS {

@XmlRootElement
public static class Class1 {

@XmlID
private String id;

private Class2 class2;

public Class1() {
this.id = UUID.randomUUID().toString();
}

public Class1(Class2 refClass) {
this();
class2 = refClass;
}

public Class2 getClass2() {
return class2;
}

public void setClass2(Class2 class2) {
this.class2 = class2;
}

@Override
public String toString() {
return this.getClass().getSimpleName();
}

}

@XmlRootElement
public static class Class2 {

private Class1 class1;

public Class2() {

}

public Class1 getClass1() {
return class1;
}

@XmlIDREF
public void setClass1(Class1 class1) {
this.class1 = class1;
}

@Override
public String toString() {
return this.getClass().getSimpleName();
}
}

@Override
public List<Class1> cyclicTest() {
//I create an instance of each class, having them a cyclic reference to the other instance
Class2 class2 = new Class2();
Class1 class1 = new Class1(class2);
class2.setClass1(class1);
return Arrays.asList(class1);
}

public static void main(String[] args) throws JAXBException {

JAXBContext ctx = JAXBContext.newInstance(Class1.class);
Marshaller m = ctx.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
List<Class1> class1s = new MyWS().cyclicTest();

for (Class1 c1 : class1s){
m.marshal(c1, System.out);
}

}

}

输出:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<class1>
<id>e9e53e73-9a96-4c7c-b919-3ed3d7aa4c5e</id>
<class2>
<class1>e9e53e73-9a96-4c7c-b919-3ed3d7aa4c5e</class1>
</class2>
</class1>

关于java - 解决jaxb中的循环引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18530151/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com