I was testing Feign Hystrix Fallbacks.

I followed the document here http://cloud.spring.io/spring-cloud-static/Camden.SR2/#spring-cloud-feign-hystrix-fallback .The code is blew:

@FeignClient(name = "microservice-provider-user", fallbackFactory = FeignClientFallbackFactory.class)
public interface UserFeignClient {
  @RequestMapping(value = "/{id}", method = RequestMethod.GET)
  public User findById(@PathVariable("id") Long id);

  @Component
  static class FeignClientFallbackFactory implements FallbackFactory<UserFeignClient> {
    private static final Logger LOGGER = LoggerFactory.getLogger(FeignClientFallbackFactory.class);

    @Override
    public UserFeignClient create(Throwable cause) {
      FeignClientFallbackFactory.LOGGER.info("fallback; reason was: {}, {}", cause.getMessage(), cause);
      return new UserFeignClient() {
        @Override
        public User findById(Long id) {
          return new User();
        }
      };
    }
  }
}

I found that a exception would happen when I start application:

java.lang.RuntimeException: null
    at org.springframework.cloud.netflix.feign.HystrixTargeter.targetWithFallbackFactory(HystrixTargeter.java:59) [spring-cloud-netflix-core-1.2.2.RELEASE.jar:1.2.2.RELEASE]
    at org.springframework.cloud.netflix.feign.HystrixTargeter.target(HystrixTargeter.java:45) [spring-cloud-netflix-core-1.2.2.RELEASE.jar:1.2.2.RELEASE]
    at org.springframework.cloud.netflix.feign.FeignClientFactoryBean.loadBalance(FeignClientFactoryBean.java:146) [spring-cloud-netflix-core-1.2.2.RELEASE.jar:1.2.2.RELEASE]
    at org.springframework.cloud.netflix.feign.FeignClientFactoryBean.getObject(FeignClientFactoryBean.java:167) [spring-cloud-netflix-core-1.2.2.RELEASE.jar:1.2.2.RELEASE]
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:168) [spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:103) [spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1606) [spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:254) [spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) [spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]

When I tracked into the class org.springframework.cloud.netflix.feign.HystrixTargeter ,I found that

private <T> T targetWithFallbackFactory(String feignClientName, FeignContext context,
                                            Target.HardCodedTarget<T> target,
                                            HystrixFeign.Builder builder,
                                            Class<?> fallbackFactoryClass) {
        FallbackFactory<? extends T> fallbackFactory = (FallbackFactory<? extends T>)
            getFromContext("fallbackFactory", feignClientName, context, fallbackFactoryClass, FallbackFactory.class);
        /* We take a sample fallback from the fallback factory to check if it returns a fallback
        that is compatible with the annotated feign interface. */
        Object exampleFallback = fallbackFactory.create(new RuntimeException());
        ....

It seems that this line of code cause the exception:

Object exampleFallback = fallbackFactory.create(new RuntimeException());

So,the question is:

  • Have I found the right reason of the exception?

  • Should I just ignore the exception when application starts up?

  • Is there any way to avoid the exception?

CODE is here https://github.com/eacdy/microservice-consumer-movie-feign-hystrix-fallback-factory

Comment From: ryanjbaxter

The reason you see the exception is because of your logger call https://github.com/eacdy/microservice-consumer-movie-feign-hystrix-fallback-factory/blob/master/src/main/java/com/itmuch/cloud/study/user/feign/UserFeignClient.java#L36

Comment From: eacdy

@ryanjbaxter I see it is because of my logger call, but I'm wondering why it comes into the method public UserFeignClient create(Throwable cause) when the application starts up.

Comment From: ryanjbaxter

See @bpicode's comment here https://github.com/spring-cloud/spring-cloud-netflix/pull/1373#discussion_r81830003

Comment From: bpicode

Is it an option for you to move the log statement inside the fallback? Schematically,

    @Override
    public UserFeignClient create(Throwable cause) {

      return new UserFeignClient() {
        @Override
        public User findById(Long id) {
          FeignClientFallbackFactory.LOGGER.info("fallback; reason was: {}, {}", cause.getMessage(), cause);
          return new User();
        }
      };
    }

Comment From: eacdy

@bpicode Thank you very much, it works.

Comment From: chenjians

我启动的时候不进 public DemoRemoteClient create(Throwable throwable) {} 大佬解答下