Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Javanica: Option to send fallback exception to client instead of primary command #1344

Closed
nytins opened this issue Sep 2, 2016 · 28 comments
Closed

Comments

@nytins
Copy link

nytins commented Sep 2, 2016

We are having an issue because javanica always sends the primary command exception to the client.

Sample code

@HystrixCommand(ignoreExceptions = {VallidationException.class}, fallbackMethod="getUserEmailsFallback")
List<String> getUserEmails(String userId) {
  return callFirstService(userId);
}

@HystrixCommand(ignoreExceptions = {VallidationException.class})
List<String> getUserEmailsFallback(String userId) {
  return callSecondService(userId);
}

What is happening
If the first service is down the first command throws ConnectException and falls back to fallback method.
If the fallback method throws ValidationException then the original ConnectException is thrown back to client.

This behaviour is undesired because its just a ValidationException and ideally we should be sending a message to client saying there is some validation exception.

What will make it better
If fallback throws any of the ignored exceptions then propagate that exception to the client instead of the exception from the primary method.

@mukteshkrmishra
Copy link

Which version of Javanica you are using?

@nytins
Copy link
Author

nytins commented Sep 2, 2016

1.4.21

@dmgcodevil
Copy link
Contributor

@nytins as it was discussed before it's hard to justify importance of an exception thrown from fallback over one thrown from command. Some clients are interested only in command exception, having said that I think it should be configurable.

@nytins
Copy link
Author

nytins commented Sep 2, 2016

@dmgcodevil here the importance of the fallback exception is that it is one of the ignored exceptions.
Ie, primary failed due to actual backend issues, fallback failed only because of invalid user input (which is an ignored exception).
In this case doesn't it make sense to send the invalid input exception to client?

Essentially, an ignored exception should get priority over other exceptions in the flow.

@nytins
Copy link
Author

nytins commented Sep 3, 2016

Another thing I noticed is that the behavior is different when the fallback method is async.

  • Sync command, sync fallback --> command exception (sample code)
  • Async command, sync fallback --> command exception (sample code)
  • Async command, async fallback --> fallback exception (sample code)

The below code snippet throws CommandException

@Autowired
private Service service;

@Test
public void test() throws Throwable {
    try {
        service.command().get();
        fail();
    } catch (Throwable e) {
        assertThat(e.getCause().getCause(), is(instanceOf(CommandException.class)));
    }
}

public static class Service {
    @HystrixCommand(fallbackMethod = "fallback")
    public Future<Object> command() {
        return new AsyncResult<Object>() {
            @Override
            public Object invoke() {
                throw new CommandException();
            }
        };
    }

    @HystrixCommand
    public Object fallback() {
        throw new FallbackException();
    }
}

But the below snippet throws FallbackException

@Autowired
private Service service;

@Test
public void test() throws Throwable {
    try {
        service.command().get();
        fail();
    } catch (Throwable e) {
        assertThat(e.getCause().getCause(), is(instanceOf(FallbackException.class)));
    }
}

public static class Service {
    @HystrixCommand(fallbackMethod = "fallback")
    public Future<Object> command() {
        return new AsyncResult<Object>() {
            @Override
            public Object invoke() {
                throw new CommandException();
            }
        };
    }

    @HystrixCommand
    public Future<Object> fallback() {
        return new AsyncResult<Object>() {
            @Override
            public Object invoke() {
                throw new FallbackException();
            }
        };
    }
}

@dmgcodevil
Copy link
Contributor

Ok, for instance you have two rest services: primary and backup. If the call to primary fails because of invalid parameters then it's consistent if fallback will fail because of invalid parameters as well; it's consistent behaviour so it doesn't matter which exemption is returned to end user, either of them is fine. On the other hand if fallback fails because of different reason then it becomes tricky. I think that returning command exception is more correct because essentially it's root cause exception.

@nytins
Copy link
Author

nytins commented Sep 3, 2016

But if you consider ignored exceptions as part of the regular application flow, then this unnecessarily breaks application.

Take this example:
Primary service is down. So primary command fails and fallback command is called. Fallback method calls backup service. The backup service receives the request, validates it and throws a validation exception.
In this scenario backup service is up and responding. But the client still gets a system down exception of the primary.

