2015-05-06 65 views
6

这个问题让我陷入了近两天的困境,我真的需要一些帮助来解决它。SOAP服务响应无法映射

我已经使用wsimport从两个不同的.wsdl文件为Java项目生成代码。

第一个服务工作正常,但由于某种原因,第二个服务的响应无法解组到响应对象。

工作业务:

@WebMethod(action = "[actionName]") 
@WebResult(name = "getSimpleCompanyInfoResponse", partName = "getSimpleCompanyInfoResponse") 
public GetSimpleCompanyInfoResponse getSimpleCompanyInfo(
     @WebParam(name = "getSimpleCompanyInfoRequest", partName = "getSimpleCompanyInfoRequest") GetSimpleCompanyInfoRequest getSimpleCompanyInfoRequest); 

响应POJO:

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "getSimpleCompanyInfoResponse", propOrder = { 
    //variables 
}) 
public class GetSimpleCompanyInfoResponse { 
    //variables 
} 

响应XML:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="[namespaceUri]" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <SOAP-ENV:Body> 
     <ns1:getSimpleCompanyInfoResponse> 
      <getSimpleCompanyInfoResponse> 
       //variables 
      </getSimpleCompanyInfoResponse> 
     </ns1:getSimpleCompanyInfoResponse> 
    </SOAP-ENV:Body> 
</SOAP-ENV:Envelope> 

工作服务:

@WebMethod(operationName = "PersonnelInfo", action = "[actionName]") 
@WebResult(name = "PersonnelInfoResponse", partName = "PersonnelInfoResponse") 
public PersonnelInfoResponse personnelInfo(
@WebParam(name = "PersonnelInfoRequest", partName = "PersonnelInfoRequest") PersonnelInfoRequest personnelInfoRequest); 

响应POJO:

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "PersonnelInfoResponse", propOrder = { 
    //variables 
}) 
public class PersonnelInfoResponse { 
    //variables 
} 

响应XML:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="[namespaceUri]" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <SOAP-ENV:Body> 
     <ns1:PersonnelInfoResponse> 
      //variables 
     </ns1:PersonnelInfoResponse> 
    </SOAP-ENV:Body> 
</SOAP-ENV:Envelope> 

使用-Dcom.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump =真或使用Wireshark进行监控我可以看到来自第二个服务的响应信封通过恰好的罚款和解组不会抛出任何例外,但最终PersonnelInfoResponse为空。

我能看到的唯一区别是XML中的第二个服务响应负载缺少似乎是问题的外部元素。但是,我不知道如何“修复”它,因此它不寻找外部元素。

如果有什么不清楚或缺失,请让我知道,我会尽力给你所有的信息。

编辑:

不,我很遗憾没有对服务本身的任何控制,我只有和的.wsdl的.xsd。

我打电话的服务这样的:

ReportsControllerPortType port = new ReportsControllerService().getReportsControllerPort(); 

PersonnelInfoRequest request = new PersonnelInfoRequest(); 
//fill the required fields in the request, username, password, etc. 

PersonnelInfoResponse response = port.personnelInfo(request); 

客户端侧的服务存根(ReportsControllerService & ReportsControllerPortType)也由的wsimport根据的.wsdl和的.xsd自动生成。

编辑2:

删除操作名称不工作,服务无法初始化。以下是两者的定义。WSDL-S:

工作业务:

<wsdl:message name="getSimpleCompanyInfoRequest"> 
    <wsdl:part name="getSimpleCompanyInfoRequest" type="tns:getSimpleCompanyInfoRequest" /> 
</wsdl:message> 
<wsdl:message name="getSimpleCompanyInfoResponse"> 
    <wsdl:part name="getSimpleCompanyInfoResponse" type="tns:getSimpleCompanyInfoResponse" /> 
</wsdl:message> 

<wsdl:portType name="MonitoringControllerPortType"> 
    <wsdl:operation name="getSimpleCompanyInfo"> 
     <wsdl:input message="tns:getSimpleCompanyInfoRequest" /> 
     <wsdl:output message="tns:getSimpleCompanyInfoResponse" /> 
    </wsdl:operation> 
</wsdl:portType> 

<wsdl:binding name="MonitoringControllerBinding" type="tns:MonitoringControllerPortType"> 
    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" /> 

    <wsdl:operation name="getSimpleCompanyInfo"> 
     <soap:operation soapAction="[domain]/#getSimpleCompanyInfo" style="rpc" /> 
     <wsdl:input> 
      <soap:body use="literal" namespace="[namespaceUri]" /> 
     </wsdl:input> 
     <wsdl:output> 
      <soap:body use="literal" namespace="[namespaceUri]" /> 
     </wsdl:output> 
    </wsdl:operation> 
</wsdl:binding> 

<wsdl:service name="MonitoringControllerService"> 
    <wsdl:port name="MonitoringControllerPort" binding="tns:MonitoringControllerBinding"> 
     <soap:address location="[serviceUri]" /> 
    </wsdl:port> 
</wsdl:service> 

工作服务:

<wsdl:message name="PersonnelInfoRequest"> 
    <wsdl:part name="PersonnelInfoRequest" type="tns:PersonnelInfoRequest" /> 
