I am sending a message to an external SOAP service that should reply with a soap Message containing, among other things, an image. This is the code I wrote to send the message:
@Bean
Jaxb2Marshaller jaxb2Marshaller() {
Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
jaxb2Marshaller.setContextPath("myContextPath");
return jaxb2Marshaller;
}
@Bean
public WebServiceTemplate webServiceTemplate() {
WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
webServiceTemplate.setMessageSender(webServiceMessageSender());
webServiceTemplate.setMarshaller(jaxb2Marshaller());
webServiceTemplate.setUnmarshaller(jaxb2Marshaller());
webServiceTemplate.setDefaultUri(defaultUri);
return webServiceTemplate;
}
public ProcessDocumentResponse sendRequest(MyRequest myRequest) {
MyResponse response = (MyResponse) webServiceTemplate.marshalSendAndReceive(
myRequest,
message -> ((SoapMessage) message).setSoapAction(theAction));
return response;
}
And this is the response, got from the log:
Receiving response: HTTP/1.1 200 OK
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: multipart/related; type="application/xop+xml";start="<http://tempuri.org/0>";boundary="uuid:_someUUID_";start-info="text/xml"
Server: Microsoft-IIS/10.0
MIME-Version: 1.0
X-AspNet-Version: ...
X-Powered-By: ...
Date: Wed, 11 Oct 2017 09:10:36 GMT
Content-Length: 228346
Connection can be kept alive indefinitely
"[\r][\n]"
"--uuid:_someUUID_[\r][\n]"
"Content-ID: <http://tempuri.org/0>[\r][\n]"
"Content-Transfer-Encoding: 8bit[\r][\n]"
"Content-Type: application/xop+xml;charset=utf-8;type="text/xml"[\r][\n]"
"[\r][\n]"
"<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body>
<here a long response and at some point:><OutputImages><ImageData><xop:Include href="cid:http://tempuri.org/1/636433219150087850" xmlns:xop="http://www.w3.org/2004/08/xop/include"/></ImageData><Metadata i:nil="true"/></OutputImages>
</s:Body></s:Envelope>[\r][\n]"
"--uuid:_someUUID_[\r][\n]"
"Content-ID: <http://tempuri.org/1/636433098360776690>[\r][\n]"
"Content-Transfer-Encoding: binary[\r][\n]"
"Content-Type: application/octet-stream[\r][\n]"
"[\r][\n]"
"[0xff][0xd8][0xff][0xe0][0x0]_here a long sequence o bytes representing an image_
<< "--uuid:_someUUID_[\r][\n]"
as you can see, there are two multipart contents. In the first multipart content there is the ImageData containing:
<OutputImages><ImageData><xop:Include href="cid:http://tempuri.org/1/636433219150087850" xmlns:xop="http://www.w3.org/2004/08/xop/include"/></ImageData><Metadata i:nil="true"/></OutputImages>
that link cid:http://tempuri.org/1/636433219150087850 is the ID of the second multipart content.
The problem is that after unmarshalling the message, my response contains a byte[] imageData that is empty but should contain the bytes in the second multipart content. So I don't exactly know how to face this problem, should I change some configuration to the unmarshaller? (how?) Should I access the HttpResponse (how?), but then how can I fill the byte[] value in the response?
Class WebServiceTemplate. The central class for client-side Web services. It provides a message-driven approach to sending and receiving WebServiceMessage instances. Code using this class need only implement callback interfaces, provide Source objects to read data from, or use the pluggable Marshaller support.
Please note that the WebServiceTemplate class is thread-safe once configured (assuming that all of it's dependencies are thread-safe too, which is the case for all of the dependencies that ship with Spring-WS), and so multiple objects can use the same shared WebServiceTemplate instance if so desired.
Class SoapActionCallback. WebServiceMessageCallback implementation that sets the SOAP Action header on the message. A usage example with WebServiceTemplate : WebServiceTemplate template = new WebServiceTemplate(messageFactory); Result result = new DOMResult(); template.
WebServiceGatewaySupport() Creates a new instance of the WebServiceGatewaySupport class, with a default WebServiceTemplate . protected. WebServiceGatewaySupport(WebServiceMessageFactory messageFactory) Creates a new WebServiceGatewaySupport instance based on the given message factory.
After a bit of struggling, I found the solution. The key was to understand how this mechanism is called, I ignored it, shame on me.
It is called MTOM and the solution of my problem is just a row more in the marshaller creation:
@Bean
Jaxb2Marshaller jaxb2Marshaller() {
Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
jaxb2Marshaller.setContextPath("myContextPath");
jaxb2Marshaller.setMtomEnabled(true); //that's it!!
return jaxb2Marshaller;
}
I found the solution when I bumped into this post, and then looking for the meaning of MTOM and finally the solution in the Spring WS Documentation
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With