My understanding is that ignored exceptions doesn't represent a system failure. They are part of the usual application flow. So by not propagating them to client hystrix is blocking information flow to the client.

@dmgcodevil
Copy link
Contributor

"ignored exceptions" shouldn't have any impact on making decision which exception to propogate to end user. I was reasoning about propagating exception from fallback to end user and I think it makes sense because an user can get an exception thrown from command by adding addition Throwable argument in fallback method signature so that it's user responsiblity to process command exception, i.e. it can be re-thrown or just logged.

@nytins
Copy link
Author

nytins commented Sep 7, 2016

I agree with the point that command exceptions can be seen in the fallback method but fallback exceptions cant be seen by the client, so it makes sense to throw fallback exceptions.

But I also think that ignored exceptions should also have impact on this decision making. But I'm happy if we just decide to proceed with propagating fallback exception :)

@jorgefr
Copy link

jorgefr commented Sep 13, 2016

I had another issue related to an exception being thrown within a fallback, which was completely ignored (#1313).

I'm joining the conversation by invitation of @dmgcodevil. The solution for my case is much simpler than what @nytins needs. I don't need to propagate the exception thrown within the fallback, just know that something unexpected happened in the fallback instead of silently fail.

So in my case, the best option is (apart than logging that exception as agreed in #1313) to add a new hook to HystrixCommandExecutionHook such as onFallbackExecutionError or similar.

But it would be more flexible to be able to choose the exception that needs to be thrown to the client. Since in @nytins case, the client doesn't need to know that the first server is down, because he is dealing with it in the fallback.

I'm not very familiar with the framework so I cannot contribute with something very useful.

@dmgcodevil
Copy link
Contributor

cc @michaelcowan, @jorgefr, @nytins

  1. I think that wrapping client exceptions in Hystrix exceptions is bad idea. Also making decision about source of an exception by checking whether it's Hystrix exception is bizarre and might be obscuring in some cases. Client should always get real exception instead of mysterious exceptions that he isn't aware of.
  2. Latest exception in flow should be propagated to end user (it should be by default). That is, if fallback fails then the exception thrown by fallback should be propagated to end user. If an exception is that it is one of the ignored exceptions then it's wrapped in HystrixBadRequestException but end user just doesn't see it. If client interested only in command exception or both then he can create a custom exception to combine them together, something like:
class HytrixFlowException extends RuntimeException {
   Throwable commandException;
   Throwable fallbackException; // or list of exceptions in the case of multiple fallback methods
}

@HytrixCommand(fallbackMethod = "fallback")
User getById(String id) {
     throw new CommandException("primary server fails");
}


User fallback(String id, Throwable commandException)  {
    throw new HytrixFlowException (commandException, new FallbackException("fallback server fails"));
}

Or always propagate command exception and omit fallback one:

User fallback(String id, Throwable commandException)  {
   try {
        // make call to backup service
    } catch (Exception e) {
        // fallback has failed but we don't care, primary is guilty
        throw commandException;
    }

}

Although, it should be feasible to implement something like to force javanica always propagating only command exception and hide fallback exception.

@hroongta
Copy link

hroongta commented Oct 12, 2016

Hi this is a big issue for us. Also the proposed solution from @michaelcowan does not seem appropriate as having it option driven.

Why cant we have it throw unchecked HystrixRuntimeException (wrapped up) when it timesout within hystrix world.

If the command it is executing throws any exception in that case let it be unwrapped. This way people using aspect and spring do not need to declare checked exception thrown from Hystrix (when Future.get throws java.util.concurrent.TimeoutException)

This seem to be working fine prior to 1.5.4

@dmgcodevil
Copy link
Contributor

hi @hroongta your suggestion is the same as @56quarters mentioned in the separate issue #1381 . It sounds reasonable for me. I will create PR shortly (this week).

NOTE: I'm going to implement this approach along with one about wrapping platform exceptions like TimeoutException in HystrixRuntimeExceptions.

guys, are you ok with this design (time box is 2 days to make a decision) ? I want to nail down this issue on this week.

cc @nytins, @hroongta, @56quarters, @jorgefr, @mukteshkrmishra

@mukteshkrmishra
Copy link

@dmgcodevil : I believe that would be the correct approach (#1344 (comment)), as it will give the ability to a user for seeing real exception (which is logical). Going ahead, if user wants to see command and fallback exception the he/she can go for CustomException route.

👍 from my side.

@nytins
Copy link
Author

nytins commented Oct 17, 2016

@dmgcodevil I am also happy with this approach.

@56quarters
Copy link

@dmgcodevil Mentioned in #1381, this approach works for me 👍

@dmgcodevil
Copy link
Contributor

dmgcodevil commented Oct 19, 2016

Created PR
@56quarters @nytins @mukteshkrmishra @jorgefr @hroongta @michaelcowan

@dmgcodevil
Copy link
Contributor

BTW, I've noticed that HystrixRuntimeException has some useful info, might be helpful in some cases. So what if user wants to get HystrixRuntimeException instead of user exception. One solution is to add a parameter to @HystrixCommand in order to switch between two options. We can do it within this issue or create new one latter on.

@michaelcowan
Copy link
Contributor

@dmgcodevil Is this not the same as my original suggestion? If it is I have sketched the idea out here https://github.com/michaelcowan/Hystrix/tree/feature/optionally-raise-hystrix-runtime-exception

@jorgefr
Copy link

jorgefr commented Oct 19, 2016

It looks ok to me. thanks!

@dmgcodevil
Copy link
Contributor

@michaelcowan could you please create a PR if you already have something.

@mattrjacobs
Copy link
Contributor

I think this issue has been addressed by #1397. If I'm mistake, please re-open

@edeandrea
Copy link

So I'm just now discovering this and thought I would add my 2 cents.

While this is a step in the right direction it does not completely solve the issue. Think about a developer who is using the MVC pattern - the service facade layer of the application is where all of this hystrix "stuff" comes into play. The API of that layer is the contract between this layer & the layer above it (for a web application - some controller/restful API layer).

This addition makes the caller of the service facade layer have to know specific details that Hystrix is involved by having to catch HystrixRuntimeException, look for a fallback exception (which is generally a FallbackInvocationException) and then have to read the cause from that.

Why can't we simply throw whatever exception is thrown from the fallback? I have a post on StackOverflow which describes the scenario I'm trying to handle.

http://stackoverflow.com/questions/40495259/capture-exception-thrown-by-hystrix-fallback

@edeandrea
Copy link

Actually I was able to solve my use case using this approach. I posted my solution back on my stackoverflow post: http://stackoverflow.com/questions/40495259/capture-exception-thrown-by-hystrix-fallback/40529532#40529532

@edeandrea
Copy link

edeandrea commented Nov 11, 2016

Actually it seems that this only works while the circuit is closed. Once the circuit is tripped open the HystrixRuntimeException gets propagated back up.

com.netflix.hystrix.exception.HystrixRuntimeException: getPolicy short-circuited and fallback failed.
    at com.company.common.api.FaultBarrier.defaultErrorHandler(FaultBarrier.java:84)
    at sun.reflect.GeneratedMethodAccessor132.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114)
    at org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver.doResolveHandlerMethodException(ExceptionHandlerExceptionResolver.java:375)
    at org.springframework.web.servlet.handler.AbstractHandlerMethodExceptionResolver.doResolveException(AbstractHandlerMethodExceptionResolver.java:59)
    at org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.resolveException(AbstractHandlerExceptionResolver.java:136)
    at org.springframework.web.servlet.handler.HandlerExceptionResolverComposite.resolveException(HandlerExceptionResolverComposite.java:74)
    at org.springframework.web.servlet.DispatcherServlet.processHandlerException(DispatcherServlet.java:1193)
    at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1030)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:980)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:105)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:89)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:107)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:108)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:784)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:802)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1410)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)
