JAXB生成不需要的@XMLValue

时间:2015-10-04 21:00:00

标签: jaxb jaxb2 maven-jaxb2-plugin

现在已经解决了大约半个星期的问题,需要帮助,因为我似乎无法取得任何进展。

我继承了一个8年来没有得到很好处理的应用程序....仍然使用Java 1.4,Maven1构建,8年没有新的单元测试......

目前升级到Java 1.6(Java 1.8分支也同时进行,将测试两者)和Maven 3.3.3正在进行中 - 已经取得了很好的进展。

现在我已经撞墙了,暂时没有取得突破。

旧的源使用本地JAXB 1.3 jar从大型XSD生成类。

我不得不从JAXB1.3迁移到JAXB2.1 - 这也意味着当命名约定发生变化时,我不得不花费大量时间重写对生成的类的所有引用。 无论如何,花了很多时间来编译代码。

最后,它编译,我尝试单元测试,看看它是如何工作的。 这就是我遇到问题的地方。

编译的大多数类工作正常,但是当我尝试生成JAXBContext时,其中三个包会抛出异常:

在派生另一个类的类上不允许使用@XmlValue。

我已将问题缩小到几个生成的类中出现的模式。 导致异常的类在模式中定义如下:

    <xs:element name="ContactName">
    <xs:complexType>
        <xs:simpleContent>
            <xs:extension base="xs:string">
                <xs:attribute name="First" type="xs:string"/>
                <xs:attribute name="Middle" type="xs:string"/>
                <xs:attribute name="Last" type="xs:string"/>
                <xs:attribute name="Name" type="xs:string"/>
            </xs:extension>
        </xs:simpleContent>
    </xs:complexType>
</xs:element>

然后在另一个元素中引用此元素,如下所示:

<xs:element name="ContactInfo">
    <xs:complexType>
        <xs:annotation>
            <xs:documentation>Common contact information</xs:documentation>
        </xs:annotation>
        <xs:sequence>
            <xs:element ref="ContactName" minOccurs="0" maxOccurs="unbounded"/>
            <xs:element ref="ContactID" minOccurs="0"/>
            <xs:element ref="ContactDivision" minOccurs="0" maxOccurs="unbounded"/>
            .....

这产生于:

联系人姓名:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "value"
})
@XmlRootElement(name = "ContactName")
public class ContactName
    extends BaseJaxbDoc
    implements Serializable, Cloneable, CopyTo
{

    private final static long serialVersionUID = 47110815L;
    @XmlValue
    protected String value;
    @XmlAttribute(name = "First")
    protected String first;
    @XmlAttribute(name = "Middle")
    protected String middle;
    @XmlAttribute(name = "Last")
    protected String last;
    @XmlAttribute(name = "Name")
    protected String name;

然后在ContactInfo中声明如下:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "contactName",
    "contactID",
    "contactDivision",
    "contactPhone",
    "contactPhoneHome",
    "contactPhoneMobile",
    "contactFax",
    "contactEmail",
    "contactEmail2"
})
@XmlRootElement(name = "ContactInfo")
public class ContactInfo
    extends BaseJaxbDoc
    implements Serializable, Cloneable, CopyTo
{

    private final static long serialVersionUID = 47110815L;
    @XmlElement(name = "ContactName")
    protected List<ContactName> contactName;

抛出的异常位于:

this problem is related to the following location:
    at protected java.lang.String xxx.xx.xxxx.xxxx.orders.jaxb.ContactName.value
    at xxx.xx.xxxx.xxxx.orders.jaxb.ContactName
    at protected java.util.List xxx.xx.xxxx.xxxx.orders.jaxb.ContactInfo.contactName
    at xxx.xx.xxxx.xxxx.orders.jaxb.ContactInfo
    at protected java.util.List xxx.xx.xxxx.xxxx.orders.jaxb.CustomerReference.contactInfo
    at xxx.xx.xxxx.xxxx.orders.jaxb.CustomerReference
    at protected java.util.List xxx.xx.xxxx.xxxx.orders.jaxb.Item.customerReference
    at xxx.xx.xxxx.xxxx.orders.jaxb.Item
    at public xxx.xx.xxxx.xxxx.orders.jaxb.Item xxx.xx.xxxx.xxxx.orders.jaxb.ObjectFactory.createItem()
    at xxx.xx.xxxx.xxxx.orders.jaxb.ObjectFactory

对原始模式进行XML转换,剥离注释并创建jaxb:typesafeEnum类型。然后,转换后的模式与jxb绑定文件一起使用,将所有内容绑定到内部jaxb帮助程序超类 - BaseJaxbDoc

        <jaxb:globalBindings generateIsSetMethod="true">
        <xjc:serializable uid="47110815"/>
        <xjc:superClass name="xxx.xx.xxxx.xxxx.helpers.BaseJaxbDoc"/>
        <jaxb:javaType name="java.math.BigDecimal" xmlType="xs:decimal" 
             parseMethod="xxx.xx.xxxx.xxxx.helpers.AmountConverter.parseAmount" 
            printMethod="xxx.xx.xxxx.xxxx.helpers.AmountConverter.printAmount"/>
        </jaxb:globalBindings>

这是因为我在9种不同的模式上使用xjc,都生成类的JAXB包。

这些类都具有相同的超类(在每个模式的绑定文件中定义),只能实现一次JAXB marshall / unmarshall类以及其他一些辅助函数。 所以我的问题是当我无法修改架构时如何解决这个异常? XSLT中的东西还是绑定文件中的东西?

My Maven依赖项: 对于JAXB:                 org.jvnet.jaxb2.maven2                 Maven的jaxb21-插件                 0.13.0

JAXB运行时:                          org.glassfish.jaxb             JAXB运行时             2.2.11            

1 个答案:

答案 0 :(得分:1)

尝试使用BaseJaxbDoc注释@XmlTransient

您遇到的问题是here

                if(getBaseClass()!=null) {
                    builder.reportError(new IllegalAnnotationException(
                        Messages.XMLVALUE_IN_DERIVED_TYPE.format(), p ));
                }

JAXB认为您的BaseJaxbDoc是基类。因此,您应该删除xjc:superClass或者将JAXB设想为认为您的类没有基类。

当我查看ModelBuilder中的this part of the code时:

        if(reader.hasClassAnnotation(clazz,XmlTransient.class) || isReplaced) {
            // handle it as if the base class was specified
            r = getClassInfo( nav.getSuperClass(clazz), searchForSuperClass,
                    new ClassLocatable<C>(upstream,clazz,nav) );
        }

似乎ModelBuilder在课堂上识别@XmlTransient并且不考虑它们。因此,@XmlTransientBaseJaxbDoc BaseJaxbDoc提供帮助的机会很有帮助。

另一个选择是删除 $source = null; $default = 'something'; if(isset($request['controller']['options']['data']['source']) && !empty($request['controller']['options']['data']['source'])) { $source = $request['controller']['options']['data']['source']; } else { $source = $default; } 构造。您可以使用类继承向模式派生类添加编组/解组功能。我宁愿将此功能移到某些外部服务中。这可能不是一个选项,因为您可能面临很多遗留代码。

另一个选择是在运行时尝试MOXy而不是JAXB RI。