Как бросить исключения из исходящего шлюза в отправителя
Я искал через Интернет и пробовал много разных способов, но я не мог заставить его работать.
Я хочу перехватывать исключения, выданные с исходящей стороны, например, некоторые проверки, которые должны возвращать отправителю исключение, если они не были успешно переданы. Я не знаю, возможно ли это без использования DirectChannel для отправки запросов с сервера.
Я надеюсь, что кто-то может помочь мне.
В приведенном ниже коде я показываю вам мою конфигурацию SI, где фильтр с выражением SPEL "checkRemoteOutputHeaders" выдает исключение при выполнении.
<int:channel id="requestChannelSb">
<int:interceptors>
<int:wire-tap channel="timeStampCalllogger" />
</int:interceptors>
</int:channel>
<task:executor id="threadPoolTaskExecutor" pool-size="10" queue-capacity="100" rejection-policy="DISCARD_OLDEST" />
<bean id="taskExecutor" class="org.springframework.integration.util.ErrorHandlingTaskExecutor">
<constructor-arg name="executor" ref="threadPoolTaskExecutor"/>
<constructor-arg name="errorHandler">
<bean class="org.springframework.integration.channel.MessagePublishingErrorHandler">
<property name="defaultErrorChannel" ref="errorChannel"/>
</bean>
</constructor-arg>
</bean>
<int:channel id="gatewayChannelSb">
<int:dispatcher task-executor="taskExecutor" failover="false"/>
<int:interceptors>
<int:wire-tap channel="timeStampInitlogger" />
</int:interceptors>
</int:channel>
<int:channel id="responseChannelSb">
<int:interceptors>
<int:wire-tap channel="timeStampEndlogger" />
</int:interceptors>
</int:channel>
<int:channel id="errorChannel">
<int:interceptors>
<int:wire-tap channel="errorlogger"/>
</int:interceptors>
</int:channel>
<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">
<int-http:uri-variable name="urlVar" expression="T(gnf.servicebroker.util.Utils).getUrl(headers)" />
</int-http:outbound-gateway>
<int:chain input-channel="responseChannelSb">
<int:header-enricher>
<int:header name="#{T(gnf.servicebroker.util.Constantes$HEADERS).BEAN}" expression="headers[T(gnf.servicebroker.util.Constantes$HEADERS).BEAN]"/>
</int:header-enricher>
<int:transformer ref="customJsonToObjectTransformer"/>
</int:chain>
<int:chain id="chain" input-channel="gatewayChannelSb" output-channel="requestChannelSb">
<int:header-enricher>
<int:error-channel ref="errorChannel" overwrite="true"/>
<int:header name="#{T(gnf.servicebroker.util.Constantes$HEADERS).REQUEST_ID}" expression="headers[T(gnf.servicebroker.util.Constantes$HEADERS).ID].toString()"/>
</int:header-enricher>
<int:filter expression="T(gnf.servicebroker.util.Utils).checkRemoteOutputHeaders(headers)" discard-channel="errorChannel" />
<int:header-enricher>
<int:header name="#{T(gnf.servicebroker.util.Constantes$HEADERS).CONTENT_TYPE}" value="text/x-json" />
<int:header name="#{T(gnf.servicebroker.util.Constantes$HEADERS).ACCEPT}" value="text/x-json" />
<int:header name="#{T(gnf.servicebroker.util.Constantes$HEADERS).BEAN}" expression="T(gnf.servicebroker.util.Utils).getPayloadCanonicalClassName(payload)" />
<int:header name="#{T(gnf.servicebroker.util.Constantes$HEADERS).SECURITY_USER}" expression="T(gnf.servicebroker.util.Utils).getSecurityUser()"/>
<int:header name="#{T(gnf.servicebroker.util.Constantes$HEADERS).TARGET}" expression="T(gnf.servicebroker.util.Utils).getTargetUrl()"/>
</int:header-enricher>
<int:object-to-json-transformer object-mapper="jsonObjectMapper"/>
</int:chain>
<!-- Logging channels -->
<int:logging-channel-adapter id="timeStampInitlogger" level="INFO" expression="'Inicio de la peticion: '.concat(T(gnf.servicebroker.util.Utils).getRequestInfoTrace(headers))"/>
<int:logging-channel-adapter id="timeStampCalllogger" level="INFO" expression="'Envio de la peticion: '.concat(T(gnf.servicebroker.util.Utils).getRequestInfoTrace(headers))"/>
<int:logging-channel-adapter id="timeStampEndlogger" level="INFO" expression="'Final de la peticion: '.concat(T(gnf.servicebroker.util.Utils).getRequestInfoTrace(headers))"/>
<int:logging-channel-adapter id="destinationCalllogger" level="INFO" expression="'Destino peticion: '.concat(headers[T(gnf.servicebroker.util.Constantes$HEADERS).SUBSYSTEM])"/>
<int:logging-channel-adapter id="errorlogger" level="ERROR" expression="'ERROR: '.concat(T(gnf.servicebroker.util.Utils).getRequestInfoTrace(headers))"/>
<!-- End Logging channels -->
<int:chain input-channel="errorChannel" output-channel="responseChannelSb">
<int:transformer ref="messageHandlingExceptionTransformer"/>
</int:chain>
В следующем коде я покажу вам преобразователь "messageHandlingExceptionTransformer", который преобразует исключение MessaggingException в ServiceException (пользовательское исключение):
@Transformer
public Message<ServiceException> transform(ErrorMessage message){
LOGGER.debug("INIT - transform(message=" + message + ")");
MessagingException messageException = (MessagingException) message.getPayload();
ServiceException serviceEx = new ServiceException(messageException.getMessage(), messageException.getCause());
Message<?> originalMsg = messageException.getFailedMessage();
Message<ServiceException> transformedObj = MessageBuilder.withPayload(serviceEx).copyHeaders(originalMsg.getHeaders()).build();
LOGGER.debug("END - transform=" + transformedObj);
return transformedObj;
}
Другой преобразователь "customJsonToObjectTransformer" просто преобразует полезную нагрузку String (JSON) в объект Java и возвращает ее, но если полезная нагрузка не является строкой, например, исключением, она возвращает ее напрямую.
Заранее.
1 ответ
Наконец, я нашел причину, по которой вызывающая сторона не получила исключение во время исходящего жизненного цикла.
Я был просто проблемой конфигурации, потому что в другом XML-файле у меня было определение шлюза, которое указывает его канал ошибок, который был тем же, что определен в исходящей конфигурации. Таким образом, он создал циклическую цепочку вызовов, потому что в исходящем случае ErrorMessage с исключением управляется в errorChannel один раз, а затем снова в канале ошибок шлюза, который был таким же, поэтому петиция снова входит в цепочку, которая управляет errorChannel и, в конце концов, происходит сбой без уведомления вызывающей стороны.
<int:gateway id="gcccSearchServiceRequestByCodeServiceSb"
service-interface="gnf.servicebroker.gps.atencioncliente.atcomercializadora.servicerequest.service.GcccSearchServiceRequestByCodeServiceISb"
default-request-channel="gatewayChannelSb"
error-channel="errorChannel">
<int:method name="gcccSearchServiceRequestByIdSr">
<int:header name="Method" value="gcccSearchServiceRequestByIdSr"/>
<int:header name="Module" value="atencioncliente"/>
<int:header name="Service" value="gnf.servicebroker.gps.atencioncliente.atcomercializadora.servicerequest.service.GcccSearchServiceRequestByCodeServiceISb"/>
<int:header name="SubSystem" value="atec-web"/>
</int:method>
</int:gateway>
Обратите внимание на атрибут error-channel, который имеет то же значение, что и определено channel error в исходящей конфигурации, поэтому, удалив этот атрибут, вызывающая сторона может перехватить исключения:
<int:gateway id="gcccSearchServiceRequestByCodeServiceSb"
service-interface="gnf.servicebroker.gps.atencioncliente.atcomercializadora.servicerequest.service.GcccSearchServiceRequestByCodeServiceISb"
default-request-channel="gatewayChannelSb">
<int:method name="gcccSearchServiceRequestByIdSr">
<int:header name="Method" value="gcccSearchServiceRequestByIdSr"/>
<int:header name="Module" value="atencioncliente"/>
<int:header name="Service" value="gnf.servicebroker.gps.atencioncliente.atcomercializadora.servicerequest.service.GcccSearchServiceRequestByCodeServiceISb"/>
<int:header name="SubSystem" value="atec-web"/>
</int:method>
</int:gateway>
Надеюсь, это кому-нибудь поможет.
Спасибо!!!