user5182503
user5182503

Reputation:

CXF - method arguments are null

I use CXF 3.3.6 with Jetty 9.4.14. Jetty doesn't know about CXF and to link them I use web.xml. In that descriptor I set CXF servlet in which I override loadBus method. When I go to http://127.0.0.1:8080/webservices/calcService?wsdl I see wsdl of the service. These are dependencies I use:

cxf-rt-transports-http-3.3.6.jar
cxf-rt-frontend-jaxws-3.3.6.jar
cxf-core-3.3.6.jar
cxf-rt-frontend-simple-3.3.6.jar
cxf-rt-bindings-soap-3.3.6.jar
cxf-rt-wsdl-3.3.6.jar
cxf-rt-databinding-jaxb-3.3.6.jar
jakarta.xml.ws-api-2.3.2.jar
jakarta.xml.soap-api-1.4.1.jar
jakarta.jws-api-1.1.1.jar
xmlschema-core-2.2.5.jar
istack-commons-runtime-3.0.8.jar
woodstox-core-5.0.3.jar
stax2-api-3.1.4.jar
wsdl4j-1.6.3.jar

//having lost any hope I also added the following:
cxf-rt-bindings-xml-3.3.6.jar
cxf-rt-ws-addr-3.3.6.jar
cxf-rt-ws-policy-3.3.6.jar
cxf-rt-transports-http-jetty-3.3.6.jar
neethi-3.1.1.jar
xml-resolver-1.2.jar
txw2-2.3.2.jar
stax-ex-1.8.3.jar
saaj-impl-1.4.0-b03.jar
mimepull-1.9.7.jar
FastInfoset-1.2.16.jar
jaxb-runtime-2.3.2.jar
jboss-rmi-api_1.0_spec-1.0.6.Final.jar
jacorb-omgapi-3.9.jar

This is my class

@WebService(name="CalculatorService", serviceName="CalculatorService")
public class CalculatorService {

    @WebMethod
    public double addNumbers(double v1, double v2) {
        return v1 + v2;
    }
}

This is generated wsdl

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="CalculatorService" targetNamespace="http://cfx.foo.com/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://cfx.foo.com/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
  <wsdl:types>
<xs:schema xmlns:tns="http://cfx.foo.com/" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="unqualified" targetNamespace="http://cfx.foo.com/" version="1.0">

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

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

  <xs:complexType name="addNumbers">
    <xs:sequence>
      <xs:element name="arg0" type="xs:double"/>
      <xs:element name="arg1" type="xs:double"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="addNumbersResponse">
    <xs:sequence>
      <xs:element name="return" type="xs:double"/>
    </xs:sequence>
  </xs:complexType>

</xs:schema>
  </wsdl:types>
  <wsdl:message name="addNumbers">
    <wsdl:part name="parameters" element="tns:addNumbers">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="addNumbersResponse">
    <wsdl:part name="parameters" element="tns:addNumbersResponse">
    </wsdl:part>
  </wsdl:message>
  <wsdl:portType name="CalculatorService">
    <wsdl:operation name="addNumbers">
      <wsdl:input name="addNumbers" message="tns:addNumbers">
    </wsdl:input>
      <wsdl:output name="addNumbersResponse" message="tns:addNumbersResponse">
    </wsdl:output>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="CalculatorServiceSoapBinding" type="tns:CalculatorService">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="addNumbers">
      <soap:operation soapAction="" style="document"/>
      <wsdl:input name="addNumbers">
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="addNumbersResponse">
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="CalculatorService">
    <wsdl:port name="CalculatorServicePort" binding="tns:CalculatorServiceSoapBinding">
      <soap:address location="http://localhost:9090/CalculatorServicePort"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

Upon generated wsdl I generate (using plugin) java client stubs. The problem is that when via client I try to call my service my arguments for method are ignored. This is what I see using ngrep:

