SOAP Request and Response using the same Element not showing in SoapUI - java

When one usually creates a SOAP request and response element, it would end in __Request and __Response and SoapUI would pick it up when you import the WSDL.
<xs:element name="SampleRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="Testing" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="SampleResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="Testing" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
I'm busy converting a piece of old VB6 code and the DTD's SOAP equivalent would use the same element for request and response:
<xs:element name="Sample">
<xs:complexType>
<xs:sequence>
<xs:element name="Testing" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
Is there something I can set in the XSD so that SOAPUI would pick up Sample as both a request and a response?

When SOAPUI reads the WSDL, it uses the element (and therefore the element name) defined in the wsdl:message element which is referenced from the wsdl:operation element as the request, response, and optional fault. Nothing you do to an XSD will change that. Nor do elements have to end with "Request" to be considered a request (same for Response).

Solved it by replacing all SampleRequest and SampleResponse with just Sample and removing the now duplicate wsdl:message:
...
<wsdl:message name="Sample">
<wsdl:part element="tns:Sample" name="Sample">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="SampleSoapService">
<wsdl:operation name="Sample">
<wsdl:input message="tns:Sample" name="Sample">
</wsdl:input>
<wsdl:output message="tns:Sample" name="Sample">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="SampleSoapServiceSoap11" type="tns:SampleSoapService">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="Sample">
<soap:operation soapAction="" />
<wsdl:input name="Sample">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="Sample">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="SampleSoapServiceService">
<wsdl:port binding="tns:SampleSoapServiceSoap11" name="SampleSoapServiceSoap11">
<soap:address location="http://localhost:8080/paygate-SampleSoapService/ws/SampleSoapService" />
</wsdl:port>
</wsdl:service>

Related

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 org.apache.cxf.core#3.3.6/org.apache.cxf.service.invoker.AbstractInvoker.createFault(AbstractInvoker.java:166)
at org.apache.cxf.core#3.3.6/org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:140)
at org.apache.cxf.core#3.3.6/org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:74)
at org.apache.cxf.core#3.3.6/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 org.apache.cxf.core#3.3.6/org.apache.cxf.interceptor.ServiceInvokerInterceptor$2.run(ServiceInvokerInterceptor.java:126)
at org.apache.cxf.core#3.3.6/org.apache.cxf.workqueue.SynchronousExecutor.execute(SynchronousExecutor.java:37)
at org.apache.cxf.core#3.3.6/org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:131)
at org.apache.cxf.core#3.3.6/org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
at org.apache.cxf.core#3.3.6/org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
at org.apache.cxf.transport.http#3.3.6/org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:267)
at org.apache.cxf.transport.http#3.3.6/org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:234)
at org.apache.cxf.transport.http#3.3.6/org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:208)
at org.apache.cxf.transport.http#3.3.6/org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:160)
at org.apache.cxf.transport.http#3.3.6/org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:225)
at org.apache.cxf.transport.http#3.3.6/org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:301)
at org.apache.cxf.transport.http#3.3.6/org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:220)
at javax.servlet.api#3.1.0/javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at org.apache.cxf.transport.http#3.3.6/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.
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>

WSDL-Content,binding: input type shown "literal" instead of the name of complextype

