soap - JAXB 'forgets' 在设置属性值但未设置元素值时添加 nil ='true'

标签 soap attributes jaxb null

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

当我们在 someField 上设置 order 属性但没有值时,JAXB 将在请求中生成不带 nill='true' 的 XML 元素,并且 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
}

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

<pay1:someField order="2"/> 

根据 XSD,这无效,并且在我们发送它时会导致 SOAP 错误。

这确实有效:

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

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

最佳答案

And is JAXB actually wrong in generating the nil-less version?

让我回复您。


Do you know how we can get JAXB be to generate the latter?

以下是您可以执行的操作

Java 模型

某些父类型

要通过现有 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配合使用,我们需要在用@XmlRegistry注释的类上有一个@XmlElementDecl

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>

关于soap - JAXB 'forgets' 在设置属性值但未设置元素值时添加 nil ='true',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26657098/

相关文章:

java - 如何使用 JAX-WS 在 AXL Java 客户端中使用 GetLineReq

javascript - 将多条数据传递给一个 JQuery 对象

java - 有没有办法在 servlet session 中创建 "one time use"属性?

java - JAXB 解码 : unexpected element

java - JAXB - 从 XSD 生成类 - 将枚举转换为自定义 toString() 而不是枚举名称

PHP-EWS "Soap client returned status of 404"

Java(Web 服务 - SOAP)- 如何在客户端添加 SOAP 处理程序并正确启用 MTOM?

java - 在 return 语句之后做一些事情 - Java

php - PHP 7 中属性的类型提示?

java - 如何在 jaxb 中编写我无法控制的对象?