Valid SOAP request tested via SOAP UI:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="some_ns1_uri">
<SOAP-ENV:Header />
<ns0:Body>
<ns1:AAA_method>
<ns1:A>A</ns1:A>
<ns1:B>B</ns1:B>
<ns1:C>
<ns1:string>C_string</ns1:string>
</ns1:C>
<ns1:D>
<ns1:string>D_string</ns1:string>
</ns1:D>
<ns1:E>
<ns1:val>E_val</ns1:val>
</ns1:E>
<ns1:F>
<ns1:val>F_val</ns1:val>
</ns1:F>
</ns1:AAA_method>
</ns0:Body>
</SOAP-ENV:Envelope>
getResponseObj method to send the message:
@Autowired
ClientConfig clientConfig;
@Autowired
Service service;
...
public ResponseObj getResponseObj() throws DatatypeConfigurationException {
RequestObj request = service.buildRequest();
WebServiceTemplate wst = clientConfig.webServiceTemplate();
return (ResponseObj) wst.marshalSendAndReceive(request, new WebServiceMessageCallback() {
@Override
public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException {
SoapMessage soapMessage = ((SoapMessage) message);
soapMessage.setSoapAction(soapActionHeader);
soapMessage.writeTo(System.out);
}
});
}
WebServiceTemplate configuration looks like this:
@Configuration
public class ClientConfig {
@Value("${ws.username}") private String username;
@Value("${ws.password}") private String usernamePassword;
@Value("${ws.uri}") private String endpointUri;
@Value("${ws.contextPath}") private String cxtPath;
@Bean
Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath(cxtPath); // package location where wsdl generated classes are
return marshaller;
}
@Bean
HttpClient httpClient() {
List<Header> headers = new ArrayList<>();
String userAndPassword = username + ":" + usernamePassword;
BasicHeader authHeader = new BasicHeader("Authorization", "Basic " + new String(Base64.encode(userAndPassword.getBytes())));
headers.add(authHeader);
RequestDefaultHeaders reqHeader = new RequestDefaultHeaders(headers);
return HttpClients.custom()
.addInterceptorFirst(new HttpComponentsMessageSender.RemoveSoapHeadersInterceptor())
.addInterceptorLast(reqHeader).build();
}
@Bean
HttpComponentsMessageSender defaultMyMessageSender() {
return new HttpComponentsMessageSender(httpClient());
}
@Bean
public WebServiceTemplate webServiceTemplate() {
WebServiceTemplate wsTemplate = new WebServiceTemplate();
wsTemplate.setDefaultUri(endpointUri);
wsTemplate.setMarshaller(marshaller());
wsTemplate.setMessageSender(defaultMyMessageSender());
return wsTemplate;
}
}
Service has buildRequest method where I set the values and return RequestObj
The writeTo prints wrong SoapMessage, the message is:
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> // here missing 3 namespaces
<SOAP-ENV:Header/>
<SOAP-ENV:Body> // wrong body tag name
<ns2:RequestObj xmlns:ns2="some_ns1_uri"> // wrong tag name (ns2)
<ns2:A>A</ns2:A>
<ns2:B>B</ns2:B>
<ns2:C>
<ns2:string>C</ns2:string>
</ns2:C>
<ns2:D>
<ns2:string>D</ns2:string>
</ns2:D>
<ns2:E>
<ns2:val/> // missing E value
</ns2:E>
<ns2:F>
<ns2:val/> // missing F value
</ns2:F>
</ns2:RequestObj>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
For missing envelope namespaces I've added the following to doWithMessage:
...
SoapEnvelope envelope = soapMessage.getEnvelope();
envelope.addNamespaceDeclaration(nXsi, nXsiUri);
envelope.addNamespaceDeclaration(nNs0, nNs0Uri);
envelope.addNamespaceDeclaration(nNs1, nNs1Uri);
/*
Results:
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="some_ns1_uri"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
*/
...
My question is how I could change:
- the body
SOAP-ENV:Bodytons0:Body? - the prefix
ns2from Body element tags tons1?
I'm using org.springframework.ws.WebServiceMessage and convering to org.springframework.ws.soap.SoapMessage.
I know the SOAPMessage API allows methods to setPrefix to change Body element tag prefixes and Body prefix too. But I need to use the org.springframework.ws.soap.SoapMessage.
My idea was to convert message.getPayloadSource() to Document and then Document convert it to InputStream to manually correct the XML and change it back to org.springframework.ws.soap.SoapMessage object to be able to send valid request. But I'm sure it's overkill...
To get back to main question - how can I modify the SoapMessage (content) to be valid to be sent?
All ideas are welcome
Update #1
When sending request (with and without fixing envelope headers it doesn't matter):
2021-01-04 10:24:49.091 ERROR 2032 --- [nio-7845-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.ws.soap.client.SoapFaultClientException: System.Web.Services.Protocols.SoapException: Server was unable to read request. ---> System.InvalidOperationException: There is an error in XML document (1, 409). ---> System.FormatException: The string '' is not a valid AllXsd value.
at System.Xml.Schema.XsdDateTime..ctor(String text, XsdDateTimeFlags kinds)
at System.Xml.XmlConvert.ToDateTime(String s, XmlDateTimeSerializationMode dateTimeOption)
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read2_ahs_date(Boolean isNullable, Boolean checkType)
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read11_RequestSeriesData()
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
--- End of inner exception stack trace ---
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
at System.Web.Services.Protocols.SoapServerProtocol.ReadParameters()
--- End of inner exception stack trace ---
at System.Web.Services.Protocols.SoapServerProtocol.ReadParameters()
at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()] with root cause
org.springframework.ws.soap.client.SoapFaultClientException: System.Web.Services.Protocols.SoapException: Server was unable to read request. ---> System.InvalidOperationException: There is an error in XML document (1, 409). ---> System.FormatException: The string '' is not a valid AllXsd value.
at System.Xml.Schema.XsdDateTime..ctor(String text, XsdDateTimeFlags kinds)
at System.Xml.XmlConvert.ToDateTime(String s, XmlDateTimeSerializationMode dateTimeOption)
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read2_e_value(Boolean isNullable, Boolean checkType)
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read11_RequestData()
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
--- End of inner exception stack trace ---
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
at System.Web.Services.Protocols.SoapServerProtocol.ReadParameters()
--- End of inner exception stack trace ---
at System.Web.Services.Protocols.SoapServerProtocol.ReadParameters()
at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()
at org.springframework.ws.soap.client.core.SoapFaultMessageResolver.resolveFault(SoapFaultMessageResolver.java:38) ~[spring-ws-core-3.0.10.RELEASE.jar:na]
at org.springframework.ws.client.core.WebServiceTemplate.handleFault(WebServiceTemplate.java:830) ~[spring-ws-core-3.0.10.RELEASE.jar:na]
at org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:624) ~[spring-ws-core-3.0.10.RELEASE.jar:na]
at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:555) ~[spring-ws-core-3.0.10.RELEASE.jar:na]
at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:390) ~[spring-ws-core-3.0.10.RELEASE.jar:na]
at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:383) ~[spring-ws-core-3.0.10.RELEASE.jar:na]
at xxx.xxxx.xxx.xxxxx.Client.getResponseObj(Client.java:60) ~[classes/:na]
at xxx.xxxx.xxxxxxx.Controller.exampleTable(Controller.java:26) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197) ~[spring-web-5.3.1.jar:5.3.1]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141) ~[spring-web-5.3.1.jar:5.3.1]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.3.1.jar:5.3.1]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:893) ~[spring-webmvc-5.3.1.jar:5.3.1]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:807) ~[spring-webmvc-5.3.1.jar:5.3.1]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.1.jar:5.3.1]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1061) ~[spring-webmvc-5.3.1.jar:5.3.1]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:961) ~[spring-webmvc-5.3.1.jar:5.3.1]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.1.jar:5.3.1]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.1.jar:5.3.1]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:626) ~[tomcat-embed-core-9.0.39.jar:4.0.FR]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.1.jar:5.3.1]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.39.jar:4.0.FR]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.39.jar:9.0.39]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.1.jar:5.3.1]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.1.jar:5.3.1]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.1.jar:5.3.1]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.1.jar:5.3.1]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.1.jar:5.3.1]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.1.jar:5.3.1]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
The E and F values are the XMLGregorianCalendar type dates and I'm using the 2021-01-05 formatted dates for it.
From wsdl file I see that e_value specified like this:
<s:complexType name="e_value">
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="val" type="s:dateTime" />
</s:sequence>
</s:complexType>
So my guess the default dateTime formatter invokes this error?