can't feign client work. first tried post. kept running errors related encoder/decoder saying type not right. found example on github call simple api , decided give shot. still fails
on github , online, seeing multiple versions of feign client spring-cloud, openfeign, netflix.feign having different versions. describe what's best , stable feign client 1 should use production?
package com.paa.controllers; import org.springframework.cloud.netflix.feign.feignclient; import org.springframework.web.bind.annotation.requestmapping; import org.springframework.web.bind.annotation.requestmethod; @feignclient (name="test-service",url="https://www.reddit.com/r") public interface getfeignclient { @requestmapping(method = requestmethod.get, value = "/java.json") public string posts(); } controller: @restcontroller @requestmapping("/some/api") public class testwlccontroller { @autowired private getfeignclient getfeignclient; .. stuff @requestmapping(value="/postsomething",method = requestmethod.post) @apioperation(value = "configures something", notes = "basic rest controller testing feign") public responseentity<someresponse> feignpost( uricomponentsbuilder builder, @apiparam(name = "myrequest", value = "request configuring something", required = true) @valid @requestbody somerequest somerequest) { string resp = null; try { resp = getfeignclient.posts(); } catch (exception er) { er.printstacktrace(); } } }
application:
tried possible permutations of annotations thinking resolve autowire stuff still fails
@configuration @componentscan @enableautoconfiguration //@enableeurekaclient @enablefeignclients //@springbootapplication //@enablefeignclients //@enablefeignclients(basepackages = {"com.paa.xenia.controllers", "com.paa.xenia.services"}) public class serviceapplication extends springbootservletinitializer { @override protected springapplicationbuilder configure(springapplicationbuilder application) { return application.sources(xeniaserviceapplication.class); } public static void main(string[] args) { springapplication.run(serviceapplication.class, args); } }
2016-07-20 18:15:42.406[0;39m [31merror[0;39m [35m32749[0;39m [2m---[0;39m [2m[ main][0;39m [36mo.s.boot.springapplication [0;39m [2m:[0;39m application startup failed
org.springframework.beans.factory.beancreationexception: error creating bean name 'testwlccontroller': injection of autowired dependencies failed; nested exception org.springframework.beans.factory.beancreationexception: not autowire field: private com.paa.controllers.getfeignclient com.paa.controllers.testwlccontroller.gfclient; nested exception org.springframework.beans.factory.beancreationexception: error creating bean name 'com.aa..controllers.getfeignclient': factorybean threw exception on object creation; nested exception java.lang.nullpointerexception @ org.springframework.beans.factory.annotation.autowiredannotationbeanpostprocessor.postprocesspropertyvalues(autowiredannotationbeanpostprocessor.java:334) ~[spring-beans-4.2.6.release.jar:4.2.6.release] @ org.springframework.beans.factory.support.abstractautowirecapablebeanfactory.populatebean(abstractautowirecapablebeanfactory.java:1214) ~[spring-beans-4.2.6.release.jar:4.2.6.release] @ org.springframework.beans.factory.support.abstractautowirecapablebeanfactory.docreatebean(abstractautowirecapablebeanfactory.java:543) ~[spring-beans-4.2.6.release.jar:4.2.6.release] @ org.springframework.beans.factory.support.abstractautowirecapablebeanfactory.createbean(abstractautowirecapablebeanfactory.java:482) ~[spring-beans-4.2.6.release.jar:4.2.6.release] @ org.springframework.beans.factory.support.abstractbeanfactory$1.getobject(abstractbeanfactory.java:306) ~[spring-beans-4.2.6.release.jar:4.2.6.release] @ org.springframework.beans.factory.support.defaultsingletonbeanregistry.getsingleton(defaultsingletonbeanregistry.java:230) ~[spring-beans-4.2.6.release.jar:4.2.6.release] @ org.springframework.beans.factory.support.abstractbeanfactory.dogetbean(abstractbeanfactory.java:302) ~[spring-beans-4.2.6.release.jar:4.2.6.release] @ org.springframework.beans.factory.support.abstractbeanfactory.getbean(abstractbeanfactory.java:197) ~[spring-beans-4.2.6.release.jar:4.2.6.release] @ org.springframework.beans.factory.support.defaultlistablebeanfactory.preinstantiatesingletons(defaultlistablebeanfactory.java:772) ~[spring-beans-4.2.6.release.jar:4.2.6.release] @ org.springframework.context.support.abstractapplicationcontext.finishbeanfactoryinitialization(abstractapplicationcontext.java:839) ~[spring-context-4.2.6.release.jar:4.2.6.release] @ org.springframework.context.support.abstractapplicationcontext.refresh(abstractapplicationcontext.java:538) ~[spring-context-4.2.6.release.jar:4.2.6.release] @ org.springframework.boot.context.embedded.embeddedwebapplicationcontext.refresh(embeddedwebapplicationcontext.java:118) ~[spring-boot-1.3.5.release.jar:1.3.5.release] @ org.springframework.boot.springapplication.refresh(springapplication.java:766) [spring-boot-1.3.5.release.jar:1.3.5.release] @ org.springframework.boot.springapplication.createandrefreshcontext(springapplication.java:361) [spring-boot-1.3.5.release.jar:1.3.5.release] @ org.springframework.boot.springapplication.run(springapplication.java:307) [spring-boot-1.3.5.release.jar:1.3.5.release] @ org.springframework.boot.springapplication.run(springapplication.java:1191) [spring-boot-1.3.5.release.jar:1.3.5.release] @ org.springframework.boot.springapplication.run(springapplication.java:1180) [spring-boot-1.3.5.release.jar:1.3.5.release] @ com.paa.serviceapplication.main(serviceapplication.java:44) [bin/:na] caused by: org.springframework.beans.factory.beancreationexception: not autowire field: private com.paa.controllers.getfeignclient com.paa.controllers.testwlccontroller.gfclient; nested exception org.springframework.beans.factory.beancreationexception: error creating bean name 'com.paa.controllers.getfeignclient': factorybean threw exception on object creation; nested exception java.lang.nullpointerexception @ org.springframework.beans.factory.annotation.autowiredannotationbeanpostprocessor$autowiredfieldelement.inject(autowiredannotationbeanpostprocessor.java:573) ~[spring-beans-4.2.6.release.jar:4.2.6.release] @ org.springframework.beans.factory.annotation.injectionmetadata.inject(injectionmetadata.java:88) ~[spring-beans-4.2.6.release.jar:4.2.6.release] @ org.springframework.beans.factory.annotation.autowiredannotationbeanpostprocessor.postprocesspropertyvalues(autowiredannotationbeanpostprocessor.java:331) ~[spring-beans-4.2.6.release.jar:4.2.6.release] ... 17 com.n frames omitted
i'm not sure if figured out yourself, sake of others might stumble across thread, below working example of trying do. i'll first point out few things incorrect, or @ least, not desired in code, show code works.
- you should try not use
url
attribute. instead, set list of servers using<feign client name>.ribbon.listofservers
inbootstrap.yml
(orbootstrap.properties
). allows client side load balancing becauselistofservers
can comma-separated list. - using ribbon https connections, need specify 2 things don't need http connections. port, part of
listofservers
,<feign client name>.ribbon.issecure: true
. without port, connection made port 80 , withoutissecure
, http used. testing using
curl
, found reddit takes very long time respond. see post details of how break down total time taken request-response cycle.$ curl -v -h "user-agent: mozilla/5.0" -w "@curl-format.txt" -o /dev/null -s "https://www.reddit.com/r/java/top.json?count=1" { [2759 bytes data] * connection #0 host www.reddit.com left intact time_namelookup: 0.527 time_connect: 0.577 time_appconnect: 0.758 time_pretransfer: 0.758 time_redirect: 0.000 time_starttransfer: 11.189 ---------- time_total: 11.218
according netflix wiki, default read , connect timeouts 3000 milliseconds, timeout unless change those.
- you may have noticed specified
user-agent
header incurl
request. that's because reddis seems picky , if not specified, returns http 429 "too many requests" of times. don't returnretry-after
header in response there's no telling how long need wait before making request. - spring cloud netflix netflix feign open source, (a lot of) patience , debugging skills come handy.
"talk cheap. show me code." (torvalds, linus (2000-08-25)).
i generated gradle app using excellent spring initializr site. here's snippet build.gradle
file.
dependencies { compile('org.springframework.cloud:spring-cloud-starter-feign') compile('org.springframework.boot:spring-boot-starter-web') testcompile('org.springframework.boot:spring-boot-starter-test') } dependencymanagement { imports { mavenbom "org.springframework.cloud:spring-cloud-dependencies:camden.sr3" } }
feign client:
@feignclient(name = "reddit") public interface redditclient { @requestmapping(method = get, value = "/r/java/top.json?count=1", headers = {user_agent + "=mozilla/5.0", accept + "=" + application_json_value}) public string posts(); }
boot application:
@springbootapplication @enablefeignclients public class demoapplication { public static void main(string[] args) { springapplication.run(demoapplication.class, args); } @restcontroller static class democontroller { @autowired private redditclient redditclient; @getmapping("/posts") public string posts() { return redditclient.posts(); } } }
bootstrap.yml:
reddit: ribbon: listofservers: www.reddit.com:443 connecttimeout: 20000 readtimeout: 20000 issecure: true hystrix.command.default.execution: timeout.enabled: true isolation.thread.timeoutinmilliseconds: 50000
integration test:
@runwith(springrunner.class) @springboottest(webenvironment = springboottest.webenvironment.random_port) public class demoapplicationtest { @autowired private testresttemplate resttemplate; @test public void testgetposts() { responseentity<string> responseentity = resttemplate.getforentity("/posts", string.class); httpstatus statuscode = responseentity.getstatuscode(); assertthat(string.format("actual status code: %d, reason: %s.", statuscode.value(), statuscode.getreasonphrase()), statuscode.is2xxsuccessful(), equalto(true)); } }
Comments
Post a Comment