java - 使用 Spring-ws 中的 WebServiceTemplate 生成空 namespace 前缀

标签 java web-services xml-namespaces spring-ws axiom

我们使用 Spring-ws 版本 2.4.2.RELEASE 从 WSDL 调用外部 WebService。

我们调用的方法是:

ValidateObjectResponse response = (ValidateObjectResponse) webServiceTemplate.marshalSendAndReceive(request);

生成的 SOAP 请求包含空命名空间前缀:

<SOAP-ENV:Envelope xmlns:SOAPENV="http://schemas.xmlsoap.org/soap/envelope/"> 
    <SOAP-ENV:Header/>
    <SOAP-ENV:Body>
        <ns2:validateObject xmlns:ns2="http://ws.validator.sch.gazelle.ihe.net/" xmlns=""><base64ObjectToValidate>Cgo8P3ht...
    </SOAP-ENV:Body>
</SOAP-ENV>

在幕后,使用了 apache axiom(版本 1.2.13),并且在发行说明中我读到了以下内容 ( https://ws.apache.org/axiom/release-notes/1.2.13.html ):

“在 Axiom 1.2.12 中,OMElement 中的 declareNamespace 方法不强制执行此约束,违反此要求的命名空间声明会在序列化过程中被静默删除。此行为是有问题的,因为它可能会导致未绑定(bind)命名空间前缀等微妙问题。在 Axiom 1.2.13 中,这些方法已更改,以便在尝试将空命名空间名称绑定(bind)到前缀时抛出异常。”

当我们调用外部Web服务时,我们得到以下异常:

java.lang.IllegalArgumentException: Cannot bind a prefix to the empty namespace name
at org.apache.axiom.om.impl.dom.ElementImpl.declareNamespace(ElementImpl.java:754)
at org.apache.axiom.om.impl.dom.ElementImpl.declareNamespace(ElementImpl.java:778)
at org.apache.axiom.om.impl.dom.ElementImpl.setAttributeNS(ElementImpl.java:559)
at com.sun.xml.bind.marshaller.SAX2DOMEx.startElement(SAX2DOMEx.java:163)
at com.sun.xml.bind.v2.runtime.output.SAXOutput.endStartTag(SAXOutput.java:124)
at com.sun.xml.bind.v2.runtime.XMLSerializer.endAttributes(XMLSerializer.java:302)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsSoleContent(XMLSerializer.java:588)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:312)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:490)
at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:328)
at com.sun.xml.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:257)
at org.springframework.oxm.jaxb.Jaxb2Marshaller.marshal(Jaxb2Marshaller.java:680)
at org.springframework.ws.support.MarshallingUtils.marshal(MarshallingUtils.java:81)
at org.springframework.ws.client.core.WebServiceTemplate$2.doWithMessage(WebServiceTemplate.java:399)
at org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:590)
at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:555)
at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:390)
at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:383)
at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:373)

我的第一个想法是将 axiom 的版本降低到 2.1.12,但这会与其他库发生冲突。

有没有办法避免使用 spring-ws 创建空 namespace 前缀?

我们有一个 WSDL,在我看来,一切都很好,但我们无法修改它:

<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://ws.validator.sch.gazelle.ihe.net/"
              xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
              name="GazelleObjectValidatorService" targetNamespace="http://ws.validator.sch.gazelle.ihe.net/">
    <wsdl:types>
        <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://ws.validator.sch.gazelle.ihe.net/"
               attributeFormDefault="unqualified" elementFormDefault="unqualified"
               targetNamespace="http://ws.validator.sch.gazelle.ihe.net/">
        <xs:element name="about" type="tns:about"/>
        <xs:element name="aboutResponse" type="tns:aboutResponse"/>
        <xs:element name="getAllAvailableObjectTypes" type="tns:getAllAvailableObjectTypes"/>
        <xs:element name="getAllAvailableObjectTypesResponse" type="tns:getAllAvailableObjectTypesResponse"/>
        <xs:element name="getAllSchematrons" type="tns:getAllSchematrons"/>
        <xs:element name="getAllSchematronsResponse" type="tns:getAllSchematronsResponse"/>
        <xs:element name="getSchematronByName" type="tns:getSchematronByName"/>
        <xs:element name="getSchematronByNameResponse" type="tns:getSchematronByNameResponse"/>
        <xs:element name="getSchematronsForAGivenType" type="tns:getSchematronsForAGivenType"/>
        <xs:element name="getSchematronsForAGivenTypeResponse" type="tns:getSchematronsForAGivenTypeResponse"/>
        <xs:element name="validateObject" type="tns:validateObject"/>
        <xs:element name="validateObjectResponse" type="tns:validateObjectResponse"/>

这是我们创建 WebServiceTemplate 的代码:

Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setPackagesToScan("com.test");
WebServiceTemplate webServiceTemplate = new WebServiceTemplate(marshaller);
webServiceTemplate.setDefaultUri(defaultUri);
webServiceTemplate.setMessageSender(new HttpComponentsMessageSender(httpClientBuilder.build()));

ValidateObject request = new ValidateObject();
request.setBase64ObjectToValidate(base64Object);
request.setXmlReferencedStandard(xmlReferencedStandard);
request.setXmlMetadata(xmlMetadata);
ValidateObjectResponse response = (ValidateObjectResponse) 
webServiceTemplate.marshalSendAndReceive(request);
return response.getValidationResult();

问题是如何避免生成空命名空间名称:

<ns2:validateObject xmlns:ns2="http://ws.validator.sch.gazelle.ihe.net/" xmlns=""> 

这样公理就不能再提示了?

最佳答案

问题最终是 spring-ws 使用的 axiom jar 和 Axis 使用的 axiom jar 之间的 jar 冲突。

通过强制 WebServiceTemplate 使用特定的 SaajSoapMessageFactory:

SaajSoapMessageFactory saajSoapMessageFactory = new SaajSoapMessageFactory(new SOAPMessageFactory1_1Impl());
saajSoapMessageFactory.setSoapVersion(SoapVersion.SOAP_11);
saajSoapMessageFactory.afterPropertiesSet();

webServiceTemplate.setMessageFactory(saajSoapMessageFactory);

我们设法解决了我们的问题。

关于java - 使用 Spring-ws 中的 WebServiceTemplate 生成空 namespace 前缀,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51482645/

相关文章:

java - 转换或使用重载方法是更好的做法吗?

javascript - Node HTTP 和 WS 服务器未按预期升级连接

c# - 在 IIS 中部署 Web 服务?

java - 来自 Apache 2.2 服务器的 CONNECTION_REFUSED(到 weblogic 10.3.6 服务器的 channel )

java - XMLEventWriter 从头开始​​ : how do I emit xmlns attribute?

c# - XAML:命名空间奇怪的行为 Visual Studio

java - ByteBuddy 子类构造器

java - Android TextView 换行

jsf - 可以将 JSF 应用程序配置为在不使用 Internet 连接的情况下运行吗?

java - 如何知道 BigDecimal 是否可以准确转换为 float 或 double?