在EclipseLink MOXy

时间:2015-10-29 14:40:26

标签: java jaxb moxy

我有一个从MOXy的XJC版本生成的JAXB模型。 xjc:superclass标记用于绑定文件中,因此所有对象都扩展了一个公共类。

package my.package
//Base.java
@XmlTransient
public class Base {
    //...
}

//MyTag.java (generated from XJC)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {/*...*/})
@XmlRootElement(name = "myTag")
public class MyTag extends Base {
    //...
}

可以更改模型和模式,但我可以更改Base类。

我需要扩展MyTag以及模型中的其他类,因此我可以从Base类中自定义其方法行为。所以我扩展了MyTag和其他需要自定义行为的域类,以及ObjectFactory。这些类存在于单独的Java包中。

package my.extended.package
//MyTagExtended.java
public class MyTagExtended extends MyTag {
    //...
}

//CustomObjectFactory.java
public class CustomObjectFactory extends ObjectFactory {
    //...

    @Override
    public MyTagExtended createMyTag() {
        return new MyTagExtended();
    }

    //...
}

申请代码:

package application
//Application.java
System.setProperty("org.eclipse.persistence.moxy.annotation.xml-value-extension", "true");
JAXBContext jc = (JAXBContext) JAXBContext.newInstance(XPSObjectFactory.class);
JAXBUnmarshaller u = jc.createUnmarshaller();
return u.unmarshal(xmlFile);

我遇到的问题是MOXy似乎随机决定是否调用CustomObjectFactory或ObjectFactory的方法。

在CustomObjectFactory类中,如果我只有一个重写方法,则始终调用该方法。但是,当我输入更多时,MOXy似乎随机决定是否调用ObjectFactory的方法或CustomObjectFactory。

当我使用与JDK提供的Oracle JAXB实现相同的设置时,它可以正常工作。始终调用CustomObjectFactory的方法。

是否需要设置配置?如何配置MOXy以始终使用我的CustomObjectFactory方法?

编辑: 为了澄清,这里是我如何使相同的场景与Oracle的JAXB实现一起工作:

JAXBContext jc = JAXBContext.newInstance("my.package");
Unmarshaller u = jc.createUnmarshaller();
u.setProperty("com.sun.xml.internal.bind.ObjectFactory", new CustomObjectFactory());

我试图在MOXy unmarshaller上设置ObjectFactory属性,但它引发了异常。

1 个答案:

答案 0 :(得分:0)

我找到了MOXy的解决方法。我在XmlClassExtractor上找到了一些信息,可用于指定要实例化的类。由于我无法修改域对象,因此使用了XML文件。

我保持扩展类相同,但修改了Application.java并编写了binding.xml文件和ClassExtractor:

package application
//Application.java
System.setProperty("org.eclipse.persistence.moxy.annotation.xml-value-extension", "true");
Map<String, Object> properties = new HashMap<String, Object>();
properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, "classExtractor.xml");
JAXBContext jc = (JAXBContext) JAXBContextFactory.createContext(new Class[]{CustomObjectFactory.class}, properties);
JAXBUnmarshaller u = jc.createUnmarshaller();
return u.unmarshal(xmlFile);

classExtractor.xml:

<?xml version="1.0"?>
<xml-bindings 
    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="my.package"
    version="2.3">
    <java-types>
        <java-type name="MyTag">
           <xml-class-extractor class="my.extended.package.MyTagClassExtractor"/>
        </java-type>
    </java-types>
</xml-bindings>

类提取器:

package my.extended.package
//MyTagExtractor.java
public class MyTagExtractor extends ClassExtractor {
    @Override
    public Class<? extends Base> extractClassFromRow(Record databaseRow, Session session) {
        return MyTagExtended.class;
    }
}

这似乎有效,但它很古怪,容易出现程序员错误,因为必须编辑多个源文件才能获得所需的功能。 unmarshaller上的Oracle的ObjectFactory属性非常简单和简化。有没有人有更好的答案?