简体   繁体   中英

Cannot read string value from SOAP response in Java

My understanding of web services is very limited, and I am struggling reading the returned value from the SOAP response envelope. Everything else seems to be working just fine.

I was tasked with creating a web service, and do so by re-purposing a Java project already configured for another web service. I went ahead and cloned the working web service project and started to modify it so that it does what's needed (or at least I had hoped that was the case).

The webservice seems to be relying on a configuration file named cxf.xml, contents pasted below:

<?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 -->

The WSDL, generated automatically, is defined below:

<!-- 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>

The DocOperations.xsd is defined below:

<?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>

I have two classes: DocOperations and DocOperationsImpl, both defined below:

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) {
        [...]
   }
}

The hideDocument method either returns SUCCESS or FAILURE.

The method is invoked correctly, and performs the operations it should. I can see from the server-side logs that the string that the method returns is the SUCCESS (this is corroborated by what I see in the SOAP response envelope). However, when the client tries to read the string value, it always reads null.

This is the soap request envelope:

<?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>

It gets interpreted correctly.

This is the soap response 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>

However, the java variable returned from the method is null:

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

My guess, is that the namespaces in the tag shouldn't be there, however I don't know if and what modifications are necessary to DocOperations.xsd (or some other place).

Any help?

Additional notes: I am using cxf-2.6.0, wsdl4j-1.6.2 and wss4j-1.6.5, and the web service is deployed as an EAR to WebLogic 12C (12.1.3).

Found a workaround to deal with this silly problem.

First, I modified the SOAPBinding annotation on the DocOperations class:

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

Using this annotation, each web service method can only receive one input parameter. Because I had a need to pass three, I created a custom Java class, with getters/setters for three properties:

@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;
  }

}

Then, I modified the DocOperations.xsd file, to make it so that the input parameters would be recognized.

I replaced the below lines:

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

With:

<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>

Finally, the wsimport command generated, along with others, the FileInfo class, which I then used in the java code:

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

The string is now being read correctly.

The SOAP request envelope now looks like this:

<?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>

The SOAP response looks like this:

<?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>

And thankfully enough, it can be read.

Still puzzled, though, as to why it is now working with the BARE setting and wasn't when it was WRAPPED.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM