Picking the Right SoapAction when using MarshallingWebServiceOutboundGateway

578 Views Asked by At

I am trying to learn Spring Integration. As a test project to explore all the features. My project goes like this

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

1.) Start the flow by Listening to a RabbitMq Queue. The RabbitMq Message that are sent will have a String Value (Example: 32) and a Header like {"operation" "CelsiusToFahrenheit"}.

2.) The RabbitMq message is then transformed to the corresponding Java Object based on the RabbitMQ Header Value ("operation").

3.) Then I am using a MarshallingWebServiceOutboundGateway to invoke the SOAP WebService @ (http://www.w3schools.com/xml/tempconvert.asmx). When I do that I am getting an Error.

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}]

As you can see the SOAPAction was Blank and the server did NOT like it.

If I hard code the SOAPAction like this

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;
}

it works!

However, the endpoint exposes 2 Services (2 Possible Actions). See below.

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

I want to be able to set the SoapAction at run time based on the RabbitMQ Header Value ("operation"). How do I do it?

On a Side note, I have done a few different experiments to solve this problem but none seems to have yielded the results I am looking for. One of the solutions I tried was to set the SoapAction as part of the Transformation process (Converting the Input from Rabbit MQ message to the corresponding Java Type based on the RabbitMQ Header Value) and send that request to the Outbound Gateway (See Code below).

@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();
}

After I do that and tap the 'webServiceRequestChannel', I see the SoapAction Header that I added previously (See Below).

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

However, when the MarshallingWebServiceOutboundGateway picked up the request and makes the outbound call to the SOAP WebService, the "SOAPAction: " is still Blank. I am not sure why the Soap Action got blanked out. What am I missing?

Sorry if I have not followed conventions when Writing / Formatting my question. This is my first time here on Stack Overflow. Any inputs or suggestions to address this issues will be greatly appriciated.

1

There are 1 best solutions below

1
On BEST ANSWER

Yeah, the mistake here that the header name must be exactly WebServiceHeaders.SOAP_ACTION, where its name is ws_soapAction. Only now a DefaultSoapHeaderMapper is able to map it into request WebserviceMessage:

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