WebService无法处理SOAP Body没有名称空间前缀的请求

use*_*997 11 java soap web-services namespaces jax-ws

当客户端调用Web服务而不在SOAP Body中传递前缀时,我的Web服务无法处理客户端的请求,如下所示:

<soap:Body> 
 <GetPatientResultsRequest xmlns="http://urlA"> 
  <PatientIdentification> 
      <PersonCivilRegistrationIdentifier xmlns="http://UrlB"/> 
  </PatientIdentification> 
  <Period> 
    <From>2012-05-26</From> 
     <To>2012-06-26</To> 
   </Period> 
 </GetPatientResultsRequest> 
</soap:Body>
Run Code Online (Sandbox Code Playgroud)

错误是GetPatientResultsRequest与其他对应的Java对象为null.

似乎在Body中没有前缀时,反序列化没有正确发生.我的Web服务只有在SOAP Body有前缀时才能响应

<soap:Body> 
 <m:GetPatientResultsRequest xmlns:m="http://urlA">
  <PatientIdentification> 
      <PersonCivilRegistrationIdentifier xmlns="http://UrlB"/> 
  </PatientIdentification> 
  <Period> 
    <From>2012-05-26</From> 
     <To>2012-06-26</To> 
   </Period> 
 </m:GetPatientResultsRequest> 
</soap:Body>
Run Code Online (Sandbox Code Playgroud)

任何人都可以让我知道该怎么做,以便我的Web服务可以获取各种SOAP请求(即在Body中有和没有前缀)?

我正在使用JAX-WS(SOAP 1.1)

Bog*_*dan 10

Web服务定义了一个您必须遵循的合同才能调用它.您发布的示例中只有一条消息与该合同匹配,因此一方合作,另一条则不起作用.

在您的第一条消息中,您定义了一个默认命名空间(因为xmlns包装器中的属性),并且所有未取消声明且没有前缀的元素都在同一命名空间中,因为它们从父节点继承它.

在第二条消息中,您有一个显式的前缀声明,只有包装器在该命名空间中,其他元素不在命名空间中,并且不从父级继承默认值(因为xmlns缺少属性).

正如我在开始时所说,Web服务定义了一个合同.修改客户端以发送正确的消息而不是更改服务以接受来自客户端的错误消息更有意义.

要控制元素的命名空间,您需要使用Web服务和客户端targetNamespace的JAX-WS注释上的值.

下面是一个示例,可以在更改目标命名空间时查看代码和消息格式的差异.我将使用基本的WSDL:

<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions 
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
xmlns:tns="http://tempuri.org" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
targetNamespace="http://tempuri.org" 
name="CalculatorWS">
  <wsdl:types>
    <xs:schema targetNamespace="http://tempuri.org">
      <xs:element name="add" type="tns:add" />
      <xs:element name="addInput" type="tns:addInput" />
      <xs:element name="addResponse" type="tns:addResponse" />
      <xs:element name="addOutput" type="tns:addOutput" />
      <xs:complexType name="add">
        <xs:sequence>
          <xs:element name="addInput" type="tns:addInput" />
        </xs:sequence>
      </xs:complexType>
      <xs:complexType name="addInput">
        <xs:sequence>
          <xs:element name="a" type="xs:int" />
          <xs:element name="b" type="xs:int" />
        </xs:sequence>
      </xs:complexType>
      <xs:complexType name="addResponse">
        <xs:sequence>
          <xs:element name="addOutput" type="tns:addOutput" />
        </xs:sequence>
      </xs:complexType>
      <xs:complexType name="addOutput">
        <xs:sequence>
          <xs:element name="result" type="xs:int" />
        </xs:sequence>
      </xs:complexType>
    </xs:schema>
  </wsdl:types>
  <wsdl:message name="add">
    <wsdl:part name="parameters" element="tns:add" />
  </wsdl:message>
  <wsdl:message name="addResponse">
    <wsdl:part name="parameters" element="tns:addResponse" />
  </wsdl:message>
  <wsdl:portType name="CalculatorWS">
    <wsdl:operation name="add">
      <wsdl:input message="tns:add" />
      <wsdl:output message="tns:addResponse" />
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="CalculatorWSPortBinding" type="tns:CalculatorWS">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
    <wsdl:operation name="add">
      <soap:operation soapAction="http://tempuri.org/add" />
      <wsdl:input>
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal" />
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="CalculatorWSService">
    <wsdl:port name="CalculatorWSPort" binding="tns:CalculatorWSPortBinding">
      <soap:address location="http://localhost:8080/WebServices/CalculatorWS" />
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>
Run Code Online (Sandbox Code Playgroud)