I deployed my webservice to tomcat. In the wsdl file the binding part is this:
<binding name="mywsPortBinding" type="tns:mywsInterface">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<operation name="update">
<soap:operation soapAction=""/>
<input> <soap:body use="literal"/> </input>
<output> <soap:body use="literal"/> </output>
</operation>
</binding>
My Question: Why are the input and output types shown to be "literal"?
As response this webservice sends back certain xml-complextyped data according to a specified xsd. Why the copmlex type name is not shown in the wsdl instead?
In binding, "literal" is only defined the encoding style used, the complex Type name is showed in the "wsdl:message" definition, which is used in "wsdl:operation" in "wsdl:portType".
You should have something like this.
`
<xs:element name="update" type="tns:update"/>
<xs:complexType name="update">
<xs:sequence>
<xs:element name="arg0" type="xs:string"/>
<xs:element name="arg1" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:element name="updateResponse" type="tns:updateResponse"/>
<xs:complexType name="updateResponse">
<xs:sequence>
<xs:element name="arg0" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<wsdl:message name="update">
<wsdl:part element="tns:update" name="parameters"/>
</wsdl:message>
<wsdl:message name="updateResponse">
<wsdl:part element="tns:updateResponse" name="parameters"/>
</wsdl:message>
<wsdl:portType name="mywsInterface">
<wsdl:operation name="update">
<wsdl:input message="tns:update" name="update"/>
<wsdl:output message="tns:updateResponse" name="updateResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="mywsPortBinding" type="tns:mywsInterface">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="update">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="update">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="updateResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
`
You can find more details and examples here
In the case of 'literal', the abstract type definitions become the concrete definitions themselves (they're 'literal' definitions). In this case, you can simply inspect the XML Schema type definitions to determine the concrete message format. For example, the operation for the document/literal binding looks like this on the wire:
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
>
<SOAP-ENV:Body>
<m:Add xmlns:m="http://example.org/math/types/">
<x>3.14159265358979</x>
<y>3.14159265358979</y>
</m:Add>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Notice that the SOAP Body simply contains an instance of the Add
element defined in the schema—this is what makes document/literal so
attractive.
Reference: Understanding WSDL

How to tell cxf to keep the wrapper types in methods?

In my WSDL I have an operation
<wsdl:operation name="theMethod">
<wsdl:input message="input1" name="input1"></wsdl:input>
<wsdl:output message="tns:classNumber1" name="classNumber1"></wsdl:output>
</wsdl:operation>
in my xsd, classNumber1 is a complex type and it is a wrapper for another type: classNumber2
<xs:complexType name="classNumber1">
<xs:sequence>
<xs:element minOccurs="0" name="arg0" type="tns:classNumber2"/>
</xs:sequence>
</xs:complexType>
when I generate classes with cxf (I use cxf maven plugin), I expected that theMethod to return a ClassNumber1 but it was a ClassNumber2.
#WebMethod
#ResponseWrapper(localName="classNumber1" , className="com.model.ClassNumber")
public ClassNumber2 theMethod (Input1 input1){
...
}
Is there a way to tell cxf to generate the method with the wrapper CLassNumber1.
Thanks.
I find the solution in this doc, question "How can I switch my generated web service method calls from wrapper style to non wrapper-style (or vice-versa)?"
The solution to keep wrappers with cxf generation is to add a binding file in the pom.xml:
<defaultOptions>
<bindingFiles>
<bindingFile>${basedir}/src/main/resources/bindings.xjb</bindingFile>
</bindingFiles>
<noAddressBinding>true</noAddressBinding>
</defaultOptions>
In the binding file you set enableWrapperStyle to false:
<jaxws:bindings
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns="http://java.sun.com/xml/ns/jaxws"
xmlns:jaxws="http://java.sun.com/xml/ns/jaxws">
<enableWrapperStyle>false</enableWrapperStyle>
</jaxws:bindings>
Based on the information you have provided I have created a basic interface as shown below.
this works as per your expectation.
<xsd:complexType name="input1">
<xsd:sequence>
<xsd:element name="in" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="ClassNumber1">
<xsd:sequence>
<xsd:element minOccurs="0" name="out" type="tns:ClassNumber2" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="ClassNumber2">
<xsd:sequence>
<xsd:element name="out" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
</wsdl:types>
<wsdl:message name="input1">
<wsdl:part element="tns:input1" name="parameters" />
</wsdl:message>
<wsdl:message name="ClassNumber1">
<wsdl:part element="tns:ClassNumber1" name="parameters" />
</wsdl:message>
<wsdl:portType name="NewWSDLFile">
<wsdl:operation name="NewOperation">
<wsdl:input message="tns:input1" />
<wsdl:output message="tns:ClassNumber1" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="NewWSDLFileSOAP" type="tns:NewWSDLFile">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="NewOperation">
<soap:operation soapAction="http://www.example.org/NewWSDLFile/NewOperation" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="NewWSDLFile">
<wsdl:port binding="tns:NewWSDLFileSOAP" name="NewWSDLFileSOAP">
<soap:address location="http://www.example.org/" />
</wsdl:port>
</wsdl:service>
Please check <wsdl:output message="tns:ClassNumber1" />
I believe you have given the wrong in your output information in your
<wsdl:message name="ClassNumber1">
<wsdl:part element="tns:ClassNumber1" name="parameters" />
</wsdl:message>
Hope this helps.

wsdl Binding is not defined

I am new to WSDL and trying to validate the WSDL. I have to generate code from WSDL. I get the following error
The operation specified for the 'DictionaryServiceServiceSoapBinding'
binding is not defined for port type 'DictionaryService'. All
operations specified in this binding must be defined in port type
'DictionaryService'.
Following is my WSDL:
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="DictionaryService" targetNamespace="http://dictionaryservice.example.com/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://dictionaryservice.example.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<wsdl:types>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://dictionaryservice.example.com/" attributeFormDefault="unqualified" elementFormDefault="unqualified" targetNamespace="http://dictionaryservice.example.com/">
<xs:element name="addDataToDict" type="tns:addDataToDict"/>
<xs:element name="addDataToDictResponse" type="tns:addDataToDictResponse"/>
<xs:complexType name="addDataToDict">
<xs:sequence>
<xs:element name="identifier" type="xs:string"/>
<xs:element name="description" type="xs:string"/>
<xs:element name="uri" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="addDataToDictResponse">
<xs:sequence>
<xs:element name="status" type="xs:boolean"/>
</xs:sequence>
</xs:complexType>
<xs:element name="listOfAllIndexes" type="tns:listOfAllIndexes"/>
<xs:element name="listOfAllIndexesResponse" type="tns:listOfAllIndexesResponse"/>
<xs:complexType name="listOfAllIndexes">
<xs:sequence>
</xs:sequence>
</xs:complexType>
<xs:complexType name="listOfAllIndexesResponse">
<xs:sequence>
<xs:element name="list" type="tns:listData"/>
</xs:sequence>
</xs:complexType>
<xs:element name="getDictByIndex" type="tns:getDictByIndex"/>
<xs:element name="getDictByIndexResponse" type="tns:getDictByIndexResponse"/>
<xs:complexType name="getDictByIndex">
<xs:sequence>
<xs:element name="index" type="xs:integer"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="getDictByIndexResponse">
<xs:sequence>
<xs:element name="data" type="tns:dictData"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="listData">
<xs:sequence>
<xs:element name="identifier" type="xs:integer"/>
<xs:element name="index" type="xs:integer"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="dictData">
<xs:sequence>
<xs:element name="identifier" type="xs:string"/>
<xs:element name="description" type="xs:string"/>
<xs:element name="uri" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
</wsdl:types>
<wsdl:message name="addDataToDict">
<wsdl:part name="NewPart" type="tns:addDataToDict"></wsdl:part>
</wsdl:message>
<wsdl:message name="addDataToDictResponse">
<wsdl:part name="NewPart" type="tns:addDataToDictResponse"></wsdl:part>
</wsdl:message>
<wsdl:message name="listOfAllIndexes">
<wsdl:part name="NewPart" type="tns:listOfAllIndexes"></wsdl:part>
</wsdl:message>
<wsdl:message name="listOfAllIndexesResponse">
<wsdl:part name="NewPart" type="tns:listOfAllIndexesResponse"></wsdl:part>
</wsdl:message>
<wsdl:message name="getDictByIndex">
<wsdl:part name="NewPart" type="tns:getDictByIndex"></wsdl:part>
</wsdl:message>
<wsdl:message name="getDictByIndexResponse">
<wsdl:part name="NewPart" type="tns:getDictByIndexResponse"></wsdl:part>
</wsdl:message>
<wsdl:portType name="DictionaryService">
<wsdl:operation name="addDataToDict">
<wsdl:input message="tns:addDataToDict"></wsdl:input>
<wsdl:output message="tns:addDataToDictResponse"></wsdl:output>
</wsdl:operation>
<wsdl:operation name="listOfAllIndexes">
<wsdl:input message="tns:listOfAllIndexes"></wsdl:input>
<wsdl:output message="tns:listOfAllIndexesResponse"></wsdl:output>
</wsdl:operation>
<wsdl:operation name="getDictByIndex">
<wsdl:input message="tns:getDictByIndex"></wsdl:input>
<wsdl:output message="tns:getDictByIndexResponse"></wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="DictionaryServiceServiceSoapBinding" type="tns:DictionaryService">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="addDataToDict">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="addDataToDict">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="addDataToDictResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="listOfAllIndexes">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="listOfAllIndexes">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="listOfAllIndexesResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getDictByIndex">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="getDictByIndex">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="getDictByIndexResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="DictionaryService">
<wsdl:port name="DictionaryServicePort" binding="tns:DictionaryServiceServiceSoapBinding">
<soap:address location="http://localhost:9090/DictionaryServicePort"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
I tried myself but couldn't find the answer.
Try giving different names for each message/part <wsdl:part name="NewPart" .....> like
<wsdl:message name="addDataToDict">
<wsdl:part name="AddDataToDictRequestPart" type="tns:addDataToDict"></wsdl:part>
</wsdl:message>
<wsdl:message name="addDataToDictResponse">
<wsdl:part name="addDataToDictResponsePart" type="tns:addDataToDictResponse"></wsdl:part>
</wsdl:message>

WebService can't handle request with SOAP Body not having a namespace prefix

My web service is not able to process my client's requests when client is calling the web service without passing prefix in the SOAP Body as follows:
<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>
The error is that the Java object corresponding to GetPatientResultsRequest and others are null.
It seems like when there is no prefix in the Body, the deserialization is not happening properly. My web service is able to respond only when the SOAP Body has a prefix like
<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>
Can anyone let me know what to do so that my web service can take SOAP requests of all kinds (i.e. with and without prefix in Body)?
I am using JAX-WS (SOAP 1.1)
A web service defines a contract that you must follow in order to call it. Only one message from the examples you posted matches that contract so that one works, the other doesn't.
In your first message you defined a default namespace (because of the xmlns attribute in the wrapper) and all your elements that don't undeclare it and that have no prefix are in the same namespace because they inherit it from their parent.
In your second message you have an explicit prefix declaration and only the wrapper is in that namespaces, the other elements are not in a namespace and don't inherit a default one from the parent (because of xmlns attribute missing).
As I said at the beginning, the web service defines a contract. It makes more sense to modify the clients to send the correct message instead of changing the service to accept incorrect messages from the client.
To control the namespaces of your elements you need to use the targetNamespace values on the JAX-WS annotations of your web service and client.
Here is an example to see the difference in code and message format when you change the target namespaces. I'll use a basic WSDL for this:
<?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>
This defines messages like:
<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>
and:
<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>
See the namespace prefix on the wrappers? That's because the elements are declared in the http://tempuri.org namespace while the others are not and are not in a namespace.
You can even remove all elements from the namespaces. Strip the target namespace from the WSDL and get it to look like this:
<?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>
This new WSDL will correspond to messages like:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<add>
<addInput>
<a>?</a>
<b>?</b>
</addInput>
</add>
</soapenv:Body>
</soapenv:Envelope>
and:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<addResponse>
<addOutput>
<result>?</result>
</addOutput>
</addResponse>
</soapenv:Body>
</soapenv:Envelope>
No prefix in this case.
Now use wsimport.exe on both WSDLs and you will see the target namespaces I was talking about at the beginning, namely a change from this:
#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);
}
to this:
#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);
}
Control the targetNamespace and you will control how the message looks.

Categories