当前位置: 首页 > 知识库问答 >
问题:

SomeObject是一个接口,JAXB无法处理接口

濮阳祯
2023-03-14

在我的应用程序中有一个对象树。要构成该树,每个对象都有一个父引用。由于某些对象类型可以是多个父对象类型的子对象,所有潜在的父对象类型都通过实现公共接口来统一。我尽可能地缩小了问题的范围(JAXB抱怨父成员变量(注释为@XmlIDREF和@xmldattribute)是一个接口):

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.非法注释异常:1次非法注释异常父级是一个接口,JAXB不能处理接口。这个问题与以下位置有关:在受保护父级的父级ChildObject.parent在私有java.util.列表R<-在仓库

在com。太阳xml。内部的绑定v2。运行时。IllegalAnnotationsException$Builder。在com上检查(IllegalAnnotationsException.java:91)。太阳xml。内部的绑定v2。运行时。JAXBContextImpl。com上的getTypeInfoSet(JAXBContextImpl.java:445)。太阳xml。内部的绑定v2。运行时。JAXBContextImpl。(JAXBContextImpl.java:277)。太阳xml。内部的绑定v2。运行时。JAXBContextImpl。(JAXBContextImpl.java:124)。太阳xml。内部的绑定v2。运行时。JAXBContextImpl$JAXBContextBuilder。在com上构建(JAXBContextImpl.java:1123)。太阳xml。内部的绑定v2。上下文工厂。sun上的createContext(ContextFactory.java:147)。反映NativeMethodAccessorImpl。在sun上调用0(本机方法)。反映NativeMethodAccessorImpl。在sun上调用(NativeMethodAccessorImpl.java:62)。反映DelegatingMethodAccessorImpl。在java上调用(DelegatingMethodAccessorImpl.java:43)。朗。反思。方法在javax调用(Method.java:498)。xml。绑定上下文查找器。javax上的newInstance(ContextFinder.java:247)。xml。绑定上下文查找器。javax上的newInstance(ContextFinder.java:234)。xml。绑定上下文查找器。在javax上查找(ContextFinder.java:462)。xml。绑定JAXBContext。javax上的newInstance(JAXBContext.java:641)。xml。绑定JAXBContext。存储库中的newInstance(JAXBContext.java:584)。main(Repository.java:33)

这是JAXB的预期行为(或者是一个bug)吗?我应该怎么做才能避免它?

共有1个答案

范高刚
2023-03-14

我通过向接口添加一个虚拟的@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)

 类似资料:
  • 问题内容: 尝试部署应用程序时,似乎出现以下异常: 我的代码运行良好,直到将返回类型从List更改为List > 这是部分Web服务: 我也尝试过通过删除@SOAPBinding并尝试使用默认值,但是会出现相同的结果。 感谢任何帮助 更新 我要注意一些事情。我将所有List更改为ArrayList,然后进行编译。我之所以说编译但不起作用是因为它的行为很奇怪。我得到一个类型为Object的对象:Re

  • 我使用CXF2.7.5调用Web服务。我使用wsdl2java程序(在命令行MSDOS和maven中)生成了客户机类。我必须使用xmlbeans数据绑定,因为使用jaxb(默认数据绑定)时会出现一些错误,并且无法修改服务器端。因此,使用xmlbeans数据绑定参数,生成就可以了。 我用以下方法调用web方法: ... 当我调用webmethods时,它可以在简单的java程序上完美地工作,但在po

  • 我越来越熟悉Java使用Jax-ws(或JAXB,不确定,反正...)的网络服务。 我用一个单一的网络服务创建了一个小项目。WS有唯一的endpoint,称为传输,并返回继承ITransferResult接口的对象。 Web服务合同 Web服务实现 转让结果合同 转移结果实现 当我发布我的Web服务时,我得到以下错误: 异常线程"main"javax.xml.ws.WebServiceExctur

  • 我是一个初学者,刚刚开始学习Spring Batch。我在这里按照这个教程创建了一个helloworld示例。当我按照教程操作时,我在尝试将导入java类时遇到了一个问题。因此我在网上搜索,发现我需要在build.gradle.中添加一些东西。问题是,即使我在build.gradle中添加了依赖项,我仍然有导入的错误消息。我正在使用EclipseJavaEE IDE 4.5.0(Mars)来完成这

  • 假设我需要依赖一个Spring bean的几个实现。我有一个接口和两个实现:和。 下面的注入将使用哪个实现?

  • 处理器接口 在服务端,处理器接口用来把服务跟具体的服务器绑定在一起。在这里,服务是指独立于具体传输协议的 RPC 服务,它是由 Service 类型实现的。而具体的服务器是指 http,tcp,udp,websocket 等服务器,这些服务器是由语言本身所提供的标准库、第三方类库或框架实现的。 在 C# 中,该接口定义如下: public interface IHandler<T> { T