使用 MarshallingWebServiceOutboundGateway 时选择正确的 SoapAction

Picking the Right SoapAction when using MarshallingWebServiceOutboundGateway

我正在尝试学习 Spring 集成。作为探索所有功能的测试项目。我的项目是这样的

AMQP Queue -> Header Router -> Transformer -> OutBound SOAP WS Call -> Log Results -> End

1.) 通过监听 RabbitMq Queue 开始流程。发送的 RabbitMq 消息将有一个字符串值(示例:32)和一个 Header,如 {"operation" "CelsiusToFahrenheit"}.

2.)然后根据RabbitMQ的Header值("operation").

将RabbitMq消息转化为对应的JavaObject

3.) 然后我使用 MarshallingWebServiceOutboundGateway 调用 SOAP WebService @ (http://www.w3schools.com/xml/tempconvert.asmx)。当我这样做时,出现错误。

ErrorMessage [payload=org.springframework.messaging.MessageHandlingException: error occurred in message handler [wsOutboundGateway]; nested exception is org.springframework.ws.soap.client.SoapFaultClientException: Server did not recognize the value of HTTP Header SOAPAction: ., headers={replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@601affec, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@601affec, id=7f6624cc-e7a4-37f6-0a1f-578dc78c4afa, timestamp=1482356790717}]

如您所见,SOAPAction 为空白,服务器不喜欢它。

如果我像这样硬编码 SOAPAction

public MessageHandler wsOutboundGateway()
{
    MarshallingWebServiceOutboundGateway temperatureConversionWebServiceGateway = new MarshallingWebServiceOutboundGateway(WEBSERVICE_URL, jaxb2Marshaller(), jaxb2Marshaller());
    temperatureConversionWebServiceGateway.setRequestCallback(new SoapActionCallback("http://www.w3schools.com/xml/CelsiusToFahrenheit"));
    temperatureConversionWebServiceGateway.setOutputChannelName("webServiceResponseChannel");
    return temperatureConversionWebServiceGateway;
}

有效!

但是,端点公开了 2 项服务(2 项可能的操作)。见下文。

FahrenheitToCelsius soapAction="http://www.w3schools.com/xml/FahrenheitToCelsius" CelsiusToFahrenheit soapAction="http://www.w3schools.com/xml/CelsiusToFahrenheit"

我希望能够根据 RabbitMQ Header 值 ("operation") 在 运行 时间设置 SoapAction。我该怎么做?

旁注,我做了几个不同的实验来解决这个问题,但 none 似乎已经产生了我正在寻找的结果。我尝试的解决方案之一是将 SoapAction 设置为转换过程的一部分(将 Rabbit MQ 消息的输入转换为基于 RabbitMQ Header 值的相应 Java 类型)并将该请求发送到出站网关(参见下面的代码)。

@Bean
public IntegrationFlow generateCelsiusToFahrenheitRequestFlow() {

    Map<String, Object> headers = new HashMap<>();
    headers.put("SOAPAction", "http://www.w3schools.com/xml/CelsiusToFahrenheit");

    return IntegrationFlows.from(celsiusToFahrenheitChannel)
            .transform(celsiusToFahrenheitTransformer)
            .enrichHeaders(headers)
            .channel(webServiceRequestChannel)
            .get();
}

在我这样做并点击 'webServiceRequestChannel' 之后,我看到了我之前添加的 SoapAction Header(见下文)。

GenericMessage [payload=CelsiusToFahrenheit [celsius=32], headers={SOAPAction=http://www.w3schools.com/xml/CelsiusToFahrenheit, amqp_receivedDeliveryMode=NON_PERSISTENT,........

但是,当 MarshallingWebServiceOutboundGateway 接收到请求并对 SOAP WebService 进行出站调用时,"SOAPAction: " 仍然是空白。我不确定为什么 Soap Action 被取消了。我错过了什么?

抱歉,如果我在编写/格式化我的问题时没有遵循惯例。这是我第一次来到 Stack Overflow。将非常感谢解决此问题的任何输入或建议。

是的,这里的错误是 header 名称必须正好是 WebServiceHeaders.SOAP_ACTION,而它的名称是 ws_soapAction。只有现在 DefaultSoapHeaderMapper 才能将其映射到请求 WebserviceMessage:

public DefaultSoapHeaderMapper() {
    super(WebServiceHeaders.PREFIX, STANDARD_HEADER_NAMES, Collections.<String>emptyList());
}