Sending XmlData in soap request using spring ws

java, soap, spring-ws

Solution

I have got the same problem in this day at work, when we must inject a CDATA section over a field text of a data structure defined into a WSDL exposed from a Bank web service.

The requirement was to introduce a CDATA section to escape the Unicode character "+" into a number telephone field. The WSDL is not possible to change for various motivation.

We have the same environment:

 org.springframework.oxm.jaxb.Jaxb2Marshaller

webServiceTemplate.marshalSendAndReceive(payloadRequest, SoapActionCallback)

and the same fail result

<![CDATA[<tag>+<\tag>

instead of

<[[CDATA[+]]>

After many and many test and after have consulting many fonts on Stackoverflow and other site, we have understand that the solution is not natively supported from JAXB engine and it's necessary to manipulate the SOAP message into a puntual step of processing the request.

Other solution indicated to use third part plugin and library, ad example MOXy, to accomplished a strong support of CDATA section also JAXB. But this solution is not possible to integrate in fast time over an huge enterprise application in form ASAP.

This solution that I publish in this reply permit to inject a CDATASection using the canonical method of a classic DOMSource object casting the message SOAP from messagecontext.

In your answer you expose a part of solution, and this is the callback of marshalSendAndReceive.

If you define an ad hoc callback supported by `marshalSendAndReceive` method and in this callback manipulate the DOMSource injecting the CDATASection you can resolve the problem.

This is the code:

WebServiceMessageCallback callbackCDATANumTelefono = new WebServiceMessageCallback() {
           public void doWithMessage(WebServiceMessage message) {

                //Recover the DOMSource dal message soap
                DOMSource domSource = (DOMSource)message.getPayloadSource();

                //recover set of child nodes of domsource
                NodeList nodeList = domSource.getNode().getChildNodes();

                //definisco il nome del tag da cercare
                String nameNumTel = "ns2:sNumTel"; //in this example, but you can define another QName string to recover the target node (or nodes)
                Node nodeNumTel = null;
                for (int i = 0; i < nodeList.getLength(); i++) {
                    //search of text node of this tag name
                    if (nodeList.item(i).getNodeName().compareTo(nameNumTel) == 0) {
                        nodeNumTel = nodeList.item(i);
                        break;
                    }
                }
                //recover the string value (in this case of telephone number)
                String valueNumTelefono = nodeNumTel.getTextContent();
                //clean of value of target text node
                nodeNumTel.setTextContent("");
                //define and inject of CDATA section, in this case encapsulate "+" character
                CDATASection cdata = nodeNumTel.getOwnerDocument().createCDATASection("+");
                //create of new text node
                Text tnode = nodeNumTel.getOwnerDocument().createTextNode(valueNumTelefono);
                //append of CDATASection (in this point is possible to inject many CDATA section on various parts of string (very usefull)
                nodeNumTel.appendChild(cdata);
                nodeNumTel.appendChild(tnode);

                //done!
            }
        };

this callback will be call from marshalSendAndReceive

PayloadSoapResponse output = (PayloadSoapResponse ) getWebServiceTemplate()
                .marshalSendAndReceive(input, callbackCDATANumTelefono);

The result is a correct send of request with CDATA section valid and not converted in ascii character.

This solution have the objective to manipolate CDATA section over Spring infrastructure with JAXB tecnology , not using third part library. In general the set of instructions of callback method is very trust and good to be injecting in all environment of a web service soap. The crucial aspect is to convert the SoapMessage in an more friendly DOMSource with canonical method to explore node. It's possible using also XPath engine to navigate this DOMSource.

Good luck!

am

Problem

I have requirement to send `XmlData` in `CDATA` to soap request which returns an attachment. Using `org.springframework.oxm.jaxb.Jaxb2Marshaller` as marshaller and unmarshaller. `<![CDATA[<tag>Test</tag>]]>` this is something I want to send in the soap request and remote service is expecting it to see the same way. I have created the data but when I use `webServiceTemplate.marshalSendAndReceive(payloadRequest, SoapActionCallback)` somehow, payload request xmltags are encoded and shows as `&lt;![CDATA[&lt;tag&gt;Test&lt;\tag&gt;` Because of this encoding, remote service cannot process the request and send `org.springframework.ws.soap.client.SoapFaultClientException: Object reference not set to an instance of an object.` how can I fix this issue? Any suggestions! Update: Does, spring mvc's defaultHtmlEscape as context-param in web.xml responsible for this behaviour?

Original source