这定义了以下消息:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
        xmlns:tem="http://tempuri.org">
   <soapenv:Body>
      <tem:add>
         <addInput>
            <a>?</a>
            <b>?</b>
         </addInput>
      </tem:add>
   </soapenv:Body>
</soapenv:Envelope>
Run Code Online (Sandbox Code Playgroud)

和:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
       xmlns:tem="http://tempuri.org">
   <soapenv:Body>
      <tem:addResponse>
         <addOutput>
            <result>?</result>
         </addOutput>
      </tem:addResponse>
   </soapenv:Body>
</soapenv:Envelope>
Run Code Online (Sandbox Code Playgroud)

请参阅包装器上的命名空间前缀?这是因为元素在http://tempuri.org命名空间中声明,而其他元素不在命名空间中.

您甚至可以从命名空间中删除所有元素.从WSDL中剥离目标命名空间并使其看起来像这样:

<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions 
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
name="CalculatorWS">
  <wsdl:types>
    <xs:schema>
      <xs:element name="add" type="add" />
      <xs:element name="addInput" type="addInput" />
      <xs:element name="addResponse" type="addResponse" />
      <xs:element name="addOutput" type="addOutput" />
      <xs:complexType name="add">
        <xs:sequence>
          <xs:element name="addInput" type="addInput" />
        </xs:sequence>
      </xs:complexType>
      <xs:complexType name="addInput">
        <xs:sequence>
          <xs:element name="a" type="xs:int" />
          <xs:element name="b" type="xs:int" />
        </xs:sequence>
      </xs:complexType>
      <xs:complexType name="addResponse">
        <xs:sequence>
          <xs:element name="addOutput" type="addOutput" />
        </xs:sequence>
      </xs:complexType>
      <xs:complexType name="addOutput">
        <xs:sequence>
          <xs:element name="result" type="xs:int" />
        </xs:sequence>
      </xs:complexType>
    </xs:schema>
  </wsdl:types>
  <wsdl:message name="add">
    <wsdl:part name="parameters" element="add" />
  </wsdl:message>
  <wsdl:message name="addResponse">
    <wsdl:part name="parameters" element="addResponse" />
  </wsdl:message>
  <wsdl:portType name="CalculatorWS">
    <wsdl:operation name="add">
      <wsdl:input message="add" />
      <wsdl:output message="addResponse" />
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="CalculatorWSPortBinding" type="CalculatorWS">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
    <wsdl:operation name="add">
      <soap:operation soapAction="http://tempuri.org/add" />
      <wsdl:input>
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal" />
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="CalculatorWSService">
    <wsdl:port name="CalculatorWSPort" binding="CalculatorWSPortBinding">
      <soap:address location="http://localhost:8080/WebServices/CalculatorWS" />
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>
Run Code Online (Sandbox Code Playgroud)

这个新的WSDL将对应于以下消息:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Body>
      <add>
         <addInput>
            <a>?</a>
            <b>?</b>
         </addInput>
      </add>
   </soapenv:Body>
</soapenv:Envelope>
Run Code Online (Sandbox Code Playgroud)

和:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Body>
      <addResponse>
         <addOutput>
            <result>?</result>
         </addOutput>
      </addResponse>
   </soapenv:Body>
</soapenv:Envelope>
Run Code Online (Sandbox Code Playgroud)

在这种情况下没有前缀.

现在wsimport.exe在两个WSDL上使用,你会看到我在开始时讨论的目标命名空间,即从这里改变:

@WebService(name = "CalculatorWS", targetNamespace = "http://tempuri.org")
public interface CalculatorWS {
    @WebMethod(action = "http://tempuri.org/add")
    @WebResult(name = "addOutput", targetNamespace = "")
    @RequestWrapper(localName = "add", targetNamespace = "http://tempuri.org", className = "your.pack.age.Add")
    @ResponseWrapper(localName = "addResponse", targetNamespace = "http://tempuri.org", className = "your.pack.age.AddResponse")
    public AddOutput add(
        @WebParam(name = "addInput", targetNamespace = "")
        AddInput addInput);
}
Run Code Online (Sandbox Code Playgroud)

对此:

@WebService(name = "CalculatorWS", targetNamespace = "")
public interface CalculatorWS {
    @WebMethod(action = "http://tempuri.org/add")
    @WebResult(name = "addOutput", targetNamespace = "")
    @RequestWrapper(localName = "add", targetNamespace = "", className = "your.pack.age.Add")
    @ResponseWrapper(localName = "addResponse", targetNamespace = "", className = "your.pack.age.AddResponse")
    public AddOutput add(
        @WebParam(name = "addInput", targetNamespace = "")
        AddInput addInput);
}
Run Code Online (Sandbox Code Playgroud)

控制targetNamespace,您将控制消息的外观.