diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientConfiguration.java index 27de09f7..53a4caed 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientConfiguration.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientConfiguration.java @@ -27,7 +27,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.client.discovery.DiscoveryClient; -import org.springframework.cloud.netflix.EurekaDiscoverClient; +import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.cloud.netflix.servo.ServoMetricReader; import org.springframework.context.ApplicationListener; import org.springframework.context.SmartLifecycle; @@ -140,7 +140,12 @@ public class EurekaClientConfiguration implements SmartLifecycle, Ordered { @Bean public DiscoveryClient discoveryClient() { - return new EurekaDiscoverClient(); + return new EurekaDiscoveryClient(); + } + + @Bean + public SpringClientFactory springClientFactory() { + return new SpringClientFactory(); } @Bean diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/EurekaDiscoverClient.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaDiscoveryClient.java similarity index 89% rename from spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/EurekaDiscoverClient.java rename to spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaDiscoveryClient.java index 5f17c55e..9dc081be 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/EurekaDiscoverClient.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaDiscoveryClient.java @@ -1,4 +1,4 @@ -package org.springframework.cloud.netflix; +package org.springframework.cloud.netflix.eureka; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; @@ -8,7 +8,7 @@ import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean; /** * @author Spencer Gibb */ -public class EurekaDiscoverClient implements DiscoveryClient { +public class EurekaDiscoveryClient implements DiscoveryClient { @Autowired private EurekaInstanceConfigBean config; diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/hystrix/EnableHystrix.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/hystrix/EnableHystrix.java index 509548f6..6c26a52c 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/hystrix/EnableHystrix.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/hystrix/EnableHystrix.java @@ -15,9 +15,7 @@ */ package org.springframework.cloud.netflix.hystrix; -import org.springframework.context.annotation.AdviceMode; import org.springframework.context.annotation.Import; -import org.springframework.core.Ordered; import java.lang.annotation.*; @@ -27,34 +25,6 @@ import java.lang.annotation.*; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented -@Import(HystrixConfigurationSelector.class) +@Import(HystrixConfiguration.class) public @interface EnableHystrix { - - /** - * Indicate whether subclass-based (CGLIB) proxies are to be created ({@code true}) as - * opposed to standard Java interface-based proxies ({@code false}). The default is - * {@code false}. Applicable only if {@link #mode()} is set to - * {@link org.springframework.context.annotation.AdviceMode#PROXY}. - *

Note that setting this attribute to {@code true} will affect all - * Spring-managed beans requiring proxying, not just those marked with - * {@code @Transactional}. For example, other beans marked with Spring's - * {@code @Async} annotation will be upgraded to subclass proxying at the same - * time. This approach has no negative impact in practice unless one is explicitly - * expecting one type of proxy vs another, e.g. in tests. - */ - boolean proxyTargetClass() default false; - - /** - * Indicate how transactional advice should be applied. The default is - * {@link org.springframework.context.annotation.AdviceMode#PROXY}. - * @see org.springframework.context.annotation.AdviceMode - */ - AdviceMode mode() default AdviceMode.PROXY; - - /** - * Indicate the ordering of the execution of the transaction advisor - * when multiple advices are applied at a specific joinpoint. - * The default is {@link org.springframework.core.Ordered#LOWEST_PRECEDENCE}. - */ - int order() default Ordered.LOWEST_PRECEDENCE; } \ No newline at end of file diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/hystrix/HystrixConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/hystrix/HystrixConfiguration.java index 78560ad8..355c34e8 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/hystrix/HystrixConfiguration.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/hystrix/HystrixConfiguration.java @@ -29,6 +29,7 @@ import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.actuate.metrics.GaugeService; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.context.SmartLifecycle; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -65,7 +66,7 @@ public class HystrixConfiguration implements ImportAware { } @Bean - // TODO: add enable/disable + @ConditionalOnExpression("${hystrix.stream.endpoint.enabled:true}") // TODO: make it @ConditionalOnWebApp (need a nested class) public HystrixStreamEndpoint hystrixStreamEndpoint() { return new HystrixStreamEndpoint(); @@ -81,20 +82,6 @@ public class HystrixConfiguration implements ImportAware { + importMetadata.getClassName()); } - @Autowired(required = false) - void setConfigurers(Collection configurers) { - if (CollectionUtils.isEmpty(configurers)) { - return; - } - if (configurers.size() > 1) { - throw new IllegalStateException( - "Only one HystrixConfigurer may exist"); - } - // TODO: create CircuitBreakerConfigurer API - // CircuitBreakerConfigurer configurer = configurers.iterator().next(); - // this.txManager = configurer.annotationDrivenTransactionManager(); - } - @Configuration @ConditionalOnClass(GaugeService.class) protected static class HystrixMetricsPollerConfiguration implements SmartLifecycle { diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/hystrix/HystrixConfigurationSelector.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/hystrix/HystrixConfigurationSelector.java deleted file mode 100644 index f1b75f80..00000000 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/hystrix/HystrixConfigurationSelector.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2013-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.cloud.netflix.hystrix; - -import org.springframework.context.annotation.AdviceMode; -import org.springframework.context.annotation.AdviceModeImportSelector; -import org.springframework.context.annotation.AutoProxyRegistrar; - -/** - * @author Spencer Gibb - */ -public class HystrixConfigurationSelector extends AdviceModeImportSelector { - - /** - * The name of the AspectJ transaction management @{@code Configuration} class. - */ - private static final String TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME = - "org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration"; - - @Override - protected String[] selectImports(AdviceMode adviceMode) { - switch (adviceMode) { - case PROXY: - return new String[]{AutoProxyRegistrar.class.getName(), HystrixConfiguration.class.getName()}; - case ASPECTJ: - return new String[]{TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME}; - default: - return null; - } - } -} diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/hystrix/HystrixConfigurer.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/hystrix/HystrixConfigurer.java deleted file mode 100644 index 6d3d2725..00000000 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/hystrix/HystrixConfigurer.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2013-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.cloud.netflix.hystrix; - -/** - * @author Spencer Gibb - */ -public interface HystrixConfigurer { -} diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancerClient.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancerClient.java index 268925c7..6b8e0380 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancerClient.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonLoadBalancerClient.java @@ -8,7 +8,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; -import com.netflix.client.ClientFactory; import com.netflix.loadbalancer.BaseLoadBalancer; import com.netflix.loadbalancer.ILoadBalancer; import com.netflix.loadbalancer.Server; @@ -22,6 +21,9 @@ public class RibbonLoadBalancerClient implements LoadBalancerClient { @Autowired private ServerListInitializer serverListInitializer; + @Autowired + private SpringClientFactory clientFactory; + private Map balancers = new HashMap(); public RibbonLoadBalancerClient(List balancers) { @@ -35,7 +37,7 @@ public class RibbonLoadBalancerClient implements LoadBalancerClient { serverListInitializer.initialize(serviceId); ILoadBalancer loadBalancer = this.balancers.get(serviceId); if (loadBalancer == null) { - loadBalancer = ClientFactory.getNamedLoadBalancer(serviceId); + loadBalancer = clientFactory.getNamedLoadBalancer(serviceId); } Server server = loadBalancer.chooseServer("default"); if (server == null) { diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/SpringClientFactory.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/SpringClientFactory.java new file mode 100644 index 00000000..7235ee7b --- /dev/null +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/SpringClientFactory.java @@ -0,0 +1,239 @@ +package org.springframework.cloud.netflix.ribbon; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import com.netflix.client.AbstractLoadBalancerAwareClient; +import com.netflix.client.ClientException; +import com.netflix.client.IClient; +import com.netflix.client.IClientConfigAware; +import lombok.extern.slf4j.Slf4j; + +import com.netflix.client.config.CommonClientConfigKey; +import com.netflix.client.config.DefaultClientConfigImpl; +import com.netflix.client.config.IClientConfig; +import com.netflix.loadbalancer.ILoadBalancer; +import com.netflix.servo.monitor.Monitors; + +/** + * A factory that creates client, load balancer and client configuration instances from properties. It also keeps mappings of client names to + * the created instances. + * + */ +@Slf4j +public class SpringClientFactory { + + private Map> simpleClientMap = new ConcurrentHashMap<>(); + private Map namedLBMap = new ConcurrentHashMap<>(); + private ConcurrentHashMap namedConfig = new ConcurrentHashMap<>(); + + /** + * Utility method to create client and load balancer (if enabled in client config) given the name and client config. + * Instances are created using reflection (see {@link #instantiateInstanceWithClientConfig(String, IClientConfig)} + * + * @param restClientName + * @param clientConfig + * @throws ClientException if any errors occurs in the process, or if the client with the same name already exists + */ + public synchronized IClient registerClientFromProperties(String restClientName, IClientConfig clientConfig) throws ClientException { + IClient client; + ILoadBalancer loadBalancer = null; + if (simpleClientMap.get(restClientName) != null) { + throw new ClientException( + ClientException.ErrorType.GENERAL, + "A Rest Client with this name is already registered. Please use a different name"); + } + try { + String clientClassName = (String) clientConfig.getProperty(CommonClientConfigKey.ClientClassName); + client = (IClient) instantiateInstanceWithClientConfig(clientClassName, clientConfig); + boolean initializeNFLoadBalancer = Boolean.parseBoolean(clientConfig.getProperty( + CommonClientConfigKey.InitializeNFLoadBalancer, DefaultClientConfigImpl.DEFAULT_ENABLE_LOADBALANCER).toString()); + if (initializeNFLoadBalancer) { + loadBalancer = getNamedLoadBalancer(restClientName, clientConfig.getClass()); + } + if (client instanceof AbstractLoadBalancerAwareClient) { + ((AbstractLoadBalancerAwareClient) client).setLoadBalancer(loadBalancer); + } + } catch (Throwable e) { + String message = "Unable to InitializeAndAssociateNFLoadBalancer set for RestClient:" + + restClientName; + log.warn(message, e); + throw new ClientException(ClientException.ErrorType.CONFIGURATION, + message, e); + } + simpleClientMap.put(restClientName, client); + + Monitors.registerObject("Client_" + restClientName, client); + + log.info("Client Registered:" + client.toString()); + return client; + } + + /** + * Return the named client from map if already created. Otherwise creates the client using the configuration returned by {@link #getNamedConfig(String)}. + * + * @throws RuntimeException if an error occurs in creating the client. + */ + public synchronized IClient getNamedClient(String name) { + return getNamedClient(name, DefaultClientConfigImpl.class); + } + + public synchronized C namedClient(String name, Class clientClass) { + return clientClass.cast(getNamedClient(name, DefaultClientConfigImpl.class)); + } + + /** + * Return the named client from map if already created. Otherwise creates the client using the configuration returned by {@link #createNamedClient(String, Class)}. + * + * @throws RuntimeException if an error occurs in creating the client. + */ + public synchronized IClient getNamedClient(String name, Class configClass) { + if (simpleClientMap.get(name) != null) { + return simpleClientMap.get(name); + } + try { + return createNamedClient(name, configClass); + } catch (ClientException e) { + throw new RuntimeException("Unable to create client", e); + } + } + + /** + * Creates a named client using a IClientConfig instance created off the configClass class object passed in as the parameter. + * + * @throws ClientException if any error occurs, or if the client with the same name already exists + */ + public synchronized IClient createNamedClient(String name, Class configClass) throws ClientException { + IClientConfig config = getNamedConfig(name, configClass); + return registerClientFromProperties(name, config); + } + + /** + * Get the load balancer associated with the name, or create one with an instance {@link DefaultClientConfigImpl} if does not exist + * + * @throws RuntimeException if any error occurs + */ + public synchronized ILoadBalancer getNamedLoadBalancer(String name) { + return getNamedLoadBalancer(name, DefaultClientConfigImpl.class); + } + + /** + * Get the load balancer associated with the name, or create one with an instance of configClass if does not exist + * + * @throws RuntimeException if any error occurs + * @see #registerNamedLoadBalancerFromProperties(String, Class) + */ + public synchronized ILoadBalancer getNamedLoadBalancer(String name, Class configClass) { + ILoadBalancer lb = namedLBMap.get(name); + if (lb != null) { + return lb; + } else { + try { + lb = registerNamedLoadBalancerFromProperties(name, configClass); + } catch (ClientException e) { + throw new RuntimeException("Unable to create load balancer", e); + } + return lb; + } + } + + /** + * Create and register a load balancer with the name and given the class of configClass. + * + * @throws ClientException if load balancer with the same name already exists or any error occurs + * @see #instantiateInstanceWithClientConfig(String, IClientConfig) + */ + public ILoadBalancer registerNamedLoadBalancerFromclientConfig(String name, IClientConfig clientConfig) throws ClientException { + if (namedLBMap.get(name) != null) { + throw new ClientException("LoadBalancer for name " + name + " already exists"); + } + ILoadBalancer lb = null; + try { + String loadBalancerClassName = (String) clientConfig.getProperty(CommonClientConfigKey.NFLoadBalancerClassName); + lb = (ILoadBalancer) instantiateInstanceWithClientConfig(loadBalancerClassName, clientConfig); + namedLBMap.put(name, lb); + log.info("Client:" + name + + " instantiated a LoadBalancer:" + lb.toString()); + return lb; + } catch (Exception e) { + throw new ClientException("Unable to instantiate/associate LoadBalancer with Client:" + name, e); + } + } + + /** + * Create and register a load balancer with the name and given the class of configClass. + * + * @throws ClientException if load balancer with the same name already exists or any error occurs + * @see #instantiateInstanceWithClientConfig(String, IClientConfig) + */ + public synchronized ILoadBalancer registerNamedLoadBalancerFromProperties(String name, Class configClass) throws ClientException { + if (namedLBMap.get(name) != null) { + throw new ClientException("LoadBalancer for name " + name + " already exists"); + } + IClientConfig clientConfig = getNamedConfig(name, configClass); + return registerNamedLoadBalancerFromclientConfig(name, clientConfig); + } + + /** + * Creates instance related to client framework using reflection. It first checks if the object is an instance of + * {@link IClientConfigAware} and if so invoke {@link IClientConfigAware#initWithNiwsConfig(IClientConfig)}. If that does not + * apply, it tries to find if there is a constructor with {@link IClientConfig} as a parameter and if so invoke that constructor. If neither applies, + * it simply invokes the no-arg constructor and ignores the clientConfig parameter. + * + * @param className Class name of the object + * @param clientConfig IClientConfig object used for initialization. + */ + @SuppressWarnings("unchecked") + public Object instantiateInstanceWithClientConfig(String className, IClientConfig clientConfig) + throws InstantiationException, IllegalAccessException, ClassNotFoundException { + Class clazz = Class.forName(className); + if (IClientConfigAware.class.isAssignableFrom(clazz)) { + IClientConfigAware obj = (IClientConfigAware) clazz.newInstance(); + obj.initWithNiwsConfig(clientConfig); + return obj; + } else { + try { + if (clazz.getConstructor(IClientConfig.class) != null) { + return clazz.getConstructor(IClientConfig.class).newInstance(clientConfig); + } + } catch (Throwable e) { // NOPMD + } + } + log.warn("Class " + className + " neither implements IClientConfigAware nor provides a constructor with IClientConfig as the parameter. Only default constructor will be used."); + return clazz.newInstance(); + } + + /** + * Get the client configuration given the name or create one with {@link DefaultClientConfigImpl} if it does not exist. + * + * @see #getNamedConfig(String, Class) + */ + public IClientConfig getNamedConfig(String name) { + return getNamedConfig(name, DefaultClientConfigImpl.class); + } + + /** + * Get the client configuration given the name or create one with clientConfigClass if it does not exist. An instance of IClientConfig + * is created and {@link IClientConfig#loadProperties(String)} will be called. + */ + public IClientConfig getNamedConfig(String name, Class clientConfigClass) { + IClientConfig config = namedConfig.get(name); + if (config != null) { + return config; + } else { + try { + config = (IClientConfig) clientConfigClass.newInstance(); + config.loadProperties(name); + } catch (Throwable e) { + log.error("Unable to create client config instance", e); + return null; + } + config.loadProperties(name); + IClientConfig old = namedConfig.putIfAbsent(name, config); + if (old != null) { + config = old; + } + return config; + } + } +} diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/eureka/EurekaRibbonInitializer.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/eureka/EurekaRibbonInitializer.java index ab14c133..3512e86b 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/eureka/EurekaRibbonInitializer.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/eureka/EurekaRibbonInitializer.java @@ -6,9 +6,9 @@ import static com.netflix.client.config.CommonClientConfigKey.NFLoadBalancerRule import static com.netflix.client.config.CommonClientConfigKey.NIWSServerListClassName; import static com.netflix.client.config.CommonClientConfigKey.NIWSServerListFilterClassName; +import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.cloud.netflix.ribbon.ServerListInitializer; -import com.netflix.client.ClientFactory; import com.netflix.config.ConfigurationManager; import com.netflix.config.DeploymentContext.ContextKey; import com.netflix.discovery.EurekaClientConfig; @@ -28,17 +28,19 @@ import com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList; */ public class EurekaRibbonInitializer implements ServerListInitializer { - private EurekaClientConfig client; + private EurekaClientConfig clientConfig; + private SpringClientFactory clientFactory; - public EurekaRibbonInitializer(EurekaClientConfig client) { - this.client = client; - } + public EurekaRibbonInitializer(EurekaClientConfig clientConfig, SpringClientFactory clientFactory) { + this.clientConfig = clientConfig; + this.clientFactory = clientFactory; + } @Override public void initialize(String serviceId) { - if (client != null + if (clientConfig != null && ConfigurationManager.getDeploymentContext().getValue(ContextKey.zone) == null) { - String[] zones = client.getAvailabilityZones(client.getRegion()); + String[] zones = clientConfig.getAvailabilityZones(clientConfig.getRegion()); String zone = zones != null && zones.length > 0 ? zones[0] : null; if (zone != null) { // You can set this with archaius.deployment.* (maybe requires @@ -58,7 +60,7 @@ public class EurekaRibbonInitializer implements ServerListInitializer { setProp(serviceId, NIWSServerListFilterClassName.key(), ZonePreferenceServerListFilter.class.getName()); setProp(serviceId, EnableZoneAffinity.key(), "true"); - ILoadBalancer loadBalancer = ClientFactory.getNamedLoadBalancer(serviceId); + ILoadBalancer loadBalancer = clientFactory.getNamedLoadBalancer(serviceId); wrapServerList(loadBalancer); } @@ -71,6 +73,7 @@ public class EurekaRibbonInitializer implements ServerListInitializer { // This is optional: you can use the native Eureka AWS features as long as // the server zone is populated. TODO: find a way to back off if AWS // metadata *is* available. + // @see com.netflix.appinfo.AmazonInfo.Builder dynamic.setServerListImpl(new DomainExtractingServerList(list)); } } diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/eureka/RibbonEurekaAutoConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/eureka/RibbonEurekaAutoConfiguration.java index 2554c346..5ec3ce34 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/eureka/RibbonEurekaAutoConfiguration.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/eureka/RibbonEurekaAutoConfiguration.java @@ -20,6 +20,7 @@ import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration; import org.springframework.cloud.netflix.ribbon.ServerListInitializer; import org.springframework.context.annotation.Bean; @@ -40,10 +41,10 @@ import com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList; public class RibbonEurekaAutoConfiguration { @Autowired(required=false) - private EurekaClientConfig client; + private EurekaClientConfig clientConfig; @Bean - public ServerListInitializer serverListInitializer() { - return new EurekaRibbonInitializer(client); + public ServerListInitializer serverListInitializer(SpringClientFactory clientFactory) { + return new EurekaRibbonInitializer(clientConfig, clientFactory); } } diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RibbonRoutingFilter.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RibbonRoutingFilter.java index ab452ddc..716cd91c 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RibbonRoutingFilter.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RibbonRoutingFilter.java @@ -16,13 +16,13 @@ import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.actuate.trace.TraceRepository; +import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.cloud.netflix.ribbon.ServerListInitializer; import org.springframework.cloud.netflix.zuul.RibbonCommand; import org.springframework.cloud.netflix.zuul.SpringFilter; import org.springframework.util.StringUtils; import com.netflix.client.ClientException; -import com.netflix.client.ClientFactory; import com.netflix.client.http.HttpRequest.Verb; import com.netflix.client.http.HttpResponse; import com.netflix.hystrix.exception.HystrixRuntimeException; @@ -71,10 +71,9 @@ public class RibbonRoutingFilter extends SpringFilter { String serviceId = (String) context.get("serviceId"); - //TODO: should this be an interface or just config? getBean(ServerListInitializer.class).initialize(serviceId); - RestClient restClient = (RestClient) ClientFactory.getNamedClient(serviceId); + RestClient restClient = getBean(SpringClientFactory.class).namedClient(serviceId, RestClient.class); String uri = request.getRequestURI(); if (context.get("requestURI") != null) { diff --git a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/eureka/EurekaRibbonInitializerTests.java b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/eureka/EurekaRibbonInitializerTests.java index c427711e..4c336c1e 100644 --- a/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/eureka/EurekaRibbonInitializerTests.java +++ b/spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/ribbon/eureka/EurekaRibbonInitializerTests.java @@ -21,9 +21,9 @@ import static org.junit.Assert.assertTrue; import org.junit.After; import org.junit.Test; +import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.cloud.netflix.eureka.EurekaClientConfigBean; -import com.netflix.client.ClientFactory; import com.netflix.config.ConfigurationManager; import com.netflix.config.DeploymentContext.ContextKey; import com.netflix.loadbalancer.ILoadBalancer; @@ -45,10 +45,11 @@ public class EurekaRibbonInitializerTests { public void basicConfigurationCreatedForLoadBalancer() { EurekaClientConfigBean client = new EurekaClientConfigBean(); client.getAvailabilityZones().put(client.getRegion(), "foo"); - EurekaRibbonInitializer initializer = new EurekaRibbonInitializer( - client); + SpringClientFactory clientFactory = new SpringClientFactory(); + EurekaRibbonInitializer initializer = new EurekaRibbonInitializer( + client, clientFactory); initializer.initialize("service"); - ILoadBalancer balancer = ClientFactory.getNamedLoadBalancer("service"); + ILoadBalancer balancer = clientFactory.getNamedLoadBalancer("service"); assertNotNull(balancer); @SuppressWarnings("unchecked") ZoneAwareLoadBalancer aware = (ZoneAwareLoadBalancer) balancer;