title: How to throw exceptions from outbound-gateway to sender
body: <p>I have been searching through Internet and trying many different ways, but I could not make it works.</p>
  
  <p>What I want is to catch exceptions thrown from the outbound side, for example some validations, which should return an Exception to the sender whe they are not succesfully passed. I do not know if it is possible without using a DirectChannel to send requests from the server.</p>
  
  <p>I hope someone can help me. </p>
  
  <p>In the code below I show you my SI configuration, where filter with the SPEL expression, "checkRemoteOutputHeaders", throws an Exception when executes.</p>
  
  <pre><code>&lt;int:channel id="requestChannelSb"&gt;
      &lt;int:interceptors&gt;
          &lt;int:wire-tap channel="timeStampCalllogger" /&gt;
      &lt;/int:interceptors&gt;
  &lt;/int:channel&gt;
  
  &lt;task:executor id="threadPoolTaskExecutor" pool-size="10" queue-capacity="100" rejection-policy="DISCARD_OLDEST" /&gt;
  
  &lt;bean id="taskExecutor" class="org.springframework.integration.util.ErrorHandlingTaskExecutor"&gt;
      &lt;constructor-arg name="executor" ref="threadPoolTaskExecutor"/&gt;
      &lt;constructor-arg name="errorHandler"&gt;
          &lt;bean class="org.springframework.integration.channel.MessagePublishingErrorHandler"&gt;
              &lt;property name="defaultErrorChannel" ref="errorChannel"/&gt;
          &lt;/bean&gt;
      &lt;/constructor-arg&gt;
  &lt;/bean&gt;
  
  &lt;int:channel id="gatewayChannelSb"&gt;
      &lt;int:dispatcher task-executor="taskExecutor" failover="false"/&gt;
  
      &lt;int:interceptors&gt;
          &lt;int:wire-tap channel="timeStampInitlogger" /&gt;
      &lt;/int:interceptors&gt;
  &lt;/int:channel&gt;
  &lt;int:channel id="responseChannelSb"&gt;
      &lt;int:interceptors&gt;
          &lt;int:wire-tap channel="timeStampEndlogger" /&gt;
      &lt;/int:interceptors&gt;
  &lt;/int:channel&gt;
  &lt;int:channel id="errorChannel"&gt;
      &lt;int:interceptors&gt;
          &lt;int:wire-tap channel="errorlogger"/&gt;
      &lt;/int:interceptors&gt;
  &lt;/int:channel&gt;
  
  
  &lt;int-http:outbound-gateway request-channel="requestChannelSb"
      url="{urlVar}" http-method="POST"
      extract-request-payload="true"
      expected-response-type="java.lang.String"
      charset="UTF-8"
      header-mapper="headerMapper"
      reply-channel="responseChannelSb"
      request-timeout="60000"&gt;
  
      &lt;int-http:uri-variable name="urlVar" expression="T(gnf.servicebroker.util.Utils).getUrl(headers)" /&gt;
  
  &lt;/int-http:outbound-gateway&gt;
  
  &lt;int:chain input-channel="responseChannelSb"&gt;
      &lt;int:header-enricher&gt;
          &lt;int:header name="#{T(gnf.servicebroker.util.Constantes$HEADERS).BEAN}" expression="headers[T(gnf.servicebroker.util.Constantes$HEADERS).BEAN]"/&gt;
      &lt;/int:header-enricher&gt;
      &lt;int:transformer ref="customJsonToObjectTransformer"/&gt;
  &lt;/int:chain&gt;
  
  
  &lt;int:chain id="chain" input-channel="gatewayChannelSb" output-channel="requestChannelSb"&gt;
  
      &lt;int:header-enricher&gt;
          &lt;int:error-channel ref="errorChannel" overwrite="true"/&gt;
          &lt;int:header name="#{T(gnf.servicebroker.util.Constantes$HEADERS).REQUEST_ID}" expression="headers[T(gnf.servicebroker.util.Constantes$HEADERS).ID].toString()"/&gt;
      &lt;/int:header-enricher&gt;
  
      &lt;int:filter expression="T(gnf.servicebroker.util.Utils).checkRemoteOutputHeaders(headers)" discard-channel="errorChannel" /&gt;
  
      &lt;int:header-enricher&gt;
          &lt;int:header name="#{T(gnf.servicebroker.util.Constantes$HEADERS).CONTENT_TYPE}" value="text/x-json" /&gt;
          &lt;int:header name="#{T(gnf.servicebroker.util.Constantes$HEADERS).ACCEPT}" value="text/x-json" /&gt;
          &lt;int:header name="#{T(gnf.servicebroker.util.Constantes$HEADERS).BEAN}" expression="T(gnf.servicebroker.util.Utils).getPayloadCanonicalClassName(payload)" /&gt;
          &lt;int:header name="#{T(gnf.servicebroker.util.Constantes$HEADERS).SECURITY_USER}" expression="T(gnf.servicebroker.util.Utils).getSecurityUser()"/&gt;
          &lt;int:header name="#{T(gnf.servicebroker.util.Constantes$HEADERS).TARGET}" expression="T(gnf.servicebroker.util.Utils).getTargetUrl()"/&gt;
      &lt;/int:header-enricher&gt;
  
      &lt;int:object-to-json-transformer object-mapper="jsonObjectMapper"/&gt;
  &lt;/int:chain&gt;
  
  
  
  &lt;!-- Logging channels --&gt;
  
  &lt;int:logging-channel-adapter id="timeStampInitlogger" level="INFO" expression="'Inicio de la peticion: '.concat(T(gnf.servicebroker.util.Utils).getRequestInfoTrace(headers))"/&gt;
  &lt;int:logging-channel-adapter id="timeStampCalllogger" level="INFO" expression="'Envio de la peticion: '.concat(T(gnf.servicebroker.util.Utils).getRequestInfoTrace(headers))"/&gt;
  &lt;int:logging-channel-adapter id="timeStampEndlogger" level="INFO" expression="'Final de la peticion: '.concat(T(gnf.servicebroker.util.Utils).getRequestInfoTrace(headers))"/&gt;
  &lt;int:logging-channel-adapter id="destinationCalllogger" level="INFO" expression="'Destino peticion: '.concat(headers[T(gnf.servicebroker.util.Constantes$HEADERS).SUBSYSTEM])"/&gt;
  
  &lt;int:logging-channel-adapter id="errorlogger" level="ERROR" expression="'ERROR: '.concat(T(gnf.servicebroker.util.Utils).getRequestInfoTrace(headers))"/&gt;
  
  &lt;!-- End Logging channels --&gt;
  
  
  &lt;int:chain input-channel="errorChannel" output-channel="responseChannelSb"&gt;
      &lt;int:transformer ref="messageHandlingExceptionTransformer"/&gt;
  &lt;/int:chain&gt;
  </code></pre>
  
  <p>In the following code I show you the transformer, "messageHandlingExceptionTransformer", which convert the MessaggingException to ServiceException (custom exception):</p>
  
  <pre><code>    @Transformer
  public Message&lt;ServiceException&gt; transform(ErrorMessage message){
  
      LOGGER.debug("INIT - transform(message=" + message + ")");
  
      MessagingException messageException = (MessagingException) message.getPayload();
  
      ServiceException serviceEx = new ServiceException(messageException.getMessage(), messageException.getCause());
  
      Message&lt;?&gt; originalMsg = messageException.getFailedMessage();
  
      Message&lt;ServiceException&gt; transformedObj = MessageBuilder.withPayload(serviceEx).copyHeaders(originalMsg.getHeaders()).build();
  
  
      LOGGER.debug("END - transform=" + transformedObj);
  
      return transformedObj;
  }
  </code></pre>
  
  <p>The other transformer "customJsonToObjectTransformer" just convert a String payload (JSON) to a Java object and returns it, but if the payload is not a String, for example an exception, it returns it directly.</p>
  
  <p>Thans in advance.</p>