Search code examples
httpmuleoutbound

Mule ESB synchronous Until Successful payload modification


I've spent hours trying to solve my problem which seems to be caused by synchronous Until Successful Scope in Mule ESB v3.5.0. It seems to modify message payload when sending an outbound HTTP requests.

I need to continue in my flow after outbound HTTP request successfully returns from a HTTP server (which sometimes has connection problems). Thus I need the sync variant of Until Successful. For now I use just a simple Logger after the Until Successful block.

The body of my HTTP request is a XML file. When there is no problem at my server and the Until Successful doesn't need to make another HTTP request again, I receive the XML which I sent.

However, when there is a connectivity problem so the Until Successful repeats requesting a few times and then the server goes back online, on my server I receive an instance of org.apache.commons.httpclient.methods.PostMethod instead of the sent XML in the request body!

So no more XML on my server. It seems this sync Until Successful simply discards the original message payload...

The standard async variant of Until Successful works as intended - getting XML in requests all the time.

Here is a minimal sample of HTTP outbound endpoint with Until Successful:

  <flow name="perform" doc:name="performHTTP">
      <until-successful  maxRetries="${repeater.retries}" millisBetweenRetries="${repeater.period}" failureExpression="#[exception != null &amp;&amp; (exception.causedBy(java.net.ConnectException) || exception.causedBy(java.net.SocketTimeoutException)) || message.inboundProperties['http.status'] != 200]"  doc:name="Until Successful - Repeater" synchronous="true">
          <http:outbound-endpoint exchange-pattern="request-response" host="${https.outbound.address}" port="${https.outbound.port}" path="${https.outbound.path}" method="POST"  mimeType="text/xml"  transformer-refs="Custom_Outbound_HTTPS_Header" contentType="text/xml" doc:name="HTTPS - Outbound" doc:description="Outcoming HTTPS connection" responseTimeout="15000"/>
      </until-successful>

      <logger message="#['Sending done']" level="INFO" doc:name="Logger - Done"/>
  </flow>

Long story short:

  • synchronous Until Successful: XML -> HTTP request - { NET } - HTTP request -> org.apache.commons.httpclient.methods.PostMethod

  • asynchronous Until Successful: XML -> HTTP request - { NET } - HTTP request -> XML


Solution

  • I had the same problem and fixed it by saving my payload and retrieving on each retry something like this

    <set-variable value="#[payload]" variableName="paloadbeforecall" doc:name="Variable" />
    
    <until-successful  maxRetries="${repeater.retries}" millisBetweenRetries="${repeater.period}" failureExpression="#[exception != null &amp;&amp; (exception.causedBy(java.net.ConnectException) || exception.causedBy(java.net.SocketTimeoutException)) || message.inboundProperties['http.status'] != 200]"  doc:name="Until Successful - Repeater" synchronous="true">
          <processor-chain>
                <set-payload  value="#[flowVars.?paloadbeforecall]"  doc:name="Variable" />
                <http:outbound-endpoint exchange-pattern="request-response" host="${https.outbound.address}" port="${https.outbound.port}" path="${https.outbound.path}" method="POST"  mimeType="text/xml"  transformer-refs="Custom_Outbound_HTTPS_Header" contentType="text/xml" doc:name="HTTPS - Outbound" doc:description="Outcoming HTTPS connection" responseTimeout="15000"/>
          </processor-chain>
    </until-successful>