Spring Boot+Apache Camel SOAP转REST遇Prolog内容错误求助
解决Apache Camel SOAP转REST时的SAXParseException(Content is not allowed in prolog)
你遇到的Content is not allowed in prolog错误,核心原因是从CXF端点获取的请求体并非原始XML字符串。CXF默认会将SOAP请求解析为SOAPMessage或Document对象,此时强行用getBody(String.class)转换得到的内容格式不符合XML解析要求,导致二次解析时出错。
以下是具体解决方案:
1. 正确获取CXF端点的原始SOAP请求内容
修改路由中的处理逻辑,通过CXF的Exchange属性获取原始XML,而不是直接转换body:
from("cxf:bean:soapCxfEndpoint") .log("Received SOAP request: ${body}") .process(exchange -> { // 从CXF消息中提取原始XML字符串 org.apache.cxf.message.Message cxfMsg = exchange.getIn().getHeader(CxfConstants.CXF_MESSAGE, org.apache.cxf.message.Message.class); String soapRequest = cxfMsg.getContent(String.class).trim(); String restRequest = transformSoapToRest(soapRequest); log.info("Transformed REST request: " + restRequest); // 修正原日志打印错误 exchange.getIn().setBody(restRequest.trim()); }) // 后续路由逻辑保持不变 .log("Transformed to REST request: ${body}") .to("http://localhost:8080/rest/api") // ... 其余代码
2. 避免重复解析XML(优化转换逻辑)
既然CXF已经完成SOAP消息解析,直接利用CXF提供的API提取arg0的值,无需自行二次解析:
private String transformSoapToRest(SOAPMessage soapMessage) throws SOAPException { SOAPBody soapBody = soapMessage.getSOAPBody(); Node arg0Node = soapBody.getElementsByTagName("arg0").item(0); String requestData = arg0Node.getTextContent(); return "{ \"requestData\": \"" + requestData + "\" }"; }
对应的路由修改:
from("cxf:bean:soapCxfEndpoint") .log("Received SOAP request: ${body}") .process(exchange -> { SOAPMessage soapMessage = exchange.getIn().getBody(SOAPMessage.class); String restRequest = transformSoapToRest(soapMessage); log.info("Transformed REST request: " + restRequest); exchange.getIn().setBody(restRequest.trim()); }) // 后续路由逻辑保持不变
3. 排查字符编码与BOM问题
如果上述方法仍无效,检查请求是否携带UTF-8 BOM(字节码为0xEFBBBF),可在转换前去除:
private String transformSoapToRest(String soapRequest) throws ParserConfigurationException, IOException, SAXException { soapRequest = soapRequest.trim(); // 检查并去除UTF-8 BOM byte[] soapBytes = soapRequest.getBytes(StandardCharsets.UTF_8); if (soapBytes.length >=3 && soapBytes[0] == (byte)0xEF && soapBytes[1] == (byte)0xBB && soapBytes[2] == (byte)0xBF) { soapRequest = new String(soapBytes, 3, soapBytes.length-3, StandardCharsets.UTF_8); } // 原解析逻辑保持不变 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse(new InputSource(new StringReader(soapRequest))); String requestData = document.getElementsByTagName("arg0").item(0).getTextContent(); return "{ \"requestData\": \"" + requestData + "\" }"; }
额外修正:原代码中的日志错误
你在转换REST请求后的日志打印的是soapRequest,应改为restRequest,避免调试混淆:
// 原错误代码 log.info("Transformed rest request: " + soapRequest); // 修正后 log.info("Transformed REST request: " + restRequest);
内容的提问来源于stack exchange,提问作者Bijaya
相关产品推荐
相关产品推荐

