From f9cc51c16bbf6f3746aaded1cb9e572b591864ce Mon Sep 17 00:00:00 2001 From: Olga Maciaszek-Sharma Date: Thu, 24 Nov 2022 19:08:48 +0100 Subject: [PATCH] Add FeignChildContextInitializer. --- spring-cloud-openfeign-core/pom.xml | 5 + .../cloud/openfeign/DefaultTargeter.java | 2 +- .../openfeign/FeignAutoConfiguration.java | 14 +- .../FeignCircuitBreakerTargeter.java | 10 +- ...gnContext.java => FeignClientFactory.java} | 5 +- .../openfeign/FeignClientFactoryBean.java | 26 +-- .../cloud/openfeign/Targeter.java | 2 +- .../aot/FeignChildContextInitializer.java | 155 ++++++++++++++++++ .../EnableFeignClientsSpringDataTests.java | 4 +- .../FeignBuilderCustomizerTests.java | 8 +- .../openfeign/FeignClientBuilderTests.java | 3 +- ...lientDisabledClientLevelFeaturesTests.java | 2 +- .../FeignClientDisabledFeaturesTests.java | 2 +- .../FeignClientErrorDecoderTests.java | 2 +- ...tTest.java => FeignClientFactoryTest.java} | 34 ++-- .../openfeign/FeignClientFactoryTests.java | 10 +- .../FeignClientOverrideDefaultsTests.java | 2 +- .../FeignClientUsingConfigurerTest.java | 2 +- .../FeignClientUsingPropertiesTests.java | 2 +- .../openfeign/FeignCompressionTests.java | 4 +- .../openfeign/FeignHttpClientUrlTests.java | 2 +- ...ientUrlWithRetryableLoadBalancerTests.java | 2 +- .../cloud/openfeign/GzipDecodingTests.java | 2 +- .../cloud/openfeign/SpringDecoderTests.java | 2 +- .../FeignChildContextInitializerTests.java | 130 +++++++++++++++ .../support/PageableEncoderTests.java | 4 +- .../PageableSpringQueryMapEncoderTests.java | 4 +- .../openfeign/support/SpringEncoderTests.java | 4 +- 28 files changed, 372 insertions(+), 72 deletions(-) rename spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/{FeignContext.java => FeignClientFactory.java} (92%) create mode 100644 spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/aot/FeignChildContextInitializer.java rename spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/{FeignContextTest.java => FeignClientFactoryTest.java} (69%) create mode 100644 spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/aot/FeignChildContextInitializerTests.java diff --git a/spring-cloud-openfeign-core/pom.xml b/spring-cloud-openfeign-core/pom.xml index 8ccb15ab..ad35b00e 100644 --- a/spring-cloud-openfeign-core/pom.xml +++ b/spring-cloud-openfeign-core/pom.xml @@ -191,6 +191,11 @@ 2.11.0 test + + org.springframework + spring-core-test + test + org.springframework.security spring-security-oauth2-client diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/DefaultTargeter.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/DefaultTargeter.java index f7789874..29d9c215 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/DefaultTargeter.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/DefaultTargeter.java @@ -25,7 +25,7 @@ import feign.Target; class DefaultTargeter implements Targeter { @Override - public T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignContext context, + public T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignClientFactory context, Target.HardCodedTarget target) { return feign.target(target); } diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignAutoConfiguration.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignAutoConfiguration.java index 820d539f..58aec375 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignAutoConfiguration.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignAutoConfiguration.java @@ -55,11 +55,13 @@ import org.springframework.cache.interceptor.CacheInterceptor; import org.springframework.cloud.client.actuator.HasFeatures; import org.springframework.cloud.client.circuitbreaker.CircuitBreaker; import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory; +import org.springframework.cloud.openfeign.aot.FeignChildContextInitializer; import org.springframework.cloud.openfeign.security.OAuth2AccessTokenInterceptor; import org.springframework.cloud.openfeign.support.FeignEncoderProperties; import org.springframework.cloud.openfeign.support.FeignHttpClientProperties; import org.springframework.cloud.openfeign.support.PageJacksonModule; import org.springframework.cloud.openfeign.support.SortJacksonModule; +import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; @@ -102,12 +104,18 @@ public class FeignAutoConfiguration { } @Bean - public FeignContext feignContext() { - FeignContext context = new FeignContext(); + public FeignClientFactory feignContext() { + FeignClientFactory context = new FeignClientFactory(); context.setConfigurations(this.configurations); return context; } + @Bean + static FeignChildContextInitializer feignChildContextInitializer(ApplicationContext parentContext, + FeignClientFactory feignClientFactory) { + return new FeignChildContextInitializer(parentContext, feignClientFactory); + } + @Bean @ConditionalOnProperty(value = "spring.cloud.openfeign.cache.enabled", matchIfMissing = true) @ConditionalOnBean(CacheInterceptor.class) @@ -116,7 +124,7 @@ public class FeignAutoConfiguration { } @Configuration(proxyBeanMethods = false) - @ConditionalOnClass({ Module.class, Page.class, Sort.class }) + @ConditionalOnClass({Module.class, Page.class, Sort.class}) @ConditionalOnProperty(value = "spring.cloud.openfeign.autoconfiguration.jackson.enabled", havingValue = "true", matchIfMissing = true) protected static class FeignJacksonConfiguration { diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignCircuitBreakerTargeter.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignCircuitBreakerTargeter.java index 0c190658..047ebb0d 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignCircuitBreakerTargeter.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignCircuitBreakerTargeter.java @@ -39,7 +39,7 @@ class FeignCircuitBreakerTargeter implements Targeter { } @Override - public T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignContext context, + public T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignClientFactory context, Target.HardCodedTarget target) { if (!(feign instanceof FeignCircuitBreaker.Builder builder)) { return feign.target(target); @@ -56,20 +56,20 @@ class FeignCircuitBreakerTargeter implements Targeter { return builder(name, builder).target(target); } - private T targetWithFallbackFactory(String feignClientName, FeignContext context, + private T targetWithFallbackFactory(String feignClientName, FeignClientFactory context, Target.HardCodedTarget target, FeignCircuitBreaker.Builder builder, Class fallbackFactoryClass) { FallbackFactory fallbackFactory = (FallbackFactory) getFromContext("fallbackFactory", feignClientName, context, fallbackFactoryClass, FallbackFactory.class); return builder(feignClientName, builder).target(target, fallbackFactory); } - private T targetWithFallback(String feignClientName, FeignContext context, Target.HardCodedTarget target, - FeignCircuitBreaker.Builder builder, Class fallback) { + private T targetWithFallback(String feignClientName, FeignClientFactory context, + Target.HardCodedTarget target, FeignCircuitBreaker.Builder builder, Class fallback) { T fallbackInstance = getFromContext("fallback", feignClientName, context, fallback, target.type()); return builder(feignClientName, builder).target(target, fallbackInstance); } - private T getFromContext(String fallbackMechanism, String feignClientName, FeignContext context, + private T getFromContext(String fallbackMechanism, String feignClientName, FeignClientFactory context, Class beanType, Class targetType) { Object fallbackInstance = context.getInstance(feignClientName, beanType); if (fallbackInstance == null) { diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignContext.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientFactory.java similarity index 92% rename from spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignContext.java rename to spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientFactory.java index 39bdef32..63d8352e 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignContext.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientFactory.java @@ -31,10 +31,11 @@ import org.springframework.lang.Nullable; * @author Dave Syer * @author Matt King * @author Jasbir Singh + * @author Olga Maciaszek-Sharma */ -public class FeignContext extends NamedContextFactory { +public class FeignClientFactory extends NamedContextFactory { - public FeignContext() { + public FeignClientFactory() { super(FeignClientsConfiguration.class, "spring.cloud.openfeign", "spring.cloud.openfeign.client.name"); } diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientFactoryBean.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientFactoryBean.java index 8677283b..195bdbef 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientFactoryBean.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientFactoryBean.java @@ -119,7 +119,7 @@ public class FeignClientFactoryBean Assert.hasText(name, "Name must be set"); } - protected Feign.Builder feign(FeignContext context) { + protected Feign.Builder feign(FeignClientFactory context) { FeignLoggerFactory loggerFactory = get(context, FeignLoggerFactory.class); Logger logger = loggerFactory.create(type); @@ -137,7 +137,7 @@ public class FeignClientFactoryBean return builder; } - private void applyBuildCustomizers(FeignContext context, Feign.Builder builder) { + private void applyBuildCustomizers(FeignClientFactory context, Feign.Builder builder) { Map customizerMap = context.getInstances(contextId, FeignBuilderCustomizer.class); @@ -148,7 +148,7 @@ public class FeignClientFactoryBean additionalCustomizers.forEach(customizer -> customizer.customize(builder)); } - protected void configureFeign(FeignContext context, Feign.Builder builder) { + protected void configureFeign(FeignClientFactory context, Feign.Builder builder) { FeignClientProperties properties = beanFactory != null ? beanFactory.getBean(FeignClientProperties.class) : applicationContext.getBean(FeignClientProperties.class); @@ -172,7 +172,7 @@ public class FeignClientFactoryBean } } - protected void configureUsingConfiguration(FeignContext context, Feign.Builder builder) { + protected void configureUsingConfiguration(FeignClientFactory context, Feign.Builder builder) { Logger.Level level = getInheritedAwareOptional(context, Logger.Level.class); if (level != null) { builder.logLevel(level); @@ -340,7 +340,7 @@ public class FeignClientFactoryBean } } - protected T get(FeignContext context, Class type) { + protected T get(FeignClientFactory context, Class type) { T instance = context.getInstance(contextId, type); if (instance == null) { throw new IllegalStateException("No bean found of type " + type + " for " + contextId); @@ -348,11 +348,11 @@ public class FeignClientFactoryBean return instance; } - protected T getOptional(FeignContext context, Class type) { + protected T getOptional(FeignClientFactory context, Class type) { return context.getInstance(contextId, type); } - protected T getInheritedAwareOptional(FeignContext context, Class type) { + protected T getInheritedAwareOptional(FeignClientFactory context, Class type) { if (inheritParentContext) { return getOptional(context, type); } @@ -361,7 +361,7 @@ public class FeignClientFactoryBean } } - protected Map getInheritedAwareInstances(FeignContext context, Class type) { + protected Map getInheritedAwareInstances(FeignClientFactory context, Class type) { if (inheritParentContext) { return context.getInstances(contextId, type); } @@ -370,7 +370,7 @@ public class FeignClientFactoryBean } } - protected T loadBalance(Feign.Builder builder, FeignContext context, HardCodedTarget target) { + protected T loadBalance(Feign.Builder builder, FeignClientFactory context, HardCodedTarget target) { Client client = getOptional(context, Client.class); if (client != null) { builder.client(client); @@ -389,7 +389,7 @@ public class FeignClientFactoryBean * @param contextId name of feign client * @return returns Options found in context */ - protected Request.Options getOptionsByName(FeignContext context, String contextId) { + protected Request.Options getOptionsByName(FeignClientFactory context, String contextId) { if (refreshableClient) { return context.getInstance(contextId, Request.Options.class.getCanonicalName() + "-" + contextId, Request.Options.class); @@ -409,8 +409,8 @@ public class FeignClientFactoryBean */ @SuppressWarnings("unchecked") T getTarget() { - FeignContext context = beanFactory != null ? beanFactory.getBean(FeignContext.class) - : applicationContext.getBean(FeignContext.class); + FeignClientFactory context = beanFactory != null ? beanFactory.getBean(FeignClientFactory.class) + : applicationContext.getBean(FeignClientFactory.class); Feign.Builder builder = feign(context); if (!StringUtils.hasText(url) && !isUrlAvailableInConfig(contextId)) { @@ -468,7 +468,7 @@ public class FeignClientFactoryBean } @SuppressWarnings({ "unchecked", "rawtypes" }) - private HardCodedTarget resolveTarget(FeignContext context, String contextId, String url) { + private HardCodedTarget resolveTarget(FeignClientFactory context, String contextId, String url) { if (StringUtils.hasText(url)) { return new HardCodedTarget(type, name, url); } diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/Targeter.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/Targeter.java index 16aaa52d..40c1e4c1 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/Targeter.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/Targeter.java @@ -24,7 +24,7 @@ import feign.Target; */ public interface Targeter { - T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignContext context, + T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignClientFactory context, Target.HardCodedTarget target); } diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/aot/FeignChildContextInitializer.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/aot/FeignChildContextInitializer.java new file mode 100644 index 00000000..7eb23c2d --- /dev/null +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/aot/FeignChildContextInitializer.java @@ -0,0 +1,155 @@ +package org.springframework.cloud.openfeign.aot; + +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import javax.lang.model.element.Modifier; + +import org.springframework.aot.generate.GeneratedMethod; +import org.springframework.aot.generate.GenerationContext; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.aot.BeanRegistrationAotContribution; +import org.springframework.beans.factory.aot.BeanRegistrationAotProcessor; +import org.springframework.beans.factory.aot.BeanRegistrationCode; +import org.springframework.beans.factory.support.RegisteredBean; +import org.springframework.boot.web.context.WebServerInitializedEvent; +import org.springframework.cloud.openfeign.FeignClientFactory; +import org.springframework.cloud.openfeign.FeignClientSpecification; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextInitializer; +import org.springframework.context.ApplicationListener; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.aot.ApplicationContextAotGenerator; +import org.springframework.context.support.GenericApplicationContext; +import org.springframework.javapoet.ClassName; +import org.springframework.util.Assert; + +/** + * A {@link BeanRegistrationAotProcessor} that creates an {@link BeanRegistrationAotContribution} for + * Feign child contexts. + * + * @author Olga Maciaszek-Sharma + * @since 4.0.0 + */ +public class FeignChildContextInitializer implements BeanRegistrationAotProcessor, ApplicationListener { + + private final ApplicationContext applicationContext; + + private final FeignClientFactory feignClientFactory; + + private final Map> applicationContextInitializers; + + public FeignChildContextInitializer(ApplicationContext applicationContext, FeignClientFactory feignClientFactory) { + this(applicationContext, feignClientFactory, new HashMap<>()); + } + + public FeignChildContextInitializer(ApplicationContext applicationContext, FeignClientFactory feignClientFactory, Map> applicationContextInitializers) { + this.applicationContext = applicationContext; + this.feignClientFactory = feignClientFactory; + this.applicationContextInitializers = applicationContextInitializers; + } + + @Override + public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) { + Assert.isInstanceOf(ConfigurableApplicationContext.class, applicationContext); + ConfigurableApplicationContext context = ((ConfigurableApplicationContext) applicationContext); + BeanFactory applicationBeanFactory = context.getBeanFactory(); + if (!(registeredBean.getBeanClass().equals(getClass()) + && registeredBean.getBeanFactory().equals(applicationBeanFactory))) { + return null; + } + Set contextIds = new HashSet<>(getContextIdsFromConfig()); + Map childContextAotContributions = contextIds.stream() + .map(contextId -> Map.entry(contextId, buildChildContext(contextId))) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + return new AotContribution(childContextAotContributions); + } + + private GenericApplicationContext buildChildContext(String contextId) { + GenericApplicationContext childContext = feignClientFactory.buildContext(contextId); + feignClientFactory.registerBeans(contextId, childContext); + return childContext; + } + + private Collection getContextIdsFromConfig() { + Map configurations = feignClientFactory.getConfigurations(); + return configurations.keySet().stream().filter(key -> !key.startsWith("default.")) + .collect(Collectors.toSet()); + } + + @SuppressWarnings("unchecked") + public FeignChildContextInitializer withApplicationContextInitializers( + Map applicationContextInitializers) { + Map> convertedInitializers = new HashMap<>(); + applicationContextInitializers.keySet() + .forEach(contextId -> convertedInitializers.put(contextId, + (ApplicationContextInitializer) applicationContextInitializers + .get(contextId))); + return new FeignChildContextInitializer(applicationContext, feignClientFactory, + convertedInitializers); + } + + @Override + public void onApplicationEvent(WebServerInitializedEvent event) { + if (applicationContext.equals(event.getApplicationContext())) { + applicationContextInitializers.keySet().forEach(contextId -> { + GenericApplicationContext childContext = feignClientFactory.buildContext(contextId); + applicationContextInitializers.get(contextId).initialize(childContext); + feignClientFactory.addContext(contextId, childContext); + childContext.refresh(); + }); + } + } + + @Override + public boolean isBeanExcludedFromAotProcessing() { + return false; + } + + private static class AotContribution implements BeanRegistrationAotContribution { + + private final Map childContexts; + + public AotContribution(Map childContexts) { + this.childContexts = childContexts.entrySet().stream() + .filter(entry -> entry.getValue() != null) + .map(entry -> Map.entry(entry.getKey(), entry.getValue())) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } + + @Override + public void applyTo(GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode) { + Map generatedInitializerClassNames = childContexts.entrySet() + .stream() + .map(entry -> { + String name = entry.getValue().getDisplayName(); + name = name.replaceAll("[-]", "_"); + GenerationContext childGenerationContext = generationContext.withName(name); + ClassName initializerClassName = new ApplicationContextAotGenerator() + .processAheadOfTime(entry.getValue(), childGenerationContext); + return Map.entry(entry.getKey(), initializerClassName); + }) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + GeneratedMethod postProcessorMethod = beanRegistrationCode.getMethods() + .add("addFeignChildContextInitializer", + method -> { + method.addJavadoc("Use AOT child context management initialization") + .addModifiers(Modifier.PRIVATE, Modifier.STATIC) + .addParameter(RegisteredBean.class, "registeredBean") + .addParameter(FeignChildContextInitializer.class, "instance") + .returns(FeignChildContextInitializer.class) + .addStatement("$T initializers = new $T<>()", Map.class, HashMap.class); + generatedInitializerClassNames.keySet() + .forEach(contextId -> method.addStatement("initializers.put($S, new $L())", contextId, + generatedInitializerClassNames.get(contextId))); + method.addStatement("return instance.withApplicationContextInitializers(initializers)"); + }); + beanRegistrationCode.addInstancePostProcessor(postProcessorMethod.toMethodReference()); + } + } + +} diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/EnableFeignClientsSpringDataTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/EnableFeignClientsSpringDataTests.java index 573e673a..2cc69bca 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/EnableFeignClientsSpringDataTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/EnableFeignClientsSpringDataTests.java @@ -34,11 +34,11 @@ import org.springframework.test.annotation.DirtiesContext; class EnableFeignClientsSpringDataTests { @Autowired - private FeignContext feignContext; + private FeignClientFactory feignClientFactory; @Test void encoderDefaultCorrect() { - PageableSpringEncoder.class.cast(this.feignContext.getInstance("foo", Encoder.class)); + PageableSpringEncoder.class.cast(this.feignClientFactory.getInstance("foo", Encoder.class)); } @Configuration(proxyBeanMethods = false) diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignBuilderCustomizerTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignBuilderCustomizerTests.java index d6ed73e6..4b728d58 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignBuilderCustomizerTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignBuilderCustomizerTests.java @@ -162,8 +162,8 @@ class FeignBuilderCustomizerTests { protected static class SampleConfiguration2 { @Bean - FeignContext feignContext() { - return new FeignContext(); + FeignClientFactory feignContext() { + return new FeignClientFactory(); } @Bean @@ -198,8 +198,8 @@ class FeignBuilderCustomizerTests { protected static class SampleConfiguration3 { @Bean - FeignContext feignContext() { - return new FeignContext(); + FeignClientFactory feignContext() { + return new FeignClientFactory(); } @Bean diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientBuilderTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientBuilderTests.java index e0c3fe1c..9a212a5a 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientBuilderTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientBuilderTests.java @@ -158,7 +158,8 @@ class FeignClientBuilderTests { @Test void forType_build() { // given: - Mockito.when(this.applicationContext.getBean(FeignContext.class)).thenThrow(new ClosedFileSystemException()); // throw + Mockito.when(this.applicationContext.getBean(FeignClientFactory.class)) + .thenThrow(new ClosedFileSystemException()); // throw // an // unusual // exception diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientDisabledClientLevelFeaturesTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientDisabledClientLevelFeaturesTests.java index abf946f9..114538f1 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientDisabledClientLevelFeaturesTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientDisabledClientLevelFeaturesTests.java @@ -46,7 +46,7 @@ import static org.assertj.core.api.Assertions.assertThat; class FeignClientDisabledClientLevelFeaturesTests { @Autowired - private FeignContext context; + private FeignClientFactory context; @Autowired private FooClient foo; diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientDisabledFeaturesTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientDisabledFeaturesTests.java index 52b05631..00d256ab 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientDisabledFeaturesTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientDisabledFeaturesTests.java @@ -45,7 +45,7 @@ import static org.assertj.core.api.Assertions.assertThat; class FeignClientDisabledFeaturesTests { @Autowired - private FeignContext context; + private FeignClientFactory context; @Autowired private FooClient foo; diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientErrorDecoderTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientErrorDecoderTests.java index 722a61ae..1c728211 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientErrorDecoderTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientErrorDecoderTests.java @@ -50,7 +50,7 @@ import static org.assertj.core.api.Assertions.assertThat; public class FeignClientErrorDecoderTests { @Autowired - private FeignContext context; + private FeignClientFactory context; @Autowired private FooClient foo; diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignContextTest.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientFactoryTest.java similarity index 69% rename from spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignContextTest.java rename to spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientFactoryTest.java index 7345aaae..890dca33 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignContextTest.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientFactoryTest.java @@ -30,18 +30,18 @@ import org.springframework.context.annotation.Import; import static org.assertj.core.api.Assertions.assertThat; -class FeignContextTest { +class FeignClientFactoryTest { @Test void getInstanceWithoutAncestors_verifyNullForMissing() { AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext(); parent.refresh(); - FeignContext feignContext = new FeignContext(); - feignContext.setApplicationContext(parent); - feignContext.setConfigurations(Lists.newArrayList(getSpec("empty", EmptyConfiguration.class))); + FeignClientFactory feignClientFactory = new FeignClientFactory(); + feignClientFactory.setApplicationContext(parent); + feignClientFactory.setConfigurations(Lists.newArrayList(getSpec("empty", EmptyConfiguration.class))); - Logger.Level level = feignContext.getInstanceWithoutAncestors("empty", Logger.Level.class); + Logger.Level level = feignClientFactory.getInstanceWithoutAncestors("empty", Logger.Level.class); assertThat(level).as("Logger was not null").isNull(); } @@ -55,11 +55,11 @@ class FeignContextTest { AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext(); parent.refresh(); - FeignContext feignContext = new FeignContext(); - feignContext.setApplicationContext(parent); - feignContext.setConfigurations(Lists.newArrayList(getSpec("empty", EmptyConfiguration.class))); + FeignClientFactory feignClientFactory = new FeignClientFactory(); + feignClientFactory.setApplicationContext(parent); + feignClientFactory.setConfigurations(Lists.newArrayList(getSpec("empty", EmptyConfiguration.class))); - Collection interceptors = feignContext + Collection interceptors = feignClientFactory .getInstancesWithoutAncestors("empty", RequestInterceptor.class).values(); assertThat(interceptors).as("Interceptors is not empty").isEmpty(); @@ -70,11 +70,11 @@ class FeignContextTest { AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext(); parent.refresh(); - FeignContext feignContext = new FeignContext(); - feignContext.setApplicationContext(parent); - feignContext.setConfigurations(Lists.newArrayList(getSpec("demo", DemoConfiguration.class))); + FeignClientFactory feignClientFactory = new FeignClientFactory(); + feignClientFactory.setApplicationContext(parent); + feignClientFactory.setConfigurations(Lists.newArrayList(getSpec("demo", DemoConfiguration.class))); - Logger.Level level = feignContext.getInstanceWithoutAncestors("demo", Logger.Level.class); + Logger.Level level = feignClientFactory.getInstanceWithoutAncestors("demo", Logger.Level.class); assertThat(level).isEqualTo(Logger.Level.FULL); } @@ -84,11 +84,11 @@ class FeignContextTest { AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext(); parent.refresh(); - FeignContext feignContext = new FeignContext(); - feignContext.setApplicationContext(parent); - feignContext.setConfigurations(Lists.newArrayList(getSpec("demo", DemoConfiguration.class))); + FeignClientFactory feignClientFactory = new FeignClientFactory(); + feignClientFactory.setApplicationContext(parent); + feignClientFactory.setConfigurations(Lists.newArrayList(getSpec("demo", DemoConfiguration.class))); - Collection interceptors = feignContext + Collection interceptors = feignClientFactory .getInstancesWithoutAncestors("demo", RequestInterceptor.class).values(); assertThat(interceptors.size()).isEqualTo(1); diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientFactoryTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientFactoryTests.java index cc7e7f59..1f238731 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientFactoryTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientFactoryTests.java @@ -52,7 +52,7 @@ public class FeignClientFactoryTests { public void testChildContexts() { AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext(); parent.refresh(); - FeignContext context = new FeignContext(); + FeignClientFactory context = new FeignClientFactory(); context.setApplicationContext(parent); context.setConfigurations(Arrays.asList(getSpec("foo", FooConfig.class), getSpec("bar", BarConfig.class))); @@ -103,11 +103,11 @@ public class FeignClientFactoryTests { } @Bean - FeignContext feignContext() { - FeignContext feignContext = new FeignContext(); - feignContext.setConfigurations(Collections.singletonList( + FeignClientFactory feignContext() { + FeignClientFactory feignClientFactory = new FeignClientFactory(); + feignClientFactory.setConfigurations(Collections.singletonList( new FeignClientSpecification("test", new Class[] { LoadBalancerAutoConfiguration.class }))); - return feignContext; + return feignClientFactory; } @Bean diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientOverrideDefaultsTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientOverrideDefaultsTests.java index cb0c5363..477392fe 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientOverrideDefaultsTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientOverrideDefaultsTests.java @@ -63,7 +63,7 @@ import static org.assertj.core.api.Assertions.assertThatCode; class FeignClientOverrideDefaultsTests { @Autowired - private FeignContext context; + private FeignClientFactory context; @Autowired private FooClient foo; diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientUsingConfigurerTest.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientUsingConfigurerTest.java index da4f2cf8..2ab06b0f 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientUsingConfigurerTest.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientUsingConfigurerTest.java @@ -55,7 +55,7 @@ class FeignClientUsingConfigurerTest { private ConfigurableListableBeanFactory beanFactory; @Autowired - private FeignContext context; + private FeignClientFactory context; @SuppressWarnings({ "unchecked", "rawtypes" }) @Test diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientUsingPropertiesTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientUsingPropertiesTests.java index 6ff8d402..7cbb6d98 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientUsingPropertiesTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignClientUsingPropertiesTests.java @@ -87,7 +87,7 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen public class FeignClientUsingPropertiesTests { @Autowired - FeignContext context; + FeignClientFactory context; @Autowired private ApplicationContext applicationContext; diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignCompressionTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignCompressionTests.java index 0a71100f..c133f8dc 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignCompressionTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignCompressionTests.java @@ -47,8 +47,8 @@ class FeignCompressionTests { FeignContentGzipEncodingAutoConfiguration.class, FeignAcceptGzipEncodingAutoConfiguration.class)) .run(context -> { - FeignContext feignContext = context.getBean(FeignContext.class); - Map interceptors = feignContext.getInstances("foo", + FeignClientFactory feignClientFactory = context.getBean(FeignClientFactory.class); + Map interceptors = feignClientFactory.getInstances("foo", RequestInterceptor.class); assertThat(interceptors.size()).isEqualTo(2); assertThat(interceptors.get("feignAcceptGzipEncodingInterceptor")) diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignHttpClientUrlTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignHttpClientUrlTests.java index 72ded3f9..92d20460 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignHttpClientUrlTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignHttpClientUrlTests.java @@ -153,7 +153,7 @@ class FeignHttpClientUrlTests { public Targeter feignTargeter() { return new Targeter() { @Override - public T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignContext context, + public T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignClientFactory context, Target.HardCodedTarget target) { Field field = ReflectionUtils.findField(Feign.Builder.class, "client"); ReflectionUtils.makeAccessible(field); diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignHttpClientUrlWithRetryableLoadBalancerTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignHttpClientUrlWithRetryableLoadBalancerTests.java index 4fca05e0..233c867c 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignHttpClientUrlWithRetryableLoadBalancerTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/FeignHttpClientUrlWithRetryableLoadBalancerTests.java @@ -154,7 +154,7 @@ class FeignHttpClientUrlWithRetryableLoadBalancerTests { public Targeter feignTargeter() { return new Targeter() { @Override - public T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignContext context, + public T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignClientFactory context, Target.HardCodedTarget target) { Field field = ReflectionUtils.findField(Feign.Builder.class, "client"); ReflectionUtils.makeAccessible(field); diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/GzipDecodingTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/GzipDecodingTests.java index a7496ff2..6ccc6df6 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/GzipDecodingTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/GzipDecodingTests.java @@ -50,7 +50,7 @@ import static org.assertj.core.api.Assertions.assertThat; class GzipDecodingTests extends FeignClientFactoryBean { @Autowired - FeignContext context; + FeignClientFactory context; @Value("${local.server.port}") private int port = 0; diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/SpringDecoderTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/SpringDecoderTests.java index b863f763..bc975bab 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/SpringDecoderTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/SpringDecoderTests.java @@ -53,7 +53,7 @@ import static org.assertj.core.api.Assertions.assertThat; class SpringDecoderTests extends FeignClientFactoryBean { @Autowired - FeignContext context; + FeignClientFactory context; @LocalServerPort private int port = 0; diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/aot/FeignChildContextInitializerTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/aot/FeignChildContextInitializerTests.java new file mode 100644 index 00000000..1807bb59 --- /dev/null +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/aot/FeignChildContextInitializerTests.java @@ -0,0 +1,130 @@ +package org.springframework.cloud.openfeign.aot; + +import java.net.URL; + +import org.apache.catalina.webresources.TomcatURLStreamHandlerFactory; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import org.springframework.aot.test.generate.TestGenerationContext; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; +import org.springframework.boot.context.annotation.UserConfigurations; +import org.springframework.boot.test.context.runner.WebApplicationContextRunner; +import org.springframework.boot.test.system.CapturedOutput; +import org.springframework.boot.test.system.OutputCaptureExtension; +import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebApplicationContext; +import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext; +import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.cloud.openfeign.FeignAutoConfiguration; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.context.ApplicationContextInitializer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.aot.ApplicationContextAotGenerator; +import org.springframework.context.support.GenericApplicationContext; +import org.springframework.core.test.tools.CompileWithForkedClassLoader; +import org.springframework.core.test.tools.TestCompiler; +import org.springframework.javapoet.ClassName; +import org.springframework.test.util.ReflectionTestUtils; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link FeignChildContextInitializer}. + * + * @author Olga Maciaszek-Sharma + */ +@ExtendWith(OutputCaptureExtension.class) +class FeignChildContextInitializerTests { + + private static final Log LOG = LogFactory.getLog(FeignChildContextInitializerTests.class); + + @BeforeEach + @AfterEach + void reset() { + ReflectionTestUtils.setField(TomcatURLStreamHandlerFactory.class, "instance", null); + ReflectionTestUtils.setField(URL.class, "factory", null); + } + + @Test + @CompileWithForkedClassLoader + @SuppressWarnings("unchecked") + void shouldStartFeignChildContextsFromAotContributions(CapturedOutput output) { + WebApplicationContextRunner contextRunner = new WebApplicationContextRunner( + AnnotationConfigServletWebApplicationContext::new) + .withConfiguration(AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class, + FeignAutoConfiguration.class)) + .withConfiguration(UserConfigurations.of(TestFeignConfiguration.class)); + contextRunner.prepare(context -> { + TestGenerationContext generationContext = new TestGenerationContext(TestTarget.class); + ClassName className = new ApplicationContextAotGenerator().processAheadOfTime( + (GenericApplicationContext) context.getSourceApplicationContext(), generationContext); + generationContext.writeGeneratedContent(); + TestCompiler compiler = TestCompiler.forSystem(); + compiler.with(generationContext).compile(compiled -> { + ServletWebServerApplicationContext freshApplicationContext = new ServletWebServerApplicationContext(); + ApplicationContextInitializer initializer = compiled + .getInstance(ApplicationContextInitializer.class, className.toString()); + initializer.initialize(freshApplicationContext); + assertThat(output).isNotEmpty(); + + // TODO + }); + }); + } + + static class TestTarget { + + } + + @Configuration(proxyBeanMethods = false) + @EnableFeignClients(clients = {TestFeignClient.class, TestFeignClientWithConfig.class}, defaultConfiguration = DefaultConfiguration.class) + public static class TestFeignConfiguration { + + } + + public static class TestConfiguration { + + @Bean + TestBean testBean() { + LOG.debug("Instantiating bean from Test custom config"); + return new TestBean(); + } + + } + + public static class DefaultConfiguration { + + @Bean + TestBean defaultTestBean() { + LOG.debug("Instantiating bean from default custom config"); + return new TestBean(); + } + + } + + public static class TestBean { + + } + + @FeignClient("test") + interface TestFeignClient { + + void test(); + + } + + // TODO: verify other annotation parameters + @FeignClient(value = "test-with-config", configuration = TestConfiguration.class) + interface TestFeignClientWithConfig { + + void test(); + + } + +} diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/support/PageableEncoderTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/support/PageableEncoderTests.java index 542fb2cb..2bbf2710 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/support/PageableEncoderTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/support/PageableEncoderTests.java @@ -22,7 +22,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.cloud.openfeign.FeignContext; +import org.springframework.cloud.openfeign.FeignClientFactory; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; @@ -51,7 +51,7 @@ class PageableEncoderTests { public static final String SORT_1 = "sort1"; @Autowired - private FeignContext context; + private FeignClientFactory context; protected String getPageParameter() { return "page"; diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/support/PageableSpringQueryMapEncoderTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/support/PageableSpringQueryMapEncoderTests.java index 2163e02b..bb14e733 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/support/PageableSpringQueryMapEncoderTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/support/PageableSpringQueryMapEncoderTests.java @@ -24,7 +24,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.cloud.openfeign.FeignContext; +import org.springframework.cloud.openfeign.FeignClientFactory; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; @@ -52,7 +52,7 @@ class PageableSpringQueryMapEncoderTests { public static final String SORT_1 = "sort1"; @Autowired - private FeignContext context; + private FeignClientFactory context; protected String getPageParameter() { return "page"; diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/support/SpringEncoderTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/support/SpringEncoderTests.java index df590c10..7e57595a 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/support/SpringEncoderTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/support/SpringEncoderTests.java @@ -34,7 +34,7 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.cloud.openfeign.FeignContext; +import org.springframework.cloud.openfeign.FeignClientFactory; import org.springframework.cloud.openfeign.encoding.HttpEncoding; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; @@ -77,7 +77,7 @@ import static org.springframework.http.MediaType.TEXT_PLAIN_VALUE; class SpringEncoderTests { @Autowired - private FeignContext context; + private FeignClientFactory context; @Autowired @Qualifier("myHttpMessageConverter")