11

The microservice I'm writting needs to communicate to other microservices in our platform. On that attempt, the ideal solution for us is Spring Cloud Netflix Feign, implemeting a @FeignClient.

However, I'm facing the exception below when I try an @Autowired ReviewProvider:

Exception (cause)

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.cloud.netflix.feign.FeignContext' available
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:353)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:351)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:340)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1093)
    at org.springframework.cloud.netflix.feign.FeignClientFactoryBean.getObject(FeignClientFactoryBean.java:155)
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:168)

ReviewProvider.java

@FeignClient("http://metadata-reviews")
public interface ReviewProvider {

    @RequestMapping(path = "sessions", method = POST)
    ReviewSessionDTO createSession();

}

ReviewProvider.java

@RunWith(SpringRunner.class)
@ActiveProfiles(INTEGRATION)
@ContextConfiguration(classes = AppEntry.class)
@AutoConfigureTestDatabase(replace = Replace.NONE)
@DataJpaTest
public class ReviewProviderTest {

    @Autowired
    private ReviewProvider provider;
    private Class<? extends ReviewProvider> providerClass;

    @Before
    public void setup() {
        providerClass = provider.getClass();
    }

    @Test
    public void classAnnotations() {
        assertTrue(providerClass.isAnnotationPresent(FeignClient.class));
        assertEquals("http://metadata-reviews", providerClass.getAnnotation(FeignClient.class).value());
    }

    @Test
    public void createSession() throws Exception {
        final Method method = providerClass.getDeclaredMethod("createSession");
        assertTrue(method.isAnnotationPresent(RequestMapping.class));

        final RequestMapping mapping = method.getAnnotation(RequestMapping.class);
        assertEquals("sessions", mapping.path());
        assertEquals(0, method.getParameters().toString());
    }
}
hudsonmendes
  • 449
  • 1
  • 6
  • 17

5 Answers5

20

Seems like there is not anything out there yet about the solution to this stuff...

Here is what I did to solve this: 1. Add this annotation to your test class:

@ImportAutoConfiguration({RibbonAutoConfiguration.class, FeignRibbonClientAutoConfiguration.class, FeignAutoConfiguration.class})

Try it, if it does not work, you might need the @EnableFeignClients annotation on your main program config

Paolo Forgia
  • 5,804
  • 7
  • 39
  • 55
Codetector
  • 544
  • 4
  • 16
  • 1
    I rebuilt the service from scratch, so got no solution yet for this. And I had the EnableFeignClients on... So the problem is no more, but also no real solution for the problem. Thanks for the follow up, thought – hudsonmendes May 25 '17 at 06:19
  • I mean, really its going to be a help for someone else maybe... I figured the cause really has to do with some annotation (I don't know what yet...) that actually prevents the import of FeignClient auto-config. So I tried to import them. Sorry to hear that you have to rebuild everything.. [sad face] but this did fix my issue. – Codetector May 26 '17 at 01:21
  • Spring Cloud Feign seems to be terribly documented and hard to test (since it does not allow one to use MockRestServiceServer). I'm rolling back on using it and moved on to Spring Cloud Ribbon which requires a little bit more coding, but feels much more reliable and is better documented. I will mark your answer as solution, because I have no grounds or interest in Spring Cloud Feign anymore. Thanks for the help! – hudsonmendes May 26 '17 at 04:25
  • If you are not using Ribbon, then only this is needed: `@ImportAutoConfiguration({FeignAutoConfiguration.class})` – ordonezalex Sep 03 '20 at 19:58
9

Recommended approach is to slice application configuration, this means you need to remove @EnableFeignClients from SpringBootApplication.

and add dedicated configuration class:

@Configuration
@EnableFeignClients
public class CloudConfiguration {

}

This is required, because all slices annotation (like @WebMvcTest) include default configuration from SpringBootApplication.

Reference:

MariuszS
  • 27,972
  • 12
  • 103
  • 144
  • 1
    For me moving `@EnableFeignClients` from Application to dedicated `@Configuration`-annotated class gave app not working. – ASten Nov 13 '19 at 12:57
  • @ASten are you sure that your configuration is scanned under application start? – MariuszS Nov 13 '19 at 16:05
  • thanks for answering. I am using `@SpringBootApplication` and I saw there `@ComponentScan` annotation with exclude filters only. My `@Configuration`-annotated classes are included in app context (related classes found them injected). Does it show that configuration have been scanned? – ASten Nov 14 '19 at 08:56
1

The only what you must to do:

  • add to your build file feign dependency, for example, for gradle

compile 'org.springframework.cloud:spring-cloud-starter-feign'

  • add @FeignClient to your interface
  • add @EnableFeignClients to any configuration or to class with annotation @SpringBootApplication
Ivan Osipov
  • 538
  • 6
  • 6
1

I solved this problem just by @EnableAutoConfiguration annotation on my class

adramazany
  • 490
  • 6
  • 13
0

I also faced this issue I followed MariuszS answer. However had to figure out couple of things so putting here... we need to tell @SpringBootTest from where to pick up the configuration so it would be like this

@SpringBootTest
@ContextConfiguration(classes = { YourClientConfig.class })
Vikky
  • 899
  • 9
  • 13