在我的应用程序中有一个对象树。要构成该树,每个对象都有一个父引用。由于某些对象类型可以是多个父对象类型的子对象,因此通过实现公共接口来统一所有潜在的父对象类型。 我缩小了问题(JAXB抱怨父成员变量(带注释的@XmlIDREF和@XmlAttribute)是一个接口)尽可能多:
public interface Parent{
@XmlID
@XmlAttribute( name = "oid" )
public String getID();
public void setID( String id );
}
@XmlRootElement
@XmlAccessorType( XmlAccessType.NONE )
public class ChildObject implements Parent{
@XmlTransient
private UUID id = UUID.randomUUID();
@XmlIDREF
@XmlAttribute
protected Parent parent = null;
public ChildObject() {}
public ChildObject( Parent parent ){
this.parent = parent;
}
@XmlID
@XmlAttribute
@Override
public String getID(){ return( id.toString() ); }
@Override
public void setID( String id ){ this.id = UUID.fromString( id ); }
}
@XmlRootElement
@XmlAccessorType( XmlAccessType.NONE )
public class Repository{
@XmlElement
private List<ChildObject> objects = new ArrayList<>();
public Repository() {}
public ChildObject addObject( ChildObject o ){
objects.add( o );
return( o );
}
public static void main( String[] args ){
Repository r = new Repository();
ChildObject root = r.addObject( new ChildObject() );
ChildObject c0 = r.addObject( new ChildObject( root ) );
ChildObject c1 = r.addObject( new ChildObject( root ) );
ChildObject c11 = r.addObject( new ChildObject( c1 ) );
ChildObject c12 = r.addObject( new ChildObject( c1 ) );
try{
JAXBContext context = JAXBContext.newInstance( Repository.class );
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, true );
marshaller.marshal( r, System.out );
}catch( Exception ex ){ ex.printStackTrace(); }
}
}
这是我尝试运行它时遇到的异常:
com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException:1 IllegalAnnotationExceptions的计数Parent是一个接口和JAXB 无法处理接口。这个问题与以下内容有关 location:at Parent at protected Parent ChildObject.parent at 私有java.util.List中的ChildObject,Repository.objects at 存储库
在 com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException $ Builder.check(IllegalAnnotationsException.java:91) 在 com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:445) 在 com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl。(JAXBContextImpl.java:277) 在 com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl。(JAXBContextImpl.java:124) 在 com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl $ JAXBContextBuilder.build(JAXBContextImpl.java:1123) 在 com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:147) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在java.lang.reflect.Method.invoke(Method.java:498)at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:247)at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:234)at javax.xml.bind.ContextFinder.find(ContextFinder.java:462)at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:641)at at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:584)at at Repository.main(Repository.java:33)
这是JAXB的预期行为(或者它是一个错误),我应该做些什么来绕过它?
答案 0 :(得分:1)
我通过在接口上添加一个虚拟@XmlJavaTypeAdapter
来解决这个问题,如下所示:
@XmlAccessorType( XmlAccessType.NONE )
@XmlJavaTypeAdapter(ChildObject.ParentAdapter.class)
public interface Parent{
@XmlID
@XmlAttribute( name = "oid" )
public abstract String getID();
public abstract void setID( String id );
}
@XmlRootElement
@XmlAccessorType( XmlAccessType.NONE )
public class ChildObject implements Parent{
@XmlTransient
private UUID id = UUID.randomUUID();
@XmlIDREF
@XmlAttribute
protected Parent parent = null;
public ChildObject() {}
public ChildObject( Parent parent ){
this.parent = parent;
}
@XmlID
@XmlAttribute( name = "oid" )
@Override
public String getID(){ return( id.toString() ); }
@Override
public void setID( String id ){ this.id = UUID.fromString( id ); }
public static class ParentAdapter extends XmlAdapter<Object,Object>{
@Override
public Object marshal( Object arg0 ) throws Exception{ return arg0; }
@Override
public Object unmarshal( Object arg0 ) throws Exception{ return arg0; }
}
}
但是,我不确定这是一个错误还是JAXB的预期行为(Oracle JDK 8u121)