如何获取SoapFault并在Quarkus+Camel路由中保留错误串继续流转
通过CXF inFaultInterceptor保留原始SoapFault XML内容
完全可以通过自定义CXF的inFaultInterceptor直接获取并保存原始的SoapFault XML内容,无需手动重构SOAPMessage,这样能完整保留响应的所有细节(包括自定义Detail、命名空间、SOAP头等)。
自定义Fault拦截器实现
创建一个继承AbstractPhaseInterceptor的拦截器,在合适的阶段读取原始Fault的输入流并转换为XML字符串,存入Camel Exchange供后续路由使用:
import org.apache.cxf.binding.soap.SoapMessage; import org.apache.cxf.interceptor.Fault; import org.apache.cxf.phase.AbstractPhaseInterceptor; import org.apache.cxf.phase.Phase; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; public class SoapFaultRawXmlInterceptor extends AbstractPhaseInterceptor<SoapMessage> { public SoapFaultRawXmlInterceptor() { // 选择RECEIVE阶段,确保在CXF解析SOAP报文前获取原始XML super(Phase.RECEIVE); } @Override public void handleMessage(SoapMessage message) throws Fault { try (InputStream inputStream = message.getContent(InputStream.class); ByteArrayOutputStream baos = new ByteArrayOutputStream()) { if (inputStream == null) { return; } // 读取原始Fault XML内容 byte[] buffer = new byte[1024]; int len; while ((len = inputStream.read(buffer)) != -1) { baos.write(buffer, 0, len); } String rawFaultXml = baos.toString("UTF-8"); // 重置输入流,保证后续拦截器能正常读取 message.setContent(InputStream.class, new ByteArrayInputStream(baos.toByteArray())); // 将原始XML存入Camel Exchange属性 org.apache.camel.Exchange camelExchange = message.getExchange().get(org.apache.camel.Exchange.class); if (camelExchange != null) { camelExchange.setProperty("RAW_SOAP_FAULT_XML", rawFaultXml); // 若需要直接替换消息体,可使用下面的代码 // camelExchange.getIn().setBody(rawFaultXml); } } catch (Exception e) { throw new Fault(e); } } }
配置拦截器到CXF Endpoint
在Quarkus环境中,先将拦截器注册为CDI Bean:
import jakarta.enterprise.context.ApplicationScoped; @ApplicationScoped public class SoapFaultRawXmlInterceptorProducer { @Produces public SoapFaultRawXmlInterceptor soapFaultRawXmlInterceptor() { return new SoapFaultRawXmlInterceptor(); } }
然后在Camel路由中配置该拦截器:
import org.apache.camel.builder.RouteBuilder; import jakarta.inject.Inject; public class SoapServiceRoute extends RouteBuilder { @Inject SoapFaultRawXmlInterceptor soapFaultRawXmlInterceptor; @Override public void configure() throws Exception { from("cxf://http://target-soap-service-url" + "?serviceClass=com.your.package.ServiceInterface" + "&inFaultInterceptors=#soapFaultRawXmlInterceptor") .process(exchange -> { // 后续路由步骤中获取原始Fault XML String rawFaultXml = exchange.getProperty("RAW_SOAP_FAULT_XML", String.class); if (rawFaultXml != null) { // 执行你的业务逻辑,比如持久化、转发等 } }); } }
关键说明
- 阶段选择:使用
Phase.RECEIVE能确保在CXF解析SOAP报文前获取最原始的XML内容,避免解析过程中丢失细节。 - 输入流重置:读取后重置输入流是为了保证后续的CXF拦截器或Camel处理器能正常处理报文内容。
- 对比原有方案:无需手动重构SOAPMessage,直接保留原始响应的所有结构和细节,避免了繁琐的节点拼接操作。
内容的提问来源于stack exchange,提问作者Martel
相关产品推荐
相关产品推荐

