【问题标题】:JAX WS, JAXB and Null elements with attributes具有属性的 JAX WS、JAXB 和 Null 元素
【发布时间】:2013-09-16 17:38:50
【问题描述】:

我正在尝试使用 JAXWS 和 wsimport 使用 Web 服务。 WSIMPORT 工具生成了所有必需的类,我可以毫无问题地调用该服务。

但是,我注意到在响应包含具有有效属性值的 nil 元素的情况下,JAXWS 无法解组它并抛出 NullPointerException。我使用 SOAP UI 来帮助调试,这就是我发现的。响应返回以下 XML(摘录):

            <externalIdentifiers>
                 <identifierType code="2" name="Passport" xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
                 <identifierValue/>
                 <issuingCountry xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
              </externalIdentifiers>

在我的 Java 代码中,当尝试读取上述标识符类型的“名称”属性时,它会抛出 NPE:

      if(id.getIdentifierType() == null)
            {
                System.out.println("NULL");
            }
            System.out.println("Identifier Type: " + id.getIdentifierType().getName());

输出:

NULL
Exception in thread "main" java.lang.NullPointerException

对我来说,在响应中看起来确实是一个合理的响应,identifierType 设置为 xsi:nil="true"。根据 W3C,这也是完全有效的 XML。问题是,这种情况下如何读取code、name等属性值?

【问题讨论】:

    标签: attributes jaxb jax-ws null


    【解决方案1】:

    以下是支持此用例的方法:

    Java 模型

    外部标识符

    您可以将identifierType 属性更改为JAXBElement&lt;IdentifierType&gt; 类型而不是IdentifierType。为此,您需要使用 @XmlElementRef 注释属性。

    import javax.xml.bind.JAXBElement;
    import javax.xml.bind.annotation.*;
    
    @XmlRootElement
    @XmlAccessorType(XmlAccessType.FIELD)
    public class ExternalIdentifiers {
    
        @XmlElementRef(name="identifierType")
        private JAXBElement<IdentifierType> identifierType;
    
        public JAXBElement<IdentifierType> getIdentifierType() {
            return identifierType;
        }
    
    }
    

    对象工厂

    您需要在使用@XmlRegistry 注释的类中的create 方法上使用相应的@XmlElementDecl 注释。

    import javax.xml.bind.JAXBElement;
    import javax.xml.bind.annotation.*;
    import javax.xml.namespace.QName;
    
    @XmlRegistry
    public class ObjectFactory {
    
        @XmlElementDecl(name="identifierType")
        public JAXBElement<IdentifierType> createIdentifierType(IdentifierType identifierType) {
            return new JAXBElement(new QName("identifierType"), IdentifierType.class, identifierType);
        }
    
    }
    

    演示代码

    input.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <externalIdentifiers>
        <identifierType code="2" name="Passport" xsi:nil="true"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
    </externalIdentifiers>
    

    演示

    import java.io.File;
    import javax.xml.bind.*;
    
    public class Demo {
    
        public static void main(String[] args) throws Exception {
            JAXBContext jc = JAXBContext.newInstance(ExternalIdentifiers.class, ObjectFactory.class);
    
            Unmarshaller unmarshaller = jc.createUnmarshaller();
            File xml = new File("src/forum18834036/input.xml");
            ExternalIdentifiers externalIdentifiers = (ExternalIdentifiers) unmarshaller.unmarshal(xml);
    
            System.out.println(externalIdentifiers.getIdentifierType().getValue().getName());
        }
    
    }
    

    输出

    Passport
    

    注意

    目前EclipseLink JAXB (MOXy) 中有一个关于此用例的错误:

    【讨论】:

    • 您好,感谢您的回复并为我指明了正确的方向。如何将它连接到 JAX-WS 客户端?我尝试创建一个外部绑定文件并使用一个类规范和一个 ref 属性,但不知道如何挂钩 ObjectFactory。我还意识到绑定文件中的以下内容也可以: > > > 但是,它将所有内容都包装在 JAXBElement 中,所以我必须对所有内容执行 getValue 。我如何挂钩您建议与 JAX-WS 客户端一起使用的内容?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-27
    • 2013-01-10
    • 1970-01-01
    • 1970-01-01
    • 2012-05-09
    • 2019-03-22
    • 1970-01-01
    相关资源
    最近更新 更多