<int:publish-subscribe-channel id="validateChannel" apply-sequence="true">
<int:interceptors>
<int:wire-tap channel="validateLogger" />
</int:interceptors>
</int:publish-subscribe-channel>
<int:logging-channel-adapter id="validateLogger" level="INFO" />
<int:bridge input-channel="validateChannel" output-channel="validateRequestOutputChannel" />
<int:bridge input-channel="validateChannel" output-channel="externalServiceChannel" />
<int:channel id="externalServiceChannel" />
I have PublishSubscribeChannel and two sequential subscribers to it. there are calls to 2 external apis.
Step 1 (call to first external api), this api will throw exception or send 200 OK, I want to call second external api(step 2) if this api throws 200 Ok or if throws exception, I want to catch it and throw custom exception to the end user.
<int:service-activator input-channel="validateRequestOutputChannel" ref="sampleTransformer" method="preprocessRequest" output-channel="testServiceRequestChannel"/>
<int-http:outbound-gateway id="testService"
url-expression="headers.testServiceURL"
http-method="POST" request-channel="testServiceRequestChannel" reply-channel="testResponseChannel"
charset="UTF-8"
extract-request-payload="true" expected-response-type="java.lang.String"
request-factory="customHttpRequestFactory"
mapped-request-headers="Content-Type:application/json"
reply-timeout="5000">
<int-http:request-handler-advice-chain>
<bean class="org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice">
<property name="onSuccessExpressionString" value="payload.delete()" />
<property name="successChannel" ref="afterSuccessFetchChannel" />
<property name="failureChannel" ref="afterFailFetchChannel" />
<property name="onFailureExpressionString" value="payload + ' was bad, with reason: ' + #exception.cause.message" />
</bean>
</int-http:request-handler-advice-chain>
</int-http:outbound-gateway>
<int:transformer input-channel="afterSuccessFetchChannel" output-channel="goodResultChannel1"
expression="'Fetching service : ' + payload + ' details was successful'" />
<int:transformer input-channel="afterFailFetchChannel" output-channel="badResultChannel1" ref="exceptionTransformer" method="handleErrorResponse"/>
<int:logging-channel-adapter id="badResultChannel1" level="ERROR"/>
<int:logging-channel-adapter id="goodResultChannel1" level="INFO" />
Step in between, for the step 2, I am using input channel as externalServiceChannel which is subscribe channel to pub sub channel but I am not able to figure out how to connect output channel of step 1 to input channel of step 2,
I was trying to use,
<int:exception-type-router input-channel="testResponseChannel" default-output-channel="errorRecoveryChannel">
<int:mapping exception-type="org.springframework.web.client.HttpClientErrorException.Conflict"
channel="lockServiceErrors"/>
</int:exception-type-router>
<int:chain input-channel="lockServiceErrors" output-channel="validateOutputChannel">
<int:header-enricher>
<int:header name="http_statusCode" value="409" />
</int:header-enricher>
<int:transformer expression="payload.failedMessage" />
</int:chain>
but the issue above is
<property name="onSuccessExpressionString" value="payload.delete()" />
but looks like it does not actually delete the payload.Could you please help?
Step 2(call to second external api):
<int:chain id="test-chain" input-channel="externalServiceChannel" output-channel="validateOutputChannel">
<int:transformer ref="sampleTransformer" method="preprocessAPIInfo" />
<int-http:outbound-gateway id="testService2"
url-expression="headers.testService2URL"
http-method="GET"
extract-request-payload="false"
expected-response-type="com.bibo.test.UserInfo"
charset="UTF-8"
request-factory="customHttpRequestFactory"
mapped-request-headers="Content-Type:application/json,Accept:application/json"
reply-timeout="5000">
<int-http:uri-variable name="userId" expression="headers.userId" />
</int-http:outbound-gateway>
<int:transformer ref="sampleTransformer" method="processUserInfo" />
<int:object-to-json-transformer/>
</int:chain>
I suggest you to revise you flow without a publish-subscribe channel, but really make it linear: call second service after the first. And if first step fails, it is not going to the second which is really an output of the first.
To keep an original request access in the second step there is a trick: place this request into headers:
<int:header-enricher>
<int:header name="originalRequest" expression="payload"/>
</int:header-enricher>
Then when you need it in the second step you just do like this:
<int:transformer expression="headers.originalRequest"/>
The rest of error handling logic is probably OK.