简体   繁体   中英

Inject custom feign client into Spring Application

I am currently trying to get a grip of both Spring and Feign. Cutting straight to the point: I am struggling to modify @FeignClient in this project: Feign Hello World by Walery so as to instead of

WikidataClient

@FeignClient(url = "https://www.wikidata.org/w")
// https://www.wikidata.org/w/api.php?action=wbsearchentities&search=apple&language=en&format=json
public interface WikidataClient {

    @RequestMapping(value = "/api.php?action=wbsearchentities&language=en&format=json", method = GET)
    WebsearchEntities searchForEntities(@RequestParam("search") final String search);
}

use @Autowired notation similar to one found here: Section called : Creating Feign Clients Manually

The purpose of this would be to inject custom decoder and encoder later on. I've been exprimenting with it for a while and all I managed to achieve was ruin the whole thing.

I gathered some clues from here and there and managed to come to the point where I created a Configuration class :

FeignConfig

@Import(FeignClientsConfiguration.class)
public class FeignConfig {
    public WikidataClient fooclient;
    @Autowired
    public FeignConfig(Encoder encoder, Decoder decoder){
        this.fooclient = Feign.builder()
                .encoder(encoder)
                .decoder(decoder)
                .target(WikidataClient.class,"https://www.wikidata.org/w");
    }
}

Modified

WikidataClient

interface slightly

//@FeignClient(url = "https://www.wikidata.org/w")
// https://www.wikidata.org/w/api.php?action=wbsearchentities&search=apple&language=en&format=json
public interface WikidataClient {

    @RequestMapping(value = "/api.php?action=wbsearchentities&language=en&format=json", method = GET)
    WebsearchEntities searchForEntities(@RequestParam("search") final String search);
}

and tried to use aforementioned class instead

WikidataRunner

@Component
public class WikidataRunner implements CommandLineRunner {
    private final WikidataClient omdbClient;
    @Autowired
    public WikidataRunner(WikidataClient omdbClient){
        this.omdbClient = omdbClient;
        this.feignConfig = new FeignConfig(new Encoder.Default(), new Decoder.Default());
    }

    FeignConfig feignConfig;
    @Override
    public void run(final String... args) throws Exception {
        final WebsearchEntities apple = feignConfig.fooclient.searchForEntities("apple");
        System.out.println(apple);
    }
}

All I got were different kind of Bean errors

2017-07-19 08:02:29.056 ERROR 2018 --- Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'wikidataRunner' defined in file [/home/mibi/IdeaProjects/FUFEign/feign-helloworld/target/classes/codes/walery/research/feign/wikidata/WikidataRunner.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [codes.walery.research.feign.wikidata.WikidataClient]: : No qualifying bean of type [codes.walery.research.feign.wikidata.WikidataClient] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [codes.walery.research.feign.wikidata.WikidataClient] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {} [
main] at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749) osboot.SpringApplication at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:185) : Application startup failed at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1143) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1046) org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [codes.walery.research.feign.wikidata.WikidataClient] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {} at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1326) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:305) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1072) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory. java:301) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:967) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE] at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:834) at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:813) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:667) at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArr ay(ConstructorResolver.java:741) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE] at org.springframework.boot.SpringApplication.doRun(SpringApplication.java:342) ... 18 common frames omitted at org.springframework.boot.SpringApplication.run(SpringApplication.java:273) at org.springframework.boot.SpringApplication.run(SpringApplication.java:980) at org.springframework.boot.SpringApplication.run(SpringApplication.java:969) at codes.walery.research.feign.FeignHelloworldApplication.main(FeignHelloworldApplication.java:12) Wrapped by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'wikidataRunner' defined in file [/home/mibi/IdeaProjects/FUFEign/feign-helloworld/target/classes/codes/walery/research/feign/wikidata/WikidataRunner.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [codes.walery.research.feign.wikidata.WikidataClient]: : No qualifying bean of type [codes.walery.research.feign.wikidata.Wikida taClient] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [codes.walery.research.feign.wikidata.WikidataClient] found for dependency: expected at least 1 beCaused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [codes.walery.research.feign.wikidata.WikidataClient] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {} at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1326) an which qualifies as autowire candidate for this dependency. Dependency annotations: {} at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1072) at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE] at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:967) at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:813) at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:185) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE] at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1143) ~[spring- beans-4.2.1.RELEASE.jar:4.2.1.RELEASE] ... 18 more at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1046) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:305) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE] at org.springframework.beans.factory.support.AbstractBean Factory.doGetBean(AbstractBeanFactory.java:301) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE] at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:834) ~[spring-context-4.2.1.RELEASE.jar:4.2.1.RELEASE] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537) ~[spring-context-4.2.1.RELEASE.jar:4.2.1.RELEASE] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:667) [spring-boot-1.3.0.M5.jar:1.3.0.M5] at org.springframework.boot.SpringApplication.doRun(SpringApplication.java:342) [spring-boot-1.3.0.M5.jar:1 .3.0.M5] at org.springframework.boot.SpringApplication.run(SpringApplication.java:273) [spring-boot-1.3.0.M5.jar:1.3.0.M5] at org.springframework.boot.SpringApplication.run(SpringApplication.java:980) [spring-boot-1.3.0.M5.jar:1.3.0.M5] at org.springframework.boot.SpringApplication.run(SpringApplication.java:969) [spring-boot-1.3.0.M5.jar:1.3.0.M5] at codes.walery.research.feign.FeignHelloworldApplication.main(FeignHelloworldApplication.java:12) [classes/:na] 2017-07-19 08:02:29.059 INFO 2018 --- [ Thread-1] scaAnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@3d8314f0: startup date [Wed Jul 19 08:02:24 CEST 2017]; root of context hierarchy

Process finished with exit code 1

I won't deny being novice at Spring and Feign. Thing is I need to undestand both of these desperately. So far I've spent 10+ hours researching about Feign to no avail.

Kindly asking for help and guidance

MissingBracket

There are several things wrong with your code, one straightaway fatal, others code smell. If you claim to be starting with Spring, reaching for Spring Cloud is, IMO, overzealous. You'll be needing help, a lot.

I've a fully working application using Feign client on my GitHub . It also uses Hystrix, but you can ignore that for your purpose. I intend to write a blog post about it, just haven't gotten around to doing so. My Eureka blog post is one of the most popular resources about Netflix Eureka on the internet.

  1. You're not supposed to put the URL in the Feign client; Feign client is an abstraction. You give it a name and configure properties elsewhere. [code smell]

  2. You're not supposed to hard code the query parameters in the Feign client. [code smell]

  3. You don't need a Feign.builder() ; Spring will autoconfigure one for you. You only need it if there's something that can't be configured using annotations or the Feign configuration. [I'm not sure of the behavior]

  4. You need to EnableFeignClients for Spring to pick up the client, assuming it's in the same, or one of the child package, of the CommandLineRunner . Like you admitted, you clearly don't know much about Spring else you'd not make it a @Component . Read up on how to implement a CommandLineRunner .[fatal]

Look at my sample app. And BTW, 10 hours is nothing; I've been working with Spring Cloud for 1.5 years now, and I still don't know all of it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM