question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Feign client with custom Configuration (custom RequestInterceptor) picking up another client Configuration (RequestInterceptor)

See original GitHub issue

Hi,

This seems to be a bug, given that this is suppose to be supported as of #288.

I am currently using Spring Boot 2.0.0.RC2 with Spring Cloud Finchley.M7.

I have two Feign clients, each with a custom Feign Configuration class adding a custom RequestInterceptor. One RequestInterceptor adds a header for auth and another is an expensive one because it does all the OAuth2 Authorization Code flow.

@FeignClient(name = "gAuthifyApiClient", url = "{gAuthifyUrl}", configuration = GAuthifyApiClient.FeignClientConfiguration.class, decode404 = true)
public interface GAuthifyApiClient {
...
    @Configuration("gAuthifyFeignClientConfiguration")
    class FeignClientConfiguration {
        @Bean
        public BasicAuthRequestInterceptor basicAuthRequestInterceptor(@Value("${gauthify.api.key}") String apiKey) {
            return new BasicAuthRequestInterceptor("", apiKey);
        }
    }
...
}
@FeignClient(name = "profileIdApiClient", url = "{profileIdUrl}", configuration = ProfileIdApiClient.FeignClientConfiguration.class, decode404 = true)
public interface ProfileIdApiClient {
...
    @Configuration("profileIdFeignClientConfiguration")
    class FeignClientConfiguration {

        @Bean
        public BearerHeaderAuthRequestInterceptor bearerHeaderAuthRequestInterceptor() {
            return new BearerHeaderAuthRequestInterceptor();
        }
    }
...
    class BearerHeaderAuthRequestInterceptor implements RequestInterceptor {
       //Expensive OAuth2 flow logic
    }
...
}

The problem is that the client that uses the former (header auth) is picking up both interceptors. Hence, when using the first client, both interceptors are triggered.

I did some debugging and it seems it has to do with the hierarchical nature of the FactoryBean used to search for RequestInterceptors for the named factory bean.

More specifically…

FeignClientFactoryBean.configureUsingConfiguration(...) {
...
   Map<String, RequestInterceptor> requestInterceptors = **context.getInstances**(this.name, RequestInterceptor.class);
...
}
NamedContextFactory.**getInstances**(String name, Class<T> type) {
	AnnotationConfigApplicationContext context = getContext(name);
	if (BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context, type).length > 0) {
		return **BeanFactoryUtils.beansOfTypeIncludingAncestors(context, type);**
	}
	return null;
}
**BeanFactoryUtils.beansOfTypeIncludingAncestors(ListableBeanFactory lbf, Class<T> type)**
			throws BeansException {
		Assert.notNull(lbf, "ListableBeanFactory must not be null");
		Map<String, T> result = new LinkedHashMap<>(4);
		result.putAll(lbf.getBeansOfType(type));
		**if (lbf instanceof HierarchicalBeanFactory)** {
			HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
			if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
				Map<String, T> parentResult = beansOfTypeIncludingAncestors(
						(ListableBeanFactory) hbf.getParentBeanFactory(), type);
				parentResult.forEach((beanName, beanType) -> {
					if (!result.containsKey(beanName) && !hbf.containsLocalBean(beanName)) {
						result.put(beanName, beanType);
					}
				});
			}
		}
		return result;
	}

Any ideas? Is this already supported in the specified version?

Thanks in advance!

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:7 (1 by maintainers)

github_iconTop GitHub Comments

4reactions
ryanjbaxtercommented, Feb 28, 2018

Can you try removing the @Configuration annotations? They are not necessary. http://cloud.spring.io/spring-cloud-static/Edgware.SR2/single/spring-cloud.html#spring-cloud-feign-overriding-defaults

Also as an FYI the Feign code has been moved to its own top level project, so future Feign specific issues should be opened in https://github.com/spring-cloud/spring-cloud-openfeign

1reaction
cebbenscommented, Oct 17, 2018

Hi.

I can tell you what it worked for me…

My Application

@SpringBootApplication
@EnableFeignClients
public class Application {
	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}
}

Notice that SpringBootApplication contains a ComponentScan.excludeFilters.

Feign client

@FeignClient(name = "acmeApiClient", url = "${acme.api.url}", configuration = AcmeApiClient.Configuration.class)
public interface AcmeApiClient {

    @GetMapping("/users")
    ResponseEntity getUsers();

    class Configuration {
        @Bean
        public BasicAuthRequestInterceptor basicAuthRequestInterceptor(@Value("${acme.api.key}") String apiKey) {
            return new BasicAuthRequestInterceptor("", apiKey);
        }
    }

I would try removing the @ComponentScan.excludeFilters and adding both annotations, @SpringBootApplication and @EnableFeignClients.

As a side note, I would suggest renaming ReportExportInterceptor to Configuration, as it is a configuration class that configures an RequestInterceptor.

Hope it helps. Please let me know how it went.

Bests

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to set a custom Feign RequestInterceptor for specific ...
With this assignment, each FeignClient has its own configuration and RequestInterceptor doesn't deal with other clients.
Read more >
Multiple Configurations for Feign Clients - Amir Shokri - Medium
We have two Feign clients for two services, FooClient and BarClient. These Feign clients need to adopt different authentication configuration.
Read more >
Setting Up Multiple Configurations for Feign Clients [A Step-by ...
We have two Feign clients for two services, FooClient and BarClient. These Feign clients need to adopt different authentication configuration.
Read more >
Feign RequestInterceptor in Spring Boot - JavaCodeMonk
All we need to do is to create a Bean of type RequestInterceptor inside a config class and provide that configuration to FeignClient....
Read more >
Configure Feign Client in Spring Boot - Coding N Concepts
Enable Feign Client; Create Feign Client; Feign Client Configuration. From Property file; From Configuration Class file; Request Interceptor ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found