无法从Java中的SOAP响应中读取字符串值

时间:2018-01-11 17:22:53

标签: java xml web-services soap wsdl

我对Web服务的理解非常有限,我正在努力从SOAP响应信封中读取返回的值。其他一切似乎都运转得很好。

我的任务是创建一个Web服务,并通过重新设计已经为另一个Web服务配置的Java项目来实现。 我继续克隆了正在运行的Web服务项目并开始对其进行修改,以便它能够满足需要(或者至少我希望是这样)。

webservice似乎依赖于名为cxf.xml的配置文件,下面粘贴了内容:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:cxf="http://cxf.apache.org/core" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />


<jaxws:endpoint id="documentOperations" implementor="mypackage.service.DocOperationsImpl" address="/documentOperations">
    <jaxws:properties>
        <entry key="schema-validation-enabled" value="true" />
        <entry key="jaxb-validation-event-handler">
            <bean class="mypackage.interceptor.ValidationEventHandler" />
        </entry>
    </jaxws:properties>

    <!--  This regulates the authentication process -->
    <jaxws:inInterceptors>
        <ref bean="logInBound" />
        <ref bean="saajInInterceptor" />
        <ref bean="wss4JInInterceptor" />        
    </jaxws:inInterceptors>


    <jaxws:schemaLocations>
        <jaxws:schemaLocation>DocOperations.xsd</jaxws:schemaLocation>
    </jaxws:schemaLocations>

</jaxws:endpoint>


<!-- Remaining part cut off, as more than likely irrelevant -->

自动生成的WSDL定义如下:

<!-- Published by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.10-b140319.1121 svn-revision#7b34660d6bc70e587e8ec81a17e4d76af68816a6. -->
<!-- Generated by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.10-b140319.1121 svn-revision#7b34660d6bc70e587e8ec81a17e4d76af68816a6. -->
<definitions targetNamespace="http://service.myservice.com/" name="DocOperations">
<types>
    <xsd:schema>
        <xsd:import namespace="http://service.myservice.com/" schemaLocation="http://localhost:7001/DocumentWebService/DocOperations?xsd=1"/>
    </xsd:schema>
</types>
<message name="hideDocument">
    <part name="parameters" element="tns:hideDocument"/>
</message>
<message name="hideDocumentResponse">
    <part name="parameters" element="tns:hideDocumentResponse"/>
</message>
<portType name="DocOperations">
    <operation name="hideDocument">
        <input wsam:Action="http://service.myservice.com/DocOperations/hideDocument" message="tns:hideDocument"/>
        <output wsam:Action="http://service.myservice.com/DocOperations/hideDocumentResponse" message="tns:hideDocumentResponse"/>
    </operation>
</portType>
<binding name="DocOperationsImplPortBinding" type="tns:DocOperations">
    <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
    <operation name="hideDocument">
        <soap12:operation soapAction="http://service.myservice.com/DocOperations/hideDocument"/>
        <input>
            <soap12:body use="literal"/>
        </input>
        <output>
            <soap12:body use="literal"/>
        </output>
    </operation>
</binding>
<service name="DocOperations">
    <port name="DocOperationsImplPort" binding="tns:DocOperationsImplPortBinding">
        <soap12:address location="http://localhost:7001/DocumentWebService/DocOperations"/>
    </port>
</service>
</definitions>

DocOperations.xsd定义如下:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:tns="http://service.myservice.com/" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0" targetNamespace="http://service.myservice.com/" elementFormDefault="qualified" attributeFormDefault="qualified">

   <xs:element name="hideDocumentResponse" type="xs:string" /> 

   <xs:element name="documentID" type="xs:string" />
   <xs:element name="fileNetGUID" type="xs:string" />
   <xs:element name="comments" type="xs:string" />


</xs:schema>

我有两个类:DocOperations和DocOperationsImpl,两者都定义如下:

DocOperations:

@WebService(name = "DocOperations")
@SOAPBinding(parameterStyle = ParameterStyle.WRAPPED, style = Style.DOCUMENT)
@BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
public interface DocOperations {

    public static final String SUCCESS = "success";
    public static final String FAILURE = "failure";

    @WebMethod(operationName = "hideDocument", action = "http://service.myservice.com/DocOperations/hideDocument")
    public String hideDocument(@WebParam(name = "documentID", targetNamespace="http://service.myservice.com/") String documentID, @WebParam(name = "fileNetGUID", targetNamespace="http://service.myservice.com/") String fileNetGUID, @WebParam(name = "comments", targetNamespace="http://service.myservice.com/") String inputComments);

}

DocOperationsImpl:

@WebService(endpointInterface = "mypackage.service.DocOperations", serviceName = "DocOperations")
@BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
public class DocOperationsImpl implements DocOperations {
    @Override   
    public String hideDocument(String documentID, String fileNetGUID, String inputComments) {
        [...]
   }
}

hideDocument方法返回SUCCESS或FAILURE。

正确调用该方法,并执行应该执行的操作。我可以从服务器端日志中看到该方法返回的字符串是SUCCESS(这可以通过我在SOAP响应信封中看到的证实)。 但是,当客户端尝试读取字符串值时,它始终读为空。

