16

I have a feign client with this external call:

@RequestMapping(method = RequestMethod.GET, value = "GetResourceA", consumes = "application/json")
@Cacheable("ResourceA")
List<Stop> getResourceA() throws MyOwnException;

And in my application.yml I have this setting:

hystrix:
  command:
    default:
      execution.isolation.thread.timeoutInMilliseconds: 1000
      fallback.enabled: false

Now if getResourceA times out, i.e. it takes more than one second to complete, I either get this:

com.netflix.hystrix.exception.HystrixRuntimeException: getResourceA timed-out and no fallback available

Or, if I define a fallback from which I throw my own exception, I get this:

com.netflix.hystrix.exception.HystrixRuntimeException: getResourceA timed-out and fallback failed.

Can I not throw my own exception from the fallback?

What if I wish to throw my own exception when the service is down? I would like to not have a fallback (because I have no reasonable value to return from the fallback), but instead throw my own error that I can catch and let the program resume. Can someone help me out with this?

Update after the answer from Ben:

So I tried the approach with catching HysterixRuntimeException and checking what caused it, but ended up with this ugly code:

try {
    getResourceA();
} catch (HystrixRuntimeException e) {
    if (e.getFailureType().name().equals("TIMEOUT")) {
        throw new MyOwnException("Service timed out");
    }
    throw e;
}

All that to be able to throw MyOwnException on a timeout. Surely there must be another way?

L42
  • 3,052
  • 4
  • 28
  • 49

3 Answers3

4

You should be able to get the exception you throw from your fallback by getting the cause of the HystrixRuntimeException

So, to handle your custom exception, you can do this:

try {
    getResourceA();
} catch (HystrixRuntimeException e) {
    if (e.getCause() instanceof MyException) {
        handleException((MyException)e.getCause());
    }
}
Ben Green
  • 3,953
  • 3
  • 29
  • 49
  • Thanks! That's what I'll do unless there's another way that doesn't require me to catch the (ugly) HystrixRuntimeException in "my own code". – L42 Aug 17 '16 at 11:07
  • @L42. No problem. I ran into the same problem last year, and this would be the best I could find. Would be keen to see if anyone else has a better suggestion I can use to tidy things up a bit :) – Ben Green Aug 17 '16 at 11:09
  • I tried it and ended up having to do the following in order to retrieve the exception I throw in the fallback method: http://pastebin.com/Dxw95kSB. Do you know a better way to do it? – L42 Aug 17 '16 at 11:49
  • No, unfortunately that may be the only way to do it. You could create a method and pass the exception in, which then checks the type of exception, gets the cause and calls itself recursively to keep checking the exception type until you get an exception that you can use? – Ben Green Aug 17 '16 at 12:07
  • I've updated my question with something that does what I want. I guess I could extract that into its own function :) – L42 Aug 17 '16 at 12:53
0

You can use an ErrorDecoder and return your own exception from there and then use an exception handler. I had a similar problem and solved it like this:

public class ExceptionHandlerControllerAdvice extends ResponseEntityExceptionHandler
...

@ResponseStatus(BAD_REQUEST)
@ExceptionHandler(HystrixRuntimeException.class)
public ExceptionResponse handleHystrixRuntimeException(HystrixRuntimeException exception) {
    if(exception.getCause() instanceof MyException) {
        return handleMyException((MyException) exception.getCause());
...

And then in my Configuration class for my FeignClient:

@Bean
public ErrorDecoder feignErrorDecoder() {
    return new ErrorDecoder() {
        @Override
        public Exception decode(String methodKey, Response response) {
            return new MyException("timeout");
        }
    };
}

That way you don't need multiple nested getCause()

steenstn
  • 21
  • 2
0

If you want replace timeout exception throw by hystrix,you can write like this:

try {
    testClient.timeoutTest();
} catch (HystrixRuntimeException e) {
    Throwable fallbackException = e.getFallbackException();
    if (fallbackException.getCause().getCause() instanceof CustomException) {
        log.info("customer exception!");
    }
}
Pat. ANDRIA
  • 2,330
  • 1
  • 13
  • 27
susama
  • 1