java - 使用扩展类时不调用 JAXB afterUnmarshall

标签 java xml jaxb unmarshalling moxy

我写了一个 bean (BaseBeanEx) 扩展了一个 JAXB 注释的 bean (BaseBean)。 BaseBean 位于数据结构某处的列表中,无法更改。软件会在需要时显式转换为 BaseBeanEx。我还编写了一个 ObjectFactory 来创建 BaseBeanEx 而不是 BaseBean。这一切都很好,但现在我向 BaseBeanEx 添加了一个 afterUnmarshal 方法,它永远不会被调用。

这是一个错误还是符合规范?如果以后是这种情况,是否有一些优雅的解决方法?

我正在使用默认的 JAXB 引擎。

最佳答案

注意:我是 EclipseLink JAXB (MOXy) JAXB 2 (JSR-222) 的领导和成员专家组。

afterUnmarshal的原因没有被调用 BaseBeanEx是元数据是建立在 BaseBean 上的类(class)。为了使您的用例正常工作,您需要让 JAXB 实现知道您确实想要映射到 BaseBeanEx 的实例。 .

选项 #1 - 任何使用注解的 JAXB 实现

您可以使用 @XmlElement用于覆盖字段/属性类型的注释。在下面的示例中,方法的签名是 List<BaseBean> ,但是 @XmlElement注释通知 JAXB 实现该属性应解释为 List<BaseBeanEx> .

package forum10174513;

import java.util.List;
import javax.xml.bind.annotation.*;

@XmlRootElement
public class Root {

    private List<BaseBean> baseBeans;

    @XmlElement(name="base-bean", type=BaseBeanEx.class)
    public List<BaseBean> getBaseBeans() {
        return baseBeans;
    }

    public void setBaseBeans(List<BaseBean> baseBeans) {
        this.baseBeans = baseBeans;
    }

}

选项 #2 - 使用 MOXy 的外部映射文件

The BaseBean is in a List somewhere in the datastructure and can't be changed.

如果您无法修改您的域模型并使用 MOXy 作为您的 JAXB 提供者,那么您可以利用其外部映射文档来应用元数据,而无需修改您的域模型。

bindings.xml

<?xml version="1.0"?>
<xml-bindings
    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="forum10174513">
    <java-types>
        <java-type name="Root">
            <java-attributes>
                <xml-element 
                    java-attribute="baseBeans"
                    name="base-bean" 
                    type="forum10174513.BaseBeanEx"/>
            </java-attributes>
        </java-type>
    </java-types>
</xml-bindings>

演示

下面是一些演示如何引导 JAXBContext 的代码。利用外部映射文档。当前存在一个错误,其中仅通过外部映射文档引用的类不会注册事件方法 (http://bugs.eclipse.org/376876)。您可以通过在用于创建 JAXBContext 的类列表中显式包含此类来解决此问题。 .

package forum10174513;

import java.io.File;
import java.util.*;
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.JAXBContextFactory;

public class Demo {

    public static void main(String[] args) throws Exception {
        Map<String, Object> properties = new HashMap<String, Object>(1);
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, "forum10174513/bindings.xml");
        JAXBContext jc = JAXBContext.newInstance(new Class[] {Root.class, BaseBeanEx.class}, properties);

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

}

BaseBean

package forum10174513;

public class BaseBean {
}

BaseBeanEx

package forum10174513;

import javax.xml.bind.Unmarshaller;

public class BaseBeanEx extends BaseBean {

    public void afterUnmarshal(Unmarshaller unmarshaller, Object parent) {
        System.out.println("AFTER UNMARSHAL WAS CALLED");
    }

}

输出

下面是运行演示代码生成的输出。

AFTER UNMARSHAL WAS CALLED
AFTER UNMARSHAL WAS CALLED

了解更多信息

关于java - 使用扩展类时不调用 JAXB afterUnmarshall,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10174513/

相关文章:

java.io.ioexception.Runtime.getRuntime().exec()。 android中的环境和工作目录空错误

java - Jasper Reports为子报表设置不同的java bean集合数据适配器

c# - 创建 xml 文档时的默认命名空间

java - 按钮未在第一次单击时调用 OnClickListener

java - 从 Spring-Jersey 1.x 迁移到 2.x

java - 如何禁止枚举类型中的某些枚举值到 XML 表示映射?

java - 调用 JvmModelInferrer/Generator 从 Java 项目生成代码时出现 NullPointerException

html - XPath:如何捕获前一个元素?

java - JAXB:从 Java 代码更改 XML 元素的名称?

java - 如果@ApplicationScope,CDI( Weld 3.0.3.Final)不会调用@PostConstruct