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

Apache Camel+CXF集成问题:响应未携带SOAP请求中的TransactionId头

Apache Camel 4.11.0 + CXF集成:SOAP请求Header原样复制到响应的解决方案

问题场景

使用Apache Camel 4.11.0与CXF集成开发SOAP服务时,响应未携带请求中的SOAP Header元素,需要将请求里的<TransactionId> Header原样复制到响应中。

请求中的SOAP Header示例:

<soapenv:Header>
    <TransactionId>54bdfeab-48ca-4497-95a9-0869ed6eabae</TransactionId>
</soapenv:Header>

当前配置

POM依赖(关键部分)

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>17</java.version>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
    <camel.version>4.11.0</camel.version>
    <springboot.version>3.4.5</springboot.version>
</properties>
<dependencyManagement>
    <dependencies>
        <!-- Spring Boot BOM -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${springboot.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!-- Camel BOM -->
        <dependency>
            <groupId>org.apache.camel.springboot</groupId>
            <artifactId>camel-spring-boot-bom</artifactId>
            <version>${camel.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

路由配置(原代码)

public class Routes extends EndpointRouteBuilder {

    @Override
    public void configure() {
        from("cxf:bean:Service?loggingFeatureEnabled=true&mergeProtocolHeaders=true")
            .to("validator:file:src/main/resources/wsdl/NorthBound/test.xsd");
    }

    @Produces
    @Named
    @Bean(name = "service")
    CxfEndpoint viewAllowanceServiceEndpoint() {
        final CxfEndpoint result = new CxfEndpoint();
        result.setDataFormat(DataFormat.PAYLOAD);
        result.setSynchronous(true);
        return result;
    }
}

当前响应(无Header)

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <ns2:Response>
          <status>0</status>
      </ns2:Response>
   </soap:Body>
</soap:Envelope>

期望响应(带原Header)

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Header>
        <TransactionId>54bdfeab-48ca-4497-95a9-0869ed6eabae</TransactionId>
    </soapenv:Header>
   <soap:Body>
      <ns2:Response>
          <status>0</status>
      </ns2:Response>
   </soap:Body>
</soap:Envelope>

解决方案

方案1:手动提取并设置SOAP Header(Payload格式下适用)

修改路由逻辑,在处理请求时提取SOAP Header并保存,响应时将Header设置回去:

import org.apache.camel.Message;
import org.apache.camel.component.cxf.CxfMessageUtils;
import org.apache.cxf.headers.Header;
import org.apache.camel.component.cxf.DefaultHeaderFilterStrategy;
import java.util.List;

public class Routes extends EndpointRouteBuilder {

    @Override
    public void configure() {
        from("cxf:bean:Service?loggingFeatureEnabled=true&mergeProtocolHeaders=true")
            // 提取请求SOAP Header并存储到Exchange属性
            .process(exchange -> {
                Message inMsg = exchange.getIn();
                List<Header> soapHeaders = CxfMessageUtils.getSoapHeaders(inMsg);
                if (!soapHeaders.isEmpty()) {
                    exchange.setProperty("REQUEST_SOAP_HEADERS", soapHeaders);
                }
            })
            .to("validator:file:src/main/resources/wsdl/NorthBound/test.xsd")
            // 将保存的Header设置到响应中
            .process(exchange -> {
                Message outMsg = exchange.getOut();
                List<Header> soapHeaders = exchange.getProperty("REQUEST_SOAP_HEADERS", List.class);
                if (soapHeaders != null && !soapHeaders.isEmpty()) {
                    CxfMessageUtils.setSoapHeaders(outMsg, soapHeaders);
                }
                // 同步请求Body到响应
                outMsg.setBody(exchange.getIn().getBody());
            });
    }

    @Produces
    @Named
    @Bean(name = "service")
    CxfEndpoint viewAllowanceServiceEndpoint() {
        final CxfEndpoint result = new CxfEndpoint();
        result.setDataFormat(DataFormat.PAYLOAD);
        result.setSynchronous(true);
        // 启用默认Header过滤策略,避免Header被过滤
        result.setHeaderFilterStrategy(new DefaultHeaderFilterStrategy());
        return result;
    }
}

方案2:使用MESSAGE数据格式(自动传递完整Envelope)

如果业务允许处理完整的SOAP Envelope,可以将CxfEndpoint的DataFormat改为MESSAGE,这样请求的完整Envelope(包括Header)会被自动传递到响应:

@Produces
@Named
@Bean(name = "service")
CxfEndpoint viewAllowanceServiceEndpoint() {
    final CxfEndpoint result = new CxfEndpoint();
    // 改为MESSAGE格式,传递完整SOAP Envelope
    result.setDataFormat(DataFormat.MESSAGE);
    result.setSynchronous(true);
    return result;
}

注意:使用MESSAGE格式时,验证器的XSD需要支持完整的SOAP Envelope结构,否则会触发验证失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 22:34:49