Caused by: com.netflix.hystrix.exception.HystrixRuntimeException: getPolicy short-circuited and fallback failed.
    at com.netflix.hystrix.AbstractCommand$22.call(AbstractCommand.java:818)
    at com.netflix.hystrix.AbstractCommand$22.call(AbstractCommand.java:793)
    at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$4.onError(OperatorOnErrorResumeNextViaFunction.java:140)
    at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)
    at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)
    at com.netflix.hystrix.AbstractCommand$DeprecatedOnFallbackHookApplication$1.onError(AbstractCommand.java:1454)
    at com.netflix.hystrix.AbstractCommand$FallbackHookApplication$1.onError(AbstractCommand.java:1379)
    at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)
    at rx.observers.Subscribers$5.onError(Subscribers.java:230)
    at rx.internal.operators.OnSubscribeThrow.call(OnSubscribeThrow.java:44)
    at rx.internal.operators.OnSubscribeThrow.call(OnSubscribeThrow.java:28)
    at rx.Observable.unsafeSubscribe(Observable.java:10151)
    at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:51)
    at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35)
    at rx.Observable.unsafeSubscribe(Observable.java:10151)
    at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)
    at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
    at rx.Observable.unsafeSubscribe(Observable.java:10151)
    at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)
    at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)
    at rx.Observable.unsafeSubscribe(Observable.java:10151)
    at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)
    at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
    at rx.Observable.unsafeSubscribe(Observable.java:10151)
    at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)
    at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
    at rx.Observable.unsafeSubscribe(Observable.java:10151)
    at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:51)
    at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35)
    at rx.Observable.unsafeSubscribe(Observable.java:10151)
    at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:48)
    at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:33)
    at rx.Observable.unsafeSubscribe(Observable.java:10151)
    at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)
    at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
    at rx.Observable.unsafeSubscribe(Observable.java:10151)
    at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)
    at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)
    at rx.Observable.unsafeSubscribe(Observable.java:10151)
    at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:51)
    at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35)
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
    at rx.Observable.subscribe(Observable.java:10247)
    at rx.Observable.subscribe(Observable.java:10214)
    at rx.internal.operators.BlockingOperatorToFuture.toFuture(BlockingOperatorToFuture.java:51)
    at rx.observables.BlockingObservable.toFuture(BlockingObservable.java:411)
    at com.netflix.hystrix.HystrixCommand.queue(HystrixCommand.java:377)
    at com.netflix.hystrix.HystrixCommand.execute(HystrixCommand.java:343)
    at com.netflix.hystrix.contrib.javanica.command.CommandExecutor.execute(CommandExecutor.java:52)
    at com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect.methodsAnnotatedWithHystrixCommand(HystrixCommandAspect.java:100)
    at sun.reflect.GeneratedMethodAccessor122.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:629)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:618)
    at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:655)
    at com.aig.entitlementsrs.service.PolicyServiceImpl$$EnhancerBySpringCGLIB$$a8f67a15.getPolicy(<generated>)
    at com.aig.entitlementsrs.api.PoliciesApi.getPolicy(PoliciesApi.java:73)
    at sun.reflect.GeneratedMethodAccessor128.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
    ... 55 common frames omitted
