Search code examples
javaspring-bootspring-cloudhystrix

How to properly handle expected errors in Hystrix fallback?


We have a Hystrix (1.4.x) command that looks like this (using Spring):

@HystrixCommand(groupKey = "GroupKey", commandKey = "CommandKey", fallbackMethod = "myFallback")
public List<X> findXs(long xId) {
   return externalService.findXsExternally(xId);
}

We actually don't want to return a (empty) List from the fallback method but rather throw an exception so that we caller of findXs knows that the externalService is down and can take action accordingly. But at the same time we would like to take advantage of the functionality that Hystrix provides.

In our case we want the caller to return an error message instead of returning a list. In Spring a fallback is implemented like this:

public List<X> myFallback(long xId) {
    // What to do?? Throw exception!?  
}

Throwing an exception from myFallback "works" but Hystrix will warn us that:

CommandKey failed and fallback failed.

I.e. it will interpret this as a fallback failure. In our case the exception should not be interpreted as a fallback failure but rather as expected behavior. We've also tried wrapping the thrown exception in a HystrixBadRequestException but it doesn't seem to work for fallbacks (according to the docs this would work for the "run" method).

How would one implement an exception-throwing fallback method in Hystrix? Can we safely ignore the warning or is Hystrix not designed work this way?


Solution

  • Why are you setting the fallback at all if you don't want to use it? Hystrix does not require you to set one. The fallback is used when you would rather return something like stale data from a cache as opposed to throwing an exception. Both cases count as a failure to Hystrix. If you were to throw an exception from the fallback method, you would only confuse Hystrix, which would think there was an error with your fallback in addition to service itself. Hystrix should throw a HystrixBadRequestException wrapping the exception thrown from your findXs method if you don't provide a fallback.