I have problem with RequestHandlerCircuitBreakerAdvice.
In code below if RequestHandlerCircuitBreakerAdvice is added as advice in passThru and passThruSecond when something fails in JmsOutboundGateway (firstHandler or secondHandler) CircuitBreaker doesn't work.
But if I add RequestHandlerCircuitBreakerAdvice direclty in JmsOutboundGateway ( inside firstHandler or secondHandler)
gateway.setAdviceChain(Collections.singletonList(requestHandlerCircuitBreakerAdvice));
and delete passThru and passThruSecond ServiceActivator with advice for CircuitBreaker.
It works fine.
Is it normal behavior that CircuitBreaker will only work when something fails directly in same ServiceActivator? or it should work even if something happens in descending ServiceActivator if I use same thread (direct channel)?
Below code doesn't work/use RequestHandlerCircuitBreakerAdvice :
@MessagingGateway(name = "LocalGateway")
public interface LocalGateway {
@Gateway(requestChannel = "inputLocalChannel")
ListenableFuture<Message<String>> sendMsg(Message<String> request);
}
@Bean
public RequestHandlerCircuitBreakerAdvice requestHandlerCircuitBreakerAdvice(){
RequestHandlerCircuitBreakerAdvice requestHandlerCircuitBreakerAdvice = new RequestHandlerCircuitBreakerAdvice();
requestHandlerCircuitBreakerAdvice.setThreshold(2);
requestHandlerCircuitBreakerAdvice.setHalfOpenAfter(20000);
return requestHandlerCircuitBreakerAdvice;
}
@Bean
MessageChannel inputLocalGatewayChannel(){
DirectChannel channel = new DirectChannel();
return channel;
}
@Bean
MessageChannel inputLocalSecondGatewayChannel(){
DirectChannel channel = new DirectChannel();
return channel;
}
@ServiceActivator(inputChannel = "inputLocalChannel", outputChannel = "inputLocalGatewayChannel", adviceChain = "requestHandlerCircuitBreakerAdvice")
public Message passThru(Message message){
return message;
}
@ServiceActivator(inputChannel = "inputLocalChannel", outputChannel = "inputLocalSecondGatewayChannel", adviceChain = "requestHandlerCircuitBreakerAdvice")
public Message passThruSecond(Message message){
return message;
}
@Bean
@ServiceActivator(inputChannel = "inputLocalGatewayChannel")
public JmsOutboundGateway firstHandler(){
// some code
}
@Bean
@ServiceActivator(inputChannel = "inputLocalSecondGatewayChannel")
public JmsOutboundGateway secondHandler(){
// some code
}
It is called AbstractRequestHandlerAdvice
for a reason.
The logic there is like this:
boolean isMessageMethod = (method.getName().equals("handleRequestMessage") || method.getName().equals("handleMessage"))
&& (arguments.length == 1 && arguments[0] instanceof Message);
So, this AOP advice is applied only for a specific method in the MessageHandler
implementation. It is not propagated downstream in the flow.
You can try to wrap that one with a HandleMessageAdviceAdapter
. See its Javadocs.
Another solution is to extract your logic into a sub-flow and apply this RequestHandlerCircuitBreakerAdvice
on the gateway()
endpoint.
See more in docs: https://docs.spring.io/spring-integration/reference/handler-advice.html