使用XmlIDRef来引用抽象类

时间:2012-08-24 14:55:27

标签: jaxb eclipselink moxy

首先是一个小例子。类ReferencingEntity包含对抽象类AbstractEntity的引用。这个类有两种实现方式:

@XmlRootElement
public abstract class AbstractEntity {

    @XmlID
    private String id;
}

@XmlRootElement
public class EntityImpl1 extends AbstractEntity {

}

@XmlRootElement
public class EntityImpl2 extends AbstractEntity {

}

@XmlRootElement
public class ReferencingEntity {

    @XmlIDREF
    private AbstractEntity entity;
}

编组ReferencingEntity实例没有问题(除了xml中没有具体类型),但是当尝试解组xml表示时,缺少描述符来确定具体实现。

目前我正在使用XmlAdapter将所有非id字段设置为null,但如果可能,最好使用@XmlID。有什么想法吗?

更新: 我在JBoss 6.1.0.Final中使用RESTEasy,提供程序创建上下文:

ContextResolver<JAXBContextFinder> resolver = providers.getContextResolver(JAXBContextFinder.class, mediaType);
JAXBContextFinder finder = resolver.getContext(type);
if (finder == null)
{
   if (reader) throw new JAXBUnmarshalException("Could not find JAXBContextFinder for media type: " + mediaType);
   else throw new JAXBMarshalException("Could not find JAXBContextFinder for media type: " + mediaType);
}
JAXBContext context = finder.findCachedContext(type, mediaType, annotations);

1 个答案:

答案 0 :(得分:1)

以下是我对你问题的初步回答。我想它会随着我更好地理解你的用例而发展。

关于@XmlID / @XmlIDREF

从带有@XmlIDREF注释的字段/属性引用的每个实例也需要通过包含引用。我将在本例中使用下面的类。

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Root {

    private AbstractEntity abstractEntity;
    private ReferencingEntity referencingEntity;

    public AbstractEntity getAbstractEntity() {
        return abstractEntity;
    }

    public void setAbstractEntity(AbstractEntity abstractEntity) {
        this.abstractEntity = abstractEntity;
    }

    public ReferencingEntity getReferencingEntity() {
        return referencingEntity;
    }

    public void setReferencingEntity(ReferencingEntity referencingEntity) {
        this.referencingEntity = referencingEntity;
    }

}

关于遗传

JAXB(JSR-222)实现无法自动发现子类,因此您需要确保JAXBContext知道它们。实现此目的的一种方法是使用父类的@XmlSeeAlso注释指向子类。

import javax.xml.bind.annotation.*;

@XmlSeeAlso({EntityImpl1.class, EntityImpl2.class})
@XmlAccessorType(XmlAccessType.FIELD)
public abstract class AbstractEntity {

    @XmlID
    private String id;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

}

DEMO CODE

<强>演示

package forum12111815;

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Root.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum12111815/input.xml");
        Root root = (Root) unmarshaller.unmarshal(xml);

        System.out.println(root.getAbstractEntity().getClass());
        System.out.println(root.getAbstractEntity() == root.getReferencingEntity().getEntity());

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(root, System.out);
    }

}

input.xml中

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <abstractEntity xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="entityImpl2">
      <id>123</id>
   </abstractEntity>
   <referencingEntity>
      <entity>123</entity>
   </referencingEntity>
</root>

输出

class forum12111815.EntityImpl2
true
<?xml version="1.0" encoding="UTF-8"?>
<root>
   <abstractEntity xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="entityImpl2">
      <id>123</id>
   </abstractEntity>
   <referencingEntity>
      <entity>123</entity>
   </referencingEntity>
</root>

更多信息