You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取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) {
                    // 执行你的业务逻辑,比如持久化、转发等
                }
            });
    }
}

关键说明

  1. 阶段选择:使用Phase.RECEIVE能确保在CXF解析SOAP报文前获取最原始的XML内容,避免解析过程中丢失细节。
  2. 输入流重置:读取后重置输入流是为了保证后续的CXF拦截器或Camel处理器能正常处理报文内容。
  3. 对比原有方案:无需手动重构SOAPMessage,直接保留原始响应的所有结构和细节,避免了繁琐的节点拼接操作。

内容的提问来源于stack exchange,提问作者Martel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 09:53:20