I'm building a SpringBoot microservice that calls another microservice and naturally want to use Hystrix and Feign clients, which are both included with Spring Cloud. I'm using version Camden.SR5.
For any timeouts, connection failures and 50x response codes from Feign, I want Hystrix to kick in and work as normal: tripping the circuit breaker and calling the fallback (if configured), etc. It does this by default, so I'm good.
But for 40x response codes, which include things like invalid entry, the wrong format of fields etc, I want Hystrix to propagate these exceptions to the caller, so I can handle them as I choose too. This isn't the default I've observed. How do you configure Hystrix/Feign to do this in Spring Cloud?
Out of the box using the following code:
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.hateoas.Resource;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@FeignClient(name = "dog-service", url = "http://...")
public interface DogsFeignClient {
@RequestMapping(method = RequestMethod.POST, path = "/dogs")
Resource<Dog> createDog(Dog dog);
}
Generates this exception, which doesn't lend itself to nicely passing that 40x response back to the caller:
com.netflix.hystrix.exception.HystrixRuntimeException: DogsFeignClient#createDog(Dog) failed and no fallback available.
at com.netflix.hystrix.AbstractCommand$22.call(AbstractCommand.java:805) ~[hystrix-core-1.5.6.jar:1.5.6]
....lines ommited for brevity....
Caused by: feign.FeignException: status 400 reading DogsFeignClient#createDog(Dog); content:
{
"errors" : [ {
"entity" : "Dog",
"property" : "numberOfLegs",
"invalidValue" : "3",
"message" : "All dogs must have 4 legs"
} ]
}
at feign.FeignException.errorStatus(FeignException.java:62) ~[feign-core-9.3.1.jar:na]
at feign.codec.ErrorDecoder$Default.decode(ErrorDecoder.java:91) ~[feign-core-9.3.1.jar:na]
at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:138) ~[feign-core-9.3.1.jar:na]
at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:76) ~[feign-core-9.3.1.jar:na]
at feign.hystrix.HystrixInvocationHandler$1.run(HystrixInvocationHandler.java:108) ~[feign-hystrix-9.3.1.jar:na]
at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:301) ~[hystrix-core-1.5.6.jar:1.5.6]
at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:297) ~[hystrix-core-1.5.6.jar:1.5.6]
at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:46) ~[rxjava-1.1.10.jar:1.1.10]
... 26 common frames omitted
I can of course look at the com.netflix.hystrix.exception.HystrixRuntimeException, cause field which contains a feign.FeignException and buried in the description is the JSON response itself, with line breaks and such. But the cause field of feign.FeignException is a reference to itself. Is there a way to get a deeper exception propagated instead of the HystrixRuntimeException?
Also is there a way to get the raw body included with the response from the downstream service, so I don't have to deconstruct the message field of the nested exception?
HystrixCommandobject or@HystrixCommandannotation and ignore certain exceptions. - spencergibb