Skip to content

Add FeignBuilderCustomizer support to FeignClientBuilder #499

@Sam-Kruglov

Description

@Sam-Kruglov

Is your feature request related to a problem? Please describe.
related to #244

It seems we only have FeignBuilderCustomizer support for annotation-driven approach but not for programmatic via org.springframework.cloud.openfeign.FeignClientBuilder. In my case, I want to create multiple instances of the same feign client at runtime because each instance will have its own authentication credentials (and possibly other settings) entered by a user.

Describe the solution you'd like
Getting hold of Feign.Builder via FeignClientBuilder somehow would be great. Like one of these:

FeignClientBuilder#customize(FeignBuilderCustomizer)
FeignClientBuilder#getFeignBuilder()

Describe alternatives you've considered
Here's my current solution, it's not very nice but bearable :)

import com.company.StuffSettings;
import com.company.StuffClient;
import feign.Feign;
import feign.auth.BasicAuthRequestInterceptor;
import lombok.EqualsAndHashCode;
import lombok.RequiredArgsConstructor;
import lombok.val;
import org.springframework.cloud.openfeign.FeignBuilderCustomizer;
import org.springframework.cloud.openfeign.FeignClientBuilder;
import org.springframework.cloud.openfeign.FeignClientFactoryBean;
import org.springframework.cloud.openfeign.FeignContext;

@RequiredArgsConstructor
public class FeignClientFactory {

    private final FeignClientBuilder clientBuilder;

    public StuffClient createStuffClient(String id, StuffSettings settings) {
        val factoryBean = new CustomizingFeignClientFactoryBean(builder -> builder
                .requestInterceptor(
                        new BasicAuthRequestInterceptor(settings.getUsername(), settings.getPassword())
                )
        );
        return clientBuilder.forType(StuffClient.class, factoryBean, "stuff-" + id)
                .url(settings.getUrl())
                .build();
    }

    @RequiredArgsConstructor
    @EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true)
    private static class CustomizingFeignClientFactoryBean extends FeignClientFactoryBean {

        private final FeignBuilderCustomizer customizer;

        @Override
        protected Feign.Builder feign(FeignContext context) {
            val builder = super.feign(context);
            customizer.customize(builder);
            return builder;
        }
    }
}

I also thought about registerring that FeignBuilderCustomizer via FeignContext#getContext()#registerBean(...) but FeignContext#getContext is protected and FeignContext is registered with just @Bean, so I can't override it.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions