创建SOAP文档时抛出IllegalArgumentException:QName本地部分不能为空
解决SOAP消息添加Fault时的QName本地部分为空异常
异常详情
Exception in thread "main" java.lang.IllegalArgumentException: local part cannot be "null" when creating a QName at javax.xml.namespace.QName.<init>(QName.java:244) at javax.xml.namespace.QName.<init>(QName.java:188) at com.sun.xml.messaging.saaj.soap.impl.ElementImpl.<init>(ElementImpl.java:156) at com.sun.xml.messaging.saaj.soap.impl.ElementFactory.createElement(ElementFactory.java:119) at com.sun.xml.messaging.saaj.soap.SOAPDocumentImpl.registerChildNodes(SOAPDocumentImpl.java:230) at com.sun.xml.messaging.saaj.soap.SOAPDocumentImpl.registerChildNodes(SOAPDocumentImpl.java:251) at com.sun.xml.messaging.saaj.soap.SOAPDocumentImpl.registerChildNodes(SOAPDocumentImpl.java:251) at com.sun.xml.messaging.saaj.soap.SOAPDocumentImpl.importNode(SOAPDocumentImpl.java:217) at com.sun.xml.messaging.saaj.soap.impl.BodyImpl.addDocument(BodyImpl.java:259) at com.example.demo.Demo1Application.getMessage(Demo1Application.java:29) at com.example.demo.Demo1Application.main(Demo1Application.java:23) Process finished with exit code 1
问题根源
你的代码存在两个核心问题:
- 元素名格式错误:在
newFaultDocument方法中,创建Fault元素时使用了"Fault:abc"作为元素名,违反了XML限定名(QName)规范。createElementNS的第二个参数应为前缀:本地名格式,但SOAP Fault的标准本地名必须是Fault,且此处的Fault并非合法前缀(SOAP信封的标准前缀是soap)。错误的元素名导致SAJ解析QName时出现本地部分为空的异常。 - 手动构建Document的风险:通过外部Document构建Fault再导入SOAPBody的方式,容易引发命名空间不匹配、QName解析错误等问题,不符合SOAP API的使用规范。
修复方案
最优方案:使用SOAP原生API创建Fault
直接利用SAJ提供的SOAPBody.addFault方法创建Fault,代码简洁且完全符合SOAP规范,避免手动构建Document的问题:
public static SOAPMessage getMessage() throws SOAPException { SOAPMessage message = newSoapMessage((XmlObject) null); SOAPBody respBody = message.getSOAPBody(); // 直接创建SOAP Fault,指定faultCode和faultString SOAPFault fault = respBody.addFault( QName.valueOf("soap:Server"), "faultText" ); message.saveChanges(); return message; }
备选方案:修正手动构建Document的代码
如果必须手动构建Document,需修正元素名和命名空间的设置:
public static Document newFaultDocument(String faultCode, String faultString) { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); try { String soapNs = "http://schemas.xmlsoap.org/soap/envelope/"; Document doc = factory.newDocumentBuilder().newDocument(); // 正确指定前缀和本地名:soap:Fault Element fault = doc.createElementNS(soapNs, "soap:Fault"); doc.appendChild(fault); // 子元素需关联SOAP命名空间 Element faultCodeElement = doc.createElementNS(soapNs, "faultcode"); faultCodeElement.setTextContent(StringEscapeUtils.escapeXml(faultCode)); fault.appendChild(faultCodeElement); Element faultStringElement = doc.createElementNS(soapNs, "faultstring"); faultStringElement.setTextContent(StringEscapeUtils.escapeXml(faultString)); fault.appendChild(faultStringElement); return doc; } catch (ParserConfigurationException e) { throw new IllegalStateException("Unexpected exception while creating Fault document", e); } }
内容的提问来源于stack exchange,提问作者SAURABH NANDY
相关产品推荐
相关产品推荐

