Not able to resolve feign client name from application yml - spring-boot

I have a spring boot app and i am trying to use feign client to make a request to an endpoint but its not able to resolve feign client name from application yml.
My application yml has following code :
ribbon:
eureka:
enabled: false
beacon:
ribbon:
isSecure: true
listOfServers: https://beacon.org
My interface look like this :
#FeignClient("beacon")
public interface BeaconClient {
#GetMapping("/api/organizations")
List<Org> getOrgs();
}
I am getting an error 500 internal server error because i see that it making a request to http://beacon/api/organizations endpoint instead of https://beacon.org/api/organizations

Your code is correct. The default feign Logger is misleading. http://beacon/.. that you see in the log isn't indicative of actual url that is being called. The actual request is resolved with https://beacon.org/...

Related

Spring Cloud API Gateway routing not working

I have designed a micro service prototype using below technologies
Eureka Server
a service
Spring Cloud API Gateway
Above mentioned service are registered in the Eureka Server
API Gateway routing Configuration
server.port=8080
eureka.client.serviceUrl.defaultZone = http://localhost:8083/eureka
spring.application.name=ApiGateway
spring.cloud.gateway.discovery.locator.enabled=true
spring.cloud.gateway.discovery.locator.lower-case-service-id=true
spring.cloud.gateway.routes[0].id=service1
spring.cloud.gateway.routes[0].uri=lb://MICROSERVICE1
spring.cloud.gateway.routes[0].predicates[0]=Path=/service1/**
The service Configuration
server.port=8081
server.address=127.0.0.1
eureka.client.serviceUrl.defaultZone = http://localhost:8083/eureka
spring.application.name=MicroService1
error.whitelabel.enabled= false
Controller
#RestController
#RequestMapping("/service1")
public class HomeController {
#GetMapping("/message")
public String hello() {
return "response from micro service1";
}
}
When I send a request to the gateway it's showing the below error
2020-12-16 22:26:09.770 ERROR 16700 --- [ctor-http-nio-3] a.w.r.e.AbstractErrorWebExceptionHandler : [d3334561-1] 500 Server Error for HTTP GET "/service1/message"
java.net.UnknownHostException: failed to resolve 'LAPTOP-KU56B6A8' after 3 queries
at io.netty.resolver.dns.DnsResolveContext.finishResolve(DnsResolveContext.java:1013) ~[netty-resolver-dns-4.1.55.Final.jar:4.1.55.Final]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ HTTP GET "/service1/message" [ExceptionHandlingWebHandler]
How can we solve the above issue?
Add eureka.instance.hostname=localhost in both the microservices instances this will work and not give an error
i have modified the API Gate Way routing Configuration like below
spring.cloud.gateway.routes[0].id=service1
spring.cloud.gateway.routes[0].uri=http://localhost:8081/service1/
spring.cloud.gateway.routes[0].predicates[0]=Path=/service1/**
Now is working fine
Add this bean in your API gateway and you are good to go.
#Bean
public HttpClient httpClient() {
return HttpClient.create().resolver(DefaultAddressResolverGroup.INSTANCE);
}
Add below to both gateway and individual microservice fix the issue
eureka.instance.hostname=localhost
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:8010/eureka/
Add in your application.properties:
spring.cloud.discovery.enabled=true
I have modified my .yaml file with this configuration.
Issue resolved for me.
**server:
port: 9999
spring:
application:
name: gateway-ws
cloud:
gateway:
discovery:
locator:
enabled: true
routes:
- id: userService
uri: http://user-service/
predicates:
- Path=/user/**
- id: contactService
uri: http://contact-service/
predicates:
- Path=/contact/**
eureka:
client:
service-url:
defaultZone: http://localhost:8085/eureka**
This is the only solution works among all of the answers above.
#Bean
public HttpClient httpClient() {
return HttpClient.create().resolver(DefaultAddressResolverGroup.INSTANCE);
}
This is the default behavior, so no effect.
spring.cloud.discovery.enabled=true
This has nothing to do with the discovery client.
It is related with the discovery server.
eureka.instance.hostname=localhost
So if you don't know, just don't mess it up with wrong directions.
hello jebji if you still have this problem
add
spring.cloud.discovery.enabled=true
in application.properties
Only Add the following property into your API gateway:
spring.cloud.discovery.enabled=true
Make sure you already added DevTool maven dependency into your API gateway project but if not then restart it.
add flowing property in application.property file of all eruka client microservice and api gateway , i face same issue and resolve doing same activity
spring.cloud.discovery.enabled=true
spring.cloud.gateway.discovery.locator.lower-case-service-id= true
spring.cloud.gateway.discovery.locator.enabled= true
eureka.instance.hostname=localhost
after adding all the above properties then also if you are facing issue then try the below one,
don't use lb://albums_service , but use lb://albums-service .Because URI don‘t support underline.
You can add the following in application.yml file
spring:
cloud:
gateway:
routes:
- id: test-service
uri: lb://MICROSERVICE1
predicates:
- Path=/microservice1/**
filters:
- RewritePath=/microservice1/(?<segment>.*), /$\{segment}
with this it should works.
Like let say if your microservice1 is url is
localhost:8081/service1/message
then you can define the base path of your microservice1 in api-gateway by setting up the path as i did in above configuration.
The error message is "failed to resolve 'LAPTOP-KU56B6A8'".
This is an DNS issue.
You can set eureka.instance.prefer-ip-address=true in the service.
So it will register with its ip at Eureka and the DNS issue can be avoided.
This is actually the same issue as this QUESTION.
With this ANSWER

Disable Feign logging on some API calls

I am using following configuration to enable logging for API calls made using feign
#Feign properties
feign:
client:
config:
default:
loggerLevel: full
My application is making calls to 3 APIs and feign is logging request and response JSON correctly for all the 3 APIs . I want to disable this logging for one of the API. Can you please let know on the necessary configuration. Thanx in advance
If you have 3 different feign clients for 3 APIs, then you can simply override logging level in this way (assuming that your feign client is called "feignClient2"):
#Feign properties
feign:
client:
config:
default:
loggerLevel: full
feignClient2:
loggerLevel: none
But if you have one feign client for 3 endpoints, then the task becomes more complicated. You can inherit feign logger class (or any of its children classes, f.e. Slf4jLogger, if you use it now) and override its logRequest and logAndRebufferResponse methods to not log anything for specific endpoint (you can get the required information from request and response method parameters respectively). Then add FeignLoggerFactory bean with your own logger:
#Bean
public FeignLoggerFactory feignLoggerFactory() {
return new DefaultFeignLoggerFactory(new CustomLogger());
}
It will override the default FeignLoggerFactory from FeignClientsConfiguration.
In summary, I would recommend you to use the first option (with separate feign client). But if you choose the second one, I could help you to do it if you provide the example of your code.

Jhipster Health Endpoint fails when mailserver not connected

JHipster / Spring boot provides a nice endpoint /management/health, where it aggregates health information for subsystems like db, disk, and mail.
Unfortunately, when the connection to the mail server fails, the whole endpoint fails. So you do not get information what has failed.
I get a strack trace like this:
o.s.b.a.health.MailHealthIndicator : Health check failed
com.sun.mail.util.MailConnectException: Couldn't connect to host, port: XXXX, NNNN25025; timeout -1
...
at org.springframework.boot.actuate.health.MailHealthIndicator.doHealthCheck(MailHealthIndicator.java:40)
at org.springframework.boot.actuate.health.AbstractHealthIndicator.health(AbstractHealthIndicator.java:43)
at org.springframework.boot.actuate.health.CompositeHealthIndicator.health(CompositeHealthIndicator.java:68)
at org.springframework.boot.actuate.endpoint.HealthEndpoint.invoke(HealthEndpoint.java:85)
at org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.getCurrentHealth(HealthMvcEndpoint.java:177)
at org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.getHealth(HealthMvcEndpoint.java:166)
at org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.invoke(HealthMvcEndpoint.java:143)
This is spring boot 1.5.9
Where should I fix this, so that the exception is catched and instead a an error status is returned?
You have to turn on your SMTP server or disable checks to it.
To disable checks to SMTP server:
management.health.mail.enabled=false
To disable checks to all server:
management.health.defaults.enabled=false
for more information, see http://www.briansjavablog.com/2017/09/health-checks-metric-s-more-with-spring.html
I believe you can handle this error with the ExceptionHandler for 1.5.9 version of Spring Boot since the newer version there is no such problem:
#ControllerAdvice
public class ExceptionController {
#ExceptionHandler(MailConnectException.class)
public ResponseEntity<?> mailExceptionHandler(MailConnectException e) {
// Do your treatment ...
} ...
}

Feign Client Prioritizing URL's in yaml over Eureka

I have a Spring Boot application which serves as a Eureka client. The application has the need to call another micro-service through REST, and I wish to make this call using Feign. The issue I am having is, my application is trying to lookup the service name in Eureka, when it is only defined in my applications yaml file.
I apologize for the hard to follow explanation, hopefully the following code snippets will help clarify.
Feign client:
#FeignClient("foo")
#Component
public interface FooServiceProxy{
#RequestMapping(value = "/balance", method = RequestMethod.POST, produces = "application/json")
ServiceResponse execute(ServiceRequest serviceRequest);
}
In my controller who calls this Feign client, the FooServiceProxy is defined using #AutoWired:
#Autowired
private FooServiceProxy fooServiceProxy;
My yaml file is as follows:
spring:
application:
name: app-name
server:
port: 8080
foo:
ribbon:
listOfServers: http://hostname:8081/balance
eureka:
client:
fetchRegistry: false
serviceUrl:
defaultZone: http://eurekasrver:8761/eureka/
My issue is, during run-time, the following error is thrown:
java.lang.RuntimeException: com.netflix.client.ClientException: Load balancer does not have available server for client: foo
Interestingly, if I remove the #EnableEurekaClient annotation from the application, everything works. I believe I understand the problem which is that instead of looking up the server for foo in my yaml file, because the application is a Eureka client, Feign is going straight to Eureka to lookup a server ip, then failing as none can be found. Despite seeming to understand the problem, I have been unable to find a solution online or to think of one myself.
Any help will be appreciated.
Thank you!
Concerning this question, you should take in account that when eureka is on your classpath, all ribbon configuration are charged by eureka, so it'll use eureka server's list.
Spring Cloud uses #RibbonClient to configure the types used by ribbon, like server list. If you have eureka on the classpath, by default it uses the eureka server list (hence your need for the flag to disable eureka).
Commented by spencergibb https://github.com/spring-cloud/spring-cloud-netflix/issues/564
You can try either by adding the NIWSServerListClassName configuration:
`someservice.ribbon:
NIWSServerListClassName:com.netflix.loadbalancer.ConfigurationBasedServerList
listOfServers: server1:80`
Or try the solution proposed in this issue https://github.com/spring-cloud/spring-cloud-netflix/issues/564

Spring Config-Client doesn't refresh if Config-Server is down during initial startup

I am running a test with a barebones Spring cloud config-server and a client-application. I executed a refresh scenario (by calling /refresh endpoint on the client-application)
after config-server was down initially. Here is what I found
Client starts up with locally packaged properties when config-server is not reachable on startup. (I have the properties in application.yml that is bundled with client-application)
Git backend has different values for the properties compared to locally packaged version. Config-server is aware of the changes in git (Confirmed by connecting directly to config-server)
I bring up config-server and do a POST to /refresh endpoint on the client-application.
Client-application is not aware of the new properties from config-server.
In the second usecase
Client-application starts up and connects to config-server successfully. I see that the values from config-server have been fetched by the client-application successfully
I make a change in Git and call the /refresh endpoint on the client-application. Properties are refreshed successfully.
At this point it looks like /refresh doesn't work if the client-application comes up initially without being able to successfully connect to config-server. I am doing this to test
a fallback strategy for the client-application if config-server is not reachable when the client-application is starting up. (The fallback strategy is to have locally packaged properties
that will be used if config-server is not available on startup. If the config-server is available then the local properties are overriden). Any pointers to why this is not working and
what I could do differently? Thanks in advance.
Edit
Server-Code
#EnableConfigServer
#SpringBootApplication
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
Client-Code
#RestController
#RefreshScope
#Component
public class Greeter {
#Value("${message.greeting}")
String greeting;
#RequestMapping(value = "/",produces = "application/json")
public List<String> index(){
List<String> env = Arrays.asList("message.greeting: " + greeting);
return env;
}
}
bootstrap.yml (On config-client application)
spring:
application:
name: configclient
cloud:
config:
uri: http://localhost:8888
management:
security:
enabled: false
logging:
config: classpath:logback.xml
server:
port: 8000
application.yml
message:
greeting: Hello from Local!
Config in Git (Served through config-server)
message:
greeting: Hello from Git-Edited!
According to spring-cloud-config documentation -
If you expect that the config server may occasionally be unavailable
when your app starts, you can ask it to keep trying after a failure.
First you need to set spring.cloud.config.failFast=true, and then you
need to add spring-retry and spring-boot-starter-aop to your
classpath. The default behaviour is to retry 6 times with an initial
backoff interval of 1000ms and an exponential multiplier of 1.1 for
subsequent backoffs. You can configure these properties (and others)
using spring.cloud.config.retry.* configuration properties.
Reference -> http://cloud.spring.io/spring-cloud-static/spring-cloud-config/1.3.1.RELEASE/

Resources