这是肥皂请求信封:

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
 <soap:Header>
    <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
      <wsse:UsernameToken wsu:Id="UsernameToken-1">
        <wsse:Username>TESTUSER</wsse:Username>
        <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">TESTPASSWORD</wsse:Password>
     </wsse:UsernameToken>
    </wsse:Security>
  </soap:Header>
  <soap:Body>
   <ns2:hideDocument xmlns:ns2="http://service.myservice.com/" xmlns:ns3="http://service.myservice.com/">
     <ns2:documentID>44951196459</ns2:documentID>
     <ns2:fileNetGUID>{2F6DE08D-78FB-40E8-95B4-F466167D157D}</ns2:fileNetGUID>
     <ns2:comments>Test</ns2:comments>
   </ns2:hideDocument>
  </soap:Body>
</soap:Envelope>

它被正确解释。

这是肥皂反应信封:

 <?xml version="1.0" encoding="UTF-8"?>
 <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <ns1:hideDocumentResponse xmlns:ns1="http://service.myservice.com/">
        <return xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://service.myservice.com/" xsi:type="xs:string">success</return>
      </ns1:hideDocumentResponse>
   </soap:Body>
</soap:Envelope>

但是,从该方法返回的java变量为null:

String documentWasHidden = webServiceClient.hideDocument(documentID, fileNetGUID, commments);
System.out.println("Value of documentWasHidden = " + documentWasHidden);

我的猜测是,标签中的名称空间不应该存在,但是我不知道DocOperations.xsd(或其他地方)是否需要修改和修改。

任何帮助?

附加说明:我使用的是cxf-2.6.0,wsdl4j-1.6.2和wss4j-1.6.5,并且Web服务作为EAR部署到WebLogic 12C(12.1.3)。

1 个答案:

答案 0 :(得分:0)

找到解决这个愚蠢问题的解决方法。

首先,我在DocOperations类上修改了SOAPBinding注释:

@SOAPBinding(parameterStyle = ParameterStyle.BARE, style = Style.DOCUMENT)

使用此批注,每个Web服务方法只能接收一个输入参数。因为我需要传递三个,所以我创建了一个自定义Java类,其中包含三个属性的getter / setter:

@XmlRootElement(name = "DocumentToHide", namespace = "http://service.myservice.com")
@XmlAccessorType(XmlAccessType.FIELD)
@BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
public class FileInfo implements Serializable {

  private static final long serialVersionUID = -4652784599316765768L;

  private String documentID;

  private String fileNetGUID;

  private String comments;

  public String getDocumentID() {
      return documentID;
  }

  public void setDocumentID(String documentID) {
      this.documentID = documentID;
  }

  public String getFileNetGUID() {
      return fileNetGUID;
  }

  public void setFileNetGUID(String fileNetGUID) {
      this.fileNetGUID = fileNetGUID;
  }

  public String getComments() {
      return comments;
  }

  public void setComments(String comments) {
      this.comments = comments;
  }

}

然后,我修改了DocOperations.xsd文件,使其能够识别输入参数。

我替换了下面的行:

<xs:element name="documentID" type="xs:string" />
<xs:element name="fileNetGUID" type="xs:string" />
<xs:element name="comments" type="xs:string" />

使用:

<xs:element name="DocumentToHide" type="tns:DocumentToHide" />

<xs:complexType name="DocumentToHide">
    <xs:sequence>
        <xs:element name="documentID" type="xs:string" />
        <xs:element name="fileNetGUID" type="xs:string" />
        <xs:element name="comments" type="xs:string" />
    </xs:sequence>
</xs:complexType>

最后,wsimport命令与其他命令一起生成了FileInfo类,然后我在java代码中使用它:

FileInfo documentToHide = new FileInfo();
documentToHide.setDocumentID(documentID);
documentToHide.setFileNetGUID(fileNetGUID);
documentToHide.setComments(commments);
String documentWasMigrated = documentMigrationWebServiceClient.hideDocument(documentToHide);

现在正在正确读取字符串。

现在,SOAP请求信封如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Header>
       <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
         <wsse:UsernameToken wsu:Id="UsernameToken-1">
            <wsse:Username>TESTUSER</wsse:Username>
            <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">TESTPASSWORD</wsse:Password>
         </wsse:UsernameToken>
       </wsse:Security>
    </soap:Header>
    <soap:Body>
       <ns2:DocumentToHide xmlns:ns2="http://service.myservice.com/">
          <ns2:documentID>44951196459</ns2:documentID>
          <ns2:fileNetGUID>{2F6DE08D-78FB-40E8-95B4-F466167D157D}</ns2:fileNetGUID>
          <ns2:comments>Test</ns2:comments>
       </ns2:DocumentToHide>
    </soap:Body>
</soap:Envelope>

SOAP响应如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <hideDocumentResponse xmlns="http://service.myservice.com/">success</hideDocumentResponse>
   </soap:Body>
</soap:Envelope>

值得庆幸的是,它可以被阅读。

但仍然感到困惑的是,为什么它现在正在使用BARE设置,而不是在它被包裹的时候。