Spring ws - Every attribute returns null - java

I have searched everywhere, but I'm not able to find the answer to this question.
I am using spring-ws to create a url that can consume a SOAP message. I followed the Producing a SOAP web service spring tutorial. When I send a value to this object, all attributes are null. I want the value of the message attribute. I can't seem to figure out why all the attributes are null. The endpoint looks like this:
#PayloadRoot(namespace = NAMESPACE_URI, localPart = "UICMessage")
#ResponsePayload
public void getMessage(#RequestPayload JAXBElement<UICMessage> request) {
System.out.println(request.getValue());
JAXBContext jaxbContext;
try {
jaxbContext = JAXBContext.newInstance(UICMessage.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.setProperty("com.sun.xml.bind.characterEscapeHandler", (CharacterEscapeHandler) (ch, start, length, isAttVal, out) -> out.write(ch, start, length));
StringWriter sw = new StringWriter();
jaxbMarshaller.marshal(request, sw);
String xmlString = sw.toString();
System.out.println(xmlString);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
UICMessage uicMessage = (UICMessage) unmarshaller.unmarshal(new StringSource(xmlString));
System.out.println(uicMessage.getMessage());
} catch (JAXBException e) {
e.printStackTrace();
}
}
The SOAP message that I am sending in a POST request to the endpoint above at /ws/ci
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:head="http://uic.cc.org/UICMessage/Header" xmlns:uic="http://uic.cc.org/UICMessage">
<soapenv:Header>
<head:signed>false</head:signed>
<head:encrypted>false</head:encrypted>
<head:compressed>false</head:compressed>
<head:messageIdentifier>xxx</head:messageIdentifier>
</soapenv:Header>
<soapenv:Body>
<uic:UICMessage>
<message>
<TrainCompositionMessage xmlns="http://taf-jsg.info/schemes" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">XMLVALUE</TrainCompositionMessage>
</message>
<senderAlias>USER</senderAlias>
</uic:UICMessage>
</soapenv:Body>
</soapenv:Envelope>
The console log that I am getting from the endpoint.
First I am trying to log the attributes, immediately. All attributes are null. Next I try to marshall them to a string again, the attributes are visible and well.
Next I try to unmarshall them again and all the attributes are null again.
UICMessage{message=[message: null], signature=null, senderAlias=[senderAlias: null], encoding=null}
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:UICMessage xmlns:ns2="http://uic.cc.org/UICMessage">
<message xmlns:head="http://uic.cc.org/UICMessage/Header" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:uic="http://uic.cc.org/UICMessage">
<TrainCompositionMessage xmlns="http://taf-jsg.info/schemes" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">XMLVALUE</TrainCompositionMessage>
</message>
<senderAlias xmlns:head="http://uic.cc.org/UICMessage/Header" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:uic="http://uic.cc.org/UICMessage">USER</senderAlias>
</ns2:UICMessage>
[message: null]
The wsdl I am using looks like this:
<wsdl:definitions xmlns:ns1="http://uic.cc.org/UICMessage/Header" xmlns:ns2="http://schemas.xmlsoap.org/soap/http"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://uic.cc.org/UICMessage"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
name="LIReceiveMessageService" targetNamespace="http://uic.cc.org/UICMessage">
<wsdl:documentation>
This WSDL describes the communication protocol for sending TAF/TAP -TSI messages with standard xml Header node
according TAF/TAP TSI Common Schema to partner using the Common Interface (CI).For more detailed Information
please refer to the specification document
</wsdl:documentation>
<wsdl:types>
<xs:schema xmlns:tns="http://uic.cc.org/UICMessage" xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="unqualified" targetNamespace="http://uic.cc.org/UICMessage" version="1.0">
<xs:element name="UICMessage" type="tns:UICMessage"/>
<xs:element name="UICMessageResponse" type="tns:UICMessageResponse"/>
<xs:complexType name="UICMessage">
<xs:sequence>
<xs:element minOccurs="0" name="message" type="xs:anyType"/>
<xs:element minOccurs="0" name="signature" type="xs:anyType"/>
<xs:element minOccurs="0" name="senderAlias" type="xs:anyType"/>
<xs:element minOccurs="0" name="encoding" type="xs:anyType"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="UICMessageResponse">
<xs:sequence>
<xs:element minOccurs="0" name="return" type="xs:anyType"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
<xsd:schema xmlns="http://uic.cc.org/UICMessage/Header" xmlns:tns="http://uic.cc.org/UICMessage"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" attributeFormDefault="unqualified"
elementFormDefault="unqualified" targetNamespace="http://uic.cc.org/UICMessage/Header">
<xsd:element name="messageIdentifier" nillable="true" type="xsd:string"/>
<xsd:element name="messageLiHost" nillable="true" type="xsd:string"/>
<xsd:element name="compressed" nillable="true" type="xsd:boolean"/>
<xsd:element name="encrypted" nillable="true" type="xsd:boolean"/>
<xsd:element name="signed" nillable="true" type="xsd:boolean"/>
</xsd:schema>
</wsdl:types>
<wsdl:message name="UICMessage">
<wsdl:part element="tns:UICMessage" name="parameters"></wsdl:part>
<wsdl:part element="ns1:messageIdentifier" name="messageIdentifier"></wsdl:part>
<wsdl:part element="ns1:messageLiHost" name="messageLiHost"></wsdl:part>
<wsdl:part element="ns1:compressed" name="compressed"></wsdl:part>
<wsdl:part element="ns1:encrypted" name="encrypted"></wsdl:part>
<wsdl:part element="ns1:signed" name="signed"></wsdl:part>
</wsdl:message>
<wsdl:message name="UICMessageResponse">
<wsdl:part element="tns:UICMessageResponse" name="parameters"></wsdl:part>
</wsdl:message>
<wsdl:portType name="UICReceiveMessage">
<wsdl:operation name="UICMessage">
<wsdl:documentation>
This operation is used to send the message to the Remote CI.
</wsdl:documentation>
<wsdl:input message="tns:UICMessage" name="UICMessage"></wsdl:input>
<wsdl:output message="tns:UICMessageResponse" name="UICMessageResponse"></wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="LIReceiveMessageServiceSoapBinding" type="tns:UICReceiveMessage">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="UICMessage">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="UICMessage">
<soap:header message="tns:UICMessage" part="messageIdentifier" use="literal"></soap:header>
<soap:header message="tns:UICMessage" part="messageLiHost" use="literal"></soap:header>
<soap:header message="tns:UICMessage" part="compressed" use="literal"></soap:header>
<soap:header message="tns:UICMessage" part="encrypted" use="literal"></soap:header>
<soap:header message="tns:UICMessage" part="signed" use="literal"></soap:header>
<soap:body parts="parameters" use="literal"/>
</wsdl:input>
<wsdl:output name="UICMessageResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="LIReceiveMessageService">
<wsdl:port binding="tns:LIReceiveMessageServiceSoapBinding" name="UICReceiveMessagePort">
<soap:address
location="http://EXTERNALLOCATION"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
Can anyone help me out on this? It seems really strange to me.

For now we solved the issue in a really dirty way. We first convert the message to XML, then get the right part with a substring. Next we convert that part we need back to an object with jaxb. If someone knows a clean way to do this, please let me know.
jaxbContext = JAXBContext.newInstance(UICMessage.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.setProperty("com.sun.xml.bind.characterEscapeHandler", (CharacterEscapeHandler) (ch, start, length, isAttVal, out) -> out.write(ch, start, length));
StringWriter sw = new StringWriter();
jaxbMarshaller.marshal(request, sw);
String xmlString = sw.toString();
String hackedString = xmlString.substring(xmlString.indexOf("<TrainCompositionMessage"), xmlString.indexOf("</message"));
jaxbContext = JAXBContext.newInstance(TrainCompositionMessage.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
TrainCompositionMessage errorMessage = (TrainCompositionMessage) unmarshaller.unmarshal(new StringSource(hackedString));

Related

XSD for use with Spring, can't get it to match WSDL

For the project I'm working on we need to create a SOAP web service (using Spring boot). The actual interface and message format is defined by a WSDL. The problem is that from what I understand from the documentation (e.g. https://www.baeldung.com/spring-boot-soap-web-service), I actually need an XSD (the WSDL will be generated from that).
Since there is only the WSDL, I tried to create the XSD myself for use in the application. Here I have run in to a couple of problems, the biggest problem being that the request messages it accepts aren't the ones that are accepted by the WSDL.
The WSDL accepts requests which simply are named payment where mine require paymentRequest as the name of the body element. This is probably something simple, but I can't find how to fix this…
Simplified wsdl:
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="http://xxx.yyy.com"
xmlns:impl="http://xxx.yyy.com"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wsdl:types>
<schema targetNamespace="http://xxx.yyy.com" xmlns="http://www.w3.org/2001/XMLSchema">
<import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
<complexType name="XxxTxnResponse">
<sequence>
<element name="resultCode" type="xsd:int"/>
</sequence>
</complexType>
<complexType name="XxxToken">
<sequence>
<element name="tokenId" nillable="true" type="xsd:string"/>
</sequence>
</complexType>
<complexType name="PaymentTxnResponse">
<complexContent>
<extension base="impl:XxxTxnResponse">
<sequence>
<element name="transactionRef" type="xsd:int"/>
</sequence>
</extension>
</complexContent>
</complexType>
</schema>
</wsdl:types>
<wsdl:message name="paymentRequest">
<wsdl:part name="posId" type="xsd:string"/>
<wsdl:part name="amountCents" type="xsd:int"/>
<wsdl:part name="token" type="impl:XxxToken"/>
</wsdl:message>
<wsdl:message name="paymentResponse">
<wsdl:part name="paymentReturn" type="impl:PaymentTxnResponse"/>
</wsdl:message>
<wsdl:portType name="XxxTxnHost">
<wsdl:operation name="payment" parameterOrder="posId amountCents token">
<wsdl:input message="impl:paymentRequest" name="paymentRequest"/>
<wsdl:output message="impl:paymentResponse" name="paymentResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="XxxTxnHostSoapBinding" type="impl:XxxTxnHost">
<wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="payment">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="paymentRequest">
<wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://xxx.yyy.com" use="encoded"/>
</wsdl:input>
<wsdl:output name="paymentResponse">
<wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://xxx.yyy.com" use="encoded"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="XxxTxnHostService">
<wsdl:port binding="impl:XxxTxnHostSoapBinding" name="XxxTxnHost">
<wsdlsoap:address location="wp.wsdl"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
Example request:
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xxx="http://xxx.yyy.com">
<soapenv:Header/>
<soapenv:Body>
<xxx:payment soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<posId xsi:type="xsd:string">?</posId>
<amountCents xsi:type="xsd:int">?</amountCents>
<token xsi:type="xxx:XxxToken">
<tokenId xsi:type="xsd:string">?</tokenId>
</token>
</xxx:payment>
</soapenv:Body>
</soapenv:Envelope>
My simplified xsd:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://xxx.yyy.com"
xmlns:tns="http://xxx.yyy.com">
<xs:import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
<xs:complexType name="XxxTxnResponse">
<xs:sequence>
<xs:element name="resultCode" type="xs:int"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="XxxToken">
<xs:sequence>
<xs:element name="tokenId" nillable="true" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="PaymentTxnResponse">
<xs:complexContent>
<xs:extension base="tns:XxxTxnResponse">
<xs:sequence>
<xs:element name="transactionRef" type="xs:int"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="paymentRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="posId" type="xs:string"/>
<xs:element name="amountCents" type="xs:int"/>
<xs:element name="token" type="tns:XxxToken"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="paymentResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="paymentReturn" type="tns:PaymentTxnResponse"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Generated wsdl:
<?xml version="1.0" encoding="UTF-8" standalone="no"?><wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:sch="http://xxx.yyy.com" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://xxx.yyy.com" targetNamespace="http://xxx.yyy.com">
<wsdl:types>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://xxx.yyy.com">
<xs:import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
<xs:complexType name="XxxTxnResponse">
<xs:sequence>
<xs:element name="resultCode" type="xs:int"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="XxxToken">
<xs:sequence>
<xs:element name="tokenId" nillable="true" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="PaymentTxnResponse">
<xs:complexContent>
<xs:extension base="tns:XxxTxnResponse">
<xs:sequence>
<xs:element name="transactionRef" type="xs:int"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="paymentRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="posId" type="xs:string"/>
<xs:element name="amountCents" type="xs:int"/>
<xs:element name="token" type="tns:XxxToken"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="paymentResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="paymentReturn" type="tns:PaymentTxnResponse"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
</wsdl:types>
<wsdl:message name="paymentResponse">
<wsdl:part element="tns:paymentResponse" name="paymentResponse">
</wsdl:part>
</wsdl:message>
<wsdl:message name="paymentRequest">
<wsdl:part element="tns:paymentRequest" name="paymentRequest">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="yyy">
<wsdl:operation name="payment">
<wsdl:input message="tns:paymentRequest" name="paymentRequest">
</wsdl:input>
<wsdl:output message="tns:paymentResponse" name="paymentResponse">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="yyySoap11" type="tns:yyy">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="payment">
<soap:operation soapAction=""/>
<wsdl:input name="paymentRequest">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="paymentResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="yyyService">
<wsdl:port binding="tns:yyySoap11" name="yyySoap11">
<soap:address location="http://localhost:8206/yyyservice/ws"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
There are a number of differences which I hope to solve in the end (no use of encoded is one), but the biggest problem is the fact that my wsdl requires paymentRequest in the request body, whereas the original message uses just payment. The response actually looked similar to what is expected.
I'm sure there something simple I have forgotten to do/specify, so hopefully one of you is able to point me in the right direction.
There is a difference in your bindings definitions. In the given wsdl there is specified that rpc/encoded is used while in your generated wsdl document/literal is used. Most likely you can set these settings before generating the wsdl.
If you alter the generated wsdl so it uses the prc/encoded the request looks like:
<SOAP-ENV:Body>
<m:payment xmlns:m="http://xxx.yyy.com">
<m:payment>
<posId xsi:type="xsd:string">String</posId>
<amountCents xsi:type="xsd:int">0</amountCents>
<token xsi:type="m:XxxToken">
<tokenId xsi:type="xsd:string">String</tokenId>
</token>
</m:payment>
</m:payment>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
see https://learn.microsoft.com/en-us/previous-versions/dotnet/articles/ms996486(v=msdn.10)?redirectedfrom=MSDN#understand_topic6
OK, after loads of trial and error, I managed to find a different solution with which I was able to consume the messages.
I didn't like my earlier attempt where I renamed paymentRequest to just payment since when looking at the wsdl, I saw all the “input” parts missing from the operations. This didn't feel good.
However, by simply specifying the type
<xs:complexType name="PaymentRequest">
<xs:sequence>
<xs:element name="posId" type="xs:string"/>
<xs:element name="amountCents" type="xs:int"/>
<xs:element name="token" type="tns:XxxToken"/>
</xs:sequence>
</xs:complexType>
and the element
<xs:element name="paymentRequest" type ="PaymentRequest">
separately, it worked, and now with the input parts showing properly again in the WSDL.
Digging around a little more, it follows the main issue is actually (fully) caused by the original WSDL using RPC/encoded instead of Document/Literal (as already suggested by #martijn in his answer). As it turns out RPC/encoded is actually deprecated (quite a number of years now…) and doesn't seem to be supported by Spring.
So unless someone knows how to get Spring to use RPC/encoded, I guess I need to go back to the company that is asking me to develop a server to communicate with their hardware and make them allow Document/literal responses (at least).

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>

<soap:header/> block in not coming in soap response

I am writing a soap web service with apache-cxf. I am following code first approach. The issue is , i am not getting "soap:header" tag under in response.I have gone through other wsdl and java implementation classes and not able to find what needs to be added in wsdl or SEI to get soap:header block in response.Please let me know if any one can help me in this.I would share more details if required.
My webservice class looks like -
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.ParameterStyle;
import javax.jws.soap.SOAPBinding.Style;
import javax.jws.soap.SOAPBinding.Use;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;
/**
* This class was generated by Apache CXF 3.1.11
* 2017-05-01T12:11:39.200+05:30
* Generated source version: 3.1.11
*
*/
#WebService(targetNamespace = "http://webservice.sample.com", name = "SampleWebService")
#XmlSeeAlso({ObjectFactory.class})
public interface SampleWebService {
#WebResult(name = "Response", targetNamespace = "" )
#RequestWrapper(localName = "requestWrapper", targetNamespace = "http://webservice.sample.com", className = "com.sample")
#WebMethod
#ResponseWrapper(localName = "responseWrapper", targetNamespace = "http://webservice.sample.com", className = "com.sample" )
public com.sample.Response requestWrapper(
#WebParam(name = "request", targetNamespace = "http://requests.webservice.sample.com")
com.sample.Request request
);
}
and wsdl -
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://webservice.sample.com" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" name="SampleWebServiceService" targetNamespace="http://webservice.sample.com">
<wsdl:types>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ns2="http://response.webservice.sample.com" xmlns:ns1="http://requests.webservice.sample.com" targetNamespace="http://webservice.sample.com" version="1.0">
<xs:import namespace="http://requests.webservice.sample.com"/>
<xs:import namespace="http://response.webservice.sample.com"/>
<xs:element name="requestWrapper" type="ns1:Create"/>
<xs:element name="responseWrapper" type="ns2:CreateConfirmation"/>
</xs:schema>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ns1="http://common.sample.com" targetNamespace="http://response.webservice.sample.com" version="1.0">
<xs:import namespace="http://common.sample.com"/>
<xs:complexType name="CreateConfirmation">
<xs:sequence>
<xs:element form="qualified" name="Response">
<xs:complexType>
<xs:sequence>
<xs:element form="qualified" name="ID" type="xs:string"/>
<xs:element form="qualified" maxOccurs="unbounded" minOccurs="0" name="Error" type="ns1:Error"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://requests.webservice.sample.com" version="1.0">
<xs:complexType name="Create">
<xs:sequence>
<xs:element form="qualified" name="Request">
<xs:complexType>
<xs:sequence>
<xs:element form="qualified" name="Name" type="xs:string"/>
<xs:element form="qualified" name="CreationDate" type="xs:string"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://common.sample.com" version="1.0">
<xs:complexType name="Error">
<xs:sequence>
<xs:element name="ErrorCode" type="xs:string"/>
<xs:element name="ErrorMessage" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
</wsdl:types>
<wsdl:message name="requestWrapper">
<wsdl:part element="tns:requestWrapper" name="parameters"></wsdl:part>
</wsdl:message>
<wsdl:message name="responseWrapper">
<wsdl:part element="tns:responseWrapper" name="parameters"></wsdl:part>
</wsdl:message>
<wsdl:portType name="SampleWebService">
<wsdl:operation name="requestWrapper">
<wsdl:input message="tns:requestWrapper" name="requestWrapper"></wsdl:input>
<wsdl:output message="tns:responseWrapper" name="responseWrapper"></wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="SampleWebServiceServiceSoapBinding" type="tns:SampleWebService">
<wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="requestWrapper">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="requestWrapper">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="responseWrapper">
<wsdlsoap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="SampleWebServiceService">
<wsdl:port binding="tns:SampleWebServiceServiceSoapBinding" name="SampleWebService">
<wsdlsoap:address location="http://localhost:8181/cxf/SampleWebService"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
Soap Request -
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://webservice.sample.com" xmlns:ord="http://requests.webservice.sample.com">
<soapenv:Header/>
<soapenv:Body>
<web:requestWrapper>
<ord:Request>
<ord:Name>Harry</ord:Name>
<ord:CreationDate>2015-09-09T12:45:00</ord:CreationDate>
</ord:Request>
</web:requestWrapper>
</soapenv:Body>
</soapenv:Envelope>
Expected Response -
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header/>
<soap:Body>
<ns2:responseWrapper xmlns:ns2="http://common.sample.com" xmlns="http://response.sample.com">
<ID>12345678910</ID>
</ns2:responseWrapper>
</soap:Body>
</soap:Envelope>
Actual Response -
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:responseWrapper xmlns:ns2="http://common.sample.com" xmlns="http://response.sample.com">
<ID>12345678910</ID>
</ns2:responseWrapper>
</soap:Body>
</soap:Envelope>
An empty header element is not required. If you want to add a header, add for example the method parameter
#WebParam(partName = "bankHeader", mode = WebParam.Mode.OUT, name = "bankRequestHeader", targetNamespace = "http://example.bank.skjolber.github.com/v1", header = true)
javax.xml.ws.Holder<BankRequestHeader> bankHeader
(The sample was generated by moving and input to output header in this sample.)

Is it possible to remove wrapper element in WS result?

I have CXF project working fine.
My WS interface is
package net.betlista.ws;
import javax.jws.WebMethod;
import javax.jws.WebService;
import org.apache.cxf.annotations.EndpointProperty;
#WebService
public interface TestWs {
#WebMethod
Result foo(String child);
}
implementation is
package net.betlista.ws;
import org.springframework.stereotype.Component;
#Component("testWsEndpoint")
public class TestWsImpl implements TestWs {
#Override
public Result foo(final String child) {
Result res = new Result();
res.status = "ok";
res.data = "bar";
return res;
}
}
Result type class:
package net.betlista.ws;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
//#XmlTransient - NOT working
#XmlType
//#SOAPBinding(parameterStyle=SOAPBinding.ParameterStyle.BARE) - NOT working
public class Result {
#XmlElement
String status;
#XmlElement
String data;
}
When I call the WS with request:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://ws.betlista.net/">
<soapenv:Header/>
<soapenv:Body>
<ws:foo>
<arg0>a</arg0>
</ws:foo>
</soapenv:Body>
</soapenv:Envelope>
the result is:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:fooResponse xmlns:ns2="http://ws.betlista.net/">
<return>
<status>ok</status>
<data>bar</data>
</return>
</ns2:fooResponse>
</soap:Body>
</soap:Envelope>
And I'd like to skip this return element.
I'd like to have:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:fooResponse xmlns:ns2="http://ws.betlista.net/">
<status>ok</status>
<data>bar</data>
</ns2:fooResponse>
</soap:Body>
</soap:Envelope>
I found this question, but if I use this, element arg is also missing from request what is something I do not want.
I tried to use this #SOAPBinding annotation for method (works as described above) and also for type Result (not working).
Requested WSDL:
<?xml version='1.0' encoding='UTF-8'?><wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://ws.betlista.net/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" name="TestWsImplService" targetNamespace="http://ws.betlista.net/">
<wsdl:types>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://ws.betlista.net/" elementFormDefault="unqualified" targetNamespace="http://ws.betlista.net/" version="1.0">
<xs:element name="foo" type="tns:foo"/>
<xs:element name="fooResponse" type="tns:fooResponse"/>
<xs:complexType name="foo">
<xs:sequence>
<xs:element minOccurs="0" name="arg0" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="fooResponse">
<xs:sequence>
<xs:element minOccurs="0" name="return" type="tns:result"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="result">
<xs:sequence>
<xs:element minOccurs="0" name="status" type="xs:string"/>
<xs:element minOccurs="0" name="data" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
</wsdl:types>
<wsdl:message name="foo">
<wsdl:part element="tns:foo" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="fooResponse">
<wsdl:part element="tns:fooResponse" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="TestWs">
<wsdl:operation name="foo">
<wsdl:input message="tns:foo" name="foo">
</wsdl:input>
<wsdl:output message="tns:fooResponse" name="fooResponse">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="TestWsImplServiceSoapBinding" type="tns:TestWs">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="foo">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="foo">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="fooResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="TestWsImplService">
<wsdl:port binding="tns:TestWsImplServiceSoapBinding" name="TestWsImplPort">
<soap:address location="http://localhost:8080/tests-wicket-cxf/ws/TestWs"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
If you want to replace arg0 with child within the SOAP request, you should add a #WebParam(name="child") annotation to your method parameter.
You can furthermore take influence on the produced style by annotating the service (the class) with #SOAPBinding(...) - which style to use depends on your needs/whises - here please refer to the link of my first comment to see the differences.
Further, please have a look at the CXF docs to see the default values for each #SOAPBinding parameter.
As you want to get rid of the return element in the response, please note that this is not WS-I complient, as only one soap::body child is allowed - but as this is your intention you should change the ParameterStyle.WRAPPED default SOAPBinding parameter to ParameterStyle.BARE. This however might change the request type too. Maybe have a look at #ResponseWrapper here. I haven't used it yet so I can't give detailed information therefore.
Instead of <return>tag you can use your own tag like <result> by adding #javax.jws.WebResult(name = "result") both in your interface and implementation.
#Override
#javax.jws.WebResult(name = "result")
public Result foo(final String child) {
Result res = new Result();
res.status = "ok";
res.data = "bar";
return res;
}

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