</wsdl:message> 
<wsdl:message name="PersonnelInfoResponse"> 
    <wsdl:part name="PersonnelInfoResponse" type="tns:PersonnelInfoResponse" /> 
</wsdl:message> 

<wsdl:portType name="ReportsControllerPortType"> 
    <wsdl:operation name="PersonnelInfo"> 
     <wsdl:input message="tns:PersonnelInfoRequest" /> 
     <wsdl:output message="tns:PersonnelInfoResponse" /> 
    </wsdl:operation> 
</wsdl:portType> 

<wsdl:binding name="ReportsControllerBinding" type="tns:ReportsControllerPortType"> 
    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" /> 
    <wsdl:operation name="PersonnelInfo"> 
     <soap:operation soapAction="[domain]/#PersonnelInfo" style="rpc" /> 
     <wsdl:input> 
      <soap:body use="literal" namespace="[namespaceUri]" /> 
     </wsdl:input> 
     <wsdl:output> 
      <soap:body use="literal" namespace="[namespaceUri]" /> 
     </wsdl:output> 
    </wsdl:operation> 
</wsdl:binding> 

<wsdl:service name="ReportsControllerService"> 
    <wsdl:port name="ReportsControllerPort" binding="tns:ReportsControllerBinding"> 
     <soap:address location="[serviceUri]" /> 
    </wsdl:port> 
</wsdl:service> 

编辑3:

ReportsControllerServiceMonitoringControllerService扩展javax.xml.ws.Service并包含使用的.wsdl模式位置和名称空间的定义。服务类返回端口类型的对象,你可以看到:

/** 
* This class was generated by the JAX-WS RI. JAX-WS RI 2.2.9-b130926.1035 Generated source version: 2.2 
*/ 
@WebServiceClient(name = "ReportsControllerService", targetNamespace = "[namespaceUri]", wsdlLocation = "[wsdlUri]") 
public class ReportsControllerService extends Service { 

    @WebEndpoint(name = "ReportsControllerPort") 
    public ReportsControllerPortType getReportsControllerPort() { 
     return super.getPort(new QName("[namespaceUri]", "ReportsControllerPort"), ReportsControllerPortType.class); 
    } 
} 

ReportsControllerPortType是其中包含了存在于服务的每一个操作终端的方法的接口

/** 
* This class was generated by the JAX-WS RI. JAX-WS RI 2.2.9-b130926.1035 Generated source version: 2.2 
*/ 
@WebService(name = "ReportsControllerPortType", targetNamespace = "[namespaceUri]") 
@SOAPBinding(style = SOAPBinding.Style.RPC) 
@XmlSeeAlso({ObjectFactory.class}) 
public interface ReportsControllerPortType { 

    @WebMethod(operationName = "PersonnelInfo", action = "[actionName]") 
    @WebResult(name = "PersonnelInfoResponse", partName = "PersonnelInfoResponse") 
    public PersonnelInfoResponse personnelInfo(
     @WebParam(name = "PersonnelInfoRequest", partName = "PersonnelInfoRequest") PersonnelInfoRequest personnelInfoRequest); 
    } 
} 

的事情是,所有的这些类是由JAX-WS根据.wsdl模式自动生成的(如您从注释中看到的那样)。这个实现抽象出JDK内部的某个地方,我也无法控制它。是的,我可以重构代码,所以我绕过JAX-WS,但据我了解,这应该是一个事实上标准的方式来使用基于.wsdl的SOAP服务。

该项目使用Spring作为基础框架,我已经确认这两个服务将工作时,我使用Spring-WS,所以我可以重构,但我想明白为什么这种方式不工作。

+0

你的问题有点不清楚:你打电话给服务?你是否控制了服务和客户? – kolossus

+0

@kolossus,我编辑了我的问题来回答你的问题。 – rorschach

+0

什么是'ReportsControllerService'和'getReportsControllerPort()'中发生了什么? – kolossus

回答

1

我相信我可能已经发现为什么你的web服务行为不当。根据规范,一个RPC web服务必须履行其肥皂以下标准结合(即@SOAPBinding注解你那里)

  1. RPC一个style:检查

  2. 一个useLITERAL:检查

  3. A parameterStyle of WRAPPED:从您给出的描述看,WRAPPED看起来是n在这里的情况下,看到你收到一个裸体PersonnelInfoResponse(并可能发送一个裸体PersonnelInfoRequest)没有任何包装表明该服务本身已被打破。

the JAX-WS spec的摘录:

RPC风格的使用方式需要使用WRAPPED参数样式。偏离这是错误

+0

'PersonnelInfoRequest'正在发送出'PersonnelInfo'包裹,但是,结果是一个裸体'PersonnelInfoResponse'。从我在Google上也能找到的问题看来确实存在问题。谢谢你确认。唉,我无法控制服务,所以我重构了代码并使用Spring-WS进行调用。现在它可以工作。 – rorschach

0

还有就是你的2个呼叫之间有一个明显的区别:

你应该尝试从你的第二个电话是不存在的第一个工作一个删除operationName = "PersonnelInfo"

+0

这不起作用,因为,据我了解,如果它缺少,然后JAX-WS尝试解析方法签名的操作名称。由于该方法以小写* p *开头,因此失败。我用.wsdl定义更新了原始文章,因为您也可以看到它们在结构上几乎完全相同。 – rorschach