T 127.0.0.1:33602 -> 127.0.0.1:8080 [AP]
  POST /webservices/calcService HTTP/1.1..Content-Type: text/xml; charset=UTF-8..Accept: */*..SOAPAction: ""..User-Agent: Apache-CXF/3.3.6.
  .Cache-Control: no-cache..Pragma: no-cache..Host: 127.0.0.1:8080..Connection: keep-alive..Content-Length: 218....                        
##
T 127.0.0.1:33602 -> 127.0.0.1:8080 [AP]
  <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:addNumbers xmlns:ns2="http://cfx.foo.com/"><arg0>1.2</arg0><arg1>1.2</arg1></ns2:addNumbers></soap:Body></soap:Envelope>                                                        
##
T 127.0.0.1:8080 -> 127.0.0.1:33602 [AP]
  HTTP/1.1 500 Server Error..Date: Thu, 30 Apr 2020 15:38:13 GMT..Content-Type: text/xml;charset=utf-8..Content-Length: 322..Server: Jetty(
  9.4.z-SNAPSHOT)....<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><soap:Fault><faultcode>soap:Server</f
  aultcode><faultstring>null while invoking public double com.foo.cfx.CalculatorService.addNumbers(double,double) with params [
  null, null].</faultstring></soap:Fault></soap:Body></soap:Envelope>                                                                      
#######

As you see both arguments for addNumbers are passed but they are ignored.

And this is the stack

org.apache.cxf.interceptor.Fault: null while invoking public double com.temp.cfx.CalculatorService.addNumbers(double,double) with params [null, null].
    at [email protected]/org.apache.cxf.service.invoker.AbstractInvoker.createFault(AbstractInvoker.java:166)
    at [email protected]/org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:140)
    at [email protected]/org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:74)
    at [email protected]/org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:59)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at [email protected]/org.apache.cxf.interceptor.ServiceInvokerInterceptor$2.run(ServiceInvokerInterceptor.java:126)
    at [email protected]/org.apache.cxf.workqueue.SynchronousExecutor.execute(SynchronousExecutor.java:37)
    at [email protected]/org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:131)
    at [email protected]/org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
    at [email protected]/org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
    at [email protected]/org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:267)
    at [email protected]/org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:234)
    at [email protected]/org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:208)
    at [email protected]/org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:160)
    at [email protected]/org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:225)
    at [email protected]/org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:301)
    at [email protected]/org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:220)
    at [email protected]/javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
    at [email protected]/org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:276)

Could anyone help to solve this problem?

I did a test project that can be run by mvn install here.

Upvotes: 2

Views: 1738

Answers (1)

s7vr
s7vr

Reputation: 75914

Looks you have incorrect namespace based on wsdl

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body>
        <ns2:addNumbers xmlns:ns2="http://webapp.mycompany.com/">
            <ns2:v1>1.2</ns2:v1>
            <ns2:v2>1.2</ns2:v2>
        </ns2:addNumbers>
    </soap:Body>
</soap:Envelope>     

Update

Server method

@WebService(name="CalculatorService", 
        serviceName="CalculatorService")
public class CalculatorService {

    @WebMethod
    public double addNumbers(@WebParam(name="value1") double v1, @WebParam(name="value2") double v2) {
        return v1 + v2;
    }
}

In your case cxf-java2ws-plugin was generating a WSDL document ( the same one you are referring in your integration test ) was the one with JAX WS annotation. Note below the WSDL generated by plugin and the actual wsdl used by service. Pay attention to the element form defaults and local elements.

Plugin Generated WSDL

<xs:schema xmlns:tns="http://webapp.mycompany.com/" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="unqualified" targetNamespace="http://webapp.mycompany.com/" version="1.0">

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

  <xs:complexType name="addNumbers">
    <xs:sequence>
      <xs:element name="value1" type="xs:double"/>
      <xs:element name="value2" type="xs:double"/>
    </xs:sequence>
  </xs:complexType>

Service Actual WSDL ( with ServerFactoryBean doesn't take JAX WS annotation into account)

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://webapp.mycompany.com/" attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://webapp.mycompany.com/">

  <xsd:element name="addNumbers" type="tns:addNumbers"/>

  <xsd:complexType name="addNumbers">
    <xsd:sequence>
      <xsd:element name="v1" type="xsd:double"/>
      <xsd:element name="v2" type="xsd:double"/>
    </xsd:sequence>
  </xsd:complexType>

So your request was failing from integration test as server doesn't understand the request being sent.

Fix was to use JaxWsServerFactoryBean when initializing servlet. Now the service wsdl matches what was generated by plugin.

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://webapp.mycompany.com/" elementFormDefault="unqualified" targetNamespace="http://webapp.mycompany.com/" version="1.0">

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

 <xs:complexType name="addNumbers">
   <xs:sequence>
     <xs:element name="value1" type="xs:double"/>
     <xs:element name="value2" type="xs:double"/>
   </xs:sequence>
 </xs:complexType>

Upvotes: 1

Related Questions