Is it possible to remove wrapper element in WS result? - java

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

Related

Spring ws - Every attribute returns null

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

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

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

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>

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