Caused by: java.lang.RuntimeException: Hystrix circuit short-circuited and is OPEN
    at com.netflix.hystrix.AbstractCommand.handleShortCircuitViaFallback(AbstractCommand.java:965)
    at com.netflix.hystrix.AbstractCommand.applyHystrixSemantics(AbstractCommand.java:546)
    at com.netflix.hystrix.AbstractCommand.access$100(AbstractCommand.java:59)
    at com.netflix.hystrix.AbstractCommand$4.call(AbstractCommand.java:408)
    at com.netflix.hystrix.AbstractCommand$4.call(AbstractCommand.java:402)
    at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:46)
    ... 102 common frames omitted

@maxromanovsky
Copy link

@edeandrea Have you managed to make it work?
@mattrjacobs I'm experiencing the same issue as @edeandrea:

Actually it seems that this only works while the circuit is closed. Once the circuit is tripped open the HystrixRuntimeException gets propagated back up.

@dmgcodevil
Copy link
Contributor

dmgcodevil commented Jul 2, 2017

@maxromanovsky, @edeandrea could you create a separate iss for this ?

@vancuongngo
Copy link

vancuongngo commented Nov 26, 2018

@dmgcodevil @edeandrea @maxromanovsky do we have any update on this, I'm using latest version of hystrix cloud from spring boot 2.1.0.RELEASE, HystrixRuntimeException gets propagated back, which brings no benefits, how can we over come it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests