I'm developing a web service which takes as input parameter two string values. The first identifies the service to use to import the xml data, and the second is a string of XML data. Here is an example of SOAP request
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://webservices.dataexchange.xxx.com/">
<soapenv:Header/>
<soapenv:Body>
<web:importDataExchange>
<ServiceID>XmlImportServiceName</ServiceID>
<ExchangeData><?xml version="1.0" encoding="UTF-8"?><srv:exchange xmlns:cnt="Container" xmlns:core="Core" xmlns:srv="Service" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="Service http://xxx/xxx.xsd"></srv:exchange></ExchangeData>
</web:importDataExchange>
</soapenv:Body>
</soapenv:Envelope>
Unfortunately, whenever I try to parse the SOAPMessage, I received the following error:
javax.xml.bind.UnmarshalException
- with linked exception:
[com.ctc.wstx.exc.WstxParsingException: Illegal processing instruction target ("xml"); xml (case insensitive) is reserved by the specs.
at [row,col {unknown-source}]: [6,28]]
This is clearly because the JAX-WS I've implemented is trying to Unmarshall the contents of the <ExchangeData> element. Of course, this can all be fixed by wrapping the contents of the <ExchangeData> in a <![CDATA[ ]]> element, however, I have no control over how the data is sent to the server. Therefore, I need a way to intercept the SOAPMessage and extract the ExchangeData as a string without Unmarshalling it. Or, I need a way to have the web service treat the contents of the ExchangeData node as a string rather than another XML node in the SOAPMessage body/payload.
I have tried implementing a SOAPHandler and also a LogicalHandler, but in both instances whenever Message/Payload is fetched the web server attempts to unmarshall the SOAP message, which reproduces the same error again.
This is the ImportServiceEndpoint that I've developed so far.
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.context.support.SpringBeanAutowiringSupport;
@WebService(serviceName = "ImportServiceEndpoint", portName = "dataexchange")
// @HandlerChain(file = "handlers.xml")
public class ImportServiceEndpoint extends SpringBeanAutowiringSupport {
private static final Logger LOGGER = LoggerFactory.getLogger(ImportServiceEndpoint.class);
/**
* The soap implementation of the data exchange service.
*
* @param serviceID
* the id of the service
* @param exchangeData
* the xml data for the request.
* @return a response about the success/failure of the dataexchange.
*/
@WebMethod
@WebResult(name = "importDataExchangeResponse")
public String importDataExchange(@ModelAttribute("ServiceID") @WebParam(name = "ServiceID") final String serviceID,
@ModelAttribute("ExchangeData") @WebParam(name = "ExchangeData") final String exchangeData) {
LOGGER.debug("Recevied Soap request for service {} with xml data '{}'", serviceID, exchangeData);
return "Message Received";
}
}
I would be grateful for any assistance. I'm getting quite frustrated as I've been working on this for a couple of days now with little to show for it.
<?xml version="1.0" encoding="UTF-8"?>from your<ExchangeData>block. You can't have a XML declaration there.exchangeDatavariable in myimportDataExchange()method?<?xml version="1.0" encoding="UTF-8"?>can't be in the<ExchangeData>it led me to the correct solution.... I hope.