当设置属性值时,JAXB'忘记'添加nil ='true',但元素值不是

时间:2014-10-30 15:29:28

标签: soap attributes jaxb null

我们使用Jaxb(jaxb-api 2.2.5)从XSD生成Java类。 'someField'元素具有nillable ='true'属性和(隐式)minoccurs ='1'。还有一个可选的“订单”属性。

当我们在someField上设置order属性但没有值时,JAXB将在请求中生成XML元素而不使用nill ='true',这不会被XSD接受并导致SOAP错误。

该字段的XSD:

<xs:element name="someField" nillable="true">
    <xs:complexType>
        <xs:simpleContent>
            <xs:extension base="iata:AlphaNumericStringLength1to19">
                <xs:attribute name="order" type="xs:integer" use="optional"/>
            </xs:extension>
        </xs:simpleContent>
    </xs:complexType>
</xs:element>

Jaxb将其转换为Java类的以下字段:

@XmlElement(required = true, nillable = true)
protected SomeParentType.SomeField someField;

SomeField类如下所示:

public static class SomeField{

    @XmlValue
    protected String value;
    @XmlAttribute
    protected BigInteger order;

    // getters  + setters
}

当我们将ATTRIBUTE的顺序设置为2(例如),并且没有为该值设置任何内容时,JAXB将生成:

<pay1:someField order="2"/> 

根据XSD,这是无效的,当我们发送它时会导致SOAP错误。

这确实有效:

<pay1:someField xsi:nil="true" order="2"/>

你知道我们如何让JAXB产生后者吗?并且JAXB在生成无零版本时实际上是错误的吗?

1 个答案:

答案 0 :(得分:2)

  

JAXB在生成无零版本时实际上是错误的吗?

让我回答你。


  

你知道如何让JAXB产生后者吗?

以下是你可以做的事情

Java模型

<强> SomeParentType

要获得您正在寻找的现有JAXB库的行为,域模型需要具有以下形式:

import java.math.BigInteger;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;

@XmlRootElement
public class SomeParentType {

    @XmlElementRef(name="someField")
    protected JAXBElement<SomeParentType.SomeField> someField;

    public static class SomeField{

        @XmlValue
        protected String value;
        @XmlAttribute
        protected BigInteger order;

        // getters  + setters
    }

}

<强>注册表

要与@XmlElementRef一起使用,我们需要在使用@XmlElementDecl注释的班级上设置@XmlRegistry

import javax.xml.namespace.QName;
import javax.xml.bind.*;
import javax.xml.bind.annotation.*;

@XmlRegistry
public class Registry {

    @XmlElementDecl(name="someField")
    public JAXBElement<SomeParentType.SomeField> createSomeField(SomeParentType.SomeField someField) {
        return new JAXBElement(new QName("someField"), SomeParentType.SomeField.class, someField);
    }

}

演示代码

下面是一些练习您的用例的演示代码:

import javax.xml.bind.*;
import java.math.BigInteger;

public class Demo {

    public static void main(String[] args) throws Exception {
        // Create the JAXBContext to bring in the Registry
        JAXBContext jc = JAXBContext.newInstance(SomeParentType.class, Registry.class);

        // Create the instance of SomeField
        SomeParentType.SomeField sf = new SomeParentType.SomeField();
        sf.order = new BigInteger("1");

        // Wrap the SomeField in a JAXBElement & specify the nil aspect
        Registry registry = new Registry();
        JAXBElement<SomeParentType.SomeField> jaxbElement = registry.createSomeField(sf);
        jaxbElement.setNil(true);

        SomeParentType spt = new SomeParentType();
        spt.someField = jaxbElement;

        // Marshal the domain model to XML
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(spt, System.out);
    }

}

<强>输出

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<someParentType>
    <someField xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" order="1" xsi:nil="true"/>
</someParentType>