Apply eclipse formatting and cleanup

This commit is contained in:
Phillip Webb
2015-01-14 13:10:41 -08:00
parent 911627c09d
commit 6a7676a93f
142 changed files with 3817 additions and 3321 deletions

View File

@@ -1,13 +1,5 @@
package org.springframework.cloud.netflix.archaius;
import static com.netflix.config.ConfigurationBasedDeploymentContext.DEPLOYMENT_APPLICATION_ID_PROPERTY;
import static com.netflix.config.ConfigurationManager.APPLICATION_PROPERTIES;
import static com.netflix.config.ConfigurationManager.DISABLE_DEFAULT_ENV_CONFIG;
import static com.netflix.config.ConfigurationManager.DISABLE_DEFAULT_SYS_CONFIG;
import static com.netflix.config.ConfigurationManager.ENV_CONFIG_NAME;
import static com.netflix.config.ConfigurationManager.SYS_CONFIG_NAME;
import static com.netflix.config.ConfigurationManager.URL_CONFIG_NAME;
import java.lang.reflect.Field;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -31,6 +23,14 @@ import com.netflix.config.ConfigurationManager;
import com.netflix.config.DynamicPropertyFactory;
import com.netflix.config.DynamicURLConfiguration;
import static com.netflix.config.ConfigurationBasedDeploymentContext.DEPLOYMENT_APPLICATION_ID_PROPERTY;
import static com.netflix.config.ConfigurationManager.APPLICATION_PROPERTIES;
import static com.netflix.config.ConfigurationManager.DISABLE_DEFAULT_ENV_CONFIG;
import static com.netflix.config.ConfigurationManager.DISABLE_DEFAULT_SYS_CONFIG;
import static com.netflix.config.ConfigurationManager.ENV_CONFIG_NAME;
import static com.netflix.config.ConfigurationManager.SYS_CONFIG_NAME;
import static com.netflix.config.ConfigurationManager.URL_CONFIG_NAME;
/**
* @author Spencer Gibb
*/
@@ -57,7 +57,7 @@ public class ArchaiusAutoConfiguration {
@Bean
public ConfigurableEnvironmentConfiguration configurableEnvironmentConfiguration() {
ConfigurableEnvironmentConfiguration envConfig = new ConfigurableEnvironmentConfiguration(
env);
this.env);
configureArchaius(envConfig);
return envConfig;
}
@@ -74,7 +74,7 @@ public class ArchaiusAutoConfiguration {
@SuppressWarnings("deprecation")
protected void configureArchaius(ConfigurableEnvironmentConfiguration envConfig) {
if (initialized.compareAndSet(false, true)) {
String appName = env.getProperty("spring.application.name");
String appName = this.env.getProperty("spring.application.name");
if (appName == null) {
appName = "application";
logger.warn("No spring.application.name found, defaulting to 'application'");

View File

@@ -26,12 +26,14 @@ import com.netflix.config.ConfigurationManager;
*
*/
public class ArchaiusDelegatingProxyUtils {
public static String APPLICATION_CONTEXT = ApplicationContext.class.getName();
public static <T> T getNamedInstance(Class<T> type, String name) {
ApplicationContext context = (ApplicationContext) ConfigurationManager.getConfigInstance().getProperty(APPLICATION_CONTEXT);
return context!=null && context.containsBean(name) ? context.getBean(name, type) : null;
ApplicationContext context = (ApplicationContext) ConfigurationManager
.getConfigInstance().getProperty(APPLICATION_CONTEXT);
return context != null && context.containsBean(name) ? context
.getBean(name, type) : null;
}
public static <T> T getInstanceWithPrefix(Class<T> type, String prefix) {
@@ -41,7 +43,7 @@ public class ArchaiusDelegatingProxyUtils {
public static void addApplicationContext(ConfigurableApplicationContext context) {
AbstractConfiguration config = ConfigurationManager.getConfigInstance();
config .clearProperty(APPLICATION_CONTEXT);
config.clearProperty(APPLICATION_CONTEXT);
config.setProperty(APPLICATION_CONTEXT, context);
}

View File

@@ -18,73 +18,74 @@ import org.springframework.core.env.StandardEnvironment;
* @author Spencer Gibb
*/
public class ConfigurableEnvironmentConfiguration extends AbstractConfiguration {
ConfigurableEnvironment environment;
ConfigurableEnvironment environment;
public ConfigurableEnvironmentConfiguration(ConfigurableEnvironment environment) {
this.environment = environment;
}
public ConfigurableEnvironmentConfiguration(ConfigurableEnvironment environment) {
this.environment = environment;
}
@Override
protected void addPropertyDirect(String key, Object value) {
@Override
protected void addPropertyDirect(String key, Object value) {
}
}
@Override
public boolean isEmpty() {
return !getKeys().hasNext(); //TODO: find a better way to do this
}
@Override
public boolean isEmpty() {
return !getKeys().hasNext(); // TODO: find a better way to do this
}
@Override
public boolean containsKey(String key) {
return environment.containsProperty(key);
}
@Override
public boolean containsKey(String key) {
return this.environment.containsProperty(key);
}
@Override
public Object getProperty(String key) {
return environment.getProperty(key);
}
@Override
public Object getProperty(String key) {
return this.environment.getProperty(key);
}
@Override
public Iterator<String> getKeys() {
List<String> result = new ArrayList<>();
for (Map.Entry<String, PropertySource<?>> entry : getPropertySources().entrySet()) {
PropertySource<?> source = entry.getValue();
if (source instanceof EnumerablePropertySource) {
EnumerablePropertySource<?> enumerable = (EnumerablePropertySource<?>) source;
for (String name : enumerable.getPropertyNames()) {
result.add(name);
}
}
}
return result.iterator();
}
@Override
public Iterator<String> getKeys() {
List<String> result = new ArrayList<>();
for (Map.Entry<String, PropertySource<?>> entry : getPropertySources().entrySet()) {
PropertySource<?> source = entry.getValue();
if (source instanceof EnumerablePropertySource) {
EnumerablePropertySource<?> enumerable = (EnumerablePropertySource<?>) source;
for (String name : enumerable.getPropertyNames()) {
result.add(name);
}
}
}
return result.iterator();
}
private Map<String, PropertySource<?>> getPropertySources() {
Map<String, PropertySource<?>> map = new LinkedHashMap<>();
MutablePropertySources sources;
if (this.environment != null
&& this.environment instanceof ConfigurableEnvironment) {
sources = this.environment.getPropertySources();
}
else {
sources = new StandardEnvironment().getPropertySources();
}
for (PropertySource<?> source : sources) {
extract("", map, source);
}
return map;
}
private Map<String, PropertySource<?>> getPropertySources() {
Map<String, PropertySource<?>> map = new LinkedHashMap<>();
MutablePropertySources sources;
if (this.environment != null
&& this.environment instanceof ConfigurableEnvironment) {
sources = this.environment.getPropertySources();
}
else {
sources = new StandardEnvironment().getPropertySources();
}
for (PropertySource<?> source : sources) {
extract("", map, source);
}
return map;
}
private void extract(String root, Map<String, PropertySource<?>> map,
PropertySource<?> source) {
if (source instanceof CompositePropertySource) {
for (PropertySource<?> nest : ((CompositePropertySource) source).getPropertySources()) {
extract(source.getName() + ":", map, nest);
}
}
else {
map.put(root + source.getName(), source);
}
}
private void extract(String root, Map<String, PropertySource<?>> map,
PropertySource<?> source) {
if (source instanceof CompositePropertySource) {
for (PropertySource<?> nest : ((CompositePropertySource) source)
.getPropertySources()) {
extract(source.getName() + ":", map, nest);
}
}
else {
map.put(root + source.getName(), source);
}
}
}

View File

@@ -37,7 +37,7 @@ import com.netflix.discovery.DiscoveryClient;
/**
* Bootstrap configuration for a config client that wants to lookup the config server via
* discovery.
*
*
* @author Dave Syer
*
*/
@@ -65,24 +65,24 @@ public class DiscoveryClientConfigServiceBootstrapConfiguration implements
log.info("Environment is not ConfigurableEnvironment so cannot look up configserver");
return;
}
InstanceInfo server = client.getNextServerFromEureka(config.getDiscovery()
.getServiceId(), false);
InstanceInfo server = this.client.getNextServerFromEureka(this.config
.getDiscovery().getServiceId(), false);
String url = server.getHomePageUrl();
if (server.getMetadata().containsKey("password")) {
String user = server.getMetadata().get("user");
user = user == null ? "user" : user;
config.setUsername(user);
this.config.setUsername(user);
String password = server.getMetadata().get("password");
config.setPassword(password);
this.config.setPassword(password);
}
if (server.getMetadata().containsKey("configPath")) {
String path = server.getMetadata().get("configPath");
if (url.endsWith("/") && path.startsWith("/")) {
url = url.substring(0, url.length()-1);
url = url.substring(0, url.length() - 1);
}
url = url + path;
}
config.setUri(url);
this.config.setUri(url);
}
catch (Exception e) {
log.warn("Could not locate configserver via discovery", e);

View File

@@ -34,24 +34,25 @@ import com.netflix.discovery.DiscoveryClient;
*/
@Configuration
@EnableConfigurationProperties
@ConditionalOnClass({EurekaInstanceConfigBean.class, DiscoveryClient.class, ConfigServerProperties.class})
@ConditionalOnClass({ EurekaInstanceConfigBean.class, DiscoveryClient.class,
ConfigServerProperties.class })
public class EurekaClientConfigServerAutoConfiguration {
@Autowired(required=false)
@Autowired(required = false)
private EurekaInstanceConfigBean instance;
@Autowired(required=false)
@Autowired(required = false)
private ConfigServerProperties server;
@PostConstruct
public void init() {
if (instance==null || server==null) {
if (this.instance == null || this.server == null) {
return;
}
String prefix = server.getPrefix();
String prefix = this.server.getPrefix();
if (StringUtils.hasText(prefix)) {
instance.getMetadataMap().put("configPath", prefix);
this.instance.getMetadataMap().put("configPath", prefix);
}
}
}

View File

@@ -1,5 +1,9 @@
package org.springframework.cloud.netflix.endpoint;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.actuate.endpoint.Endpoint;
@@ -11,66 +15,61 @@ import org.springframework.web.context.ServletContextAware;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.ServletWrappingController;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* TODO: move to spring-boot?
* User: spencergibb
* Date: 4/24/14
* Time: 9:13 PM
* TODO: move to spring-boot? User: spencergibb Date: 4/24/14 Time: 9:13 PM
*/
public abstract class ServletWrappingEndpoint implements InitializingBean,
ApplicationContextAware, ServletContextAware, MvcEndpoint {
ApplicationContextAware, ServletContextAware, MvcEndpoint {
protected String path;
protected boolean sensitive;
protected boolean enabled = true;
protected String path;
protected boolean sensitive;
protected boolean enabled = true;
protected final ServletWrappingController controller = new ServletWrappingController();
protected final ServletWrappingController controller = new ServletWrappingController();
@Override
public void afterPropertiesSet() throws Exception {
this.controller.afterPropertiesSet();
}
@Override
public void afterPropertiesSet() throws Exception {
this.controller.afterPropertiesSet();
}
@Override
public void setServletContext(ServletContext servletContext) {
this.controller.setServletContext(servletContext);
}
@Override
public void setServletContext(ServletContext servletContext) {
this.controller.setServletContext(servletContext);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.controller.setApplicationContext(applicationContext);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.controller.setApplicationContext(applicationContext);
}
protected ServletWrappingEndpoint(Class<?> servletClass, String servletName, String path,
boolean sensitive, boolean enabled) {
controller.setServletClass(servletClass);
controller.setServletName(servletName);
this.path = path;
this.sensitive = sensitive;
this.enabled = enabled;
}
protected ServletWrappingEndpoint(Class<?> servletClass, String servletName,
String path, boolean sensitive, boolean enabled) {
this.controller.setServletClass(servletClass);
this.controller.setServletName(servletName);
this.path = path;
this.sensitive = sensitive;
this.enabled = enabled;
}
@RequestMapping("**")
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response) throws Exception {
return this.controller.handleRequest(request, response);
}
@RequestMapping("**")
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response)
throws Exception {
return this.controller.handleRequest(request, response);
}
@Override
public String getPath() {
return path;
}
@Override
public String getPath() {
return this.path;
}
@Override
public boolean isSensitive() {
return sensitive;
}
@Override
public boolean isSensitive() {
return this.sensitive;
}
@Override
public Class<? extends Endpoint<?>> getEndpointType() {
return null;
}
@Override
public Class<? extends Endpoint<?>> getEndpointType() {
return null;
}
}

View File

@@ -15,6 +15,14 @@
*/
package org.springframework.cloud.netflix.eureka;
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.cloud.client.discovery.DiscoveryHeartbeatEvent;
import org.springframework.context.ApplicationContext;
import com.netflix.appinfo.DataCenterInfo;
import com.netflix.appinfo.DataCenterInfo.Name;
import com.netflix.appinfo.InstanceInfo;
@@ -23,17 +31,15 @@ import com.netflix.discovery.converters.Converters.ApplicationsConverter;
import com.netflix.discovery.converters.Converters.InstanceInfoConverter;
import com.netflix.discovery.shared.Applications;
import com.thoughtworks.xstream.MarshallingStrategy;
import com.thoughtworks.xstream.converters.*;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.ConverterLookup;
import com.thoughtworks.xstream.converters.DataHolder;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.core.TreeMarshallingStrategy;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.mapper.Mapper;
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.cloud.client.discovery.DiscoveryHeartbeatEvent;
import org.springframework.context.ApplicationContext;
/**
* A special purpose wrapper for an XStream TreeMarshallingStrategy that is aware of the
@@ -44,7 +50,7 @@ import org.springframework.context.ApplicationContext;
* is useful when not running Eureka in bare EC2 VMs, so the EC2 metadata is not available
* for uniquely identifying the InstanceInfo (the default is to just use the hostname, but
* that isn't very useful when sitting behind a proxy).
*
*
* @author Dave Syer
*
*/
@@ -60,15 +66,17 @@ public class DataCenterAwareMarshallingStrategy implements MarshallingStrategy {
@Override
public Object unmarshal(Object root, HierarchicalStreamReader reader,
DataHolder dataHolder, ConverterLookup converterLookup, Mapper mapper) {
ConverterLookup wrapped = new DataCenterAwareConverterLookup(converterLookup, context);
return delegate.unmarshal(root, reader, dataHolder, wrapped, mapper);
ConverterLookup wrapped = new DataCenterAwareConverterLookup(converterLookup,
this.context);
return this.delegate.unmarshal(root, reader, dataHolder, wrapped, mapper);
}
@Override
public void marshal(HierarchicalStreamWriter writer, Object obj,
ConverterLookup converterLookup, Mapper mapper, DataHolder dataHolder) {
ConverterLookup wrapped = new DataCenterAwareConverterLookup(converterLookup, context);
delegate.marshal(writer, obj, wrapped, mapper, dataHolder);
ConverterLookup wrapped = new DataCenterAwareConverterLookup(converterLookup,
this.context);
this.delegate.marshal(writer, obj, wrapped, mapper, dataHolder);
}
public static class InstanceIdDataCenterInfo implements DataCenterInfo,
@@ -87,7 +95,7 @@ public class DataCenterAwareMarshallingStrategy implements MarshallingStrategy {
@Override
public String getId() {
return instanceId;
return this.instanceId;
}
}
@@ -97,18 +105,20 @@ public class DataCenterAwareMarshallingStrategy implements MarshallingStrategy {
private ConverterLookup delegate;
private ApplicationContext context;
public DataCenterAwareConverterLookup(ConverterLookup delegate, ApplicationContext context) {
public DataCenterAwareConverterLookup(ConverterLookup delegate,
ApplicationContext context) {
this.delegate = delegate;
this.context = context;
}
@Override
public Converter lookupConverterForType(@SuppressWarnings("rawtypes") Class type) {
Converter converter = delegate.lookupConverterForType(type);
Converter converter = this.delegate.lookupConverterForType(type);
if (InstanceInfo.class == type) {
return new DataCenterAwareConverter();
} else if (Applications.class == type) {
return new PublishingApplicationsConverter(context);
}
else if (Applications.class == type) {
return new PublishingApplicationsConverter(this.context);
}
return converter;
}
@@ -124,7 +134,8 @@ public class DataCenterAwareMarshallingStrategy implements MarshallingStrategy {
}
@Override
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext unmarshallingContext) {
public Object unmarshal(HierarchicalStreamReader reader,
UnmarshallingContext unmarshallingContext) {
Object obj = super.unmarshal(reader, unmarshallingContext);
ProxyFactory factory = new ProxyFactory(obj);
@@ -147,14 +158,15 @@ public class DataCenterAwareMarshallingStrategy implements MarshallingStrategy {
if ("setVersion".equals(invocation.getMethod().getName())) {
Long version = Long.class.cast(invocation.getArguments()[0]);
log.debug("Applications.setVersion() called with version: " + version);
context.publishEvent(new DiscoveryHeartbeatEvent(invocation.getThis(), version));
this.context.publishEvent(new DiscoveryHeartbeatEvent(invocation
.getThis(), version));
}
return ret;
}
}
private static class DataCenterAwareConverter extends InstanceInfoConverter {
@Override
public void marshal(Object source, HierarchicalStreamWriter writer,
MarshallingContext context) {

View File

@@ -11,16 +11,16 @@ import com.netflix.discovery.EurekaClientConfig;
*/
public class DiscoveryManagerInitializer {
@Autowired
private EurekaClientConfig clientConfig;
@Autowired
private EurekaClientConfig clientConfig;
@Autowired
private EurekaInstanceConfig instanceConfig;
@Autowired
private EurekaInstanceConfig instanceConfig;
public synchronized void init() {
if (DiscoveryManager.getInstance().getDiscoveryClient() == null) {
DiscoveryManager.getInstance().initComponent(instanceConfig, clientConfig);
}
}
public synchronized void init() {
if (DiscoveryManager.getInstance().getDiscoveryClient() == null) {
DiscoveryManager.getInstance().initComponent(this.instanceConfig,
this.clientConfig);
}
}
}

View File

@@ -19,7 +19,7 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
* it is Eureka you want. All it does is turn on discovery and let the autoconfiguration
* find the eureka classes if they are available (i.e. you need Eureka on the classpath as
* well).
*
*
* @author Dave Syer
*
*/

View File

@@ -47,9 +47,9 @@ public class EurekaClientAutoConfiguration {
@PostConstruct
public void init() {
XmlXStream.getInstance().setMarshallingStrategy(
new DataCenterAwareMarshallingStrategy(context));
new DataCenterAwareMarshallingStrategy(this.context));
JsonXStream.getInstance().setMarshallingStrategy(
new DataCenterAwareMarshallingStrategy(context));
new DataCenterAwareMarshallingStrategy(this.context));
}
@Bean
@@ -64,5 +64,4 @@ public class EurekaClientAutoConfiguration {
return new EurekaInstanceConfigBean();
}
}

View File

@@ -35,12 +35,13 @@ import com.netflix.discovery.EurekaClientConfig;
@ConfigurationProperties("eureka.client")
public class EurekaClientConfigBean implements EurekaClientConfig {
public static final String DEFAULT_URL = "http://localhost:8761" + EurekaServerConfigBean.DEFAULT_PREFIX + "/";
public static final String DEFAULT_URL = "http://localhost:8761"
+ EurekaServerConfigBean.DEFAULT_PREFIX + "/";
public static final String DEFAULT_ZONE = "defaultZone";
private static final int MINUTES = 60;
private boolean enabled = true;
private int registryFetchIntervalSeconds = 30;
@@ -55,9 +56,9 @@ public class EurekaClientConfigBean implements EurekaClientConfig {
private String proxyHost;
private String proxyUserName;
private String proxyUserName;
private String proxyPassword;
private String proxyPassword;
private int eurekaServerReadTimeoutSeconds = 8;
@@ -83,16 +84,16 @@ public class EurekaClientConfigBean implements EurekaClientConfig {
private int heartbeatExecutorThreadPoolSize = 2;
private int heartbeatExecutorExponentialBackOffBound = 10;
private int heartbeatExecutorExponentialBackOffBound = 10;
private int cacheRefreshExecutorThreadPoolSize = 2;
private int cacheRefreshExecutorExponentialBackOffBound = 10;
private int cacheRefreshExecutorExponentialBackOffBound = 10;
private Map<String, String> serviceUrl = new HashMap<String, String>();
private Map<String,String> serviceUrl = new HashMap<String, String>();
{
serviceUrl.put(DEFAULT_ZONE, DEFAULT_URL);
this.serviceUrl.put(DEFAULT_ZONE, DEFAULT_URL);
}
private boolean gZipContent = true;
@@ -117,43 +118,43 @@ public class EurekaClientConfigBean implements EurekaClientConfig {
@Override
public boolean shouldGZipContent() {
return gZipContent;
return this.gZipContent;
}
@Override
public boolean shouldUseDnsForFetchingServiceUrls() {
return useDnsForFetchingServiceUrls;
return this.useDnsForFetchingServiceUrls;
}
@Override
public boolean shouldRegisterWithEureka() {
return registerWithEureka;
return this.registerWithEureka;
}
@Override
public boolean shouldPreferSameZoneEureka() {
return preferSameZoneEureka;
return this.preferSameZoneEureka;
}
@Override
public boolean shouldLogDeltaDiff() {
return logDeltaDiff;
return this.logDeltaDiff;
}
@Override
public boolean shouldDisableDelta() {
return disableDelta;
return this.disableDelta;
}
@Override
public String fetchRegistryForRemoteRegions() {
return fetchRemoteRegionsRegistry;
return this.fetchRemoteRegionsRegistry;
}
@Override
public String[] getAvailabilityZones(String region) {
String value = availabilityZones.get(region);
if (value==null) {
String value = this.availabilityZones.get(region);
if (value == null) {
value = DEFAULT_ZONE;
}
return value.split(",");
@@ -161,25 +162,25 @@ public class EurekaClientConfigBean implements EurekaClientConfig {
@Override
public List<String> getEurekaServerServiceUrls(String myZone) {
String serviceUrls = serviceUrl.get(myZone);
if (serviceUrls == null || serviceUrls.isEmpty()) {
serviceUrls = serviceUrl.get(DEFAULT_ZONE);
}
if (serviceUrls != null) {
return Arrays.asList(serviceUrls.split(","));
}
String serviceUrls = this.serviceUrl.get(myZone);
if (serviceUrls == null || serviceUrls.isEmpty()) {
serviceUrls = this.serviceUrl.get(DEFAULT_ZONE);
}
if (serviceUrls != null) {
return Arrays.asList(serviceUrls.split(","));
}
return new ArrayList<>();
return new ArrayList<>();
}
@Override
public boolean shouldFilterOnlyUpInstances() {
return filterOnlyUpInstances;
return this.filterOnlyUpInstances;
}
@Override
public boolean shouldFetchRegistry() {
return fetchRegistry;
return this.fetchRegistry;
}
}

View File

@@ -1,20 +1,24 @@
package org.springframework.cloud.netflix.eureka;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import com.google.common.base.Function;
import com.google.common.base.Predicates;
import com.google.common.collect.Lists;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.shared.Application;
import com.netflix.discovery.shared.Applications;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.List;
import static com.google.common.collect.Iterables.*;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.transform;
/**
* @author Spencer Gibb
@@ -24,10 +28,10 @@ public class EurekaDiscoveryClient implements DiscoveryClient {
public static final String DESCRIPTION = "Spring Cloud Eureka Discovery Client";
@Autowired
private EurekaInstanceConfigBean config;
private EurekaInstanceConfigBean config;
@Autowired
private com.netflix.discovery.DiscoveryClient discovery;
@Autowired
private com.netflix.discovery.DiscoveryClient discovery;
@Override
public String description() {
@@ -35,96 +39,103 @@ public class EurekaDiscoveryClient implements DiscoveryClient {
}
@Override
public ServiceInstance getLocalServiceInstance() {
return new ServiceInstance() {
@Override
public String getServiceId() {
return config.getAppname();
}
public ServiceInstance getLocalServiceInstance() {
return new ServiceInstance() {
@Override
public String getServiceId() {
return EurekaDiscoveryClient.this.config.getAppname();
}
@Override
public String getHost() {
return config.getHostname();
}
@Override
public String getHost() {
return EurekaDiscoveryClient.this.config.getHostname();
}
@Override
public int getPort() {
return config.getNonSecurePort();
}
};
}
@Override
public int getPort() {
return EurekaDiscoveryClient.this.config.getNonSecurePort();
}
};
}
@Override
public List<ServiceInstance> getInstances(String serviceId) {
List<InstanceInfo> infos = discovery.getInstancesByVipAddress(serviceId, false);
Iterable<ServiceInstance> instances = transform(infos, new Function<InstanceInfo, ServiceInstance>() {
@Nullable
@Override
public ServiceInstance apply(@Nullable InstanceInfo info) {
return new EurekaServiceInstance(info);
}
});
return Lists.newArrayList(instances);
}
@Override
public List<ServiceInstance> getInstances(String serviceId) {
List<InstanceInfo> infos = this.discovery.getInstancesByVipAddress(serviceId,
false);
Iterable<ServiceInstance> instances = transform(infos,
new Function<InstanceInfo, ServiceInstance>() {
@Nullable
@Override
public ServiceInstance apply(@Nullable InstanceInfo info) {
return new EurekaServiceInstance(info);
}
});
return Lists.newArrayList(instances);
}
static class EurekaServiceInstance implements ServiceInstance {
InstanceInfo instance;
static class EurekaServiceInstance implements ServiceInstance {
InstanceInfo instance;
EurekaServiceInstance(InstanceInfo instance) {
this.instance = instance;
}
EurekaServiceInstance(InstanceInfo instance) {
this.instance = instance;
}
@Override
public String getServiceId() {
return instance.getAppName();
}
@Override
public String getServiceId() {
return this.instance.getAppName();
}
@Override
public String getHost() {
return instance.getHostName();
}
@Override
public String getHost() {
return this.instance.getHostName();
}
@Override
public int getPort() {
return instance.getPort();
}
}
@Override
public int getPort() {
return this.instance.getPort();
}
}
@Override
public List<String> getServices() {
Applications applications = discovery.getApplications();
if (applications == null) {
return Collections.emptyList();
}
return Lists.newArrayList(filter(transform(applications.getRegisteredApplications(), new Function<Application, String>() {
@Nullable
@Override
public String apply(@Nullable Application app) {
if (app.getInstances().isEmpty()) {
return null;
}
return app.getName().toLowerCase();
}
}), Predicates.notNull()));
}
@Override
public List<String> getServices() {
Applications applications = this.discovery.getApplications();
if (applications == null) {
return Collections.emptyList();
}
return Lists.newArrayList(filter(
transform(applications.getRegisteredApplications(),
new Function<Application, String>() {
@Nullable
@Override
public String apply(@Nullable Application app) {
if (app.getInstances().isEmpty()) {
return null;
}
return app.getName().toLowerCase();
}
}), Predicates.notNull()));
}
@Override
public List<ServiceInstance> getAllInstances() {
Applications applications = discovery.getApplications();
if (applications == null) {
return Collections.emptyList();
}
Iterable<ServiceInstance> instances = transform(concat(transform(applications.getRegisteredApplications(), new Function<Application, List<InstanceInfo>>() {
public List<InstanceInfo> apply(@Nullable Application app) {
return app.getInstances();
}
})), new Function<InstanceInfo, ServiceInstance>() {
@Nullable
@Override
public ServiceInstance apply(@Nullable InstanceInfo info) {
return new EurekaServiceInstance(info);
}
});
return Lists.newArrayList(instances);
}
@Override
public List<ServiceInstance> getAllInstances() {
Applications applications = this.discovery.getApplications();
if (applications == null) {
return Collections.emptyList();
}
Iterable<ServiceInstance> instances = transform(
concat(transform(applications.getRegisteredApplications(),
new Function<Application, List<InstanceInfo>>() {
@Override
public List<InstanceInfo> apply(@Nullable Application app) {
return app.getInstances();
}
})), new Function<InstanceInfo, ServiceInstance>() {
@Nullable
@Override
public ServiceInstance apply(@Nullable InstanceInfo info) {
return new EurekaServiceInstance(info);
}
});
return Lists.newArrayList(instances);
}
}

View File

@@ -84,7 +84,8 @@ public class EurekaDiscoveryClientConfiguration implements SmartLifecycle, Order
@PreDestroy
public void close() {
closeDiscoveryClientJersey();
logger.info("Removing application {} from eureka", instanceConfig.getAppname());
logger.info("Removing application {} from eureka",
this.instanceConfig.getAppname());
DiscoveryManager.getInstance().shutdownComponent();
}
@@ -112,25 +113,27 @@ public class EurekaDiscoveryClientConfiguration implements SmartLifecycle, Order
@Override
public void start() {
// only set the port if the nonSecurePort is 0 and this.port != 0
if (port.get() != 0 && instanceConfig.getNonSecurePort() == 0) {
instanceConfig.setNonSecurePort(port.get());
if (this.port.get() != 0 && this.instanceConfig.getNonSecurePort() == 0) {
this.instanceConfig.setNonSecurePort(this.port.get());
}
// only initialize if nonSecurePort is greater than 0 and it isn't already running
// because of containerPortInitializer below
if (!running.get() && instanceConfig.getNonSecurePort() > 0) {
if (!this.running.get() && this.instanceConfig.getNonSecurePort() > 0) {
discoveryManagerIntitializer().init();
logger.info("Registering application {} with eureka with status {}",
instanceConfig.getAppname(), instanceConfig.getInitialStatus());
this.instanceConfig.getAppname(),
this.instanceConfig.getInitialStatus());
ApplicationInfoManager.getInstance().setInstanceStatus(
instanceConfig.getInitialStatus());
this.instanceConfig.getInitialStatus());
if (healthCheckHandler != null) {
if (this.healthCheckHandler != null) {
DiscoveryManager.getInstance().getDiscoveryClient()
.registerHealthCheck(healthCheckHandler);
.registerHealthCheck(this.healthCheckHandler);
}
context.publishEvent(new InstanceRegisteredEvent<>(this, instanceConfig));
running.set(true);
this.context.publishEvent(new InstanceRegisteredEvent<>(this,
this.instanceConfig));
this.running.set(true);
}
}
@@ -138,15 +141,15 @@ public class EurekaDiscoveryClientConfiguration implements SmartLifecycle, Order
public void stop() {
logger.info(
"Unregistering application {} with eureka with status OUT_OF_SERVICE",
instanceConfig.getAppname());
this.instanceConfig.getAppname());
ApplicationInfoManager.getInstance().setInstanceStatus(
InstanceStatus.OUT_OF_SERVICE);
running.set(false);
this.running.set(false);
}
@Override
public boolean isRunning() {
return running.get();
return this.running.get();
}
@Override
@@ -166,7 +169,7 @@ public class EurekaDiscoveryClientConfiguration implements SmartLifecycle, Order
@Override
public int getOrder() {
return order;
return this.order;
}
@Bean

View File

@@ -24,12 +24,12 @@ import org.springframework.boot.actuate.health.Health.Builder;
import org.springframework.boot.actuate.health.Status;
import org.springframework.boot.actuate.metrics.Metric;
import org.springframework.boot.actuate.metrics.reader.MetricReader;
import org.springframework.cloud.client.discovery.DiscoveryHealthIndicator;
import com.netflix.appinfo.EurekaInstanceConfig;
import com.netflix.discovery.DiscoveryClient;
import com.netflix.discovery.shared.Application;
import com.netflix.discovery.shared.Applications;
import org.springframework.cloud.client.discovery.DiscoveryHealthIndicator;
/**
* @author Dave Syer
@@ -67,28 +67,29 @@ public class EurekaHealthIndicator implements DiscoveryHealthIndicator {
}
private Status getStatus(Builder builder) {
Status status = new Status(discovery.getInstanceRemoteStatus().toString(),
Status status = new Status(this.discovery.getInstanceRemoteStatus().toString(),
"Remote status from Eureka server");
@SuppressWarnings("unchecked")
Metric<Number> value = (Metric<Number>) metrics
Metric<Number> value = (Metric<Number>) this.metrics
.findOne("counter.servo.discoveryclient_failed");
if (value != null) {
int renewalPeriod = instanceConfig.getLeaseRenewalIntervalInSeconds();
int renewalPeriod = this.instanceConfig.getLeaseRenewalIntervalInSeconds();
int latest = value.getValue().intValue();
builder.withDetail("failCount", latest);
builder.withDetail("renewalPeriod", renewalPeriod);
if (failCount < latest) {
if (this.failCount < latest) {
status = new Status("UP", "Eureka discovery client is reporting failures");
failCount = latest;
} else {
status = new Status("UP", "No new failures in Eureka discovery client");
this.failCount = latest;
}
else {
status = new Status("UP", "No new failures in Eureka discovery client");
}
}
return status;
}
private Map<String, Object> getApplications() {
Applications applications = discovery.getApplications();
Applications applications = this.discovery.getApplications();
if (applications == null) {
return Collections.emptyMap();
}

View File

@@ -42,99 +42,104 @@ import com.netflix.appinfo.UniqueIdentifier;
@Data
@ConfigurationProperties("eureka.instance")
public class EurekaInstanceConfigBean implements EurekaInstanceConfig {
private static final Log logger = LogFactory.getLog(EurekaInstanceConfigBean.class);
@Getter(AccessLevel.PRIVATE) @Setter(AccessLevel.PRIVATE)
@Getter(AccessLevel.PRIVATE)
@Setter(AccessLevel.PRIVATE)
private String[] hostInfo = initHostInfo();
@Value("${spring.application.name:unknown}")
private String appname = "unknown";
private String appname = "unknown";
private String appGroupName;
private boolean instanceEnabledOnit;
private String appGroupName;
private boolean instanceEnabledOnit;
@Value("${server.port:${SERVER_PORT:${PORT:8080}}}")
private int nonSecurePort = 80;
private int nonSecurePort = 80;
private int securePort = 443;
private int securePort = 443;
private boolean nonSecurePortEnabled = true;
private boolean nonSecurePortEnabled = true;
private boolean securePortEnabled;
private boolean securePortEnabled;
private int leaseRenewalIntervalInSeconds = 30;
private int leaseRenewalIntervalInSeconds = 30;
private int leaseExpirationDurationInSeconds = 90;
private int leaseExpirationDurationInSeconds = 90;
@Value("${spring.application.name:unknown}")
private String virtualHostName;
private String virtualHostName;
private String secureVirtualHostName;
private String secureVirtualHostName;
private String aSGName;
private String aSGName;
private Map<String, String> metadataMap = new HashMap<>();
private Map<String, String> metadataMap = new HashMap<>();
private DataCenterInfo dataCenterInfo = new IdentifyingDataCenterInfo();
private DataCenterInfo dataCenterInfo = new IdentifyingDataCenterInfo();
private String ipAddress = hostInfo[0];
private String ipAddress = this.hostInfo[0];
private String statusPageUrlPath = "/info";
private String statusPageUrlPath = "/info";
private String statusPageUrl;
private String statusPageUrl;
private String homePageUrlPath = "/";
private String homePageUrlPath = "/";
private String homePageUrl;
private String homePageUrl;
private String healthCheckUrlPath = "/health";
private String healthCheckUrlPath = "/health";
private String healthCheckUrl;
private String healthCheckUrl;
private String secureHealthCheckUrl;
private String secureHealthCheckUrl;
private String namespace = "eureka";
private String namespace = "eureka";
private String hostname = this.hostInfo[1];
private String hostname = hostInfo[1];
private boolean preferIpAddress = false;
private InstanceStatus initialStatus = InstanceStatus.UP;
private InstanceStatus initialStatus = InstanceStatus.UP;
public String getHostname() {
return preferIpAddress ? ipAddress : hostname;
return this.preferIpAddress ? this.ipAddress : this.hostname;
}
@Override
public boolean getSecurePortEnabled() {
return securePortEnabled;
return this.securePortEnabled;
}
private String[] initHostInfo() {
String[] info = new String[2];
try {
info[0] = InetAddress.getLocalHost().getHostAddress();
info[1] = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
logger.error("Cannot get host info", e);
}
return info ;
info[1] = InetAddress.getLocalHost().getHostName();
}
catch (UnknownHostException e) {
logger.error("Cannot get host info", e);
}
return info;
}
@Override
public String getHostName(boolean refresh) {
return preferIpAddress ? ipAddress : hostname;
return this.preferIpAddress ? this.ipAddress : this.hostname;
}
private final class IdentifyingDataCenterInfo implements DataCenterInfo, UniqueIdentifier {
@Getter @Setter
private Name name = Name.MyOwn;
private final class IdentifyingDataCenterInfo implements DataCenterInfo,
UniqueIdentifier {
@Getter
@Setter
private Name name = Name.MyOwn;
@Override
public String getId() {
String instanceId = metadataMap.get("instanceId");
String instanceId = EurekaInstanceConfigBean.this.metadataMap
.get("instanceId");
if (instanceId != null) {
String old = getHostname();
String id = old.endsWith(instanceId) ? old : old + ":" + instanceId;
@@ -142,7 +147,7 @@ public class EurekaInstanceConfigBean implements EurekaInstanceConfig {
}
return getHostname();
}
}
}

View File

@@ -20,10 +20,10 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.springframework.boot.context.properties.ConfigurationProperties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import com.netflix.eureka.EurekaServerConfig;
/**
@@ -46,10 +46,11 @@ public class EurekaServerConfigBean implements EurekaServerConfig {
private int eIPBindingRetryIntervalMs = 5 * MINUTES;
private boolean enableSelfPreservation = true;
private boolean enableSelfPreservation = true;
@Override
public boolean shouldEnableSelfPreservation() {
return enableSelfPreservation;
return this.enableSelfPreservation;
}
private double renewalPercentThreshold = 0.85;
@@ -88,10 +89,11 @@ public class EurekaServerConfigBean implements EurekaServerConfig {
private long responseCacheUpdateIntervalMs = 30 * 1000;
private boolean disableDelta;
private boolean disableDelta;
@Override
public boolean shouldDisableDelta() {
return disableDelta;
return this.disableDelta;
}
private long maxIdleThreadInMinutesAgeForStatusReplication = 10;
@@ -102,10 +104,11 @@ public class EurekaServerConfigBean implements EurekaServerConfig {
private int maxElementsInStatusReplicationPool = 10000;
private boolean syncWhenTimestampDiffers = true;
private boolean syncWhenTimestampDiffers = true;
@Override
public boolean shouldSyncWhenTimestampDiffers() {
return syncWhenTimestampDiffers;
return this.syncWhenTimestampDiffers;
}
private int registrySyncRetries = 5;
@@ -120,16 +123,18 @@ public class EurekaServerConfigBean implements EurekaServerConfig {
private int maxTimeForReplication = 30000;
private boolean primeAwsReplicaConnections = true;
private boolean primeAwsReplicaConnections = true;
@Override
public boolean shouldPrimeAwsReplicaConnections() {
return primeAwsReplicaConnections;
return this.primeAwsReplicaConnections;
}
private boolean disableDeltaForRemoteRegions;
private boolean disableDeltaForRemoteRegions;
@Override
public boolean shouldDisableDeltaForRemoteRegions() {
return disableDeltaForRemoteRegions;
return this.disableDeltaForRemoteRegions;
}
private int remoteRegionConnectTimeoutMs = 1000;
@@ -142,25 +147,28 @@ public class EurekaServerConfigBean implements EurekaServerConfig {
private int remoteRegionConnectionIdleTimeoutSeconds = 30;
private boolean gZipContentFromRemoteRegion = true;
private boolean gZipContentFromRemoteRegion = true;
@Override
public boolean shouldGZipContentFromRemoteRegion() {
return gZipContentFromRemoteRegion;
return this.gZipContentFromRemoteRegion;
}
private Map<String, String> remoteRegionUrlsWithName = new HashMap<String, String>();
private String[] remoteRegionUrls;
private String[] remoteRegionUrls;
private Map<String, Set<String>> remoteRegionAppWhitelist;
@Override
@Override
public Set<String> getRemoteRegionAppWhitelist(String regionName) {
if (null == regionName) {
regionName = "global";
} else {
regionName = regionName.trim().toLowerCase();
}
return remoteRegionAppWhitelist.get(regionName);
if (null == regionName) {
regionName = "global";
}
else {
regionName = regionName.trim().toLowerCase();
}
return this.remoteRegionAppWhitelist.get(regionName);
}
private int remoteRegionRegistryFetchInterval = 30;
@@ -170,34 +178,35 @@ public class EurekaServerConfigBean implements EurekaServerConfig {
private String remoteRegionTrustStorePassword = "changeit";
private boolean disableTransparentFallbackToOtherRegion;
@Override
public boolean disableTransparentFallbackToOtherRegion() {
return disableTransparentFallbackToOtherRegion;
return this.disableTransparentFallbackToOtherRegion;
}
private boolean batchReplication;
private boolean batchReplication;
@Override
public boolean shouldBatchReplication() {
return batchReplication;
return this.batchReplication;
}
private boolean logIdentityHeaders = true;
private boolean logIdentityHeaders = true;
@Override
public boolean shouldLogIdentityHeaders() {
return logIdentityHeaders;
}
@Override
public boolean shouldLogIdentityHeaders() {
return this.logIdentityHeaders;
}
private boolean rateLimiterEnabled = false;
private boolean rateLimiterEnabled = false;
private boolean rateLimiterThrottleStandardClients = false;
private boolean rateLimiterThrottleStandardClients = false;
private Set<String> rateLimiterPrivilegedClients = Collections.emptySet();
private Set<String> rateLimiterPrivilegedClients = Collections.emptySet();
private int rateLimiterBurstSize = 10;
private int rateLimiterBurstSize = 10;
private int rateLimiterRegistryFetchAverageRate = 500;
private int rateLimiterRegistryFetchAverageRate = 500;
private int rateLimiterFullFetchAverageRate = 100;
private int rateLimiterFullFetchAverageRate = 100;
}

View File

@@ -1,20 +1,20 @@
package org.springframework.cloud.netflix.feign;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration;
import org.springframework.cloud.netflix.feign.ribbon.FeignRibbonClient;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.netflix.loadbalancer.ILoadBalancer;
import feign.Client;
import feign.Contract;
import feign.Feign;
import feign.Logger;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.cloud.netflix.feign.ribbon.FeignRibbonClient;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration;
import com.netflix.loadbalancer.ILoadBalancer;
/**
* @author Spencer Gibb
* @author Julien Roy

View File

@@ -1,6 +1,10 @@
package org.springframework.cloud.netflix.feign;
import java.lang.annotation.*;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author Spencer Gibb
@@ -10,9 +14,10 @@ import java.lang.annotation.*;
@Documented
public @interface FeignClient {
/**
* @return serviceId if loadbalance is true, url otherwise
* No need to prefix serviceId with http://
* @return serviceId if loadbalance is true, url otherwise No need to prefix serviceId
* with http://
*/
String value();
boolean loadbalance() default true;
}

View File

@@ -6,10 +6,10 @@ import lombok.EqualsAndHashCode;
import org.springframework.beans.factory.FactoryBean;
/**
* @author Spencer Gibb
*/
* @author Spencer Gibb
*/
@Data
@EqualsAndHashCode(callSuper=false)
@EqualsAndHashCode(callSuper = false)
class FeignClientFactoryBean extends FeignConfiguration implements FactoryBean<Object> {
private boolean loadbalance;
@@ -18,18 +18,18 @@ class FeignClientFactoryBean extends FeignConfiguration implements FactoryBean<O
@Override
public Object getObject() throws Exception {
if (!schemeName.startsWith("http")) {
schemeName = "http://"+schemeName;
if (!this.schemeName.startsWith("http")) {
this.schemeName = "http://" + this.schemeName;
}
if (loadbalance) {
return loadBalance(type, schemeName);
if (this.loadbalance) {
return loadBalance(this.type, this.schemeName);
}
return feign().target(type, schemeName);
return feign().target(this.type, this.schemeName);
}
@Override
public Class<?> getObjectType() {
return type;
return this.type;
}
@Override

View File

@@ -9,8 +9,9 @@ import java.lang.annotation.Target;
import org.springframework.context.annotation.Import;
/**
* Configures component scanning directives for use with @{@link org.springframework.context.annotation.Configuration} classes.
* Scan Spring Integration specific components.
* Configures component scanning directives for use with @
* {@link org.springframework.context.annotation.Configuration} classes. Scan Spring
* Integration specific components.
*
* @author Artem Bilan
* @since 4.0
@@ -22,9 +23,8 @@ import org.springframework.context.annotation.Import;
public @interface FeignClientScan {
/**
* Alias for the {@link #basePackages()} attribute.
* Allows for more concise annotation declarations e.g.:
* {@code @ComponentScan("org.my.pkg")} instead of
* Alias for the {@link #basePackages()} attribute. Allows for more concise annotation
* declarations e.g.: {@code @ComponentScan("org.my.pkg")} instead of
* {@code @ComponentScan(basePackages="org.my.pkg")}.
*
* @return the array of 'basePackages'.
@@ -33,18 +33,22 @@ public @interface FeignClientScan {
/**
* Base packages to scan for annotated components.
* <p>{@link #value()} is an alias for (and mutually exclusive with) this attribute.
* <p>Use {@link #basePackageClasses()} for a type-safe alternative to String-based package names.
* <p>
* {@link #value()} is an alias for (and mutually exclusive with) this attribute.
* <p>
* Use {@link #basePackageClasses()} for a type-safe alternative to String-based
* package names.
*
* @return the array of 'basePackages'.
*/
String[] basePackages() default {};
/**
* Type-safe alternative to {@link #basePackages()} for specifying the packages
* to scan for annotated components. The package of each class specified will be scanned.
* <p>Consider creating a special no-op marker class or interface in each package
* that serves no purpose other than being referenced by this attribute.
* Type-safe alternative to {@link #basePackages()} for specifying the packages to
* scan for annotated components. The package of each class specified will be scanned.
* <p>
* Consider creating a special no-op marker class or interface in each package that
* serves no purpose other than being referenced by this attribute.
*
* @return the array of 'basePackageClasses'.
*/

View File

@@ -23,11 +23,11 @@ import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/**
* @author Spencer Gibb
* patterned after Spring Integration IntegrationComponentScanRegistrar
* @author Spencer Gibb patterned after Spring Integration
* IntegrationComponentScanRegistrar
*/
public class FeignClientScanRegistrar extends FeignConfiguration
implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, BeanClassLoaderAware {
public class FeignClientScanRegistrar extends FeignConfiguration implements
ImportBeanDefinitionRegistrar, ResourceLoaderAware, BeanClassLoaderAware {
private ResourceLoader resourceLoader;
@@ -47,22 +47,25 @@ public class FeignClientScanRegistrar extends FeignConfiguration
}
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
Set<String> basePackages = getBasePackages(importingClassMetadata);
ClassPathScanningCandidateComponentProvider scanner = getScanner();
scanner.addIncludeFilter(new AnnotationTypeFilter(FeignClient.class));
scanner.setResourceLoader(resourceLoader);
scanner.setResourceLoader(this.resourceLoader);
for (String basePackage : basePackages) {
Set<BeanDefinition> candidateComponents = scanner.findCandidateComponents(basePackage);
Set<BeanDefinition> candidateComponents = scanner
.findCandidateComponents(basePackage);
for (BeanDefinition candidateComponent : candidateComponents) {
if (candidateComponent instanceof AnnotatedBeanDefinition) {
//verify annotated class is an interface
// verify annotated class is an interface
AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition) candidateComponent;
AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
Assert.isTrue(annotationMetadata.isInterface(), "@FeignClient can only be specified on an interface");
Assert.isTrue(annotationMetadata.isInterface(),
"@FeignClient can only be specified on an interface");
BeanDefinitionHolder holder = createBeanDefinition(annotationMetadata);
BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
@@ -72,42 +75,49 @@ public class FeignClientScanRegistrar extends FeignConfiguration
}
public BeanDefinitionHolder createBeanDefinition(AnnotationMetadata annotationMetadata) {
Map<String, Object> attributes = annotationMetadata.getAnnotationAttributes(FeignClient.class.getCanonicalName());
Map<String, Object> attributes = annotationMetadata
.getAnnotationAttributes(FeignClient.class.getCanonicalName());
String className = annotationMetadata.getClassName();
BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(FeignClientFactoryBean.class);
BeanDefinitionBuilder definition = BeanDefinitionBuilder
.genericBeanDefinition(FeignClientFactoryBean.class);
definition.addPropertyValue("loadbalance", attributes.get("loadbalance"));
definition.addPropertyValue("type", className);
definition.addPropertyValue("schemeName", attributes.get("value"));
String beanName = StringUtils.uncapitalize(className.substring(className.lastIndexOf(".") + 1));
String beanName = StringUtils.uncapitalize(className.substring(className
.lastIndexOf(".") + 1));
return new BeanDefinitionHolder(definition.getBeanDefinition(), beanName);
}
protected ClassPathScanningCandidateComponentProvider getScanner() {
return new ClassPathScanningCandidateComponentProvider(false) {
@Override
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
if (beanDefinition.getMetadata().isIndependent()) {
// TODO until SPR-11711 will be resolved
if (beanDefinition.getMetadata().isInterface() &&
beanDefinition.getMetadata().getInterfaceNames().length == 1 &&
Annotation.class.getName().equals(beanDefinition.getMetadata().getInterfaceNames()[0])) {
try {
Class<?> target = ClassUtils.forName(beanDefinition.getMetadata().getClassName(), classLoader);
return !target.isAnnotation();
}
catch (Exception e) {
logger.error("Could not load target class: " + beanDefinition.getMetadata().getClassName(), e);
}
@Override
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
if (beanDefinition.getMetadata().isIndependent()) {
// TODO until SPR-11711 will be resolved
if (beanDefinition.getMetadata().isInterface()
&& beanDefinition.getMetadata().getInterfaceNames().length == 1
&& Annotation.class.getName().equals(
beanDefinition.getMetadata().getInterfaceNames()[0])) {
try {
Class<?> target = ClassUtils.forName(beanDefinition
.getMetadata().getClassName(),
FeignClientScanRegistrar.this.classLoader);
return !target.isAnnotation();
}
catch (Exception e) {
this.logger.error("Could not load target class: "
+ beanDefinition.getMetadata().getClassName(), e);
}
return true;
}
return false;
return true;
}
};
return false;
}
};
}
protected Set<String> getBasePackages(AnnotationMetadata importingClassMetadata) {
@@ -130,7 +140,8 @@ public class FeignClientScanRegistrar extends FeignConfiguration
}
if (basePackages.isEmpty()) {
basePackages.add(ClassUtils.getPackageName(importingClassMetadata.getClassName()));
basePackages.add(ClassUtils.getPackageName(importingClassMetadata
.getClassName()));
}
return basePackages;
}

View File

@@ -20,20 +20,20 @@ import feign.ribbon.LoadBalancingTarget;
*/
@Configuration
public class FeignConfiguration {
@Autowired
ConfigurableEnvironmentConfiguration envConfig; //FIXME: howto enforce this?
@Autowired
ConfigurableEnvironmentConfiguration envConfig; // FIXME: howto enforce this?
@Autowired
Decoder decoder;
@Autowired
Decoder decoder;
@Autowired
Encoder encoder;
@Autowired
Encoder encoder;
@Autowired
Logger logger;
@Autowired
Logger logger;
@Autowired
Contract contract;
@Autowired
Contract contract;
@Autowired(required = false)
Logger.Level logLevel;
@@ -47,40 +47,43 @@ public class FeignConfiguration {
@Autowired(required = false)
Request.Options options;
@Autowired(required = false)
Client ribbonClient;
@Autowired(required = false)
Client ribbonClient;
protected Feign.Builder feign() {
protected Feign.Builder feign() {
Feign.Builder builder = Feign.builder()
//required values
.logger(logger)
.encoder(encoder)
.decoder(decoder)
.contract(contract);
// required values
.logger(this.logger).encoder(this.encoder).decoder(this.decoder)
.contract(this.contract);
//optional values
if (logLevel != null)
builder.logLevel(logLevel);
if (retryer != null)
builder.retryer(retryer);
if (errorDecoder != null)
builder.errorDecoder(errorDecoder);
if (options != null)
builder.options(options);
// optional values
if (this.logLevel != null) {
builder.logLevel(this.logLevel);
}
if (this.retryer != null) {
builder.retryer(this.retryer);
}
if (this.errorDecoder != null) {
builder.errorDecoder(this.errorDecoder);
}
if (this.options != null) {
builder.options(this.options);
}
return builder;
}
}
protected <T> T loadBalance(Class<T> type, String schemeName) {
return loadBalance(feign(), type, schemeName);
}
protected <T> T loadBalance(Class<T> type, String schemeName) {
return loadBalance(feign(), type, schemeName);
}
protected <T> T loadBalance(Feign.Builder builder, Class<T> type, String schemeName) {
if(ribbonClient != null) {
return builder.client(ribbonClient).target(type, schemeName);
} else {
return builder.target(LoadBalancingTarget.create(type, schemeName));
}
}
protected <T> T loadBalance(Feign.Builder builder, Class<T> type, String schemeName) {
if (this.ribbonClient != null) {
return builder.client(this.ribbonClient).target(type, schemeName);
}
else {
return builder.target(LoadBalancingTarget.create(type, schemeName));
}
}
}

View File

@@ -1,20 +1,20 @@
package org.springframework.cloud.netflix.feign;
import org.springframework.http.HttpHeaders;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import org.springframework.http.HttpHeaders;
/**
* @author Spencer Gibb
*/
public class FeignUtils {
static HttpHeaders getHttpHeaders(Map<String, Collection<String>> headers) {
HttpHeaders httpHeaders = new HttpHeaders();
for (Map.Entry<String, Collection<String>> entry : headers.entrySet()) {
httpHeaders.put(entry.getKey(), new ArrayList<>(entry.getValue()));
}
return httpHeaders;
}
static HttpHeaders getHttpHeaders(Map<String, Collection<String>> headers) {
HttpHeaders httpHeaders = new HttpHeaders();
for (Map.Entry<String, Collection<String>> entry : headers.entrySet()) {
httpHeaders.put(entry.getKey(), new ArrayList<>(entry.getValue()));
}
return httpHeaders;
}
}

View File

@@ -5,6 +5,8 @@ import java.io.InputStream;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import javax.inject.Provider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
import org.springframework.http.HttpHeaders;
@@ -17,8 +19,6 @@ import feign.Response;
import feign.codec.DecodeException;
import feign.codec.Decoder;
import javax.inject.Provider;
import static org.springframework.cloud.netflix.feign.FeignUtils.getHttpHeaders;
/**
@@ -26,25 +26,27 @@ import static org.springframework.cloud.netflix.feign.FeignUtils.getHttpHeaders;
*/
public class SpringDecoder implements Decoder {
@Autowired
Provider<HttpMessageConverters> messageConverters;
@Autowired
Provider<HttpMessageConverters> messageConverters;
public SpringDecoder() {
}
@Override
public Object decode(final Response response, Type type) throws IOException, FeignException {
public Object decode(final Response response, Type type) throws IOException,
FeignException {
if (type instanceof Class || type instanceof ParameterizedType) {
@SuppressWarnings({ "unchecked", "rawtypes" })
HttpMessageConverterExtractor<?> extractor = new HttpMessageConverterExtractor(
type, messageConverters.get().getConverters());
@SuppressWarnings({ "unchecked", "rawtypes" })
HttpMessageConverterExtractor<?> extractor = new HttpMessageConverterExtractor(
type, this.messageConverters.get().getConverters());
return extractor.extractData(new FeignResponseAdapter(response));
}
throw new DecodeException("type is not an instance of Class or ParameterizedType: " + type);
return extractor.extractData(new FeignResponseAdapter(response));
}
throw new DecodeException(
"type is not an instance of Class or ParameterizedType: " + type);
}
private class FeignResponseAdapter implements ClientHttpResponse {
private class FeignResponseAdapter implements ClientHttpResponse {
private final Response response;
private FeignResponseAdapter(Response response) {
@@ -53,23 +55,23 @@ public class SpringDecoder implements Decoder {
@Override
public HttpStatus getStatusCode() throws IOException {
return HttpStatus.valueOf(response.status());
return HttpStatus.valueOf(this.response.status());
}
@Override
public int getRawStatusCode() throws IOException {
return response.status();
return this.response.status();
}
@Override
public String getStatusText() throws IOException {
return response.reason();
return this.response.reason();
}
@Override
public void close() {
try {
response.body().close();
this.response.body().close();
}
catch (IOException e) {
e.printStackTrace();
@@ -78,12 +80,12 @@ public class SpringDecoder implements Decoder {
@Override
public InputStream getBody() throws IOException {
return response.body().asInputStream();
return this.response.body().asInputStream();
}
@Override
public HttpHeaders getHeaders() {
return getHttpHeaders(response.headers());
return getHttpHeaders(this.response.headers());
}
}

View File

@@ -1,10 +1,11 @@
package org.springframework.cloud.netflix.feign;
import com.google.common.base.Charsets;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collection;
import feign.RequestTemplate;
import feign.codec.EncodeException;
import feign.codec.Encoder;
import javax.inject.Provider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -15,11 +16,11 @@ import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import javax.inject.Provider;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collection;
import com.google.common.base.Charsets;
import feign.RequestTemplate;
import feign.codec.EncodeException;
import feign.codec.Encoder;
import static org.springframework.cloud.netflix.feign.FeignUtils.getHttpHeaders;
@@ -29,8 +30,8 @@ import static org.springframework.cloud.netflix.feign.FeignUtils.getHttpHeaders;
public class SpringEncoder implements Encoder {
private static final Logger logger = LoggerFactory.getLogger(SpringEncoder.class);
@Autowired
Provider<HttpMessageConverters> messageConverters;
@Autowired
Provider<HttpMessageConverters> messageConverters;
public SpringEncoder() {
}
@@ -49,7 +50,8 @@ public class SpringEncoder implements Encoder {
requestContentType = MediaType.valueOf(type);
}
for (HttpMessageConverter<?> messageConverter : messageConverters.get().getConverters()) {
for (HttpMessageConverter<?> messageConverter : this.messageConverters.get()
.getConverters()) {
if (messageConverter.canWrite(requestType, requestContentType)) {
if (logger.isDebugEnabled()) {
if (requestContentType != null) {
@@ -97,16 +99,16 @@ public class SpringEncoder implements Encoder {
@Override
public OutputStream getBody() throws IOException {
return outputStream;
return this.outputStream;
}
@Override
public HttpHeaders getHeaders() {
return getHttpHeaders(request.headers());
return getHttpHeaders(this.request.headers());
}
public ByteArrayOutputStream getOutputStream() {
return outputStream;
return this.outputStream;
}
}
}

View File

@@ -1,8 +1,5 @@
package org.springframework.cloud.netflix.feign;
import static feign.Util.checkState;
import static feign.Util.emptyToNull;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
@@ -12,128 +9,151 @@ import java.util.Map;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import feign.Contract;
import feign.MethodMetadata;
import org.springframework.web.bind.annotation.RequestParam;
import static feign.Util.checkState;
import static feign.Util.emptyToNull;
/**
* @author Spencer Gibb
*/
public class SpringMvcContract extends Contract.BaseContract {
static final String ACCEPT = "Accept";
static final String CONTENT_TYPE = "Content-Type";
static final String ACCEPT = "Accept";
static final String CONTENT_TYPE = "Content-Type";
@Override
protected void processAnnotationOnMethod(MethodMetadata data, Annotation methodAnnotation, Method method) {
RequestMapping mapping = RequestMapping.class.cast(methodAnnotation);
if (mapping != null) {
//HTTP Method
checkOne(method, mapping.method(), "method");
data.template().method(mapping.method()[0].name());
@Override
protected void processAnnotationOnMethod(MethodMetadata data,
Annotation methodAnnotation, Method method) {
RequestMapping mapping = RequestMapping.class.cast(methodAnnotation);
if (mapping != null) {
// HTTP Method
checkOne(method, mapping.method(), "method");
data.template().method(mapping.method()[0].name());
//path
checkOne(method, mapping.value(), "value");
// path
checkOne(method, mapping.value(), "value");
String methodAnnotationValue = mapping.value()[0];
String pathValue = emptyToNull(methodAnnotationValue);
checkState(pathValue != null, "value was empty on method %s", method.getName());
if (!methodAnnotationValue.startsWith("/") && !data.template().toString().endsWith("/")) {
methodAnnotationValue = "/" + methodAnnotationValue;
}
data.template().append(methodAnnotationValue);
String methodAnnotationValue = mapping.value()[0];
String pathValue = emptyToNull(methodAnnotationValue);
checkState(pathValue != null, "value was empty on method %s",
method.getName());
if (!methodAnnotationValue.startsWith("/")
&& !data.template().toString().endsWith("/")) {
methodAnnotationValue = "/" + methodAnnotationValue;
}
data.template().append(methodAnnotationValue);
//produces
checkAtMostOne(method, mapping.produces(), "produces");
String[] serverProduces = mapping.produces();
String clientAccepts = serverProduces.length == 0 ? null: emptyToNull(serverProduces[0]);
if (clientAccepts != null) {
data.template().header(ACCEPT, clientAccepts);
}
// produces
checkAtMostOne(method, mapping.produces(), "produces");
String[] serverProduces = mapping.produces();
String clientAccepts = serverProduces.length == 0 ? null
: emptyToNull(serverProduces[0]);
if (clientAccepts != null) {
data.template().header(ACCEPT, clientAccepts);
}
//consumes
checkAtMostOne(method, mapping.consumes(), "consumes");
String[] serverConsumes = mapping.consumes();
String clientProduces = serverConsumes.length == 0 ? null: emptyToNull(serverConsumes[0]);
if (clientProduces != null) {
data.template().header(CONTENT_TYPE, clientProduces);
}
// consumes
checkAtMostOne(method, mapping.consumes(), "consumes");
String[] serverConsumes = mapping.consumes();
String clientProduces = serverConsumes.length == 0 ? null
: emptyToNull(serverConsumes[0]);
if (clientProduces != null) {
data.template().header(CONTENT_TYPE, clientProduces);
}
//headers
//TODO: only supports one header value per key
if (mapping.headers() != null && mapping.headers().length > 0)
for (String header : mapping.headers()) {
int colon = header.indexOf(':');
data.template().header(header.substring(0, colon), header.substring(colon + 2));
}
}
}
// headers
// TODO: only supports one header value per key
if (mapping.headers() != null && mapping.headers().length > 0) {
for (String header : mapping.headers()) {
int colon = header.indexOf(':');
data.template().header(header.substring(0, colon),
header.substring(colon + 2));
}
}
}
}
private void checkAtMostOne(Method method, Object[] values, String fieldName) {
checkState(values != null && (values.length == 0 || values.length == 1),
"Method %s can only contain at most 1 %s field. Found: %s", method.getName(), fieldName,
values == null ? null : Arrays.asList(values));
}
private void checkAtMostOne(Method method, Object[] values, String fieldName) {
checkState(values != null && (values.length == 0 || values.length == 1),
"Method %s can only contain at most 1 %s field. Found: %s",
method.getName(), fieldName,
values == null ? null : Arrays.asList(values));
}
private void checkOne(Method method, Object[] values, String fieldName) {
checkState(values != null && values.length == 1,
"Method %s can only contain 1 %s field. Found: %s", method.getName(), fieldName,
values == null ? null : Arrays.asList(values));
}
private void checkOne(Method method, Object[] values, String fieldName) {
checkState(values != null && values.length == 1,
"Method %s can only contain 1 %s field. Found: %s", method.getName(),
fieldName, values == null ? null : Arrays.asList(values));
}
@Override
protected boolean processAnnotationsOnParameter(MethodMetadata data, Annotation[] annotations, int paramIndex) {
boolean isHttpAnnotation = false;
//TODO: support spring parameter annotations?
for (Annotation parameterAnnotation : annotations) {
Class<? extends Annotation> annotationType = parameterAnnotation.annotationType();
if (annotationType == PathVariable.class) {
String name = PathVariable.class.cast(parameterAnnotation).value();
checkState(emptyToNull(name) != null, "PathVariable annotation was empty on param %s.", paramIndex);
nameParam(data, name, paramIndex);
isHttpAnnotation = true;
String varName = '{' + name + '}';
if (data.template().url().indexOf(varName) == -1 &&
!searchMapValues(data.template().queries(), varName) &&
!searchMapValues(data.template().headers(), varName)) {
data.formParams().add(name);
}
} else if (annotationType == RequestParam.class) {
String name = RequestParam.class.cast(parameterAnnotation).value();
checkState(emptyToNull(name) != null, "QueryParam.value() was empty on parameter %s", paramIndex);
Collection<String> query = addTemplatedParam(data.template().queries().get(name), name);
data.template().query(name, query);
nameParam(data, name, paramIndex);
isHttpAnnotation = true;
} else if (annotationType == RequestHeader.class) {
String name = RequestHeader.class.cast(parameterAnnotation).value();
checkState(emptyToNull(name) != null, "HeaderParam.value() was empty on parameter %s", paramIndex);
Collection<String> header = addTemplatedParam(data.template().headers().get(name), name);
data.template().header(name, header);
nameParam(data, name, paramIndex);
isHttpAnnotation = true;
}/* else if (annotationType == FormParam.class) {
String name = FormParam.class.cast(parameterAnnotation).value();
checkState(emptyToNull(name) != null, "FormParam.value() was empty on parameter %s", paramIndex);
data.formParams().add(name);
nameParam(data, name, paramIndex);
isHttpAnnotation = true;
}*/
@Override
protected boolean processAnnotationsOnParameter(MethodMetadata data,
Annotation[] annotations, int paramIndex) {
boolean isHttpAnnotation = false;
// TODO: support spring parameter annotations?
for (Annotation parameterAnnotation : annotations) {
Class<? extends Annotation> annotationType = parameterAnnotation
.annotationType();
if (annotationType == PathVariable.class) {
String name = PathVariable.class.cast(parameterAnnotation).value();
checkState(emptyToNull(name) != null,
"PathVariable annotation was empty on param %s.", paramIndex);
nameParam(data, name, paramIndex);
isHttpAnnotation = true;
String varName = '{' + name + '}';
if (data.template().url().indexOf(varName) == -1
&& !searchMapValues(data.template().queries(), varName)
&& !searchMapValues(data.template().headers(), varName)) {
data.formParams().add(name);
}
}
else if (annotationType == RequestParam.class) {
String name = RequestParam.class.cast(parameterAnnotation).value();
checkState(emptyToNull(name) != null,
"QueryParam.value() was empty on parameter %s", paramIndex);
Collection<String> query = addTemplatedParam(data.template().queries()
.get(name), name);
data.template().query(name, query);
nameParam(data, name, paramIndex);
isHttpAnnotation = true;
}
else if (annotationType == RequestHeader.class) {
String name = RequestHeader.class.cast(parameterAnnotation).value();
checkState(emptyToNull(name) != null,
"HeaderParam.value() was empty on parameter %s", paramIndex);
Collection<String> header = addTemplatedParam(data.template().headers()
.get(name), name);
data.template().header(name, header);
nameParam(data, name, paramIndex);
isHttpAnnotation = true;
}/*
* else if (annotationType == FormParam.class) { String name =
* FormParam.class.cast(parameterAnnotation).value();
* checkState(emptyToNull(name) != null,
* "FormParam.value() was empty on parameter %s", paramIndex);
* data.formParams().add(name); nameParam(data, name, paramIndex);
* isHttpAnnotation = true; }
*/
}
return isHttpAnnotation;
}
}
return isHttpAnnotation;
}
private <K, V> boolean searchMapValues(Map<K, Collection<V>> map, V search) {
Collection<Collection<V>> values = map.values();
if (values == null)
return false;
private <K, V> boolean searchMapValues(Map<K, Collection<V>> map, V search) {
Collection<Collection<V>> values = map.values();
if (values == null) {
return false;
}
for (Collection<V> entry : values) {
if (entry.contains(search))
return true;
}
for (Collection<V> entry : values) {
if (entry.contains(search)) {
return true;
}
}
return false;
}
return false;
}
}

View File

@@ -25,18 +25,17 @@ import feign.Response;
*/
public class FeignRibbonClient implements Client {
private Client defaultClient = new Default(
new Lazy<SSLSocketFactory>() {
@Override
public SSLSocketFactory get() {
return (SSLSocketFactory) SSLSocketFactory.getDefault();
}
}, new Lazy<HostnameVerifier>() {
@Override
public HostnameVerifier get() {
return HttpsURLConnection.getDefaultHostnameVerifier();
}
});
private Client defaultClient = new Default(new Lazy<SSLSocketFactory>() {
@Override
public SSLSocketFactory get() {
return (SSLSocketFactory) SSLSocketFactory.getDefault();
}
}, new Lazy<HostnameVerifier>() {
@Override
public HostnameVerifier get() {
return HttpsURLConnection.getDefaultHostnameVerifier();
}
});
private SpringClientFactory factory;
public FeignRibbonClient(SpringClientFactory factory) {
@@ -44,30 +43,34 @@ public class FeignRibbonClient implements Client {
}
@Override
public Response execute(Request request, Request.Options options) throws IOException {
try {
public Response execute(Request request, Request.Options options) throws IOException {
try {
URI asUri = URI.create(request.url());
String clientName = asUri.getHost();
URI uriWithoutSchemeAndPort = URI.create(request.url().replace(asUri.getScheme() + "://" + asUri.getHost(), ""));
RibbonLoadBalancer.RibbonRequest ribbonRequest = new RibbonLoadBalancer.RibbonRequest(request, uriWithoutSchemeAndPort);
return lbClient(clientName).executeWithLoadBalancer(ribbonRequest).toResponse();
URI asUri = URI.create(request.url());
String clientName = asUri.getHost();
URI uriWithoutSchemeAndPort = URI.create(request.url().replace(
asUri.getScheme() + "://" + asUri.getHost(), ""));
RibbonLoadBalancer.RibbonRequest ribbonRequest = new RibbonLoadBalancer.RibbonRequest(
request, uriWithoutSchemeAndPort);
return lbClient(clientName).executeWithLoadBalancer(ribbonRequest)
.toResponse();
} catch (ClientException e) {
if (e.getCause() instanceof IOException) {
throw IOException.class.cast(e.getCause());
}
throw Throwables.propagate(e);
}
}
}
catch (ClientException e) {
if (e.getCause() instanceof IOException) {
throw IOException.class.cast(e.getCause());
}
throw Throwables.propagate(e);
}
}
private RibbonLoadBalancer lbClient(String clientName) {
IClientConfig config = factory.getClientConfig(clientName);
ILoadBalancer lb = factory.getLoadBalancer(clientName);
return new RibbonLoadBalancer(defaultClient, lb, config);
}
private RibbonLoadBalancer lbClient(String clientName) {
IClientConfig config = this.factory.getClientConfig(clientName);
ILoadBalancer lb = this.factory.getLoadBalancer(clientName);
return new RibbonLoadBalancer(this.defaultClient, lb, config);
}
public void setDefaultClient(Client defaultClient) {
this.defaultClient = defaultClient;
}
public void setDefaultClient(Client defaultClient) {
this.defaultClient = defaultClient;
}
}

View File

@@ -20,115 +20,125 @@ import feign.Request;
import feign.RequestTemplate;
import feign.Response;
public class RibbonLoadBalancer extends AbstractLoadBalancerAwareClient<RibbonLoadBalancer.RibbonRequest, RibbonLoadBalancer.RibbonResponse> {
public class RibbonLoadBalancer
extends
AbstractLoadBalancerAwareClient<RibbonLoadBalancer.RibbonRequest, RibbonLoadBalancer.RibbonResponse> {
private final Client delegate;
private final int connectTimeout;
private final int readTimeout;
private final IClientConfig clientConfig;
private final Client delegate;
private final int connectTimeout;
private final int readTimeout;
private final IClientConfig clientConfig;
public RibbonLoadBalancer(Client delegate, ILoadBalancer lb, IClientConfig clientConfig) {
super(lb, clientConfig);
this.setRetryHandler(RetryHandler.DEFAULT);
this.clientConfig = clientConfig;
this.delegate = delegate;
connectTimeout = clientConfig.get(CommonClientConfigKey.ConnectTimeout);
readTimeout = clientConfig.get(CommonClientConfigKey.ReadTimeout);
}
public RibbonLoadBalancer(Client delegate, ILoadBalancer lb,
IClientConfig clientConfig) {
super(lb, clientConfig);
this.setRetryHandler(RetryHandler.DEFAULT);
this.clientConfig = clientConfig;
this.delegate = delegate;
this.connectTimeout = clientConfig.get(CommonClientConfigKey.ConnectTimeout);
this.readTimeout = clientConfig.get(CommonClientConfigKey.ReadTimeout);
}
@Override
public RibbonResponse execute(RibbonRequest request, IClientConfig configOverride) throws IOException {
Request.Options options;
if (configOverride != null) {
options = new Request.Options(configOverride.get(CommonClientConfigKey.ConnectTimeout, connectTimeout), (configOverride.get(CommonClientConfigKey.ReadTimeout, readTimeout)));
} else {
options = new Request.Options(connectTimeout, readTimeout);
}
Response response = delegate.execute(request.toRequest(), options);
return new RibbonResponse(request.getUri(), response);
}
@Override
public RibbonResponse execute(RibbonRequest request, IClientConfig configOverride)
throws IOException {
Request.Options options;
if (configOverride != null) {
options = new Request.Options(configOverride.get(
CommonClientConfigKey.ConnectTimeout, this.connectTimeout),
(configOverride.get(CommonClientConfigKey.ReadTimeout,
this.readTimeout)));
}
else {
options = new Request.Options(this.connectTimeout, this.readTimeout);
}
Response response = this.delegate.execute(request.toRequest(), options);
return new RibbonResponse(request.getUri(), response);
}
@Override
public RequestSpecificRetryHandler getRequestSpecificRetryHandler(
RibbonRequest request, IClientConfig requestConfig) {
if (clientConfig.get(CommonClientConfigKey.OkToRetryOnAllOperations, false)) {
return new RequestSpecificRetryHandler(true, true, this.getRetryHandler(), requestConfig);
}
if (!request.toRequest().method().equals("GET")) {
return new RequestSpecificRetryHandler(true, false, this.getRetryHandler(), requestConfig);
} else {
return new RequestSpecificRetryHandler(true, true, this.getRetryHandler(), requestConfig);
}
}
@Override
public RequestSpecificRetryHandler getRequestSpecificRetryHandler(
RibbonRequest request, IClientConfig requestConfig) {
if (this.clientConfig.get(CommonClientConfigKey.OkToRetryOnAllOperations, false)) {
return new RequestSpecificRetryHandler(true, true, this.getRetryHandler(),
requestConfig);
}
if (!request.toRequest().method().equals("GET")) {
return new RequestSpecificRetryHandler(true, false, this.getRetryHandler(),
requestConfig);
}
else {
return new RequestSpecificRetryHandler(true, true, this.getRetryHandler(),
requestConfig);
}
}
static class RibbonRequest extends ClientRequest implements Cloneable {
static class RibbonRequest extends ClientRequest implements Cloneable {
private final Request request;
private final Request request;
RibbonRequest(Request request, URI uri) {
this.request = request;
setUri(uri);
}
RibbonRequest(Request request, URI uri) {
this.request = request;
setUri(uri);
}
Request toRequest() {
return new RequestTemplate()
.method(request.method())
.append(getUri().toASCIIString())
.headers(request.headers())
.body(request.body(), request.charset())
.request();
}
Request toRequest() {
return new RequestTemplate().method(this.request.method())
.append(getUri().toASCIIString()).headers(this.request.headers())
.body(this.request.body(), this.request.charset()).request();
}
public Object clone() {
return new RibbonRequest(request, getUri());
}
}
@Override
public Object clone() {
return new RibbonRequest(this.request, getUri());
}
}
static class RibbonResponse implements IResponse {
static class RibbonResponse implements IResponse {
private final URI uri;
private final Response response;
private final URI uri;
private final Response response;
RibbonResponse(URI uri, Response response) {
this.uri = uri;
this.response = response;
}
RibbonResponse(URI uri, Response response) {
this.uri = uri;
this.response = response;
}
@Override
public Object getPayload() throws ClientException {
return response.body();
}
@Override
public Object getPayload() throws ClientException {
return this.response.body();
}
@Override
public boolean hasPayload() {
return response.body() != null;
}
@Override
public boolean hasPayload() {
return this.response.body() != null;
}
@Override
public boolean isSuccess() {
return response.status() == 200;
}
@Override
public boolean isSuccess() {
return this.response.status() == 200;
}
@Override
public URI getRequestedURI() {
return uri;
}
@Override
public URI getRequestedURI() {
return this.uri;
}
@Override
public Map<String, Collection<String>> getHeaders() {
return response.headers();
}
@Override
public Map<String, Collection<String>> getHeaders() {
return this.response.headers();
}
Response toResponse() {
return response;
}
Response toResponse() {
return this.response;
}
@Override
public void close() throws IOException {
if (response != null && response.body() != null) {
response.body().close();
}
}
@Override
public void close() throws IOException {
if (this.response != null && this.response.body() != null) {
this.response.body().close();
}
}
}
}
}
}

View File

@@ -19,7 +19,7 @@ import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
* you want. All it does is turn on circuit breakers and let the autoconfiguration find
* the Hystrix classes if they are available (i.e. you need Hystrix on the classpath as
* well).
*
*
* @author Dave Syer
*
*/

View File

@@ -16,12 +16,12 @@
package org.springframework.cloud.netflix.hystrix;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.netflix.hystrix.Hystrix;
import com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect;
import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsPoller;
import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsPoller.MetricsAsJsonPollerListener;
import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.catalina.core.ApplicationContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -37,11 +37,12 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.netflix.hystrix.Hystrix;
import com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect;
import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsPoller;
import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsPoller.MetricsAsJsonPollerListener;
import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
/**
* @author Spencer Gibb
@@ -63,7 +64,7 @@ public class HystrixCircuitBreakerConfiguration {
@Configuration
@ConditionalOnExpression("${hystrix.stream.endpoint.enabled:true}")
@ConditionalOnWebApplication
@ConditionalOnClass({Endpoint.class, HystrixMetricsStreamServlet.class})
@ConditionalOnClass({ Endpoint.class, HystrixMetricsStreamServlet.class })
protected static class HystrixWebConfiguration {
@Bean
@@ -74,13 +75,13 @@ public class HystrixCircuitBreakerConfiguration {
}
@Configuration
@ConditionalOnClass({HystrixMetricsPoller.class, GaugeService.class})
@ConditionalOnClass({ HystrixMetricsPoller.class, GaugeService.class })
protected static class HystrixMetricsPollerConfiguration implements SmartLifecycle {
private static Log logger = LogFactory
.getLog(HystrixMetricsPollerConfiguration.class);
@Autowired(required=false)
@Autowired(required = false)
private GaugeService gauges;
private ObjectMapper mapper = new ObjectMapper();
@@ -92,7 +93,7 @@ public class HystrixCircuitBreakerConfiguration {
@Override
public void start() {
if (gauges==null) {
if (this.gauges == null) {
return;
}
MetricsAsJsonPollerListener listener = new MetricsAsJsonPollerListener() {
@@ -100,7 +101,8 @@ public class HystrixCircuitBreakerConfiguration {
public void handleJsonMetric(String json) {
try {
@SuppressWarnings("unchecked")
Map<String, Object> map = mapper.readValue(json, Map.class);
Map<String, Object> map = HystrixMetricsPollerConfiguration.this.mapper
.readValue(json, Map.class);
if (map != null && map.containsKey("type")) {
addMetrics(map, "hystrix.");
}
@@ -111,9 +113,9 @@ public class HystrixCircuitBreakerConfiguration {
}
};
poller = new HystrixMetricsPoller(listener, 2000);
this.poller = new HystrixMetricsPoller(listener, 2000);
// start polling and it will write directly to the listener
poller.start();
this.poller.start();
logger.info("Starting poller");
}
@@ -129,10 +131,10 @@ public class HystrixCircuitBreakerConfiguration {
String prefix = prefixBuilder.toString();
for (String key : map.keySet()) {
Object value = map.get(key);
if (!reserved.contains(key)) {
if (!this.reserved.contains(key)) {
if (value instanceof Number) {
String name = prefix + "." + key;
gauges.submit(name, ((Number) value).doubleValue());
this.gauges.submit(name, ((Number) value).doubleValue());
}
else if (value instanceof Map) {
@SuppressWarnings("unchecked")
@@ -145,14 +147,14 @@ public class HystrixCircuitBreakerConfiguration {
@Override
public void stop() {
if (poller != null) {
poller.shutdown();
if (this.poller != null) {
this.poller.shutdown();
}
}
@Override
public boolean isRunning() {
return poller != null ? poller.isRunning() : false;
return this.poller != null ? this.poller.isRunning() : false;
}
@Override
@@ -167,8 +169,8 @@ public class HystrixCircuitBreakerConfiguration {
@Override
public void stop(Runnable callback) {
if (poller != null) {
poller.shutdown();
if (this.poller != null) {
this.poller.shutdown();
}
callback.run();
}

View File

@@ -28,34 +28,38 @@ import com.netflix.hystrix.HystrixCircuitBreaker;
import com.netflix.hystrix.HystrixCommandMetrics;
/**
* A {@link HealthIndicator} implementation for Hystrix circuit breakers.
* A {@link HealthIndicator} implementation for Hystrix circuit breakers.
* <p>
* This default implementation will set the system to <code>OUT_OF_SERVICE</code> and
* include all open circuits by name.
*
* This default implementation will set the system to <code>OUT_OF_SERVICE</code> and
* include all open circuits by name.
*
* @author Christian Dupuis
*/
public class HystrixHealthIndicator extends AbstractHealthIndicator {
/** Status code for open circuits */
private static final Status CIRCUIT_OPEN = new Status("CIRCUIT_OPEN");
private static final Status CIRCUIT_OPEN = new Status("CIRCUIT_OPEN");
@Override
protected void doHealthCheck(Builder builder) throws Exception {
List<String> openCircuitBreakers = new ArrayList<String>();
// Collect all open circuit breakers from Hystrix
for (HystrixCommandMetrics metrics : HystrixCommandMetrics.getInstances()) {
HystrixCircuitBreaker circuitBreaker = HystrixCircuitBreaker.Factory.getInstance(metrics.getCommandKey());
HystrixCircuitBreaker circuitBreaker = HystrixCircuitBreaker.Factory
.getInstance(metrics.getCommandKey());
if (circuitBreaker.isOpen()) {
openCircuitBreakers.add(metrics.getCommandGroup().name() + "::" + metrics.getCommandKey().name());
openCircuitBreakers.add(metrics.getCommandGroup().name() + "::"
+ metrics.getCommandKey().name());
}
}
// If there is at least one open circuit report OUT_OF_SERVICE adding the command group
// If there is at least one open circuit report OUT_OF_SERVICE adding the command
// group
// and key name
if (openCircuitBreakers.size() > 0) {
builder.status(CIRCUIT_OPEN).withDetail("openCircuitBreakers", openCircuitBreakers);
builder.status(CIRCUIT_OPEN).withDetail("openCircuitBreakers",
openCircuitBreakers);
}
else {
builder.up();

View File

@@ -24,7 +24,8 @@ import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServl
*/
public class HystrixStreamEndpoint extends ServletWrappingEndpoint {
public HystrixStreamEndpoint() {
super(HystrixMetricsStreamServlet.class, "hystrixStream", "/hystrix.stream", false, true);
}
public HystrixStreamEndpoint() {
super(HystrixMetricsStreamServlet.class, "hystrixStream", "/hystrix.stream",
false, true);
}
}

View File

@@ -22,22 +22,22 @@ import com.netflix.client.IClient;
* @author Dave Syer
*/
@Configuration
@ConditionalOnClass({IClient.class, RestTemplate.class})
@ConditionalOnClass({ IClient.class, RestTemplate.class })
@RibbonClients
@AutoConfigureAfter(EurekaClientAutoConfiguration.class)
public class RibbonAutoConfiguration {
@Autowired(required=false)
private List<RibbonClientSpecification> configurations = new ArrayList<>();
@Autowired(required = false)
private List<RibbonClientSpecification> configurations = new ArrayList<>();
@Bean
public SpringClientFactory springClientFactory() {
SpringClientFactory factory = new SpringClientFactory();
factory.setConfigurations(configurations);
public SpringClientFactory springClientFactory() {
SpringClientFactory factory = new SpringClientFactory();
factory.setConfigurations(this.configurations);
return factory;
}
}
@Bean
@Bean
@ConditionalOnMissingBean(RestTemplate.class)
public RestTemplate restTemplate(RibbonInterceptor ribbonInterceptor) {
RestTemplate restTemplate = new RestTemplate();

View File

@@ -35,6 +35,8 @@ import org.springframework.context.annotation.Import;
@Documented
public @interface RibbonClient {
String value() default "";
String name() default "";
Class<?>[] configuration() default {};
}

View File

@@ -51,12 +51,12 @@ public class RibbonClientConfiguration {
// TODO: maybe re-instate autowired load balancers: identified by name they could be
// associated with ribbon clients
@Bean
@ConditionalOnMissingBean
public IClientConfig ribbonClientConfig() {
DefaultClientConfigImpl config = new DefaultClientConfigImpl();
config.loadProperties(name);
config.loadProperties(this.name);
return config;
}
@@ -65,20 +65,21 @@ public class RibbonClientConfiguration {
public RestClient ribbonRestClient(IClientConfig config, ILoadBalancer loadBalancer) {
RestClient client = new RestClient(config);
client.setLoadBalancer(loadBalancer);
Monitors.registerObject("Client_" + name, client);
Monitors.registerObject("Client_" + this.name, client);
return client;
}
@Bean
@ConditionalOnMissingBean
//TODO: move to ribbon.eureka package
public ILoadBalancer ribbonLoadBalancer(IClientConfig config, ServerListFilter<Server> filter) {
// TODO: move to ribbon.eureka package
public ILoadBalancer ribbonLoadBalancer(IClientConfig config,
ServerListFilter<Server> filter) {
ZoneAwareLoadBalancer<Server> balancer = new ZoneAwareLoadBalancer<>(config);
wrapServerList(balancer);
balancer.setFilter(filter);
return balancer;
}
@Bean
@ConditionalOnMissingBean
public ServerListFilter<Server> ribbonServerListFilter(IClientConfig config) {
@@ -86,10 +87,11 @@ public class RibbonClientConfiguration {
filter.initWithNiwsConfig(config);
return filter;
}
@Bean
@ConditionalOnMissingBean
public RibbonLoadBalancerContext ribbonLoadBalancerContext(ILoadBalancer loadBalancer, IClientConfig config) {
public RibbonLoadBalancerContext ribbonLoadBalancerContext(
ILoadBalancer loadBalancer, IClientConfig config) {
return new RibbonLoadBalancerContext(loadBalancer, config);
}
@@ -104,7 +106,7 @@ public class RibbonClientConfiguration {
// metadata *is* available.
// @see com.netflix.appinfo.AmazonInfo.Builder
dynamic.setServerListImpl(new DomainExtractingServerList(list, dynamic
.getClientConfig(), approximateZoneFromHostname));
.getClientConfig(), this.approximateZoneFromHostname));
}
}
}

View File

@@ -56,7 +56,7 @@ public class RibbonClientConfigurationRegistrar implements ImportBeanDefinitionR
}
private String getClientName(Map<String, Object> client) {
if (client==null) {
if (client == null) {
return null;
}
String value = (String) client.get("value");
@@ -67,7 +67,8 @@ public class RibbonClientConfigurationRegistrar implements ImportBeanDefinitionR
if (value != null && StringUtils.hasText(value)) {
return value;
}
throw new IllegalStateException("Either 'name' or 'value' must be provided in @RibbonClient");
throw new IllegalStateException(
"Either 'name' or 'value' must be provided in @RibbonClient");
}
private void registerClientConfiguration(BeanDefinitionRegistry registry,

View File

@@ -27,7 +27,7 @@ import org.springframework.context.annotation.Import;
/**
* Convenience annotation that allows user to combine multiple <code>@RibbonClient</code>
* annotations on a single class (including in Java 7).
*
*
* @author Dave Syer
*
*/

View File

@@ -1,5 +1,8 @@
package org.springframework.cloud.netflix.ribbon;
import java.io.IOException;
import java.net.URI;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerRequest;
@@ -9,36 +12,37 @@ import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.support.HttpRequestWrapper;
import java.io.IOException;
import java.net.URI;
/**
* @author Spencer Gibb
*/
public class RibbonInterceptor implements ClientHttpRequestInterceptor {
private LoadBalancerClient loadBalancer;
private LoadBalancerClient loadBalancer;
public RibbonInterceptor(LoadBalancerClient loadBalancer) {
this.loadBalancer = loadBalancer;
}
public RibbonInterceptor(LoadBalancerClient loadBalancer) {
this.loadBalancer = loadBalancer;
}
@Override
public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) throws IOException {
final URI originalUri = request.getURI();
String serviceName = originalUri.getHost();
return loadBalancer.execute(serviceName, new LoadBalancerRequest<ClientHttpResponse>() {
@Override
public ClientHttpResponse apply(final ServiceInstance instance) throws Exception {
HttpRequestWrapper wrapper = new HttpRequestWrapper(request) {
@Override
public URI getURI() {
URI uri = loadBalancer.reconstructURI(instance, originalUri);
return uri;
}
};
return execution.execute(wrapper, body);
}
});
}
@Override
public ClientHttpResponse intercept(final HttpRequest request, final byte[] body,
final ClientHttpRequestExecution execution) throws IOException {
final URI originalUri = request.getURI();
String serviceName = originalUri.getHost();
return this.loadBalancer.execute(serviceName,
new LoadBalancerRequest<ClientHttpResponse>() {
@Override
public ClientHttpResponse apply(final ServiceInstance instance)
throws Exception {
HttpRequestWrapper wrapper = new HttpRequestWrapper(request) {
@Override
public URI getURI() {
URI uri = RibbonInterceptor.this.loadBalancer
.reconstructURI(instance, originalUri);
return uri;
}
};
return execution.execute(wrapper, body);
}
});
}
}

View File

@@ -19,72 +19,76 @@ import com.netflix.servo.monitor.Stopwatch;
*/
public class RibbonLoadBalancerClient implements LoadBalancerClient {
private SpringClientFactory clientFactory;
private SpringClientFactory clientFactory;
public RibbonLoadBalancerClient(SpringClientFactory clientFactory) {
this.clientFactory = clientFactory;
}
@Override
public URI reconstructURI(ServiceInstance instance, URI original) {
String serviceId = instance.getServiceId();
RibbonLoadBalancerContext context = clientFactory.getLoadBalancerContext(serviceId);
Server server = new Server(instance.getHost(), instance.getPort());
return context.reconstructURIWithServer(server, original);
}
@Override
public URI reconstructURI(ServiceInstance instance, URI original) {
String serviceId = instance.getServiceId();
RibbonLoadBalancerContext context = this.clientFactory
.getLoadBalancerContext(serviceId);
Server server = new Server(instance.getHost(), instance.getPort());
return context.reconstructURIWithServer(server, original);
}
@Override
@Override
public ServiceInstance choose(String serviceId) {
return new RibbonServer(serviceId, getServer(serviceId));
}
@Override
public <T> T execute(String serviceId, LoadBalancerRequest<T> request) {
ILoadBalancer loadBalancer = getLoadBalancer(serviceId);
RibbonLoadBalancerContext context = clientFactory.getLoadBalancerContext(serviceId);
Server server = getServer(serviceId, loadBalancer);
RibbonServer ribbonServer = new RibbonServer(serviceId, server);
@Override
public <T> T execute(String serviceId, LoadBalancerRequest<T> request) {
ILoadBalancer loadBalancer = getLoadBalancer(serviceId);
RibbonLoadBalancerContext context = this.clientFactory
.getLoadBalancerContext(serviceId);
Server server = getServer(serviceId, loadBalancer);
RibbonServer ribbonServer = new RibbonServer(serviceId, server);
ServerStats serverStats = context.getServerStats(server);
context.noteOpenConnection(serverStats);
Stopwatch tracer = context.getExecuteTracer().start();
ServerStats serverStats = context.getServerStats(server);
context.noteOpenConnection(serverStats);
Stopwatch tracer = context.getExecuteTracer().start();
try {
try {
T returnVal = request.apply(ribbonServer);
recordStats(context, tracer, serverStats, returnVal, null);
return returnVal;
} catch (Exception e) {
recordStats(context, tracer, serverStats, null, e);
Throwables.propagate(e);
}
return null;
}
T returnVal = request.apply(ribbonServer);
recordStats(context, tracer, serverStats, returnVal, null);
return returnVal;
}
catch (Exception e) {
recordStats(context, tracer, serverStats, null, e);
Throwables.propagate(e);
}
return null;
}
private void recordStats(RibbonLoadBalancerContext context, Stopwatch tracer, ServerStats serverStats, Object entity, Throwable exception) {
tracer.stop();
long duration = tracer.getDuration(TimeUnit.MILLISECONDS);
context.noteRequestCompletion(serverStats, entity, exception, duration, null/*errorHandler*/);
}
private void recordStats(RibbonLoadBalancerContext context, Stopwatch tracer,
ServerStats serverStats, Object entity, Throwable exception) {
tracer.stop();
long duration = tracer.getDuration(TimeUnit.MILLISECONDS);
context.noteRequestCompletion(serverStats, entity, exception, duration, null/* errorHandler */);
}
protected Server getServer(String serviceId) {
return getServer(serviceId, getLoadBalancer(serviceId));
}
protected Server getServer(String serviceId) {
return getServer(serviceId, getLoadBalancer(serviceId));
}
protected Server getServer(String serviceId, ILoadBalancer loadBalancer) {
Server server = loadBalancer.chooseServer("default");
if (server == null) {
throw new IllegalStateException(
"Unable to locate ILoadBalancer for service: " + serviceId);
}
return server;
}
protected Server getServer(String serviceId, ILoadBalancer loadBalancer) {
Server server = loadBalancer.chooseServer("default");
if (server == null) {
throw new IllegalStateException(
"Unable to locate ILoadBalancer for service: " + serviceId);
}
return server;
}
protected ILoadBalancer getLoadBalancer(String serviceId) {
return clientFactory.getLoadBalancer(serviceId);
}
protected ILoadBalancer getLoadBalancer(String serviceId) {
return this.clientFactory.getLoadBalancer(serviceId);
}
protected static class RibbonServer implements ServiceInstance {
protected static class RibbonServer implements ServiceInstance {
protected String serviceId;
protected Server server;
@@ -95,17 +99,17 @@ public class RibbonLoadBalancerClient implements LoadBalancerClient {
@Override
public String getServiceId() {
return serviceId;
return this.serviceId;
}
@Override
public String getHost() {
return server.getHost();
return this.server.getHost();
}
@Override
public int getPort() {
return server.getPort();
return this.server.getPort();
}
}
}

View File

@@ -11,35 +11,38 @@ import com.netflix.servo.monitor.Timer;
* @author Spencer Gibb
*/
public class RibbonLoadBalancerContext extends LoadBalancerContext {
public RibbonLoadBalancerContext(ILoadBalancer lb) {
super(lb);
}
public RibbonLoadBalancerContext(ILoadBalancer lb) {
super(lb);
}
public RibbonLoadBalancerContext(ILoadBalancer lb, IClientConfig clientConfig) {
super(lb, clientConfig);
}
public RibbonLoadBalancerContext(ILoadBalancer lb, IClientConfig clientConfig) {
super(lb, clientConfig);
}
public RibbonLoadBalancerContext(ILoadBalancer lb, IClientConfig clientConfig, RetryHandler handler) {
super(lb, clientConfig, handler);
}
public RibbonLoadBalancerContext(ILoadBalancer lb, IClientConfig clientConfig,
RetryHandler handler) {
super(lb, clientConfig, handler);
}
@Override
public void noteOpenConnection(ServerStats serverStats) {
super.noteOpenConnection(serverStats);
}
@Override
public void noteOpenConnection(ServerStats serverStats) {
super.noteOpenConnection(serverStats);
}
@Override
public Timer getExecuteTracer() {
return super.getExecuteTracer();
}
@Override
public Timer getExecuteTracer() {
return super.getExecuteTracer();
}
@Override
public void noteRequestCompletion(ServerStats stats, Object response, Throwable e, long responseTime) {
super.noteRequestCompletion(stats, response, e, responseTime);
}
@Override
public void noteRequestCompletion(ServerStats stats, Object response, Throwable e,
long responseTime) {
super.noteRequestCompletion(stats, response, e, responseTime);
}
@Override
public void noteRequestCompletion(ServerStats stats, Object response, Throwable e, long responseTime, RetryHandler errorHandler) {
super.noteRequestCompletion(stats, response, e, responseTime, errorHandler);
}
@Override
public void noteRequestCompletion(ServerStats stats, Object response, Throwable e,
long responseTime, RetryHandler errorHandler) {
super.noteRequestCompletion(stats, response, e, responseTime, errorHandler);
}
}

View File

@@ -38,7 +38,7 @@ public class SpringClientFactory implements DisposableBean, ApplicationContextAw
public void setApplicationContext(ApplicationContext parent) throws BeansException {
this.parent = parent;
}
public void setConfigurations(List<RibbonClientSpecification> configurations) {
for (RibbonClientSpecification client : configurations) {
this.configurations.put(client.getName(), client);
@@ -47,8 +47,8 @@ public class SpringClientFactory implements DisposableBean, ApplicationContextAw
@Override
public void destroy() {
Collection<AnnotationConfigApplicationContext> values = contexts.values();
contexts.clear();
Collection<AnnotationConfigApplicationContext> values = this.contexts.values();
this.contexts.clear();
for (AnnotationConfigApplicationContext context : values) {
context.close();
}
@@ -91,28 +91,30 @@ public class SpringClientFactory implements DisposableBean, ApplicationContextAw
}
private AnnotationConfigApplicationContext getContext(String name) {
if (!contexts.containsKey(name)) {
synchronized (contexts) {
if (!contexts.containsKey(name)) {
contexts.put(name, createContext(name));
if (!this.contexts.containsKey(name)) {
synchronized (this.contexts) {
if (!this.contexts.containsKey(name)) {
this.contexts.put(name, createContext(name));
}
}
}
return contexts.get(name);
return this.contexts.get(name);
}
private AnnotationConfigApplicationContext createContext(String name) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
if (configurations.containsKey(name)) {
for (Class<?> configuration : configurations.get(name).getConfiguration()) {
if (this.configurations.containsKey(name)) {
for (Class<?> configuration : this.configurations.get(name)
.getConfiguration()) {
context.register(configuration);
}
}
for (Entry<String, RibbonClientSpecification> entry : configurations.entrySet()) {
for (Entry<String, RibbonClientSpecification> entry : this.configurations
.entrySet()) {
if (entry.getKey().startsWith("default.")) {
for (Class<?> configuration : entry.getValue().getConfiguration()) {
context.register(configuration);
}
}
}
}
context.register(PropertyPlaceholderAutoConfiguration.class,
@@ -123,9 +125,9 @@ public class SpringClientFactory implements DisposableBean, ApplicationContextAw
new MapPropertySource("ribbon",
Collections.<String, Object> singletonMap(
"ribbon.client.name", name)));
if (parent != null) {
if (this.parent != null) {
// Uses Environment from parent as well as beans
context.setParent(parent);
context.setParent(this.parent);
}
context.refresh();
return context;

View File

@@ -18,14 +18,14 @@ package org.springframework.cloud.netflix.ribbon.eureka;
import java.util.ArrayList;
import java.util.List;
import com.netflix.client.config.CommonClientConfigKey;
import com.netflix.client.config.IClientConfig;
import lombok.Getter;
import lombok.Setter;
import org.springframework.util.StringUtils;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.client.config.CommonClientConfigKey;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;
import com.netflix.niws.loadbalancer.DiscoveryEnabledServer;
@@ -36,88 +36,92 @@ import com.netflix.niws.loadbalancer.DiscoveryEnabledServer;
*/
public class DomainExtractingServerList implements ServerList<Server> {
private ServerList<Server> list;
private IClientConfig clientConfig;
private ServerList<Server> list;
private IClientConfig clientConfig;
private boolean approximateZoneFromHostname;
public DomainExtractingServerList(ServerList<Server> list, IClientConfig clientConfig, boolean approximateZoneFromHostname) {
this.list = list;
this.clientConfig = clientConfig;
public DomainExtractingServerList(ServerList<Server> list,
IClientConfig clientConfig, boolean approximateZoneFromHostname) {
this.list = list;
this.clientConfig = clientConfig;
this.approximateZoneFromHostname = approximateZoneFromHostname;
}
@Override
public List<Server> getInitialListOfServers() {
List<Server> servers = setZones(list.getInitialListOfServers());
return servers;
}
@Override
public List<Server> getInitialListOfServers() {
List<Server> servers = setZones(this.list.getInitialListOfServers());
return servers;
}
@Override
public List<Server> getUpdatedListOfServers() {
List<Server> servers = setZones(list.getUpdatedListOfServers());
return servers;
}
@Override
public List<Server> getUpdatedListOfServers() {
List<Server> servers = setZones(this.list.getUpdatedListOfServers());
return servers;
}
private List<Server> setZones(List<Server> servers) {
List<Server> result = new ArrayList<>();
boolean isSecure = clientConfig.getPropertyAsBoolean(CommonClientConfigKey.IsSecure, Boolean.TRUE);
boolean shouldUseIpAddr = clientConfig.getPropertyAsBoolean(CommonClientConfigKey.UseIPAddrForServer, Boolean.FALSE);
for (Server server : servers) {
if (server instanceof DiscoveryEnabledServer) {
result.add(new DomainExtractingServer((DiscoveryEnabledServer) server,
isSecure, shouldUseIpAddr, approximateZoneFromHostname));
}
else {
result.add(server);
}
}
return result;
}
private List<Server> setZones(List<Server> servers) {
List<Server> result = new ArrayList<>();
boolean isSecure = this.clientConfig.getPropertyAsBoolean(
CommonClientConfigKey.IsSecure, Boolean.TRUE);
boolean shouldUseIpAddr = this.clientConfig.getPropertyAsBoolean(
CommonClientConfigKey.UseIPAddrForServer, Boolean.FALSE);
for (Server server : servers) {
if (server instanceof DiscoveryEnabledServer) {
result.add(new DomainExtractingServer((DiscoveryEnabledServer) server,
isSecure, shouldUseIpAddr, this.approximateZoneFromHostname));
}
else {
result.add(server);
}
}
return result;
}
}
class DomainExtractingServer extends DiscoveryEnabledServer {
@Getter
@Setter
private String id;
@Getter
@Setter
private String id;
public DomainExtractingServer(DiscoveryEnabledServer server, boolean useSecurePort, boolean useIpAddr, boolean approximateZoneFromHostname) {
//host and port are set in super()
super(server.getInstanceInfo(), useSecurePort, useIpAddr);
public DomainExtractingServer(DiscoveryEnabledServer server, boolean useSecurePort,
boolean useIpAddr, boolean approximateZoneFromHostname) {
// host and port are set in super()
super(server.getInstanceInfo(), useSecurePort, useIpAddr);
if (approximateZoneFromHostname) {
setZone(extractApproximateZone(server));
} else {
}
else {
setZone(server.getZone());
}
setId(extractId(server));
setId(extractId(server));
setAlive(server.isAlive());
setReadyToServe(server.isReadyToServe());
}
}
private String extractId(Server server) {
if (server instanceof DiscoveryEnabledServer) {
DiscoveryEnabledServer enabled = (DiscoveryEnabledServer) server;
InstanceInfo instance = enabled.getInstanceInfo();
if (instance.getMetadata().containsKey("instanceId")) {
return instance.getMetadata().get("instanceId");
}
}
return super.getId();
}
private String extractId(Server server) {
if (server instanceof DiscoveryEnabledServer) {
DiscoveryEnabledServer enabled = (DiscoveryEnabledServer) server;
InstanceInfo instance = enabled.getInstanceInfo();
if (instance.getMetadata().containsKey("instanceId")) {
return instance.getMetadata().get("instanceId");
}
}
return super.getId();
}
private String extractApproximateZone(Server server) {
String host = server.getHost();
if (!host.contains(".")) {
return host;
}
String[] split = StringUtils.split(host, ".");
StringBuilder builder = new StringBuilder(split[1]);
for (int i = 2; i < split.length; i++) {
builder.append(".").append(split[i]);
}
return builder.toString();
}
private String extractApproximateZone(Server server) {
String host = server.getHost();
if (!host.contains(".")) {
return host;
}
String[] split = StringUtils.split(host, ".");
StringBuilder builder = new StringBuilder(split[1]);
for (int i = 2; i < split.length; i++) {
builder.append(".").append(split[i]);
}
return builder.toString();
}
}

View File

@@ -1,11 +1,5 @@
package org.springframework.cloud.netflix.ribbon.eureka;
import static com.netflix.client.config.CommonClientConfigKey.DeploymentContextBasedVipAddresses;
import static com.netflix.client.config.CommonClientConfigKey.EnableZoneAffinity;
import static com.netflix.client.config.CommonClientConfigKey.NFLoadBalancerRuleClassName;
import static com.netflix.client.config.CommonClientConfigKey.NIWSServerListClassName;
import static com.netflix.client.config.CommonClientConfigKey.NIWSServerListFilterClassName;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
@@ -20,11 +14,17 @@ import com.netflix.discovery.EurekaClientConfig;
import com.netflix.loadbalancer.ZoneAvoidanceRule;
import com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList;
import static com.netflix.client.config.CommonClientConfigKey.DeploymentContextBasedVipAddresses;
import static com.netflix.client.config.CommonClientConfigKey.EnableZoneAffinity;
import static com.netflix.client.config.CommonClientConfigKey.NFLoadBalancerRuleClassName;
import static com.netflix.client.config.CommonClientConfigKey.NIWSServerListClassName;
import static com.netflix.client.config.CommonClientConfigKey.NIWSServerListFilterClassName;
/**
* Preprocessor that configures defaults for eureka-discovered ribbon clients. Such as:
* <code>@zone</code>, NIWSServerListClassName, DeploymentContextBasedVipAddresses,
* NFLoadBalancerRuleClassName, NIWSServerListFilterClassName and more
*
*
* @author Spencer Gibb
* @author Dave Syer
*/
@@ -51,9 +51,10 @@ public class EurekaRibbonClientConfiguration {
@PostConstruct
public void preprocess() {
if (clientConfig != null
if (this.clientConfig != null
&& ConfigurationManager.getDeploymentContext().getValue(ContextKey.zone) == null) {
String[] zones = clientConfig.getAvailabilityZones(clientConfig.getRegion());
String[] zones = this.clientConfig.getAvailabilityZones(this.clientConfig
.getRegion());
String zone = zones != null && zones.length > 0 ? zones[0] : null;
if (zone != null) {
// You can set this with archaius.deployment.* (maybe requires
@@ -63,15 +64,15 @@ public class EurekaRibbonClientConfiguration {
}
}
// TODO: should this look more like hibernate spring boot props?
setProp(serviceId, NIWSServerListClassName.key(),
setProp(this.serviceId, NIWSServerListClassName.key(),
DiscoveryEnabledNIWSServerList.class.getName());
// FIXME: what should this be?
setProp(serviceId, DeploymentContextBasedVipAddresses.key(), serviceId);
setProp(serviceId, NFLoadBalancerRuleClassName.key(),
setProp(this.serviceId, DeploymentContextBasedVipAddresses.key(), this.serviceId);
setProp(this.serviceId, NFLoadBalancerRuleClassName.key(),
ZoneAvoidanceRule.class.getName());
setProp(serviceId, NIWSServerListFilterClassName.key(),
setProp(this.serviceId, NIWSServerListFilterClassName.key(),
ZonePreferenceServerListFilter.class.getName());
setProp(serviceId, EnableZoneAffinity.key(), "true");
setProp(this.serviceId, EnableZoneAffinity.key(), "true");
}
protected void setProp(String serviceId, String suffix, String value) {

View File

@@ -30,13 +30,13 @@ import com.netflix.loadbalancer.ZoneAffinityServerListFilter;
/**
* A filter that actively prefers the local zone (as defined by the deployment context, or
* the Eureka instance metadata).
*
*
* @author Dave Syer
*
* TODO: move out of ribbon.eureka package since it has nothing specific to eureka
*/
@Data
@EqualsAndHashCode(callSuper=false)
@EqualsAndHashCode(callSuper = false)
public class ZonePreferenceServerListFilter extends ZoneAffinityServerListFilter<Server> {
private String zone;
@@ -45,17 +45,18 @@ public class ZonePreferenceServerListFilter extends ZoneAffinityServerListFilter
public void initWithNiwsConfig(IClientConfig niwsClientConfig) {
super.initWithNiwsConfig(niwsClientConfig);
if (ConfigurationManager.getDeploymentContext() != null) {
zone = ConfigurationManager.getDeploymentContext().getValue(ContextKey.zone);
this.zone = ConfigurationManager.getDeploymentContext().getValue(
ContextKey.zone);
}
}
@Override
public List<Server> getFilteredListOfServers(List<Server> servers) {
List<Server> output = super.getFilteredListOfServers(servers);
if (zone != null && output.size() == servers.size()) {
if (this.zone != null && output.size() == servers.size()) {
List<Server> local = new ArrayList<Server>();
for (Server server : output) {
if (zone.equalsIgnoreCase(server.getZone())) {
if (this.zone.equalsIgnoreCase(server.getZone())) {
local.add(server);
}
}

View File

@@ -22,6 +22,7 @@ import java.util.List;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.boot.actuate.metrics.Metric;
import org.springframework.boot.actuate.metrics.reader.MetricReader;
@@ -38,7 +39,7 @@ import com.netflix.servo.publish.PollScheduler;
/**
* {@link MetricReader} implementation that registers a {@link MetricObserver} with the
* Netflix Servo library and exposes Servo metrics to the <code>/metric</code> endpoint.
*
*
* @author Dave Syer
* @author Christian Dupuis
*/
@@ -88,8 +89,9 @@ public class ServoMetricCollector implements DisposableBean {
.append(config.getName()).toString().toLowerCase();
if (servoMetric.hasNumberValue()) {
metrics.set(new Metric<Number>(key, servoMetric.getNumberValue(),
new Date(servoMetric.getTimestamp())));
this.metrics.set(new Metric<Number>(key,
servoMetric.getNumberValue(), new Date(servoMetric
.getTimestamp())));
}
}
}

View File

@@ -31,8 +31,8 @@ import org.springframework.context.annotation.Configuration;
import com.netflix.servo.monitor.Monitors;
/**
* Auto configuration to configure Servo support.
*
* Auto configuration to configure Servo support.
*
* @author Dave Syer
* @author Christian Dupuis
*/
@@ -40,9 +40,9 @@ import com.netflix.servo.monitor.Monitors;
@ConditionalOnClass({ Monitors.class, MetricReader.class })
@ConditionalOnBean(MetricReader.class)
@AutoConfigureBefore(EndpointAutoConfiguration.class)
@AutoConfigureAfter({MetricRepositoryAutoConfiguration.class})
@AutoConfigureAfter({ MetricRepositoryAutoConfiguration.class })
public class ServoMetricsAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public ServoMetricCollector servoMetricCollector(MetricWriter metrics) {

View File

@@ -1,21 +1,21 @@
package org.springframework.cloud.netflix.zuul;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Import;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Import;
/**
* Sets up a Zuul server endpoint and installs some reverse proxy filters in it, so it can
* forward requests to backend servers. The backends can be registered manually through
* configuration or via Eureka.
*
*
* @see EnableZuulServer for how to get a Zuul server without any proxying
*
*
* @author Spencer Gibb
* @author Dave Syer
*/

View File

@@ -12,9 +12,9 @@ import org.springframework.context.annotation.Import;
* Set up the application to act as a generic Zuul server without any built-in reverse
* proxy features. The routes into the Zuul server can be configured through
* {@link ZuulProperties} (by default there are none).
*
*
* @see EnableZuulProxy to see how to get reverse proxy out of the box
*
*
* @author Spencer Gibb
*/
@Target(ElementType.TYPE)

View File

@@ -41,12 +41,12 @@ public class ProxyRouteLocator implements RouteLocator {
}
public void addRoute(String path, String location) {
staticRoutes.put(path, new ZuulRoute(path, location));
this.staticRoutes.put(path, new ZuulRoute(path, location));
resetRoutes();
}
public void addRoute(ZuulRoute route) {
staticRoutes.put(route.getPath(), route);
this.staticRoutes.put(route.getPath(), route);
resetRoutes();
}
@@ -57,15 +57,15 @@ public class ProxyRouteLocator implements RouteLocator {
public Map<String, String> getRoutes() {
if (routes.get() == null) {
routes.set(locateRoutes());
if (this.routes.get() == null) {
this.routes.set(locateRoutes());
}
Map<String, String> values = new LinkedHashMap<>();
for (String key : routes.get().keySet()) {
for (String key : this.routes.get().keySet()) {
String url = key;
values.put(url, routes.get().get(key).getLocation());
values.put(url, this.routes.get().get(key).getLocation());
}
return values;
@@ -75,15 +75,15 @@ public class ProxyRouteLocator implements RouteLocator {
String location = null;
String targetPath = null;
String id = null;
String prefix = properties.getPrefix();
for (Entry<String, ZuulRoute> entry : routes.get().entrySet()) {
String prefix = this.properties.getPrefix();
for (Entry<String, ZuulRoute> entry : this.routes.get().entrySet()) {
String pattern = entry.getKey();
if (pathMatcher.match(pattern, path)) {
if (this.pathMatcher.match(pattern, path)) {
ZuulRoute route = entry.getValue();
id = route.getId();
location = route.getLocation();
targetPath = path;
if (path.startsWith(prefix) && properties.isStripPrefix()) {
if (path.startsWith(prefix) && this.properties.isStripPrefix()) {
targetPath = path.substring(prefix.length());
}
if (route.isStripPrefix()) {
@@ -102,7 +102,7 @@ public class ProxyRouteLocator implements RouteLocator {
}
public void resetRoutes() {
routes.set(locateRoutes());
this.routes.set(locateRoutes());
}
protected LinkedHashMap<String, ZuulRoute> locateRoutes() {
@@ -110,16 +110,16 @@ public class ProxyRouteLocator implements RouteLocator {
LinkedHashMap<String, ZuulRoute> routesMap = new LinkedHashMap<>();
addConfiguredRoutes(routesMap);
routesMap.putAll(staticRoutes);
routesMap.putAll(this.staticRoutes);
if (discovery != null) {
if (this.discovery != null) {
// Add routes for discovery services by default
List<String> services = discovery.getServices();
List<String> services = this.discovery.getServices();
for (String serviceId : services) {
// Ignore specifically ignored services and those that were manually
// configured
String key = "/" + serviceId + "/**";
if (!properties.getIgnoredServices().contains(serviceId)
if (!this.properties.getIgnoredServices().contains(serviceId)
&& !routesMap.containsKey(key)) {
routesMap.put(key, new ZuulRoute(key, serviceId));
}
@@ -142,8 +142,8 @@ public class ProxyRouteLocator implements RouteLocator {
path = "/" + path;
}
if (StringUtils.hasText(properties.getPrefix())) {
path = properties.getPrefix() + path;
if (StringUtils.hasText(this.properties.getPrefix())) {
path = this.properties.getPrefix() + path;
if (!path.startsWith("/")) {
path = "/" + path;
}
@@ -158,7 +158,7 @@ public class ProxyRouteLocator implements RouteLocator {
}
protected void addConfiguredRoutes(Map<String, ZuulRoute> routes) {
Map<String, ZuulRoute> routeEntries = properties.getRoutes();
Map<String, ZuulRoute> routeEntries = this.properties.getRoutes();
for (ZuulRoute entry : routeEntries.values()) {
String route = entry.getPath();
if (routes.containsKey(route)) {

View File

@@ -16,7 +16,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
/**
* Endpoint to display and reset the zuul proxy routes
*
*
* @author Spencer Gibb
* @author Dave Syer
*/
@@ -40,7 +40,7 @@ public class RoutesEndpoint implements MvcEndpoint, ApplicationEventPublisherAwa
@ResponseBody
@ManagedOperation
public Map<String, String> reset() {
publisher.publishEvent(new RoutesRefreshedEvent(routes));
this.publisher.publishEvent(new RoutesRefreshedEvent(this.routes));
return getRoutes();
}
@@ -48,7 +48,7 @@ public class RoutesEndpoint implements MvcEndpoint, ApplicationEventPublisherAwa
@ResponseBody
@ManagedAttribute
public Map<String, String> getRoutes() {
return routes.getRoutes();
return this.routes.getRoutes();
}
@Override

View File

@@ -32,7 +32,7 @@ public class RoutesRefreshedEvent extends ApplicationEvent {
}
public RouteLocator getLocator() {
return locator;
return this.locator;
}
}

View File

@@ -35,7 +35,7 @@ public class SimpleRouteLocator implements RouteLocator {
@Override
public Collection<String> getRoutePaths() {
Collection<String> paths = new LinkedHashSet<String>();
for (ZuulRoute route : properties.getRoutes().values()) {
for (ZuulRoute route : this.properties.getRoutes().values()) {
paths.add(route.getPath());
}
return paths;

View File

@@ -34,7 +34,7 @@ public class ZuulConfiguration {
@Bean
public RouteLocator routeLocator() {
return new SimpleRouteLocator(zuulProperties);
return new SimpleRouteLocator(this.zuulProperties);
}
@Bean
@@ -55,7 +55,7 @@ public class ZuulConfiguration {
@Bean
public ZuulFilterInitializer zuulFilterInitializer() {
return new ZuulFilterInitializer(filters);
return new ZuulFilterInitializer(this.filters);
}
}
@@ -74,8 +74,9 @@ public class ZuulConfiguration {
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ContextRefreshedEvent
|| event instanceof RefreshScopeRefreshedEvent)
zuulHandlerMapping.registerHandlers();
|| event instanceof RefreshScopeRefreshedEvent) {
this.zuulHandlerMapping.registerHandlers();
}
}
}

View File

@@ -1,31 +1,34 @@
package org.springframework.cloud.netflix.zuul;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.http.ZuulServlet;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.ServletWrappingController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.ServletWrappingController;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.http.ZuulServlet;
/**
* @author Spencer Gibb
*/
public class ZuulController extends ServletWrappingController {
public ZuulController() {
setServletClass(ZuulServlet.class);
setServletName("zuul");
setSupportedMethods((String[])null); // Allow all
}
public ZuulController() {
setServletClass(ZuulServlet.class);
setServletName("zuul");
setSupportedMethods((String[]) null); // Allow all
}
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {
try {
return super.handleRequestInternal(request, response);
} finally {
// @see com.netflix.zuul.context.ContextLifecycleFilter.doFilter
RequestContext.getCurrentContext().unset();
}
}
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception {
try {
return super.handleRequestInternal(request, response);
}
finally {
// @see com.netflix.zuul.context.ContextLifecycleFilter.doFilter
RequestContext.getCurrentContext().unset();
}
}
}

View File

@@ -17,43 +17,44 @@ import com.netflix.zuul.monitoring.MonitoringHelper;
/**
* @author Spencer Gibb
*
* TODO: .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
*
* TODO: .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
*/
public class ZuulFilterInitializer implements ServletContextListener {
private static final Logger LOGGER = LoggerFactory.getLogger(ZuulFilterInitializer.class);
private static final Logger LOGGER = LoggerFactory
.getLogger(ZuulFilterInitializer.class);
private Map<String, ZuulFilter> filters;
private Map<String, ZuulFilter> filters;
public ZuulFilterInitializer(Map<String, ZuulFilter> filters) {
this.filters = filters;
}
@Override
public void contextInitialized(ServletContextEvent sce) {
public void contextInitialized(ServletContextEvent sce) {
LOGGER.info("Starting filter initializer context listener");
LOGGER.info("Starting filter initializer context listener");
//FIXME: mocks monitoring infrastructure as we don't need it for this simple app
MonitoringHelper.initMocks();
// FIXME: mocks monitoring infrastructure as we don't need it for this simple app
MonitoringHelper.initMocks();
FilterRegistry registry = FilterRegistry.instance();
FilterRegistry registry = FilterRegistry.instance();
for (Map.Entry<String, ZuulFilter> entry : filters.entrySet()) {
registry.put(entry.getKey(), entry.getValue());
}
}
for (Map.Entry<String, ZuulFilter> entry : this.filters.entrySet()) {
registry.put(entry.getKey(), entry.getValue());
}
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
LOGGER.info("Stopping filter initializer context listener");
FilterRegistry registry = FilterRegistry.instance();
for (Map.Entry<String, ZuulFilter> entry : filters.entrySet()) {
registry.remove(entry.getKey());
}
clearLoaderCache();
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
LOGGER.info("Stopping filter initializer context listener");
FilterRegistry registry = FilterRegistry.instance();
for (Map.Entry<String, ZuulFilter> entry : this.filters.entrySet()) {
registry.remove(entry.getKey());
}
clearLoaderCache();
}
private void clearLoaderCache() {
FilterLoader instance = FilterLoader.getInstance();
@@ -64,24 +65,17 @@ public class ZuulFilterInitializer implements ServletContextListener {
cache.clear();
}
/*private void initGroovyFilterManager() {
//TODO: support groovy filters loaded from filesystem in proxy
FilterLoader.getInstance().setCompiler(new GroovyCompiler());
final String scriptRoot = props.getFilterRoot();
LOGGER.info("Using file system script: " + scriptRoot);
try {
FilterFileManager.setFilenameFilter(new GroovyFileFilter());
FilterFileManager.init(5,
scriptRoot + "/pre",
scriptRoot + "/route",
scriptRoot + "/post"
);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}*/
/*
* private void initGroovyFilterManager() {
*
* //TODO: support groovy filters loaded from filesystem in proxy
* FilterLoader.getInstance().setCompiler(new GroovyCompiler());
*
* final String scriptRoot = props.getFilterRoot();
* LOGGER.info("Using file system script: " + scriptRoot);
*
* try { FilterFileManager.setFilenameFilter(new GroovyFileFilter());
* FilterFileManager.init(5, scriptRoot + "/pre", scriptRoot + "/route", scriptRoot +
* "/post" ); } catch (Exception e) { throw new RuntimeException(e); } }
*/
}

View File

@@ -7,7 +7,7 @@ import org.springframework.web.servlet.handler.AbstractUrlHandlerMapping;
/**
* MVC HandlerMapping that maps incoming request paths to remote services.
*
*
* @author Spencer Gibb
* @author Dave Syer
*/
@@ -25,13 +25,13 @@ public class ZuulHandlerMapping extends AbstractUrlHandlerMapping {
}
protected void registerHandlers() {
Collection<String> routes = routeLocator.getRoutePaths();
Collection<String> routes = this.routeLocator.getRoutePaths();
if (routes.isEmpty()) {
logger.warn("No routes found from ProxyRouteLocator");
this.logger.warn("No routes found from ProxyRouteLocator");
}
else {
for (String url : routes) {
registerHandler(url, zuul);
registerHandler(url, this.zuul);
}
}
}

View File

@@ -78,19 +78,19 @@ public class ZuulProperties {
}
public String getLocation() {
if (StringUtils.hasText(url)) {
return url;
if (StringUtils.hasText(this.url)) {
return this.url;
}
return serviceId;
return this.serviceId;
}
public void setLocation(String location) {
if (location != null
&& (location.startsWith("http:") || location.startsWith("https:"))) {
url = location;
this.url = location;
}
else {
serviceId = location;
this.serviceId = location;
}
}

View File

@@ -42,7 +42,7 @@ public class ZuulProxyConfiguration extends ZuulConfiguration {
@Bean
@Override
public ProxyRouteLocator routeLocator() {
return new ProxyRouteLocator(discovery, zuulProperties);
return new ProxyRouteLocator(this.discovery, this.zuulProperties);
}
@Configuration
@@ -54,32 +54,32 @@ public class ZuulProxyConfiguration extends ZuulConfiguration {
@Bean
// @RefreshScope
public RoutesEndpoint zuulEndpoint() {
return new RoutesEndpoint(routeLocator);
return new RoutesEndpoint(this.routeLocator);
}
}
// pre filters
@Bean
public PreDecorationFilter preDecorationFilter() {
return new PreDecorationFilter(routeLocator(), zuulProperties);
return new PreDecorationFilter(routeLocator(), this.zuulProperties);
}
// route filters
@Bean
public RibbonRoutingFilter ribbonRoutingFilter() {
ProxyRequestHelper helper = new ProxyRequestHelper();
if (traces != null) {
helper.setTraces(traces);
if (this.traces != null) {
helper.setTraces(this.traces);
}
RibbonRoutingFilter filter = new RibbonRoutingFilter(helper, clientFactory);
RibbonRoutingFilter filter = new RibbonRoutingFilter(helper, this.clientFactory);
return filter;
}
@Bean
public SimpleHostRoutingFilter simpleHostRoutingFilter() {
ProxyRequestHelper helper = new ProxyRequestHelper();
if (traces != null) {
helper.setTraces(traces);
if (this.traces != null) {
helper.setTraces(this.traces);
}
return new SimpleHostRoutingFilter(helper);
}
@@ -110,9 +110,9 @@ public class ZuulProxyConfiguration extends ZuulConfiguration {
}
else if (event instanceof DiscoveryHeartbeatEvent) {
DiscoveryHeartbeatEvent e = (DiscoveryHeartbeatEvent) event;
if (latestHeartbeat.get() == null
|| !latestHeartbeat.get().equals(e.getValue())) {
latestHeartbeat.set(e.getValue());
if (this.latestHeartbeat.get() == null
|| !this.latestHeartbeat.get().equals(e.getValue())) {
this.latestHeartbeat.set(e.getValue());
reset();
}
}
@@ -120,8 +120,8 @@ public class ZuulProxyConfiguration extends ZuulConfiguration {
}
private void reset() {
routeLocator.resetRoutes();
zuulHandlerMapping.registerHandlers();
this.routeLocator.resetRoutes();
this.zuulHandlerMapping.registerHandlers();
}
}

View File

@@ -63,8 +63,9 @@ public class ProxyRequestHelper {
Map<String, List<String>> map = HTTPRequestUtils.getInstance().getQueryParams();
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
if (map == null)
if (map == null) {
return params;
}
for (String key : map.keySet()) {
@@ -86,8 +87,9 @@ public class ProxyRequestHelper {
while (headerNames.hasMoreElements()) {
String name = (String) headerNames.nextElement();
String value = request.getHeader(name);
if (isIncludedHeader(name))
if (isIncludedHeader(name)) {
headers.set(name, value);
}
}
}
Map<String, String> zuulRequestHeaders = context.getZuulRequestHeaders();
@@ -129,8 +131,9 @@ public class ProxyRequestHelper {
for (String value : header.getValue()) {
ctx.addOriginResponseHeader(name, value);
if (name.equalsIgnoreCase("content-length"))
if (name.equalsIgnoreCase("content-length")) {
ctx.setOriginContentLength(value);
}
if (isIncludedHeader(name)) {
ctx.addZuulResponseHeader(name, value);
@@ -179,7 +182,7 @@ public class ProxyRequestHelper {
InputStream requestEntity) throws IOException {
Map<String, Object> info = new LinkedHashMap<String, Object>();
if (traces != null) {
if (this.traces != null) {
RequestContext context = RequestContext.getCurrentContext();
StringBuilder query = new StringBuilder();
@@ -216,7 +219,7 @@ public class ProxyRequestHelper {
debugRequestEntity(info, ctx.getRequest().getInputStream());
}
}
traces.add(info);
this.traces.add(info);
return info;
}
return info;
@@ -224,7 +227,7 @@ public class ProxyRequestHelper {
public void appendDebug(Map<String, Object> info, int status,
MultiValueMap<String, String> headers) {
if (traces != null) {
if (this.traces != null) {
@SuppressWarnings("unchecked")
Map<String, Object> trace = (Map<String, Object>) info.get("headers");
Map<String, Object> output = new LinkedHashMap<String, Object>();

View File

@@ -1,12 +1,14 @@
package org.springframework.cloud.netflix.zuul.filters.post;
import javax.servlet.RequestDispatcher;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import com.google.common.base.Throwables;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import javax.servlet.RequestDispatcher;
/**
* @author Spencer Gibb
@@ -14,53 +16,56 @@ import javax.servlet.RequestDispatcher;
@Slf4j
public class SendErrorFilter extends ZuulFilter {
protected static final String SEND_ERROR_FILTER_RAN = "sendErrorFilter.ran";
protected static final String SEND_ERROR_FILTER_RAN = "sendErrorFilter.ran";
@Value("${error.path:/error}")
private String errorPath;
@Value("${error.path:/error}")
private String errorPath;
@Override
public String filterType() {
return "post";
}
@Override
public String filterType() {
return "post";
}
@Override
public int filterOrder() {
return 0;
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
RequestContext ctx = RequestContext.getCurrentContext();
//only forward to errorPath if it hasn't been forwarded to already
return ctx.containsKey("error.status_code") && !ctx.getBoolean(SEND_ERROR_FILTER_RAN, false);
}
@Override
public boolean shouldFilter() {
RequestContext ctx = RequestContext.getCurrentContext();
// only forward to errorPath if it hasn't been forwarded to already
return ctx.containsKey("error.status_code")
&& !ctx.getBoolean(SEND_ERROR_FILTER_RAN, false);
}
@Override
public Object run() {
try {
RequestContext ctx = RequestContext.getCurrentContext();
int statusCode = (Integer)ctx.get("error.status_code");
if (ctx.containsKey("error.exception")) {
Object e = ctx.get("error.exception");
log.warn("Error during filtering", Throwable.class.cast(e));
ctx.getRequest().setAttribute("javax.servlet.error.exception", e);
}
ctx.getRequest().setAttribute("javax.servlet.error.status_code", statusCode);
RequestDispatcher dispatcher = ctx.getRequest().getRequestDispatcher(errorPath);
@Override
public Object run() {
try {
RequestContext ctx = RequestContext.getCurrentContext();
int statusCode = (Integer) ctx.get("error.status_code");
if (ctx.containsKey("error.exception")) {
Object e = ctx.get("error.exception");
log.warn("Error during filtering", Throwable.class.cast(e));
ctx.getRequest().setAttribute("javax.servlet.error.exception", e);
}
ctx.getRequest().setAttribute("javax.servlet.error.status_code", statusCode);
RequestDispatcher dispatcher = ctx.getRequest().getRequestDispatcher(
this.errorPath);
if (dispatcher != null) {
ctx.set(SEND_ERROR_FILTER_RAN, true);
if (!ctx.getResponse().isCommitted()) {
dispatcher.forward(ctx.getRequest(), ctx.getResponse());
}
if (!ctx.getResponse().isCommitted()) {
dispatcher.forward(ctx.getRequest(), ctx.getResponse());
}
}
} catch (Exception e) {
Throwables.propagate(e);
}
return null;
}
}
catch (Exception e) {
Throwables.propagate(e);
}
return null;
}
public void setErrorPath(String errorPath) {
this.errorPath = errorPath;
}
public void setErrorPath(String errorPath) {
this.errorPath = errorPath;
}
}

View File

@@ -43,12 +43,14 @@ public class SendResponseFilter extends ZuulFilter {
return 1000;
}
@Override
public boolean shouldFilter() {
return !RequestContext.getCurrentContext().getZuulResponseHeaders().isEmpty()
|| RequestContext.getCurrentContext().getResponseDataStream() != null
|| RequestContext.getCurrentContext().getResponseBody() != null;
}
@Override
public Object run() {
try {
addResponseHeaders();
@@ -64,8 +66,9 @@ public class SendResponseFilter extends ZuulFilter {
RequestContext context = RequestContext.getCurrentContext();
// there is no body to send
if (context.getResponseBody() == null && context.getResponseDataStream() == null)
if (context.getResponseBody() == null && context.getResponseDataStream() == null) {
return;
}
HttpServletResponse servletResponse = context.getResponse();
servletResponse.setCharacterEncoding("UTF-8");
@@ -82,8 +85,9 @@ public class SendResponseFilter extends ZuulFilter {
boolean isGzipRequested = false;
final String requestEncoding = context.getRequest().getHeader(
ZuulHeaders.ACCEPT_ENCODING);
if (requestEncoding != null && requestEncoding.equals("gzip"))
if (requestEncoding != null && requestEncoding.equals("gzip")) {
isGzipRequested = true;
}
is = context.getResponseDataStream();
InputStream inputStream = is;
@@ -93,7 +97,7 @@ public class SendResponseFilter extends ZuulFilter {
// decompress stream
// before sending to client
// else, stream gzip directly to client
if (context.getResponseGZipped() && !isGzipRequested)
if (context.getResponseGZipped() && !isGzipRequested) {
try {
inputStream = new GZIPInputStream(is);
@@ -106,8 +110,10 @@ public class SendResponseFilter extends ZuulFilter {
.toString());
inputStream = is;
}
else if (context.getResponseGZipped() && isGzipRequested)
}
else if (context.getResponseGZipped() && isGzipRequested) {
servletResponse.setHeader(ZuulHeaders.CONTENT_ENCODING, "gzip");
}
writeResponse(inputStream, outStream);
}
}
@@ -115,8 +121,9 @@ public class SendResponseFilter extends ZuulFilter {
}
finally {
try {
if (is != null)
if (is != null) {
is.close();
}
outStream.flush();
outStream.close();
@@ -164,8 +171,9 @@ public class SendResponseFilter extends ZuulFilter {
for (String it : rd) {
debugHeader.append("[[[" + it + "]]]");
}
if (INCLUDE_DEBUG_HEADER.get())
if (INCLUDE_DEBUG_HEADER.get()) {
servletResponse.addHeader("X-Zuul-Debug-Header", debugHeader.toString());
}
}
if (zuulResponseHeaders != null) {
@@ -180,8 +188,9 @@ public class SendResponseFilter extends ZuulFilter {
// Only inserts Content-Length if origin provides it and origin response is not
// gzipped
if (SET_CONTENT_LENGTH.get()) {
if (contentLength != null && !ctx.getResponseGZipped())
if (contentLength != null && !ctx.getResponseGZipped()) {
servletResponse.setContentLength(contentLength);
}
}
}

View File

@@ -1,5 +1,7 @@
package org.springframework.cloud.netflix.zuul.filters.pre;
import javax.servlet.http.HttpServletRequest;
import com.netflix.config.DynamicBooleanProperty;
import com.netflix.config.DynamicPropertyFactory;
import com.netflix.config.DynamicStringProperty;
@@ -7,42 +9,39 @@ import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.constants.ZuulConstants;
import com.netflix.zuul.context.RequestContext;
import javax.servlet.http.HttpServletRequest;
public class DebugFilter extends ZuulFilter {
static final DynamicBooleanProperty routingDebug = DynamicPropertyFactory.getInstance()
.getBooleanProperty(ZuulConstants.ZUUL_DEBUG_REQUEST, false);
static final DynamicStringProperty debugParameter = DynamicPropertyFactory.getInstance()
.getStringProperty(ZuulConstants.ZUUL_DEBUG_PARAMETER, "debug");
static final DynamicBooleanProperty routingDebug = DynamicPropertyFactory
.getInstance().getBooleanProperty(ZuulConstants.ZUUL_DEBUG_REQUEST, false);
static final DynamicStringProperty debugParameter = DynamicPropertyFactory
.getInstance().getStringProperty(ZuulConstants.ZUUL_DEBUG_PARAMETER, "debug");
@Override
public String filterType() {
return "pre";
}
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 1;
}
@Override
public int filterOrder() {
return 1;
}
public boolean shouldFilter() {
HttpServletRequest request = RequestContext.getCurrentContext().getRequest();
if ("true".equals(request.getParameter(debugParameter.get())))
return true;
@Override
public boolean shouldFilter() {
HttpServletRequest request = RequestContext.getCurrentContext().getRequest();
if ("true".equals(request.getParameter(debugParameter.get()))) {
return true;
}
return routingDebug.get();
}
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
ctx.setDebugRouting(true);
ctx.setDebugRequest(true);
return null;
}
return routingDebug.get();
}
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
ctx.setDebugRouting(true);
ctx.setDebugRequest(true);
return null;
}
}

View File

@@ -26,10 +26,10 @@ public class FormBodyWrapperFilter extends ZuulFilter {
protected Field requestField = null;
public FormBodyWrapperFilter() {
requestField = ReflectionUtils.findField(HttpServletRequestWrapper.class, "req",
HttpServletRequest.class);
Assert.notNull(requestField, "HttpServletRequestWrapper.req field not found");
requestField.setAccessible(true);
this.requestField = ReflectionUtils.findField(HttpServletRequestWrapper.class,
"req", HttpServletRequest.class);
Assert.notNull(this.requestField, "HttpServletRequestWrapper.req field not found");
this.requestField.setAccessible(true);
}
@Override
@@ -48,15 +48,17 @@ public class FormBodyWrapperFilter extends ZuulFilter {
HttpServletRequest request = ctx.getRequest();
String contentType = request.getContentType();
//Don't use this filter on GET method
if(contentType == null) {
// Don't use this filter on GET method
if (contentType == null) {
return false;
}
//Only use this filter for MediaType : application/x-www-form-urlencoded
// Only use this filter for MediaType : application/x-www-form-urlencoded
try {
return MediaType.APPLICATION_FORM_URLENCODED.includes(MediaType.valueOf(contentType));
} catch (InvalidMediaTypeException imte) {
return MediaType.APPLICATION_FORM_URLENCODED.includes(MediaType
.valueOf(contentType));
}
catch (InvalidMediaTypeException imte) {
return false;
}
}
@@ -67,8 +69,9 @@ public class FormBodyWrapperFilter extends ZuulFilter {
HttpServletRequest request = ctx.getRequest();
if (request instanceof HttpServletRequestWrapper) {
try {
HttpServletRequest wrapped = (HttpServletRequest) requestField.get(request);
requestField.set(request, new FormBodyRequestWrapper(wrapped));
HttpServletRequest wrapped = (HttpServletRequest) this.requestField
.get(request);
this.requestField.set(request, new FormBodyRequestWrapper(wrapped));
}
catch (IllegalAccessException e) {
Throwables.propagate(e);
@@ -92,28 +95,29 @@ public class FormBodyWrapperFilter extends ZuulFilter {
@Override
public int getContentLength() {
if (contentData == null) {
contentData = buildContentData();
if (this.contentData == null) {
this.contentData = buildContentData();
}
return contentData.length;
return this.contentData.length;
}
@Override
public ServletInputStream getInputStream() throws IOException {
if (RequestContext.getCurrentContext().isChunkedRequestBody()) {
return request.getInputStream();
return this.request.getInputStream();
}
else {
if (contentData == null) {
contentData = buildContentData();
if (this.contentData == null) {
this.contentData = buildContentData();
}
return new ServletInputStreamWrapper(contentData);
return new ServletInputStreamWrapper(this.contentData);
}
}
private byte[] buildContentData() {
StringBuilder builder = new StringBuilder();
for (Entry<String, String[]> entry : request.getParameterMap().entrySet()) {
for (Entry<String, String[]> entry : this.request.getParameterMap()
.entrySet()) {
for (String value : entry.getValue()) {
if (builder.length() != 0) {
builder.append("&");

View File

@@ -48,14 +48,14 @@ public class PreDecorationFilter extends ZuulFilter {
final String requestURI = ctx.getRequest().getRequestURI();
ProxyRouteSpec route = routeLocator.getMatchingRoute(requestURI);
ProxyRouteSpec route = this.routeLocator.getMatchingRoute(requestURI);
if (route != null) {
String location = route.getLocation();
if (location != null) {
ctx.put("requestURI", route.getPath());
ctx.put("proxy", route.getId());
@@ -70,7 +70,7 @@ public class PreDecorationFilter extends ZuulFilter {
ctx.addOriginResponseHeader("X-Zuul-ServiceId", location);
}
if (properties.isAddProxyHeaders()) {
if (this.properties.isAddProxyHeaders()) {
ctx.addZuulRequestHeader(
"X-Forwarded-Host",
ctx.getRequest().getServerName() + ":"

View File

@@ -1,130 +1,142 @@
package org.springframework.cloud.netflix.zuul.filters.pre;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Collection;
import javax.servlet.AsyncContext;
import javax.servlet.DispatcherType;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
import com.google.common.base.Throwables;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.http.HttpServletRequestWrapper;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Collection;
/**
* @author Spencer Gibb
*/
public class Servlet30WrapperFilter extends ZuulFilter {
protected Field requestField = null;
protected Field requestField = null;
public Servlet30WrapperFilter() {
requestField = ReflectionUtils.findField(HttpServletRequestWrapper.class, "req",
HttpServletRequest.class);
Assert.notNull(requestField, "HttpServletRequestWrapper.req field not found");
requestField.setAccessible(true);
}
public Servlet30WrapperFilter() {
this.requestField = ReflectionUtils.findField(HttpServletRequestWrapper.class,
"req", HttpServletRequest.class);
Assert.notNull(this.requestField, "HttpServletRequestWrapper.req field not found");
this.requestField.setAccessible(true);
}
@Override
public String filterType() {
return "pre";
}
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 0;
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
return true; //TODO: only if in servlet 3.0 env
}
@Override
public boolean shouldFilter() {
return true; // TODO: only if in servlet 3.0 env
}
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
if (request instanceof HttpServletRequestWrapper) {
try {
request = (HttpServletRequest) requestField.get(request);
} catch (IllegalAccessException e) {
Throwables.propagate(e);
}
}
ctx.setRequest(new Servlet30RequestWrapper(request));
//ctx.setResponse(new HttpServletResponseWrapper(ctx.getResponse()));
return null;
}
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
if (request instanceof HttpServletRequestWrapper) {
try {
request = (HttpServletRequest) this.requestField.get(request);
}
catch (IllegalAccessException e) {
Throwables.propagate(e);
}
}
ctx.setRequest(new Servlet30RequestWrapper(request));
// ctx.setResponse(new HttpServletResponseWrapper(ctx.getResponse()));
return null;
}
private class Servlet30RequestWrapper extends HttpServletRequestWrapper {
private HttpServletRequest request;
private class Servlet30RequestWrapper extends HttpServletRequestWrapper {
private HttpServletRequest request;
Servlet30RequestWrapper(HttpServletRequest request) {
super(request);
this.request = request;
}
Servlet30RequestWrapper(HttpServletRequest request) {
super(request);
this.request = request;
}
@Override
public boolean authenticate(HttpServletResponse response) throws IOException, ServletException {
return request.authenticate(response);
}
@Override
public boolean authenticate(HttpServletResponse response) throws IOException,
ServletException {
return this.request.authenticate(response);
}
@Override
public void login(String username, String password) throws ServletException {
request.login(username, password);
}
@Override
public void login(String username, String password) throws ServletException {
this.request.login(username, password);
}
@Override
public void logout() throws ServletException {
request.logout();
}
@Override
public void logout() throws ServletException {
this.request.logout();
}
@Override
public Collection<Part> getParts() throws IOException, IllegalStateException, ServletException {
return request.getParts();
}
@Override
public Collection<Part> getParts() throws IOException, IllegalStateException,
ServletException {
return this.request.getParts();
}
@Override
public Part getPart(String name) throws IOException, IllegalStateException, ServletException {
return request.getPart(name);
}
@Override
public Part getPart(String name) throws IOException, IllegalStateException,
ServletException {
return this.request.getPart(name);
}
@Override
public ServletContext getServletContext() {
return request.getServletContext();
}
@Override
public ServletContext getServletContext() {
return this.request.getServletContext();
}
@Override
public AsyncContext startAsync() {
return request.startAsync();
}
@Override
public AsyncContext startAsync() {
return this.request.startAsync();
}
@Override
public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) {
return request.startAsync(servletRequest, servletResponse);
}
@Override
public AsyncContext startAsync(ServletRequest servletRequest,
ServletResponse servletResponse) {
return this.request.startAsync(servletRequest, servletResponse);
}
@Override
public boolean isAsyncStarted() {
return request.isAsyncStarted();
}
@Override
public boolean isAsyncStarted() {
return this.request.isAsyncStarted();
}
@Override
public boolean isAsyncSupported() {
return request.isAsyncSupported();
}
@Override
public boolean isAsyncSupported() {
return this.request.isAsyncSupported();
}
@Override
public AsyncContext getAsyncContext() {
return request.getAsyncContext();
}
@Override
public AsyncContext getAsyncContext() {
return this.request.getAsyncContext();
}
@Override
public DispatcherType getDispatcherType() {
return request.getDispatcherType();
}
}
@Override
public DispatcherType getDispatcherType() {
return this.request.getDispatcherType();
}
}
}

View File

@@ -22,87 +22,94 @@ import com.netflix.zuul.context.RequestContext;
/**
* Hystrix wrapper around Eureka Ribbon command
*
* see original https://github.com/Netflix/zuul/blob/master/zuul-netflix/src/main/java/com/netflix/zuul/dependency/ribbon/hystrix/RibbonCommand.java
* see original
* https://github.com/Netflix/zuul/blob/master/zuul-netflix/src/main/java/com/
* netflix/zuul/dependency/ribbon/hystrix/RibbonCommand.java
*/
public class RibbonCommand extends HystrixCommand<HttpResponse> {
private RestClient restClient;
private Verb verb;
private URI uri;
private MultivaluedMap<String, String> headers;
private MultivaluedMap<String, String> params;
private InputStream requestEntity;
private RestClient restClient;
private Verb verb;
private URI uri;
private MultivaluedMap<String, String> headers;
private MultivaluedMap<String, String> params;
private InputStream requestEntity;
public RibbonCommand(RestClient restClient,
Verb verb,
String uri,
MultivaluedMap<String, String> headers,
MultivaluedMap<String, String> params,
InputStream requestEntity) throws URISyntaxException {
this("default", restClient, verb, uri, headers, params, requestEntity);
}
public RibbonCommand(RestClient restClient, Verb verb, String uri,
MultivaluedMap<String, String> headers,
MultivaluedMap<String, String> params, InputStream requestEntity)
throws URISyntaxException {
this("default", restClient, verb, uri, headers, params, requestEntity);
}
public RibbonCommand(String commandKey,
RestClient restClient,
Verb verb,
String uri,
MultivaluedMap<String, String> headers,
MultivaluedMap<String, String> params,
InputStream requestEntity) throws URISyntaxException {
public RibbonCommand(String commandKey, RestClient restClient, Verb verb, String uri,
MultivaluedMap<String, String> headers,
MultivaluedMap<String, String> params, InputStream requestEntity)
throws URISyntaxException {
super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(commandKey)).andCommandPropertiesDefaults(
// we want to default to semaphore-isolation since this wraps
// 2 others commands that are already thread isolated
HystrixCommandProperties.Setter().withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE)
.withExecutionIsolationSemaphoreMaxConcurrentRequests(DynamicPropertyFactory.getInstance().
getIntProperty(ZuulConstants.ZUUL_EUREKA + commandKey + ".semaphore.maxSemaphores", 100).get())));
super(
Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(commandKey))
.andCommandPropertiesDefaults(
// we want to default to semaphore-isolation since this wraps
// 2 others commands that are already thread isolated
HystrixCommandProperties
.Setter()
.withExecutionIsolationStrategy(
HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE)
.withExecutionIsolationSemaphoreMaxConcurrentRequests(
DynamicPropertyFactory
.getInstance()
.getIntProperty(
ZuulConstants.ZUUL_EUREKA
+ commandKey
+ ".semaphore.maxSemaphores",
100).get())));
this.restClient = restClient;
this.verb = verb;
this.uri = new URI(uri);
this.headers = headers;
this.params = params;
this.requestEntity = requestEntity;
}
this.restClient = restClient;
this.verb = verb;
this.uri = new URI(uri);
this.headers = headers;
this.params = params;
this.requestEntity = requestEntity;
}
@Override
protected HttpResponse run() throws Exception {
try {
return forward();
} catch (Exception e) {
throw e;
}
}
@Override
protected HttpResponse run() throws Exception {
try {
return forward();
}
catch (Exception e) {
throw e;
}
}
private HttpResponse forward() throws Exception {
private HttpResponse forward() throws Exception {
RequestContext context = RequestContext.getCurrentContext();
RequestContext context = RequestContext.getCurrentContext();
Builder builder = HttpRequest.newBuilder().
verb(verb).
uri(uri).
entity(requestEntity);
Builder builder = HttpRequest.newBuilder().verb(this.verb).uri(this.uri)
.entity(this.requestEntity);
for (String name : headers.keySet()) {
List<String> values = headers.get(name);
for (String value : values) {
builder.header(name, value);
}
}
for (String name : this.headers.keySet()) {
List<String> values = this.headers.get(name);
for (String value : values) {
builder.header(name, value);
}
}
for (String name : params.keySet()) {
List<String> values = params.get(name);
for (String value : values) {
builder.queryParams(name, value);
}
}
for (String name : this.params.keySet()) {
List<String> values = this.params.get(name);
for (String value : values) {
builder.queryParams(name, value);
}
}
HttpRequest httpClientRequest = builder.build();
HttpResponse response = restClient.executeWithLoadBalancer(httpClientRequest);
context.set("ribbonResponse", response);
return response;
}
HttpRequest httpClientRequest = builder.build();
HttpResponse response = this.restClient
.executeWithLoadBalancer(httpClientRequest);
context.set("ribbonResponse", response);
return response;
}
}

View File

@@ -59,25 +59,28 @@ public class RibbonRoutingFilter extends ZuulFilter {
return 10;
}
@Override
public boolean shouldFilter() {
RequestContext ctx = RequestContext.getCurrentContext();
return (ctx.getRouteHost() == null && ctx.get("serviceId") != null && ctx
.sendZuulResponse());
}
@Override
public Object run() {
RequestContext context = RequestContext.getCurrentContext();
HttpServletRequest request = context.getRequest();
MultiValueMap<String, String> headers = helper.buildZuulRequestHeaders(request);
MultiValueMap<String, String> params = helper
MultiValueMap<String, String> headers = this.helper
.buildZuulRequestHeaders(request);
MultiValueMap<String, String> params = this.helper
.buildZuulRequestQueryParams(request);
Verb verb = getVerb(request);
InputStream requestEntity = getRequestBody(request);
String serviceId = (String) context.get("serviceId");
RestClient restClient = clientFactory.getClient(serviceId, RestClient.class);
RestClient restClient = this.clientFactory.getClient(serviceId, RestClient.class);
String uri = request.getRequestURI();
if (context.get("requestURI") != null) {
@@ -103,14 +106,14 @@ public class RibbonRoutingFilter extends ZuulFilter {
MultiValueMap<String, String> headers, MultiValueMap<String, String> params,
InputStream requestEntity) throws Exception {
Map<String, Object> info = helper.debug(verb.verb(), uri, headers, params,
Map<String, Object> info = this.helper.debug(verb.verb(), uri, headers, params,
requestEntity);
RibbonCommand command = new RibbonCommand(restClient, verb, uri,
convertHeaders(headers), convertHeaders(params), requestEntity);
try {
HttpResponse response = command.execute();
helper.appendDebug(info, response.getStatus(),
this.helper.appendDebug(info, response.getStatus(),
revertHeaders(response.getHeaders()));
return response;
}
@@ -174,24 +177,30 @@ public class RibbonRoutingFilter extends ZuulFilter {
}
Verb getVerb(String sMethod) {
if (sMethod == null)
if (sMethod == null) {
return Verb.GET;
}
sMethod = sMethod.toLowerCase();
if (sMethod.equals("post"))
if (sMethod.equals("post")) {
return Verb.POST;
if (sMethod.equals("put"))
}
if (sMethod.equals("put")) {
return Verb.PUT;
if (sMethod.equals("delete"))
}
if (sMethod.equals("delete")) {
return Verb.DELETE;
if (sMethod.equals("options"))
}
if (sMethod.equals("options")) {
return Verb.OPTIONS;
if (sMethod.equals("head"))
}
if (sMethod.equals("head")) {
return Verb.HEAD;
}
return Verb.GET;
}
private void setResponse(HttpResponse resp) throws ClientException, IOException {
helper.setResponse(resp.getStatus(),
this.helper.setResponse(resp.getStatus(),
!resp.hasEntity() ? null : resp.getInputStream(),
revertHeaders(resp.getHeaders()));
}

View File

@@ -85,7 +85,8 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
private static final AtomicReference<HttpClient> CLIENT = new AtomicReference<HttpClient>(
newClient());
private static final Timer CONNECTION_MANAGER_TIMER = new Timer("SimpleHostRoutingFilter.CONNECTION_MANAGER_TIMER", true);
private static final Timer CONNECTION_MANAGER_TIMER = new Timer(
"SimpleHostRoutingFilter.CONNECTION_MANAGER_TIMER", true);
// cleans expired connections at an interval
static {
@@ -96,8 +97,9 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
public void run() {
try {
final HttpClient hc = CLIENT.get();
if (hc == null)
if (hc == null) {
return;
}
hc.getConnectionManager().closeExpiredConnections();
}
catch (Throwable t) {
@@ -153,6 +155,7 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
return 100;
}
@Override
public boolean shouldFilter() {
return RequestContext.getCurrentContext().getRouteHost() != null
&& RequestContext.getCurrentContext().sendZuulResponse();
@@ -213,11 +216,13 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
}
}
@Override
public Object run() {
RequestContext context = RequestContext.getCurrentContext();
HttpServletRequest request = context.getRequest();
MultiValueMap<String, String> headers = helper.buildZuulRequestHeaders(request);
MultiValueMap<String, String> params = helper
MultiValueMap<String, String> headers = this.helper
.buildZuulRequestHeaders(request);
MultiValueMap<String, String> params = this.helper
.buildZuulRequestQueryParams(request);
String verb = getVerb(request);
InputStream requestEntity = getRequestBody(request);
@@ -245,8 +250,8 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
MultiValueMap<String, String> params, InputStream requestEntity)
throws Exception {
Map<String, Object> info = helper
.debug(verb, uri, headers, params, requestEntity);
Map<String, Object> info = this.helper.debug(verb, uri, headers, params,
requestEntity);
URL host = RequestContext.getCurrentContext().getRouteHost();
HttpHost httpHost = getHttpHost(host);
@@ -277,7 +282,7 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
LOG.debug(httpHost.getHostName() + " " + httpHost.getPort() + " "
+ httpHost.getSchemeName());
HttpResponse zuulResponse = forwardRequest(httpclient, httpHost, httpRequest);
helper.appendDebug(info, zuulResponse.getStatusLine().getStatusCode(),
this.helper.appendDebug(info, zuulResponse.getStatusLine().getStatusCode(),
revertHeaders(zuulResponse.getAllHeaders()));
return zuulResponse;
}
@@ -346,7 +351,7 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
}
private void setResponse(HttpResponse response) throws IOException {
helper.setResponse(response.getStatusLine().getStatusCode(),
this.helper.setResponse(response.getStatusLine().getStatusCode(),
response.getEntity() == null ? null : response.getEntity().getContent(),
revertHeaders(response.getAllHeaders()));
}
@@ -359,14 +364,17 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
super(truststore);
TrustManager tm = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
@@ -374,19 +382,19 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
TrustManager[] tms = new TrustManager[1];
tms[0] = tm;
sslContext.init(null, tms, null);
this.sslContext.init(null, tms, null);
}
@Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose)
throws IOException, UnknownHostException {
return sslContext.getSocketFactory().createSocket(socket, host, port,
return this.sslContext.getSocketFactory().createSocket(socket, host, port,
autoClose);
}
@Override
public Socket createSocket() throws IOException {
return sslContext.getSocketFactory().createSocket();
return this.sslContext.getSocketFactory().createSocket();
}
}
}

View File

@@ -29,7 +29,8 @@ import org.springframework.cloud.netflix.zuul.SimpleZuulServerApplicationTests;
* @author Dave Syer
*/
@RunWith(Suite.class)
@SuiteClasses({ SimpleZuulServerApplicationTests.class, SampleZuulProxyApplicationTests.class })
@SuiteClasses({ SimpleZuulServerApplicationTests.class,
SampleZuulProxyApplicationTests.class })
@Ignore
public class AdhocTestSuite {

View File

@@ -15,13 +15,13 @@
*/
package org.springframework.cloud.netflix.archaius;
import static org.junit.Assert.assertNotNull;
import org.apache.commons.configuration.AbstractConfiguration;
import org.junit.After;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import static org.junit.Assert.assertNotNull;
/**
* @author Dave Syer
*
@@ -29,18 +29,20 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
public class ArchaiusAutoConfigurationTests {
private AnnotationConfigApplicationContext context;
@After
public void close() {
if (context!=null) {
context.close();
if (this.context != null) {
this.context.close();
}
}
@Test
public void configurationCreated() {
context = new AnnotationConfigApplicationContext(ArchaiusAutoConfiguration.class);
AbstractConfiguration config = context.getBean(ConfigurableEnvironmentConfiguration.class);
this.context = new AnnotationConfigApplicationContext(
ArchaiusAutoConfiguration.class);
AbstractConfiguration config = this.context
.getBean(ConfigurableEnvironmentConfiguration.class);
assertNotNull(config.getString("java.io.tmpdir"));
}

View File

@@ -15,9 +15,6 @@
*/
package org.springframework.cloud.netflix.archaius;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.Map;
import org.junit.Test;
@@ -26,6 +23,9 @@ import org.springframework.core.env.StandardEnvironment;
import com.netflix.config.ConcurrentCompositeConfiguration;
import com.netflix.config.ConfigurationManager;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* @author Dave Syer
*
@@ -37,17 +37,19 @@ public class ArchaiusEndpointTests {
@Test
public void detectsPropertiesWhenSet() {
ConfigurationManager.getConfigInstance().setProperty("foo", "bar");
assertTrue(endpoint.invoke().containsKey("foo"));
assertTrue(this.endpoint.invoke().containsKey("foo"));
}
@Test
public void doesNotIncludeSpringEnvironment() {
ConcurrentCompositeConfiguration composite = new ConcurrentCompositeConfiguration(ConfigurationManager.getConfigInstance());
ConfigurableEnvironmentConfiguration config = new ConfigurableEnvironmentConfiguration(new StandardEnvironment());
ConcurrentCompositeConfiguration composite = new ConcurrentCompositeConfiguration(
ConfigurationManager.getConfigInstance());
ConfigurableEnvironmentConfiguration config = new ConfigurableEnvironmentConfiguration(
new StandardEnvironment());
assertTrue(config.containsKey("user.dir"));
composite.addConfiguration(config);
ConfigurationManager.getConfigInstance().setProperty("foo", "bar");
Map<String, Object> map = endpoint.invoke();
Map<String, Object> map = this.endpoint.invoke();
assertTrue(map.containsKey("foo"));
assertFalse(map.containsKey("user.dir"));
}

View File

@@ -15,8 +15,6 @@
*/
package org.springframework.cloud.netflix.config;
import static org.junit.Assert.assertEquals;
import org.junit.After;
import org.junit.Test;
import org.mockito.Mockito;
@@ -28,6 +26,8 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.DiscoveryClient;
import static org.junit.Assert.assertEquals;
/**
* @author Dave Syer
*
@@ -43,41 +43,45 @@ public class DiscoveryClientConfigServiceBootstrapConfigurationTests {
@After
public void close() {
if (context != null) {
context.close();
if (this.context != null) {
this.context.close();
}
}
@Test
public void offByDefault() throws Exception {
context = new AnnotationConfigApplicationContext(
this.context = new AnnotationConfigApplicationContext(
DiscoveryClientConfigServiceBootstrapConfiguration.class);
assertEquals(0, context.getBeanNamesForType(DiscoveryClient.class).length);
assertEquals(0, this.context.getBeanNamesForType(DiscoveryClient.class).length);
assertEquals(
0,
context.getBeanNamesForType(DiscoveryClientConfigServiceBootstrapConfiguration.class).length);
this.context
.getBeanNamesForType(DiscoveryClientConfigServiceBootstrapConfiguration.class).length);
}
@Test
public void onWhenRequested() throws Exception {
Mockito.when(client.getNextServerFromEureka("CONFIGSERVER", false)).thenReturn(
info);
Mockito.when(this.client.getNextServerFromEureka("CONFIGSERVER", false))
.thenReturn(this.info);
setup("spring.cloud.config.discovery.enabled=true");
assertEquals(
1,
context.getBeanNamesForType(DiscoveryClientConfigServiceBootstrapConfiguration.class).length);
Mockito.verify(client).getNextServerFromEureka("CONFIGSERVER", false);
ConfigClientProperties locator = context.getBean(ConfigClientProperties.class);
this.context
.getBeanNamesForType(DiscoveryClientConfigServiceBootstrapConfiguration.class).length);
Mockito.verify(this.client).getNextServerFromEureka("CONFIGSERVER", false);
ConfigClientProperties locator = this.context
.getBean(ConfigClientProperties.class);
assertEquals("http://foo:7001/", locator.getUri());
}
@Test
public void setsPasssword() throws Exception {
info.getMetadata().put("password", "bar");
Mockito.when(client.getNextServerFromEureka("CONFIGSERVER", false)).thenReturn(
info);
this.info.getMetadata().put("password", "bar");
Mockito.when(this.client.getNextServerFromEureka("CONFIGSERVER", false))
.thenReturn(this.info);
setup("spring.cloud.config.discovery.enabled=true");
ConfigClientProperties locator = context.getBean(ConfigClientProperties.class);
ConfigClientProperties locator = this.context
.getBean(ConfigClientProperties.class);
assertEquals("http://foo:7001/", locator.getUri());
assertEquals("bar", locator.getPassword());
assertEquals("user", locator.getUsername());
@@ -85,23 +89,24 @@ public class DiscoveryClientConfigServiceBootstrapConfigurationTests {
@Test
public void setsPath() throws Exception {
info.getMetadata().put("configPath", "/bar");
Mockito.when(client.getNextServerFromEureka("CONFIGSERVER", false)).thenReturn(
info);
this.info.getMetadata().put("configPath", "/bar");
Mockito.when(this.client.getNextServerFromEureka("CONFIGSERVER", false))
.thenReturn(this.info);
setup("spring.cloud.config.discovery.enabled=true");
ConfigClientProperties locator = context.getBean(ConfigClientProperties.class);
ConfigClientProperties locator = this.context
.getBean(ConfigClientProperties.class);
assertEquals("http://foo:7001/bar", locator.getUri());
}
private void setup(String... env) {
context = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(context, env);
context.getDefaultListableBeanFactory().registerSingleton("mockDiscoveryClient",
client);
context.register(PropertyPlaceholderAutoConfiguration.class,
this.context = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(this.context, env);
this.context.getDefaultListableBeanFactory().registerSingleton(
"mockDiscoveryClient", this.client);
this.context.register(PropertyPlaceholderAutoConfiguration.class,
DiscoveryClientConfigServiceBootstrapConfiguration.class,
ConfigClientProperties.class);
context.refresh();
this.context.refresh();
}
}

View File

@@ -15,8 +15,6 @@
*/
package org.springframework.cloud.netflix.config;
import static org.junit.Assert.assertEquals;
import org.junit.After;
import org.junit.Test;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
@@ -28,6 +26,8 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
import com.netflix.appinfo.EurekaInstanceConfig;
import static org.junit.Assert.assertEquals;
/**
* @author Dave Syer
*
@@ -38,29 +38,30 @@ public class EurekaClientConfigServerAutoConfigurationTests {
@After
public void close() {
if (context != null) {
context.close();
if (this.context != null) {
this.context.close();
}
}
@Test
public void offByDefault() throws Exception {
context = new AnnotationConfigApplicationContext(
this.context = new AnnotationConfigApplicationContext(
EurekaClientConfigServerAutoConfiguration.class);
assertEquals(0,
context.getBeanNamesForType(EurekaInstanceConfigBean.class).length);
this.context.getBeanNamesForType(EurekaInstanceConfigBean.class).length);
}
@Test
public void onWhenRequested() throws Exception {
setup("spring.cloud.config.server.prefix=/config");
assertEquals(1, context.getBeanNamesForType(EurekaInstanceConfig.class).length);
EurekaInstanceConfig instance = context.getBean(EurekaInstanceConfig.class);
assertEquals(1,
this.context.getBeanNamesForType(EurekaInstanceConfig.class).length);
EurekaInstanceConfig instance = this.context.getBean(EurekaInstanceConfig.class);
assertEquals("/config", instance.getMetadataMap().get("configPath"));
}
private void setup(String... env) {
context = new SpringApplicationBuilder(
this.context = new SpringApplicationBuilder(
PropertyPlaceholderAutoConfiguration.class,
EurekaClientConfigServerAutoConfiguration.class,
ConfigServerProperties.class, EurekaInstanceConfigBean.class).web(false)

View File

@@ -15,8 +15,6 @@
*/
package org.springframework.cloud.netflix.eureka;
import static org.junit.Assert.assertEquals;
import java.util.Collections;
import org.junit.After;
@@ -29,6 +27,8 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.MapPropertySource;
import static org.junit.Assert.assertEquals;
/**
* @author Dave Syer
*
@@ -39,65 +39,64 @@ public class EurekaClientConfigBeanTests {
@After
public void init() {
if (context != null) {
context.close();
if (this.context != null) {
this.context.close();
}
}
@Test
public void basicBinding() {
EnvironmentTestUtils.addEnvironment(context,
EnvironmentTestUtils.addEnvironment(this.context,
"eureka.client.proxyHost=example.com");
context.register(PropertyPlaceholderAutoConfiguration.class,
this.context.register(PropertyPlaceholderAutoConfiguration.class,
TestConfiguration.class);
context.refresh();
assertEquals("example.com", context.getBean(EurekaClientConfigBean.class)
this.context.refresh();
assertEquals("example.com", this.context.getBean(EurekaClientConfigBean.class)
.getProxyHost());
}
@Test
public void serviceUrl() {
EnvironmentTestUtils.addEnvironment(context,
EnvironmentTestUtils.addEnvironment(this.context,
"eureka.client.serviceUrl.defaultZone:http://example.com");
context.register(PropertyPlaceholderAutoConfiguration.class,
this.context.register(PropertyPlaceholderAutoConfiguration.class,
TestConfiguration.class);
context.refresh();
this.context.refresh();
assertEquals("{defaultZone=http://example.com}",
context.getBean(EurekaClientConfigBean.class).getServiceUrl().toString());
assertEquals(
"[http://example.com]",
context.getBean(EurekaClientConfigBean.class)
this.context.getBean(EurekaClientConfigBean.class).getServiceUrl()
.toString());
assertEquals("[http://example.com]",
this.context.getBean(EurekaClientConfigBean.class)
.getEurekaServerServiceUrls("defaultZone").toString());
}
@Test
public void serviceUrlWithCompositePropertySource() {
CompositePropertySource source = new CompositePropertySource("composite");
context.getEnvironment().getPropertySources().addFirst(source);
this.context.getEnvironment().getPropertySources().addFirst(source);
source.addPropertySource(new MapPropertySource("config", Collections
.<String, Object> singletonMap("eureka.client.serviceUrl.defaultZone",
"http://example.com")));
context.register(PropertyPlaceholderAutoConfiguration.class,
this.context.register(PropertyPlaceholderAutoConfiguration.class,
TestConfiguration.class);
context.refresh();
this.context.refresh();
assertEquals("{defaultZone=http://example.com}",
context.getBean(EurekaClientConfigBean.class).getServiceUrl().toString());
assertEquals(
"[http://example.com]",
context.getBean(EurekaClientConfigBean.class)
this.context.getBean(EurekaClientConfigBean.class).getServiceUrl()
.toString());
assertEquals("[http://example.com]",
this.context.getBean(EurekaClientConfigBean.class)
.getEurekaServerServiceUrls("defaultZone").toString());
}
@Test
public void serviceUrlWithDefault() {
EnvironmentTestUtils.addEnvironment(context,
EnvironmentTestUtils.addEnvironment(this.context,
"eureka.client.serviceUrl.defaultZone:http://example.com");
context.register(PropertyPlaceholderAutoConfiguration.class,
this.context.register(PropertyPlaceholderAutoConfiguration.class,
TestConfiguration.class);
context.refresh();
assertEquals(
"[http://example.com]",
context.getBean(EurekaClientConfigBean.class)
this.context.refresh();
assertEquals("[http://example.com]",
this.context.getBean(EurekaClientConfigBean.class)
.getEurekaServerServiceUrls("defaultZone").toString());
}

View File

@@ -15,10 +15,6 @@
*/
package org.springframework.cloud.netflix.eureka;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.springframework.boot.test.EnvironmentTestUtils.addEnvironment;
import org.junit.After;
import org.junit.Test;
import org.springframework.beans.factory.BeanCreationException;
@@ -30,6 +26,10 @@ import org.springframework.context.annotation.Configuration;
import com.netflix.appinfo.InstanceInfo.InstanceStatus;
import com.netflix.appinfo.UniqueIdentifier;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.springframework.boot.test.EnvironmentTestUtils.addEnvironment;
/**
* @author Dave Syer
*
@@ -40,8 +40,8 @@ public class EurekaInstanceConfigBeanTests {
@After
public void init() {
if (context != null) {
context.close();
if (this.context != null) {
this.context.close();
}
}
@@ -55,7 +55,7 @@ public class EurekaInstanceConfigBeanTests {
@Test
public void basicBinding() {
addEnvironment(context, "eureka.instance.appGroupName=mygroup");
addEnvironment(this.context, "eureka.instance.appGroupName=mygroup");
setupContext();
assertEquals("mygroup", getInstanceConfig().getAppGroupName());
}
@@ -81,7 +81,7 @@ public class EurekaInstanceConfigBeanTests {
}
private void testNonSecurePort(String propName) {
addEnvironment(context, propName + ":8888");
addEnvironment(this.context, propName + ":8888");
setupContext();
assertEquals(8888, getInstanceConfig().getNonSecurePort());
}
@@ -95,13 +95,13 @@ public class EurekaInstanceConfigBeanTests {
@Test(expected = BeanCreationException.class)
public void testBadInitialStatus() {
addEnvironment(context, "eureka.instance.initial-status:FOO");
addEnvironment(this.context, "eureka.instance.initial-status:FOO");
setupContext();
}
@Test
public void testCustomInitialStatus() {
addEnvironment(context, "eureka.instance.initial-status:STARTING");
addEnvironment(this.context, "eureka.instance.initial-status:STARTING");
setupContext();
assertEquals("initialStatus wrong", InstanceStatus.STARTING, getInstanceConfig()
.getInitialStatus());
@@ -109,17 +109,17 @@ public class EurekaInstanceConfigBeanTests {
@Test
public void testPerferIpAddress() throws Exception {
addEnvironment(context, "eureka.instance.preferIpAddress:true");
addEnvironment(this.context, "eureka.instance.preferIpAddress:true");
setupContext();
EurekaInstanceConfigBean instance = getInstanceConfig();
assertTrue("Wrong hostname: " + instance.getHostname(),
getInstanceConfig().getHostname().equals(instance.getIpAddress()));
assertTrue("Wrong hostname: " + instance.getHostname(), getInstanceConfig()
.getHostname().equals(instance.getIpAddress()));
}
@Test
public void testPerferIpAddressInDatacenter() throws Exception {
addEnvironment(context, "eureka.instance.preferIpAddress:true");
addEnvironment(this.context, "eureka.instance.preferIpAddress:true");
setupContext();
EurekaInstanceConfigBean instance = getInstanceConfig();
String id = ((UniqueIdentifier) instance.getDataCenterInfo()).getId();
@@ -128,13 +128,13 @@ public class EurekaInstanceConfigBeanTests {
}
private void setupContext() {
context.register(PropertyPlaceholderAutoConfiguration.class,
this.context.register(PropertyPlaceholderAutoConfiguration.class,
TestConfiguration.class);
context.refresh();
this.context.refresh();
}
protected EurekaInstanceConfigBean getInstanceConfig() {
return context.getBean(EurekaInstanceConfigBean.class);
return this.context.getBean(EurekaInstanceConfigBean.class);
}
@Configuration

View File

@@ -25,21 +25,22 @@ public class EurekaSampleApplication {
return new InMemoryMetricRepository();
}
@Bean
public HealthCheckHandler healthCheckHandler() {
return new HealthCheckHandler() {
@Override
public InstanceInfo.InstanceStatus getStatus(InstanceInfo.InstanceStatus currentStatus) {
return InstanceInfo.InstanceStatus.UP;
}
};
}
@Bean
public HealthCheckHandler healthCheckHandler() {
return new HealthCheckHandler() {
@Override
public InstanceInfo.InstanceStatus getStatus(
InstanceInfo.InstanceStatus currentStatus) {
return InstanceInfo.InstanceStatus.UP;
}
};
}
@RequestMapping("/")
public String home() {
return "Hello world";
}
public static void main(String[] args) {
new SpringApplicationBuilder(EurekaSampleApplication.class).web(true).run(args);
}

View File

@@ -1,8 +1,5 @@
package org.springframework.cloud.netflix.feign;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
@@ -28,6 +25,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
* @author Spencer Gibb
*/
@@ -38,74 +38,75 @@ import org.springframework.web.bind.annotation.RestController;
@DirtiesContext
public class FeignClientTests extends FeignConfiguration {
@Value("${local.server.port}")
private int port = 0;
@Value("${local.server.port}")
private int port = 0;
@Autowired
TestClient testClient;
TestClient testClient;
//@FeignClient(value = "http://localhost:9876", loadbalance = false)
// @FeignClient(value = "http://localhost:9876", loadbalance = false)
@FeignClient("feignclienttest")
protected static interface TestClient {
@RequestMapping(method = RequestMethod.GET, value = "/hello")
public Hello getHello();
@RequestMapping(method = RequestMethod.GET, value = "/hellos")
public List<Hello> getHellos();
@RequestMapping(method = RequestMethod.GET, value = "/hellostrings")
public List<String> getHelloStrings();
}
@Configuration
@EnableAutoConfiguration
@RestController
@FeignClientScan
protected static class Application {
protected static interface TestClient {
@RequestMapping(method = RequestMethod.GET, value = "/hello")
public Hello getHello() {
return new Hello("hello world 1");
}
public Hello getHello();
@RequestMapping(method = RequestMethod.GET, value = "/hellos")
public List<Hello> getHellos() {
ArrayList<Hello> hellos = new ArrayList<>();
hellos.add(new Hello("hello world 1"));
hellos.add(new Hello("oi terra 2"));
return hellos;
}
public List<Hello> getHellos();
@RequestMapping(method = RequestMethod.GET, value = "/hellostrings")
public List<String> getHelloStrings() {
ArrayList<String> hellos = new ArrayList<>();
hellos.add("hello world 1");
hellos.add("oi terra 2");
return hellos;
}
public List<String> getHelloStrings();
}
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).properties(
"spring.application.name=feignclienttest", "management.contextPath=/admin")
.run(args);
}
}
@Configuration
@EnableAutoConfiguration
@RestController
@FeignClientScan
protected static class Application {
@Test
public void testClient() {
assertNotNull("testClient was null", testClient);
assertTrue("testClient is not a java Proxy", Proxy.isProxyClass(testClient.getClass()));
InvocationHandler invocationHandler = Proxy.getInvocationHandler(testClient);
@RequestMapping(method = RequestMethod.GET, value = "/hello")
public Hello getHello() {
return new Hello("hello world 1");
}
@RequestMapping(method = RequestMethod.GET, value = "/hellos")
public List<Hello> getHellos() {
ArrayList<Hello> hellos = new ArrayList<>();
hellos.add(new Hello("hello world 1"));
hellos.add(new Hello("oi terra 2"));
return hellos;
}
@RequestMapping(method = RequestMethod.GET, value = "/hellostrings")
public List<String> getHelloStrings() {
ArrayList<String> hellos = new ArrayList<>();
hellos.add("hello world 1");
hellos.add("oi terra 2");
return hellos;
}
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).properties(
"spring.application.name=feignclienttest",
"management.contextPath=/admin").run(args);
}
}
@Test
public void testClient() {
assertNotNull("testClient was null", this.testClient);
assertTrue("testClient is not a java Proxy",
Proxy.isProxyClass(this.testClient.getClass()));
InvocationHandler invocationHandler = Proxy.getInvocationHandler(this.testClient);
assertNotNull("invocationHandler was null", invocationHandler);
}
//TODO: only works if port is hardcoded cant resolve ${local.server.port} in annotation
/*@Test
public void testSimpleType() {
Hello hello = testClient.getHello();
assertNotNull("hello was null", hello);
assertEquals("first hello didn't match", new Hello("hello world 1"), hello);
}*/
// TODO: only works if port is hardcoded cant resolve ${local.server.port} in
// annotation
/*
* @Test public void testSimpleType() { Hello hello = testClient.getHello();
* assertNotNull("hello was null", hello); assertEquals("first hello didn't match",
* new Hello("hello world 1"), hello); }
*/
@Data
@AllArgsConstructor

View File

@@ -1,6 +1,8 @@
package org.springframework.cloud.netflix.feign;
import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@@ -20,8 +22,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
/**
* @author Spencer Gibb
@@ -29,85 +31,90 @@ import java.util.List;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SpringDecoderTests.Application.class)
@WebAppConfiguration
@IntegrationTest({ "server.port=0", "spring.application.name=springdecodertest", "spring.jmx.enabled=true" })
@IntegrationTest({ "server.port=0", "spring.application.name=springdecodertest",
"spring.jmx.enabled=true" })
@DirtiesContext
public class SpringDecoderTests extends FeignConfiguration {
@Value("${local.server.port}")
private int port = 0;
@Value("${local.server.port}")
private int port = 0;
public TestClient testClient() {
return feign().target(TestClient.class, "http://localhost:"+port);
}
public TestClient testClient() {
return feign().target(TestClient.class, "http://localhost:" + this.port);
}
protected static interface TestClient {
@RequestMapping(method = RequestMethod.GET, value = "/hello")
public Hello getHello();
protected static interface TestClient {
@RequestMapping(method = RequestMethod.GET, value = "/hello")
public Hello getHello();
@RequestMapping(method = RequestMethod.GET, value = "/hellos")
public List<Hello> getHellos();
@RequestMapping(method = RequestMethod.GET, value = "/hellos")
public List<Hello> getHellos();
@RequestMapping(method = RequestMethod.GET, value = "/hellostrings")
public List<String> getHelloStrings();
}
@RequestMapping(method = RequestMethod.GET, value = "/hellostrings")
public List<String> getHelloStrings();
}
@Configuration
@EnableAutoConfiguration
@RestController
protected static class Application implements TestClient {
@Configuration
@EnableAutoConfiguration
@RestController
protected static class Application implements TestClient {
public Hello getHello() {
return new Hello("hello world 1");
}
@Override
public Hello getHello() {
return new Hello("hello world 1");
}
public List<Hello> getHellos() {
ArrayList<Hello> hellos = new ArrayList<>();
hellos.add(new Hello("hello world 1"));
hellos.add(new Hello("oi terra 2"));
return hellos;
}
@Override
public List<Hello> getHellos() {
ArrayList<Hello> hellos = new ArrayList<>();
hellos.add(new Hello("hello world 1"));
hellos.add(new Hello("oi terra 2"));
return hellos;
}
public List<String> getHelloStrings() {
ArrayList<String> hellos = new ArrayList<>();
hellos.add("hello world 1");
hellos.add("oi terra 2");
return hellos;
}
@Override
public List<String> getHelloStrings() {
ArrayList<String> hellos = new ArrayList<>();
hellos.add("hello world 1");
hellos.add("oi terra 2");
return hellos;
}
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).properties(
"spring.application.name=springdecodertest", "management.contextPath=/admin")
.run(args);
}
}
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).properties(
"spring.application.name=springdecodertest",
"management.contextPath=/admin").run(args);
}
}
@Test
public void testSimpleType() {
Hello hello = testClient().getHello();
assertNotNull("hello was null", hello);
assertEquals("first hello didn't match", new Hello("hello world 1"), hello);
}
@Test
public void testSimpleType() {
Hello hello = testClient().getHello();
assertNotNull("hello was null", hello);
assertEquals("first hello didn't match", new Hello("hello world 1"), hello);
}
@Test
public void testUserParameterizedTypeDecode() {
List<Hello> hellos = testClient().getHellos();
assertNotNull("hellos was null", hellos);
assertEquals("hellos was not the right size", 2, hellos.size());
assertEquals("first hello didn't match", new Hello("hello world 1"), hellos.get(0));
}
@Test
public void testUserParameterizedTypeDecode() {
List<Hello> hellos = testClient().getHellos();
assertNotNull("hellos was null", hellos);
assertEquals("hellos was not the right size", 2, hellos.size());
assertEquals("first hello didn't match", new Hello("hello world 1"),
hellos.get(0));
}
@Test
public void testSimpleParameterizedTypeDecode() {
List<String> hellos = testClient().getHelloStrings();
assertNotNull("hellos was null", hellos);
assertEquals("hellos was not the right size", 2, hellos.size());
assertEquals("first hello didn't match", "hello world 1", hellos.get(0));
}
@Test
public void testSimpleParameterizedTypeDecode() {
List<String> hellos = testClient().getHelloStrings();
assertNotNull("hellos was null", hellos);
assertEquals("hellos was not the right size", 2, hellos.size());
assertEquals("first hello didn't match", "hello world 1", hellos.get(0));
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class Hello {
private String message;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class Hello {
private String message;
}
}

View File

@@ -26,7 +26,8 @@ public class HystrixConfigurationTests {
@Test
public void nonWebAppStartsUp() {
new SpringApplicationBuilder(HystrixCircuitBreakerConfiguration.class).web(false).run().close();
new SpringApplicationBuilder(HystrixCircuitBreakerConfiguration.class).web(false)
.run().close();
}
}

View File

@@ -1,6 +1,7 @@
package org.springframework.cloud.netflix.hystrix;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@@ -19,9 +20,11 @@ import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* @author Spencer Gibb
@@ -38,13 +41,15 @@ public class HystrixOnlyTests {
@Test
public void testNormalExecution() {
String s = new TestRestTemplate().getForObject("http://localhost:" + port + "/", String.class);
String s = new TestRestTemplate().getForObject("http://localhost:" + this.port
+ "/", String.class);
assertEquals("incorrect response", "Hello world", s);
}
@Test
public void testFailureFallback() {
String s = new TestRestTemplate().getForObject("http://localhost:" + port + "/fail", String.class);
String s = new TestRestTemplate().getForObject("http://localhost:" + this.port
+ "/fail", String.class);
assertEquals("incorrect fallback", "Fallback Hello world", s);
}
@@ -59,12 +64,14 @@ public class HystrixOnlyTests {
@Test
public void testNoDiscoveryHealth() {
Map map = getHealth();
//There is explicitly no discovery, so there should be no discovery health key
assertFalse("Incorrect existing discovery health key", map.containsKey("discovery"));
// There is explicitly no discovery, so there should be no discovery health key
assertFalse("Incorrect existing discovery health key",
map.containsKey("discovery"));
}
private Map getHealth() {
return new TestRestTemplate().getForObject("http://localhost:" + port + "/admin/health", Map.class);
return new TestRestTemplate().getForObject("http://localhost:" + this.port
+ "/admin/health", Map.class);
}
}
@@ -84,7 +91,7 @@ class Service {
}
}
//Don't use @SpringBootApplication because we don't want to component scan
// Don't use @SpringBootApplication because we don't want to component scan
@Configuration
@EnableAutoConfiguration
@EnableCircuitBreaker
@@ -101,12 +108,12 @@ class HystrixOnlyApplication {
@RequestMapping("/")
public String home() {
return service.hello();
return this.service.hello();
}
@RequestMapping("/fail")
public String fail() {
return service.fail();
return this.service.fail();
}
public static void main(String[] args) {

View File

@@ -15,10 +15,10 @@
*/
package org.springframework.cloud.netflix.hystrix;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
/**
* @author Dave Syer
*

View File

@@ -46,7 +46,7 @@ public class PlainRibbonClientPreprocessorIntegrationTests {
@Test
public void serverListIsWrapped() throws Exception {
@SuppressWarnings("unchecked")
ZoneAwareLoadBalancer<Server> loadBalancer = (ZoneAwareLoadBalancer<Server>) factory
ZoneAwareLoadBalancer<Server> loadBalancer = (ZoneAwareLoadBalancer<Server>) this.factory
.getLoadBalancer("foo");
DomainExtractingServerList.class.cast(loadBalancer.getServerListImpl());
}

View File

@@ -15,8 +15,6 @@
*/
package org.springframework.cloud.netflix.ribbon;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@@ -36,6 +34,8 @@ import com.netflix.loadbalancer.AvailabilityFilteringRule;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ZoneAwareLoadBalancer;
import static org.junit.Assert.assertEquals;
/**
* @author Dave Syer
*
@@ -51,7 +51,7 @@ public class RibbonClientPreprocessorIntegrationTests {
@Test
public void serverListIsWrapped() throws Exception {
@SuppressWarnings("unchecked")
ZoneAwareLoadBalancer<Server> loadBalancer = (ZoneAwareLoadBalancer<Server>) factory
ZoneAwareLoadBalancer<Server> loadBalancer = (ZoneAwareLoadBalancer<Server>) this.factory
.getLoadBalancer("foo");
DomainExtractingServerList.class.cast(loadBalancer.getServerListImpl());
}
@@ -59,7 +59,7 @@ public class RibbonClientPreprocessorIntegrationTests {
@Test
public void ruleDefaultsToAvailability() throws Exception {
@SuppressWarnings("unchecked")
ZoneAwareLoadBalancer<Server> loadBalancer = (ZoneAwareLoadBalancer<Server>) factory
ZoneAwareLoadBalancer<Server> loadBalancer = (ZoneAwareLoadBalancer<Server>) this.factory
.getLoadBalancer("foo");
AvailabilityFilteringRule.class.cast(loadBalancer.getRule());
}
@@ -67,7 +67,7 @@ public class RibbonClientPreprocessorIntegrationTests {
@Test
public void serverListFilterOverride() throws Exception {
@SuppressWarnings("unchecked")
ZoneAwareLoadBalancer<Server> loadBalancer = (ZoneAwareLoadBalancer<Server>) factory
ZoneAwareLoadBalancer<Server> loadBalancer = (ZoneAwareLoadBalancer<Server>) this.factory
.getLoadBalancer("foo");
assertEquals("myTestZone",
ZonePreferenceServerListFilter.class.cast(loadBalancer.getFilter())

View File

@@ -15,8 +15,6 @@
*/
package org.springframework.cloud.netflix.ribbon;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@@ -24,10 +22,6 @@ import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfigurati
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration;
import org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration;
import org.springframework.cloud.netflix.ribbon.RibbonClients;
import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.netflix.ribbon.RibbonClientsPreprocessorIntegrationTests.TestConfiguration;
import org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList;
import org.springframework.cloud.netflix.ribbon.eureka.RibbonEurekaAutoConfiguration;
@@ -42,6 +36,8 @@ import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ZoneAvoidanceRule;
import com.netflix.loadbalancer.ZoneAwareLoadBalancer;
import static org.junit.Assert.assertEquals;
/**
* @author Dave Syer
*
@@ -57,7 +53,7 @@ public class RibbonClientsPreprocessorIntegrationTests {
@Test
public void serverListIsWrapped() throws Exception {
@SuppressWarnings("unchecked")
ZoneAwareLoadBalancer<Server> loadBalancer = (ZoneAwareLoadBalancer<Server>) factory
ZoneAwareLoadBalancer<Server> loadBalancer = (ZoneAwareLoadBalancer<Server>) this.factory
.getLoadBalancer("foo");
DomainExtractingServerList.class.cast(loadBalancer.getServerListImpl());
}
@@ -65,7 +61,7 @@ public class RibbonClientsPreprocessorIntegrationTests {
@Test
public void ruleDefaultsToZoneAvoidance() throws Exception {
@SuppressWarnings("unchecked")
ZoneAwareLoadBalancer<Server> loadBalancer = (ZoneAwareLoadBalancer<Server>) factory
ZoneAwareLoadBalancer<Server> loadBalancer = (ZoneAwareLoadBalancer<Server>) this.factory
.getLoadBalancer("foo");
ZoneAvoidanceRule.class.cast(loadBalancer.getRule());
}
@@ -73,10 +69,11 @@ public class RibbonClientsPreprocessorIntegrationTests {
@Test
public void serverListFilterOverride() throws Exception {
@SuppressWarnings("unchecked")
ZoneAwareLoadBalancer<Server> loadBalancer = (ZoneAwareLoadBalancer<Server>) factory
ZoneAwareLoadBalancer<Server> loadBalancer = (ZoneAwareLoadBalancer<Server>) this.factory
.getLoadBalancer("foo");
assertEquals("myTestZone",
ZonePreferenceServerListFilter.class.cast(loadBalancer.getFilter()).getZone());
ZonePreferenceServerListFilter.class.cast(loadBalancer.getFilter())
.getZone());
}
@Configuration

View File

@@ -1,7 +1,8 @@
package org.springframework.cloud.netflix.ribbon;
import com.google.common.base.Throwables;
import com.netflix.loadbalancer.Server;
import java.net.URI;
import java.net.URL;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
@@ -17,77 +18,82 @@ import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.support.HttpRequestWrapper;
import org.springframework.web.util.UriComponentsBuilder;
import java.net.URI;
import java.net.URL;
import com.google.common.base.Throwables;
import com.netflix.loadbalancer.Server;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Matchers.isA;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* @author Spencer Gibb
*/
public class RibbonInterceptorTests {
@Mock
HttpRequest request;
@Mock
HttpRequest request;
@Mock
ClientHttpRequestExecution execution;
@Mock
ClientHttpRequestExecution execution;
@Mock
ClientHttpResponse response;
@Mock
ClientHttpResponse response;
@Before
public void init() {
MockitoAnnotations.initMocks(this);
}
@Before
public void init() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testIntercept() throws Exception {
RibbonServer server = new RibbonServer("myservice", new Server("myhost", 8080));
RibbonInterceptor interceptor = new RibbonInterceptor(new MyClient(server));
@Test
public void testIntercept() throws Exception {
RibbonServer server = new RibbonServer("myservice", new Server("myhost", 8080));
RibbonInterceptor interceptor = new RibbonInterceptor(new MyClient(server));
when(request.getURI()).thenReturn(new URL("http://myservice").toURI());
when(execution.execute(isA(HttpRequest.class), isA(byte[].class))).thenReturn(response);
ArgumentCaptor<HttpRequestWrapper> argument = ArgumentCaptor.forClass(HttpRequestWrapper.class);
when(this.request.getURI()).thenReturn(new URL("http://myservice").toURI());
when(this.execution.execute(isA(HttpRequest.class), isA(byte[].class)))
.thenReturn(this.response);
ArgumentCaptor<HttpRequestWrapper> argument = ArgumentCaptor
.forClass(HttpRequestWrapper.class);
ClientHttpResponse response = interceptor.intercept(request, new byte[0], execution);
ClientHttpResponse response = interceptor.intercept(this.request, new byte[0],
this.execution);
assertNotNull("response was null", response);
verify(execution).execute(argument.capture(), isA(byte[].class));
HttpRequestWrapper wrapper = argument.getValue();
assertEquals("wrong constructed uri", new URL("http://myhost:8080").toURI(), wrapper.getURI());
}
assertNotNull("response was null", response);
verify(this.execution).execute(argument.capture(), isA(byte[].class));
HttpRequestWrapper wrapper = argument.getValue();
assertEquals("wrong constructed uri", new URL("http://myhost:8080").toURI(),
wrapper.getURI());
}
protected static class MyClient implements LoadBalancerClient {
ServiceInstance instance;
protected static class MyClient implements LoadBalancerClient {
ServiceInstance instance;
public MyClient(ServiceInstance instance) {
this.instance = instance;
}
public MyClient(ServiceInstance instance) {
this.instance = instance;
}
@Override
public ServiceInstance choose(String serviceId) {
return instance;
}
@Override
public ServiceInstance choose(String serviceId) {
return this.instance;
}
@Override
public <T> T execute(String serviceId, LoadBalancerRequest<T> request) {
try {
return request.apply(instance);
} catch (Exception e) {
Throwables.propagate(e);
}
return null;
}
@Override
public <T> T execute(String serviceId, LoadBalancerRequest<T> request) {
try {
return request.apply(this.instance);
}
catch (Exception e) {
Throwables.propagate(e);
}
return null;
}
@Override
public URI reconstructURI(ServiceInstance instance, URI original) {
return UriComponentsBuilder.fromUri(original)
.host(instance.getHost())
.port(instance.getPort())
.build()
.toUri();
}
}
@Override
public URI reconstructURI(ServiceInstance instance, URI original) {
return UriComponentsBuilder.fromUri(original).host(instance.getHost())
.port(instance.getPort()).build().toUri();
}
}
}

View File

@@ -1,13 +1,5 @@
package org.springframework.cloud.netflix.ribbon;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.anyDouble;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.net.URI;
import java.net.URL;
@@ -25,113 +17,130 @@ import com.netflix.loadbalancer.LoadBalancerStats;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerStats;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.anyDouble;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* @author Spencer Gibb
*/
public class RibbonLoadBalancerClientTests {
@Mock
SpringClientFactory clientFactory;
@Mock
SpringClientFactory clientFactory;
@Mock
BaseLoadBalancer loadBalancer;
@Mock
BaseLoadBalancer loadBalancer;
@Mock
LoadBalancerStats loadBalancerStats;
@Mock
LoadBalancerStats loadBalancerStats;
@Mock
ServerStats serverStats;
@Mock
ServerStats serverStats;
@Before
public void init() {
MockitoAnnotations.initMocks(this);
Mockito.when(clientFactory.getLoadBalancerContext(anyString())).thenReturn(new RibbonLoadBalancerContext(loadBalancer));
}
@Before
public void init() {
MockitoAnnotations.initMocks(this);
Mockito.when(this.clientFactory.getLoadBalancerContext(anyString())).thenReturn(
new RibbonLoadBalancerContext(this.loadBalancer));
}
@Test
public void reconstructURI() throws Exception {
RibbonServer server = getRibbonServer();
RibbonLoadBalancerClient client = getRibbonLoadBalancerClient(server);
ServiceInstance serviceInstance = client.choose(server.getServiceId());
URI uri = client.reconstructURI(serviceInstance, new URL("http://" + server.serviceId).toURI());
assertEquals(server.getHost(), uri.getHost());
assertEquals(server.getPort(), uri.getPort());
}
@Test
public void reconstructURI() throws Exception {
RibbonServer server = getRibbonServer();
RibbonLoadBalancerClient client = getRibbonLoadBalancerClient(server);
ServiceInstance serviceInstance = client.choose(server.getServiceId());
URI uri = client.reconstructURI(serviceInstance, new URL("http://"
+ server.serviceId).toURI());
assertEquals(server.getHost(), uri.getHost());
assertEquals(server.getPort(), uri.getPort());
}
@Test
public void testChoose() {
RibbonServer server = getRibbonServer();
RibbonLoadBalancerClient client = getRibbonLoadBalancerClient(server);
ServiceInstance serviceInstance = client.choose(server.getServiceId());
assertServiceInstance(server, serviceInstance);
}
@Test
public void testChoose() {
RibbonServer server = getRibbonServer();
RibbonLoadBalancerClient client = getRibbonLoadBalancerClient(server);
ServiceInstance serviceInstance = client.choose(server.getServiceId());
assertServiceInstance(server, serviceInstance);
}
@Test
public void testExecute() {
final RibbonServer server = getRibbonServer();
RibbonLoadBalancerClient client = getRibbonLoadBalancerClient(server);
@Test
public void testExecute() {
final RibbonServer server = getRibbonServer();
RibbonLoadBalancerClient client = getRibbonLoadBalancerClient(server);
final String returnVal = "myval";
Object actualReturn = client.execute(server.getServiceId(), new LoadBalancerRequest<Object>() {
@Override
public Object apply(ServiceInstance instance) throws Exception {
assertServiceInstance(server, instance);
return returnVal;
}
});
final String returnVal = "myval";
Object actualReturn = client.execute(server.getServiceId(),
new LoadBalancerRequest<Object>() {
@Override
public Object apply(ServiceInstance instance) throws Exception {
assertServiceInstance(server, instance);
return returnVal;
}
});
verifyServerStats();
verifyServerStats();
assertEquals("retVal was wrong", returnVal, actualReturn);
}
assertEquals("retVal was wrong", returnVal, actualReturn);
}
@Test
public void testExecuteException() {
final RibbonServer ribbonServer = getRibbonServer();
RibbonLoadBalancerClient client = getRibbonLoadBalancerClient(ribbonServer);
@Test
public void testExecuteException() {
final RibbonServer ribbonServer = getRibbonServer();
RibbonLoadBalancerClient client = getRibbonLoadBalancerClient(ribbonServer);
try {
client.execute(ribbonServer.getServiceId(),
new LoadBalancerRequest<Object>() {
@Override
public Object apply(ServiceInstance instance) throws Exception {
assertServiceInstance(ribbonServer, instance);
throw new RuntimeException();
}
});
fail("Should have thrown exception");
}
catch (Exception e) {
assertNotNull(e);
}
try {
client.execute(ribbonServer.getServiceId(), new LoadBalancerRequest<Object>() {
@Override
public Object apply(ServiceInstance instance) throws Exception {
assertServiceInstance(ribbonServer, instance);
throw new RuntimeException();
}
});
fail("Should have thrown exception");
} catch (Exception e) {
assertNotNull(e);
}
verifyServerStats();
}
verifyServerStats();
}
protected RibbonServer getRibbonServer() {
return new RibbonServer("testService", new Server("myhost", 9080));
}
protected RibbonServer getRibbonServer() {
return new RibbonServer("testService", new Server("myhost", 9080));
}
protected void verifyServerStats() {
verify(this.serverStats).incrementActiveRequestsCount();
verify(this.serverStats).decrementActiveRequestsCount();
verify(this.serverStats).incrementNumRequests();
verify(this.serverStats).noteResponseTime(anyDouble());
}
protected void verifyServerStats() {
verify(serverStats).incrementActiveRequestsCount();
verify(serverStats).decrementActiveRequestsCount();
verify(serverStats).incrementNumRequests();
verify(serverStats).noteResponseTime(anyDouble());
}
protected void assertServiceInstance(RibbonServer ribbonServer,
ServiceInstance instance) {
assertNotNull("instance was null", instance);
assertEquals("serviceId was wrong", ribbonServer.getServiceId(),
instance.getServiceId());
assertEquals("host was wrong", ribbonServer.getHost(), instance.getHost());
assertEquals("port was wrong", ribbonServer.getPort(), instance.getPort());
}
protected void assertServiceInstance(RibbonServer ribbonServer, ServiceInstance instance) {
assertNotNull("instance was null", instance);
assertEquals("serviceId was wrong", ribbonServer.getServiceId(), instance.getServiceId());
assertEquals("host was wrong", ribbonServer.getHost(), instance.getHost());
assertEquals("port was wrong", ribbonServer.getPort(), instance.getPort());
}
protected RibbonLoadBalancerClient getRibbonLoadBalancerClient(
RibbonServer ribbonServer) {
when(this.loadBalancer.getName()).thenReturn(ribbonServer.getServiceId());
when(this.loadBalancer.chooseServer(anyString())).thenReturn(ribbonServer.server);
when(this.loadBalancer.getLoadBalancerStats()).thenReturn(this.loadBalancerStats);
when(this.loadBalancerStats.getSingleServerStat(ribbonServer.server)).thenReturn(
this.serverStats);
when(this.clientFactory.getLoadBalancer(this.loadBalancer.getName())).thenReturn(
this.loadBalancer);
protected RibbonLoadBalancerClient getRibbonLoadBalancerClient(RibbonServer ribbonServer) {
when(loadBalancer.getName()).thenReturn(ribbonServer.getServiceId());
when(loadBalancer.chooseServer(anyString())).thenReturn(ribbonServer.server);
when(loadBalancer.getLoadBalancerStats()).thenReturn(loadBalancerStats);
when(loadBalancerStats.getSingleServerStat(ribbonServer.server)).thenReturn(serverStats);
when(clientFactory.getLoadBalancer(loadBalancer.getName())).thenReturn(loadBalancer);
return new RibbonLoadBalancerClient(clientFactory);
}
return new RibbonLoadBalancerClient(this.clientFactory);
}
}

View File

@@ -15,8 +15,6 @@
*/
package org.springframework.cloud.netflix.ribbon;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.springframework.boot.test.EnvironmentTestUtils;
import org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration;
@@ -24,6 +22,8 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
import com.netflix.client.DefaultLoadBalancerRetryHandler;
import static org.junit.Assert.assertEquals;
/**
* @author Dave Syer
*
@@ -34,14 +34,15 @@ public class SpringClientFactoryTests {
@Test
public void testConfigureRetry() {
AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext(ArchaiusAutoConfiguration.class);
AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext(
ArchaiusAutoConfiguration.class);
EnvironmentTestUtils.addEnvironment(parent, "foo.ribbon.MaxAutoRetries:2");
factory.setApplicationContext(parent);
DefaultLoadBalancerRetryHandler retryHandler = (DefaultLoadBalancerRetryHandler) factory
this.factory.setApplicationContext(parent);
DefaultLoadBalancerRetryHandler retryHandler = (DefaultLoadBalancerRetryHandler) this.factory
.getLoadBalancerContext("foo").getRetryHandler();
assertEquals(2, retryHandler.getMaxRetriesOnSameServer());
parent.close();
factory.destroy();
this.factory.destroy();
}
}

View File

@@ -1,11 +1,5 @@
package org.springframework.cloud.netflix.ribbon.eureka;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import java.util.List;
@@ -19,81 +13,97 @@ import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;
import com.netflix.niws.loadbalancer.DiscoveryEnabledServer;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
* @author Spencer Gibb
*/
public class DomainExtractingServerListTests {
static final String IP_ADDR = "10.0.0.2";
static final int PORT = 8080;
static final String ZONE = "myzone.mydomain.com";
static final String HOST_NAME = "myHostName."+ZONE;
static final String INSTANCE_ID = "myInstanceId";
static final String IP_ADDR = "10.0.0.2";
static final int PORT = 8080;
static final String ZONE = "myzone.mydomain.com";
static final String HOST_NAME = "myHostName." + ZONE;
static final String INSTANCE_ID = "myInstanceId";
@Test
public void testDomainExtractingServer() {
DomainExtractingServerList serverList = getDomainExtractingServerList(new DefaultClientConfigImpl(), true);
@Test
public void testDomainExtractingServer() {
DomainExtractingServerList serverList = getDomainExtractingServerList(
new DefaultClientConfigImpl(), true);
List<Server> servers = serverList.getInitialListOfServers();
assertNotNull("servers was null", servers);
assertEquals("servers was not size 1", 1, servers.size());
List<Server> servers = serverList.getInitialListOfServers();
assertNotNull("servers was null", servers);
assertEquals("servers was not size 1", 1, servers.size());
DomainExtractingServer des = assertDomainExtractingServer(servers, ZONE);
assertEquals("hostPort was wrong", HOST_NAME+":"+PORT, des.getHostPort());
}
DomainExtractingServer des = assertDomainExtractingServer(servers, ZONE);
assertEquals("hostPort was wrong", HOST_NAME + ":" + PORT, des.getHostPort());
}
@Test
public void testDomainExtractingServerDontApproximateZone() {
DomainExtractingServerList serverList = getDomainExtractingServerList(new DefaultClientConfigImpl(), false);
DomainExtractingServerList serverList = getDomainExtractingServerList(
new DefaultClientConfigImpl(), false);
List<Server> servers = serverList.getInitialListOfServers();
assertNotNull("servers was null", servers);
assertEquals("servers was not size 1", 1, servers.size());
DomainExtractingServer des = assertDomainExtractingServer(servers, null);
assertEquals("hostPort was wrong", HOST_NAME+":"+PORT, des.getHostPort());
assertEquals("hostPort was wrong", HOST_NAME + ":" + PORT, des.getHostPort());
}
protected DomainExtractingServer assertDomainExtractingServer(List<Server> servers, String zone) {
Server actualServer = servers.get(0);
assertTrue("server was not a DomainExtractingServer", actualServer instanceof DomainExtractingServer);
DomainExtractingServer des = DomainExtractingServer.class.cast(actualServer);
assertEquals("zone was wrong", zone, des.getZone());
assertEquals("instanceId was wrong", INSTANCE_ID, des.getId());
return des;
}
protected DomainExtractingServer assertDomainExtractingServer(List<Server> servers,
String zone) {
Server actualServer = servers.get(0);
assertTrue("server was not a DomainExtractingServer",
actualServer instanceof DomainExtractingServer);
DomainExtractingServer des = DomainExtractingServer.class.cast(actualServer);
assertEquals("zone was wrong", zone, des.getZone());
assertEquals("instanceId was wrong", INSTANCE_ID, des.getId());
return des;
}
@Test
public void testDomainExtractingServerUseIpAddress() {
DefaultClientConfigImpl config = new DefaultClientConfigImpl();
config.setProperty(CommonClientConfigKey.UseIPAddrForServer, true);
DomainExtractingServerList serverList = getDomainExtractingServerList(config, true);
@Test
public void testDomainExtractingServerUseIpAddress() {
DefaultClientConfigImpl config = new DefaultClientConfigImpl();
config.setProperty(CommonClientConfigKey.UseIPAddrForServer, true);
DomainExtractingServerList serverList = getDomainExtractingServerList(config,
true);
List<Server> servers = serverList.getInitialListOfServers();
assertNotNull("servers was null", servers);
assertEquals("servers was not size 1", 1, servers.size());
List<Server> servers = serverList.getInitialListOfServers();
assertNotNull("servers was null", servers);
assertEquals("servers was not size 1", 1, servers.size());
DomainExtractingServer des = assertDomainExtractingServer(servers, ZONE);
assertEquals("hostPort was wrong", IP_ADDR+":"+PORT, des.getHostPort());
}
DomainExtractingServer des = assertDomainExtractingServer(servers, ZONE);
assertEquals("hostPort was wrong", IP_ADDR + ":" + PORT, des.getHostPort());
}
protected DomainExtractingServerList getDomainExtractingServerList(DefaultClientConfigImpl config, boolean approximateZoneFromHostname) {
DiscoveryEnabledServer server = mock(DiscoveryEnabledServer.class);
protected DomainExtractingServerList getDomainExtractingServerList(
DefaultClientConfigImpl config, boolean approximateZoneFromHostname) {
DiscoveryEnabledServer server = mock(DiscoveryEnabledServer.class);
@SuppressWarnings("unchecked")
ServerList<Server> originalServerList = mock(ServerList.class);
InstanceInfo instanceInfo = mock(InstanceInfo.class);
InstanceInfo instanceInfo = mock(InstanceInfo.class);
when(server.getInstanceInfo()).thenReturn(instanceInfo);
when(server.getHost()).thenReturn(HOST_NAME);
when(server.getInstanceInfo()).thenReturn(instanceInfo);
when(server.getHost()).thenReturn(HOST_NAME);
when(instanceInfo.getMetadata()).thenReturn(ImmutableMap.<String, String>builder().put("instanceId", INSTANCE_ID).build());
when(instanceInfo.getHostName()).thenReturn(HOST_NAME);
when(instanceInfo.getIPAddr()).thenReturn(IP_ADDR);
when(instanceInfo.getPort()).thenReturn(PORT);
when(instanceInfo.getMetadata()).thenReturn(
ImmutableMap.<String, String> builder().put("instanceId", INSTANCE_ID)
.build());
when(instanceInfo.getHostName()).thenReturn(HOST_NAME);
when(instanceInfo.getIPAddr()).thenReturn(IP_ADDR);
when(instanceInfo.getPort()).thenReturn(PORT);
when(originalServerList.getInitialListOfServers()).thenReturn(Arrays.<Server>asList(server));
when(originalServerList.getInitialListOfServers()).thenReturn(
Arrays.<Server> asList(server));
return new DomainExtractingServerList(originalServerList, config, approximateZoneFromHostname);
}
return new DomainExtractingServerList(originalServerList, config,
approximateZoneFromHostname);
}
}

View File

@@ -15,11 +15,6 @@
*/
package org.springframework.cloud.netflix.ribbon.eureka;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.springframework.cloud.netflix.ribbon.eureka.EurekaRibbonClientConfiguration.VALUE_NOT_SET;
import org.junit.After;
import org.junit.Ignore;
import org.junit.Test;
@@ -33,6 +28,11 @@ import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ZoneAwareLoadBalancer;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.springframework.cloud.netflix.ribbon.eureka.EurekaRibbonClientConfiguration.VALUE_NOT_SET;
/**
* @author Dave Syer
*

View File

@@ -50,7 +50,7 @@ public class EurekaRibbonClientPreprocessorIntegrationTests {
@Test
public void ruleDefaultsToZoneAvoidance() throws Exception {
@SuppressWarnings("unchecked")
ZoneAwareLoadBalancer<Server> loadBalancer = (ZoneAwareLoadBalancer<Server>) factory
ZoneAwareLoadBalancer<Server> loadBalancer = (ZoneAwareLoadBalancer<Server>) this.factory
.getLoadBalancer("foo");
ZoneAvoidanceRule.class.cast(loadBalancer.getRule());
}

View File

@@ -15,8 +15,6 @@
*/
package org.springframework.cloud.netflix.ribbon.eureka;
import static org.junit.Assert.assertEquals;
import java.util.Arrays;
import java.util.List;
@@ -26,6 +24,8 @@ import org.springframework.test.util.ReflectionTestUtils;
import com.netflix.loadbalancer.Server;
import static org.junit.Assert.assertEquals;
/**
* @author Dave Syer
*
@@ -34,17 +34,18 @@ public class ZonePreferenceServerListFilterTests {
private Server dsyer = new Server("dsyer", 8080);
private Server localhost = new Server("localhost", 8080);
@Before
public void init() {
dsyer.setZone("dsyer");
localhost.setZone("localhost");
this.dsyer.setZone("dsyer");
this.localhost.setZone("localhost");
}
@Test
public void noZoneSet() {
ZonePreferenceServerListFilter filter = new ZonePreferenceServerListFilter();
List<Server> result = filter.getFilteredListOfServers(Arrays.asList(localhost));
List<Server> result = filter.getFilteredListOfServers(Arrays
.asList(this.localhost));
assertEquals(1, result.size());
}
@@ -52,7 +53,8 @@ public class ZonePreferenceServerListFilterTests {
public void withZoneSetAndNoMatches() {
ZonePreferenceServerListFilter filter = new ZonePreferenceServerListFilter();
ReflectionTestUtils.setField(filter, "zone", "dsyer");
List<Server> result = filter.getFilteredListOfServers(Arrays.asList(localhost));
List<Server> result = filter.getFilteredListOfServers(Arrays
.asList(this.localhost));
assertEquals(1, result.size());
}
@@ -60,7 +62,8 @@ public class ZonePreferenceServerListFilterTests {
public void withZoneSetAndMatches() {
ZonePreferenceServerListFilter filter = new ZonePreferenceServerListFilter();
ReflectionTestUtils.setField(filter, "zone", "dsyer");
List<Server> result = filter.getFilteredListOfServers(Arrays.asList(dsyer, localhost));
List<Server> result = filter.getFilteredListOfServers(Arrays.asList(this.dsyer,
this.localhost));
assertEquals(1, result.size());
}

View File

@@ -1,7 +1,5 @@
package org.springframework.cloud.netflix.zuul;
import static org.junit.Assert.assertEquals;
import java.util.Arrays;
import org.junit.Test;
@@ -38,11 +36,12 @@ import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import com.netflix.zuul.ZuulFilter;
import static org.junit.Assert.assertEquals;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = FormZuulProxyApplication.class)
@WebAppConfiguration
@IntegrationTest({ "server.port: 0",
"zuul.routes.simple: /simple/**" })
@IntegrationTest({ "server.port: 0", "zuul.routes.simple: /simple/**" })
@DirtiesContext
public class FormZuulProxyApplicationTests {
@@ -62,8 +61,9 @@ public class FormZuulProxyApplicationTests {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
ResponseEntity<String> result = new TestRestTemplate().exchange(
"http://localhost:" + port + "/simple", HttpMethod.POST,
new HttpEntity<MultiValueMap<String,String>>(form, headers), String.class);
"http://localhost:" + this.port + "/simple", HttpMethod.POST,
new HttpEntity<MultiValueMap<String, String>>(form, headers),
String.class);
assertEquals(HttpStatus.OK, result.getStatusCode());
assertEquals("Posted! {foo=[bar]}", result.getBody());
}
@@ -73,16 +73,18 @@ public class FormZuulProxyApplicationTests {
MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();
form.set("foo", "bar");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.valueOf(MediaType.APPLICATION_FORM_URLENCODED_VALUE+"; charset=UTF-8"));
headers.setContentType(MediaType
.valueOf(MediaType.APPLICATION_FORM_URLENCODED_VALUE + "; charset=UTF-8"));
ResponseEntity<String> result = new TestRestTemplate().exchange(
"http://localhost:" + port + "/simple", HttpMethod.POST,
new HttpEntity<MultiValueMap<String,String>>(form, headers), String.class);
"http://localhost:" + this.port + "/simple", HttpMethod.POST,
new HttpEntity<MultiValueMap<String, String>>(form, headers),
String.class);
assertEquals(HttpStatus.OK, result.getStatusCode());
assertEquals("Posted! {foo=[bar]}", result.getBody());
}
}
//Don't use @SpringBootApplication because we don't want to component scan
// Don't use @SpringBootApplication because we don't want to component scan
@Configuration
@EnableAutoConfiguration
@RestController
@@ -126,7 +128,7 @@ class FormZuulProxyApplication {
}
//Load balancer with fixed server list for "simple" pointing to localhost
// Load balancer with fixed server list for "simple" pointing to localhost
@Configuration
class FormRibbonClientConfiguration {
@Bean

View File

@@ -1,12 +1,5 @@
package org.springframework.cloud.netflix.zuul;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
import java.util.Map;
import org.junit.Before;
@@ -19,6 +12,13 @@ import org.springframework.core.env.ConfigurableEnvironment;
import com.google.common.collect.Lists;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
/**
* @author Spencer Gibb
* @author Dave Syer
@@ -41,12 +41,13 @@ public class ProxyRouteLocatorTests {
public void init() {
initMocks(this);
}
@Test
public void testGetMatchingPath() throws Exception {
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery, this.properties);
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery,
this.properties);
this.properties.getRoutes().put("foo", new ZuulRoute("/foo/**"));
properties.init();
this.properties.init();
routeLocator.getRoutes(); // force refresh
ProxyRouteSpec route = routeLocator.getMatchingRoute("/foo/1");
assertEquals("foo", route.getLocation());
@@ -55,10 +56,11 @@ public class ProxyRouteLocatorTests {
@Test
public void testGetMatchingPathWithPrefix() throws Exception {
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery, this.properties);
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery,
this.properties);
this.properties.getRoutes().put("foo", new ZuulRoute("/foo/**"));
this.properties.setPrefix("/proxy");
properties.init();
this.properties.init();
routeLocator.getRoutes(); // force refresh
ProxyRouteSpec route = routeLocator.getMatchingRoute("/proxy/foo/1");
assertEquals("foo", route.getLocation());
@@ -67,8 +69,10 @@ public class ProxyRouteLocatorTests {
@Test
public void testGetMatchingPathWithNoPrefixStripping() throws Exception {
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery, this.properties);
this.properties.getRoutes().put("foo", new ZuulRoute("foo", "/foo/**", "foo", null, false));
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery,
this.properties);
this.properties.getRoutes().put("foo",
new ZuulRoute("foo", "/foo/**", "foo", null, false));
this.properties.setStripPrefix(false);
this.properties.setPrefix("/proxy");
routeLocator.getRoutes(); // force refresh
@@ -79,7 +83,8 @@ public class ProxyRouteLocatorTests {
@Test
public void testGetMatchingPathWithLocalPrefixStripping() throws Exception {
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery, this.properties);
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery,
this.properties);
this.properties.getRoutes().put("foo", new ZuulRoute("/foo/**", "foo"));
this.properties.setStripPrefix(false);
this.properties.setPrefix("/proxy");
@@ -91,8 +96,10 @@ public class ProxyRouteLocatorTests {
@Test
public void testGetMatchingPathWithGlobalPrefixStripping() throws Exception {
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery, this.properties);
this.properties.getRoutes().put("foo", new ZuulRoute("foo", "/foo/**", "foo", null, false));
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery,
this.properties);
this.properties.getRoutes().put("foo",
new ZuulRoute("foo", "/foo/**", "foo", null, false));
this.properties.setPrefix("/proxy");
routeLocator.getRoutes(); // force refresh
ProxyRouteSpec route = routeLocator.getMatchingRoute("/proxy/foo/1");
@@ -102,11 +109,12 @@ public class ProxyRouteLocatorTests {
@Test
public void testGetMatchingPathWithRoutePrefixStripping() throws Exception {
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery, this.properties);
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery,
this.properties);
ZuulRoute zuulRoute = new ZuulRoute("/foo/**");
zuulRoute.setStripPrefix(true);
this.properties.getRoutes().put("foo", zuulRoute);
properties.init();
this.properties.init();
routeLocator.getRoutes(); // force refresh
ProxyRouteSpec route = routeLocator.getMatchingRoute("/foo/1");
assertEquals("foo", route.getLocation());
@@ -115,9 +123,10 @@ public class ProxyRouteLocatorTests {
@Test
public void testGetRoutes() {
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery, this.properties);
this.properties.getRoutes().put(ASERVICE, new ZuulRoute("/"+ASERVICE + "/**"));
properties.init();
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery,
this.properties);
this.properties.getRoutes().put(ASERVICE, new ZuulRoute("/" + ASERVICE + "/**"));
this.properties.init();
Map<String, String> routesMap = routeLocator.getRoutes();
@@ -128,8 +137,10 @@ public class ProxyRouteLocatorTests {
@Test
public void testGetRoutesWithMapping() {
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery, this.properties);
this.properties.getRoutes().put(ASERVICE, new ZuulRoute("/"+ASERVICE + "/**", ASERVICE));
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery,
this.properties);
this.properties.getRoutes().put(ASERVICE,
new ZuulRoute("/" + ASERVICE + "/**", ASERVICE));
this.properties.setPrefix("/foo");
Map<String, String> routesMap = routeLocator.getRoutes();
@@ -138,8 +149,10 @@ public class ProxyRouteLocatorTests {
@Test
public void testGetPhysicalRoutes() {
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery, this.properties);
this.properties.getRoutes().put(ASERVICE, new ZuulRoute("/"+ASERVICE + "/**", "http://" + ASERVICE));
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery,
this.properties);
this.properties.getRoutes().put(ASERVICE,
new ZuulRoute("/" + ASERVICE + "/**", "http://" + ASERVICE));
Map<String, String> routesMap = routeLocator.getRoutes();
@@ -150,7 +163,8 @@ public class ProxyRouteLocatorTests {
@Test
public void testGetDefaultRoute() {
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery, this.properties);
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery,
this.properties);
this.properties.getRoutes().put(ASERVICE, new ZuulRoute("/**", ASERVICE));
Map<String, String> routesMap = routeLocator.getRoutes();
@@ -162,8 +176,10 @@ public class ProxyRouteLocatorTests {
@Test
public void testGetDefaultPhysicalRoute() {
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery, this.properties);
this.properties.getRoutes().put(ASERVICE, new ZuulRoute("/**", "http://" + ASERVICE));
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery,
this.properties);
this.properties.getRoutes().put(ASERVICE,
new ZuulRoute("/**", "http://" + ASERVICE));
Map<String, String> routesMap = routeLocator.getRoutes();
@@ -174,11 +190,11 @@ public class ProxyRouteLocatorTests {
@Test
public void testIgnoreRoutes() {
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery, this.properties);
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery,
this.properties);
this.properties.setIgnoredServices(Lists.newArrayList(IGNOREDSERVICE));
when(discovery.getServices()).thenReturn(
Lists.newArrayList(IGNOREDSERVICE));
when(this.discovery.getServices()).thenReturn(Lists.newArrayList(IGNOREDSERVICE));
Map<String, String> routesMap = routeLocator.getRoutes();
String serviceId = routesMap.get(getMapping(IGNOREDSERVICE));
@@ -187,10 +203,10 @@ public class ProxyRouteLocatorTests {
@Test
public void testAutoRoutes() {
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery, this.properties);
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery,
this.properties);
when(discovery.getServices()).thenReturn(
Lists.newArrayList(MYSERVICE));
when(this.discovery.getServices()).thenReturn(Lists.newArrayList(MYSERVICE));
Map<String, String> routesMap = routeLocator.getRoutes();
@@ -201,11 +217,14 @@ public class ProxyRouteLocatorTests {
@Test
public void testAutoRoutesCanBeOverridden() {
this.properties.getRoutes().put(MYSERVICE, new ZuulRoute("/"+MYSERVICE + "/**", "http://example.com/" + MYSERVICE));
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery, this.properties);
this.properties.getRoutes()
.put(MYSERVICE,
new ZuulRoute("/" + MYSERVICE + "/**", "http://example.com/"
+ MYSERVICE));
ProxyRouteLocator routeLocator = new ProxyRouteLocator(this.discovery,
this.properties);
when(discovery.getServices()).thenReturn(
Lists.newArrayList(MYSERVICE));
when(this.discovery.getServices()).thenReturn(Lists.newArrayList(MYSERVICE));
Map<String, String> routesMap = routeLocator.getRoutes();
@@ -217,22 +236,22 @@ public class ProxyRouteLocatorTests {
protected void assertMapping(Map<String, String> routesMap, String serviceId) {
assertMapping(routesMap, serviceId, serviceId);
}
protected void assertMapping(Map<String, String> routesMap, String expectedRoute, String key) {
protected void assertMapping(Map<String, String> routesMap, String expectedRoute,
String key) {
String mapping = getMapping(key);
String route = routesMap.get(mapping);
assertEquals("routesMap had wrong value for " + mapping, expectedRoute,
route);
assertEquals("routesMap had wrong value for " + mapping, expectedRoute, route);
}
private String getMapping(String serviceId) {
return "/" + serviceId + "/**";
}
protected void assertDefaultMapping(Map<String, String> routesMap, String expectedRoute) {
protected void assertDefaultMapping(Map<String, String> routesMap,
String expectedRoute) {
String mapping = "/**";
String route = routesMap.get(mapping);
assertEquals("routesMap had wrong value for " + mapping, expectedRoute,
route);
assertEquals("routesMap had wrong value for " + mapping, expectedRoute, route);
}
}

View File

@@ -1,7 +1,5 @@
package org.springframework.cloud.netflix.zuul;
import static org.junit.Assert.assertEquals;
import java.util.Arrays;
import org.junit.Test;
@@ -34,13 +32,14 @@ import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import com.netflix.zuul.ZuulFilter;
import static org.junit.Assert.assertEquals;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SampleZuulProxyApplication.class)
@WebAppConfiguration
@IntegrationTest({ "server.port: 0",
"zuul.routes.other: /test/**=http://localhost:7777/local",
"zuul.routes.another: /another/twolevel/**",
"zuul.routes.simple: /simple/**" })
"zuul.routes.another: /another/twolevel/**", "zuul.routes.simple: /simple/**" })
@DirtiesContext
public class SampleZuulProxyApplicationTests {
@@ -55,18 +54,19 @@ public class SampleZuulProxyApplicationTests {
@Test
public void bindRouteUsingPhysicalRoute() {
assertEquals("http://localhost:7777/local", routes.getRoutes().get("/test/**"));
assertEquals("http://localhost:7777/local",
this.routes.getRoutes().get("/test/**"));
}
@Test
public void bindRouteUsingOnlyPath() {
assertEquals("simple", routes.getRoutes().get("/simple/**"));
assertEquals("simple", this.routes.getRoutes().get("/simple/**"));
}
@Test
public void getOnSelfViaRibbonRoutingFilter() {
ResponseEntity<String> result = new TestRestTemplate().exchange(
"http://localhost:" + port + "/simple/local/1", HttpMethod.GET,
"http://localhost:" + this.port + "/simple/local/1", HttpMethod.GET,
new HttpEntity<>((Void) null), String.class);
assertEquals(HttpStatus.OK, result.getStatusCode());
assertEquals("Gotten!", result.getBody());
@@ -74,10 +74,10 @@ public class SampleZuulProxyApplicationTests {
@Test
public void deleteOnSelfViaSimpleHostRoutingFilter() {
routes.addRoute("/self/**", "http://localhost:" + port + "/local");
endpoint.reset();
this.routes.addRoute("/self/**", "http://localhost:" + this.port + "/local");
this.endpoint.reset();
ResponseEntity<String> result = new TestRestTemplate().exchange(
"http://localhost:" + port + "/self/1", HttpMethod.DELETE,
"http://localhost:" + this.port + "/self/1", HttpMethod.DELETE,
new HttpEntity<>((Void) null), String.class);
assertEquals(HttpStatus.OK, result.getStatusCode());
assertEquals("Deleted!", result.getBody());
@@ -86,7 +86,7 @@ public class SampleZuulProxyApplicationTests {
@Test
public void testNotFound() {
ResponseEntity<String> result = new TestRestTemplate().exchange(
"http://localhost:" + port + "/myinvalidpath", HttpMethod.GET,
"http://localhost:" + this.port + "/myinvalidpath", HttpMethod.GET,
new HttpEntity<>((Void) null), String.class);
assertEquals(HttpStatus.NOT_FOUND, result.getStatusCode());
}
@@ -94,22 +94,21 @@ public class SampleZuulProxyApplicationTests {
@Test
public void getSecondLevel() {
ResponseEntity<String> result = new TestRestTemplate().exchange(
"http://localhost:" + port + "/another/twolevel/local/1", HttpMethod.GET,
new HttpEntity<>((Void) null), String.class);
"http://localhost:" + this.port + "/another/twolevel/local/1",
HttpMethod.GET, new HttpEntity<>((Void) null), String.class);
assertEquals(HttpStatus.OK, result.getStatusCode());
assertEquals("Gotten!", result.getBody());
}
}
//Don't use @SpringBootApplication because we don't want to component scan
// Don't use @SpringBootApplication because we don't want to component scan
@Configuration
@EnableAutoConfiguration
@RestController
@EnableZuulProxy
@RibbonClients({
@RibbonClient(name = "simple", configuration = SimpleRibbonClientConfiguration.class),
@RibbonClient(name = "another", configuration = AnotherRibbonClientConfiguration.class)
})
@RibbonClient(name = "simple", configuration = SimpleRibbonClientConfiguration.class),
@RibbonClient(name = "another", configuration = AnotherRibbonClientConfiguration.class) })
class SampleZuulProxyApplication {
@RequestMapping("/testing123")
@@ -168,7 +167,7 @@ class SampleZuulProxyApplication {
}
//Load balancer with fixed server list for "simple" pointing to localhost
// Load balancer with fixed server list for "simple" pointing to localhost
@Configuration
class SimpleRibbonClientConfiguration {
@Bean
@@ -179,6 +178,7 @@ class SimpleRibbonClientConfiguration {
return balancer;
}
}
@Configuration
class AnotherRibbonClientConfiguration {
@Bean

View File

@@ -1,8 +1,5 @@
package org.springframework.cloud.netflix.zuul;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@@ -26,10 +23,13 @@ import org.springframework.web.bind.annotation.RestController;
import com.netflix.zuul.ZuulFilter;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SimpleZuulServerApplication.class)
@WebAppConfiguration
@IntegrationTest({ "server.port: 0"})
@IntegrationTest({ "server.port: 0" })
@DirtiesContext
public class SimpleZuulServerApplicationTests {
@@ -41,13 +41,13 @@ public class SimpleZuulServerApplicationTests {
@Test
public void bindRoute() {
assertTrue(routes.getRoutePaths().contains("/testing123/**"));
assertTrue(this.routes.getRoutePaths().contains("/testing123/**"));
}
@Test
public void getOnSelf() {
ResponseEntity<String> result = new TestRestTemplate().exchange(
"http://localhost:" + port + "/", HttpMethod.GET,
"http://localhost:" + this.port + "/", HttpMethod.GET,
new HttpEntity<Void>((Void) null), String.class);
assertEquals(HttpStatus.OK, result.getStatusCode());
assertEquals("Hello world", result.getBody());
@@ -56,14 +56,14 @@ public class SimpleZuulServerApplicationTests {
@Test
public void getOnSelfViaFilter() {
ResponseEntity<String> result = new TestRestTemplate().exchange(
"http://localhost:" + port + "/testing123/1", HttpMethod.GET,
"http://localhost:" + this.port + "/testing123/1", HttpMethod.GET,
new HttpEntity<Void>((Void) null), String.class);
assertEquals(HttpStatus.OK, result.getStatusCode());
}
}
//Don't use @SpringBootApplication because we don't want to component scan
// Don't use @SpringBootApplication because we don't want to component scan
@Configuration
@EnableAutoConfiguration
@RestController

View File

@@ -1,16 +1,18 @@
package org.springframework.cloud.netflix.zuul.filters.post;
import com.netflix.zuul.context.RequestContext;
import javax.servlet.http.HttpServletRequest;
import org.junit.After;
import org.junit.Test;
import org.springframework.http.HttpStatus;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import javax.servlet.http.HttpServletRequest;
import com.netflix.zuul.context.RequestContext;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
/**
* @author Spencer Gibb

View File

@@ -1,8 +1,5 @@
package org.springframework.cloud.netflix.zuul.filters.pre;
import static org.junit.Assert.assertEquals;
import static org.mockito.MockitoAnnotations.initMocks;
import java.util.List;
import org.junit.Before;
@@ -17,12 +14,15 @@ import org.springframework.mock.web.MockHttpServletRequest;
import com.netflix.util.Pair;
import com.netflix.zuul.context.RequestContext;
import static org.junit.Assert.assertEquals;
import static org.mockito.MockitoAnnotations.initMocks;
/**
* @author Dave Syer
*
*/
public class PreDecorationFilterTests {
private PreDecorationFilter filter;
@Mock
@@ -31,32 +31,32 @@ public class PreDecorationFilterTests {
private ZuulProperties properties = new ZuulProperties();
private ProxyRouteLocator routeLocator;
private MockHttpServletRequest request = new MockHttpServletRequest();
@Before
public void init() {
initMocks(this);
routeLocator = new ProxyRouteLocator(discovery, properties);
filter = new PreDecorationFilter(routeLocator, properties);
this.routeLocator = new ProxyRouteLocator(this.discovery, this.properties);
this.filter = new PreDecorationFilter(this.routeLocator, this.properties);
RequestContext ctx = RequestContext.getCurrentContext();
ctx.setRequest(request);
ctx.setRequest(this.request);
}
@Test
public void basicProperties() throws Exception {
assertEquals(5, filter.filterOrder());
assertEquals(true, filter.shouldFilter());
assertEquals("pre", filter.filterType());
assertEquals(5, this.filter.filterOrder());
assertEquals(true, this.filter.shouldFilter());
assertEquals("pre", this.filter.filterType());
}
@Test
public void prefixRouteAddsHeader() throws Exception {
properties.setPrefix("/api");
properties.setStripPrefix(true);
request.setRequestURI("/api/foo/1");
routeLocator.addRoute(new ZuulRoute("foo", "/foo/**", "foo", null, false));
filter.run();
this.properties.setPrefix("/api");
this.properties.setStripPrefix(true);
this.request.setRequestURI("/api/foo/1");
this.routeLocator.addRoute(new ZuulRoute("foo", "/foo/**", "foo", null, false));
this.filter.run();
RequestContext ctx = RequestContext.getCurrentContext();
assertEquals("/foo/1", ctx.get("requestURI"));
assertEquals("localhost:80", ctx.getZuulRequestHeaders().get("x-forwarded-host"));
@@ -66,11 +66,11 @@ public class PreDecorationFilterTests {
@Test
public void prefixRouteWithRouteStrippingAddsHeader() throws Exception {
properties.setPrefix("/api");
properties.setStripPrefix(true);
request.setRequestURI("/api/foo/1");
routeLocator.addRoute("/foo/**", "foo");
filter.run();
this.properties.setPrefix("/api");
this.properties.setStripPrefix(true);
this.request.setRequestURI("/api/foo/1");
this.routeLocator.addRoute("/foo/**", "foo");
this.filter.run();
RequestContext ctx = RequestContext.getCurrentContext();
assertEquals("/1", ctx.get("requestURI"));
assertEquals("localhost:80", ctx.getZuulRequestHeaders().get("x-forwarded-host"));
@@ -78,8 +78,7 @@ public class PreDecorationFilterTests {
assertEquals("foo", getHeader(ctx.getOriginResponseHeaders(), "x-zuul-serviceid"));
}
private Object getHeader(List<Pair<String, String>> headers,
String key) {
private Object getHeader(List<Pair<String, String>> headers, String key) {
String value = null;
for (Pair<String, String> pair : headers) {
if (pair.first().toLowerCase().equals(key.toLowerCase())) {

View File

@@ -35,213 +35,226 @@ import com.netflix.eureka.util.StatusInfo;
@RequestMapping("${eureka.dashboard.path:/}")
public class EurekaController {
@Value("${eureka.dashboard.path:/}")
private String dashboardPath = "";
@Value("${eureka.dashboard.path:/}")
private String dashboardPath = "";
@RequestMapping(method = RequestMethod.GET)
public String status(HttpServletRequest request, Map<String, Object> model) {
populateBase(request, model);
@RequestMapping(method = RequestMethod.GET)
public String status(HttpServletRequest request, Map<String, Object> model) {
populateBase(request, model);
populateApps(model);
populateApps(model);
StatusInfo statusInfo = new StatusResource().getStatusInfo();
model.put("statusInfo", statusInfo);
StatusInfo statusInfo = new StatusResource().getStatusInfo();
model.put("statusInfo", statusInfo);
populateInstanceInfo(model, statusInfo);
populateInstanceInfo(model, statusInfo);
return "eureka/status";
}
return "eureka/status";
}
@RequestMapping(value = "/lastn", method = RequestMethod.GET)
public String lastn(HttpServletRequest request, Map<String, Object> model) {
populateBase(request, model);
PeerAwareInstanceRegistry registery = PeerAwareInstanceRegistry.getInstance();
@RequestMapping(value = "/lastn", method = RequestMethod.GET)
public String lastn(HttpServletRequest request, Map<String, Object> model) {
populateBase(request, model);
PeerAwareInstanceRegistry registery = PeerAwareInstanceRegistry.getInstance();
ArrayList<Map<String, Object>> lastNCanceled = new ArrayList<>();
List<Pair<Long, String>> list = registery.getLastNCanceledInstances();
for (Pair<Long, String> entry : list) {
lastNCanceled.add(registeredInstance(entry.second(), entry.first().longValue()));
}
model.put("lastNCanceled", lastNCanceled);
ArrayList<Map<String, Object>> lastNCanceled = new ArrayList<>();
List<Pair<Long, String>> list = registery.getLastNCanceledInstances();
for (Pair<Long, String> entry : list) {
lastNCanceled.add(registeredInstance(entry.second(), entry.first()
.longValue()));
}
model.put("lastNCanceled", lastNCanceled);
list = registery.getLastNRegisteredInstances();
ArrayList<Map<String, Object>> lastNRegistered = new ArrayList<>();
for (Pair<Long, String> entry : list) {
lastNRegistered.add(registeredInstance(entry.second(), entry.first().longValue()));
}
model.put("lastNRegistered", lastNRegistered);
list = registery.getLastNRegisteredInstances();
ArrayList<Map<String, Object>> lastNRegistered = new ArrayList<>();
for (Pair<Long, String> entry : list) {
lastNRegistered.add(registeredInstance(entry.second(), entry.first()
.longValue()));
}
model.put("lastNRegistered", lastNRegistered);
return "eureka/lastn";
}
return "eureka/lastn";
}
private Map<String, Object> registeredInstance(String id, long date) {
HashMap<String, Object> map = new HashMap<>();
map.put("id", id);
map.put("date", new Date(date));
return map;
}
private Map<String, Object> registeredInstance(String id, long date) {
HashMap<String, Object> map = new HashMap<>();
map.put("id", id);
map.put("date", new Date(date));
return map;
}
protected void populateBase(HttpServletRequest request, Map<String, Object> model) {
model.put("time", new Date());
model.put("basePath", "/");
model.put("dashboardPath", dashboardPath.equals("/") ? "" : dashboardPath);
protected void populateBase(HttpServletRequest request, Map<String, Object> model) {
model.put("time", new Date());
model.put("basePath", "/");
model.put("dashboardPath", this.dashboardPath.equals("/") ? ""
: this.dashboardPath);
populateHeader(model);
populateHeader(model);
populateNavbar(request, model);
}
populateNavbar(request, model);
}
private void populateHeader(Map<String, Object> model) {
model.put("currentTime", StatusResource.getCurrentTimeAsString());
model.put("upTime", StatusInfo.getUpTime());
model.put("environment", ConfigurationManager.getDeploymentContext().getDeploymentEnvironment());
model.put("datacenter", ConfigurationManager.getDeploymentContext().getDeploymentDatacenter());
model.put("registry", PeerAwareInstanceRegistry.getInstance());
model.put("isBelowRenewThresold", PeerAwareInstanceRegistry.getInstance().isBelowRenewThresold() == 1);
private void populateHeader(Map<String, Object> model) {
model.put("currentTime", StatusResource.getCurrentTimeAsString());
model.put("upTime", StatusInfo.getUpTime());
model.put("environment", ConfigurationManager.getDeploymentContext()
.getDeploymentEnvironment());
model.put("datacenter", ConfigurationManager.getDeploymentContext()
.getDeploymentDatacenter());
model.put("registry", PeerAwareInstanceRegistry.getInstance());
model.put("isBelowRenewThresold", PeerAwareInstanceRegistry.getInstance()
.isBelowRenewThresold() == 1);
DataCenterInfo info = ApplicationInfoManager.getInstance().getInfo().getDataCenterInfo();
if(info.getName() == DataCenterInfo.Name.Amazon) {
AmazonInfo amazonInfo = (AmazonInfo) info;
model.put("amazonInfo", amazonInfo);
model.put("amiId", amazonInfo.get(AmazonInfo.MetaDataKey.amiId));
model.put("availabilityZone", amazonInfo.get(AmazonInfo.MetaDataKey.availabilityZone));
model.put("instanceId", amazonInfo.get(AmazonInfo.MetaDataKey.instanceId));
}
}
DataCenterInfo info = ApplicationInfoManager.getInstance().getInfo()
.getDataCenterInfo();
if (info.getName() == DataCenterInfo.Name.Amazon) {
AmazonInfo amazonInfo = (AmazonInfo) info;
model.put("amazonInfo", amazonInfo);
model.put("amiId", amazonInfo.get(AmazonInfo.MetaDataKey.amiId));
model.put("availabilityZone",
amazonInfo.get(AmazonInfo.MetaDataKey.availabilityZone));
model.put("instanceId", amazonInfo.get(AmazonInfo.MetaDataKey.instanceId));
}
}
private void populateNavbar(HttpServletRequest request, Map<String, Object> model) {
Map<String, String> replicas = new LinkedHashMap<>();
List<PeerEurekaNode> list = PeerAwareInstanceRegistry.getInstance().getReplicaNodes();
for (PeerEurekaNode node : list) {
try {
URI uri = new URI(node.getServiceUrl());
String href = node.getServiceUrl();
replicas.put(uri.getHost(), href);
} catch(Exception e) {
//ignore?
}
}
model.put("replicas", replicas.entrySet());
}
private void populateNavbar(HttpServletRequest request, Map<String, Object> model) {
Map<String, String> replicas = new LinkedHashMap<>();
List<PeerEurekaNode> list = PeerAwareInstanceRegistry.getInstance()
.getReplicaNodes();
for (PeerEurekaNode node : list) {
try {
URI uri = new URI(node.getServiceUrl());
String href = node.getServiceUrl();
replicas.put(uri.getHost(), href);
}
catch (Exception e) {
// ignore?
}
}
model.put("replicas", replicas.entrySet());
}
private void populateApps(Map<String, Object> model) {
List<com.netflix.discovery.shared.Application> sortedApplications = PeerAwareInstanceRegistry.getInstance().getSortedApplications();
private void populateApps(Map<String, Object> model) {
List<com.netflix.discovery.shared.Application> sortedApplications = PeerAwareInstanceRegistry
.getInstance().getSortedApplications();
ArrayList<Map<String, Object>> apps = new ArrayList<>();
ArrayList<Map<String, Object>> apps = new ArrayList<>();
for(Application app : sortedApplications) {
LinkedHashMap<String, Object> appData = new LinkedHashMap<>();
apps.add(appData);
for (Application app : sortedApplications) {
LinkedHashMap<String, Object> appData = new LinkedHashMap<>();
apps.add(appData);
appData.put("name", app.getName());
Map<String, Integer> amiCounts = new HashMap<>();
Map<InstanceInfo.InstanceStatus,List<Pair<String, String>>> instancesByStatus = new HashMap<>();
Map<String,Integer> zoneCounts = new HashMap<>();
appData.put("name", app.getName());
Map<String, Integer> amiCounts = new HashMap<>();
Map<InstanceInfo.InstanceStatus, List<Pair<String, String>>> instancesByStatus = new HashMap<>();
Map<String, Integer> zoneCounts = new HashMap<>();
for(InstanceInfo info : app.getInstances()){
String id = info.getId();
String url = info.getStatusPageUrl();
InstanceInfo.InstanceStatus status = info.getStatus();
String ami = "n/a";
String zone = "";
if(info.getDataCenterInfo().getName() == DataCenterInfo.Name.Amazon){
AmazonInfo dcInfo = (AmazonInfo)info.getDataCenterInfo();
ami = dcInfo.get(AmazonInfo.MetaDataKey.amiId);
zone = dcInfo.get(AmazonInfo.MetaDataKey.availabilityZone);
}
for (InstanceInfo info : app.getInstances()) {
String id = info.getId();
String url = info.getStatusPageUrl();
InstanceInfo.InstanceStatus status = info.getStatus();
String ami = "n/a";
String zone = "";
if (info.getDataCenterInfo().getName() == DataCenterInfo.Name.Amazon) {
AmazonInfo dcInfo = (AmazonInfo) info.getDataCenterInfo();
ami = dcInfo.get(AmazonInfo.MetaDataKey.amiId);
zone = dcInfo.get(AmazonInfo.MetaDataKey.availabilityZone);
}
Integer count = amiCounts.get(ami);
if(count != null){
amiCounts.put(ami, Integer.valueOf(count.intValue()+1));
}else {
amiCounts.put(ami, Integer.valueOf(1));
}
Integer count = amiCounts.get(ami);
if (count != null) {
amiCounts.put(ami, Integer.valueOf(count.intValue() + 1));
}
else {
amiCounts.put(ami, Integer.valueOf(1));
}
count = zoneCounts.get(zone);
if(count != null){
zoneCounts.put(zone, Integer.valueOf(count.intValue()+1));
}else {
zoneCounts.put(zone, Integer.valueOf(1));
}
List<Pair<String, String>> list = instancesByStatus.get(status);
count = zoneCounts.get(zone);
if (count != null) {
zoneCounts.put(zone, Integer.valueOf(count.intValue() + 1));
}
else {
zoneCounts.put(zone, Integer.valueOf(1));
}
List<Pair<String, String>> list = instancesByStatus.get(status);
if(list == null){
list = new ArrayList<>();
instancesByStatus.put(status, list);
}
list.add(new Pair<>(id, url));
}
if (list == null) {
list = new ArrayList<>();
instancesByStatus.put(status, list);
}
list.add(new Pair<>(id, url));
}
appData.put("amiCounts", amiCounts.entrySet());
appData.put("zoneCounts", zoneCounts.entrySet());
appData.put("amiCounts", amiCounts.entrySet());
appData.put("zoneCounts", zoneCounts.entrySet());
ArrayList<Map<String, Object>> instanceInfos = new ArrayList<>();
appData.put("instanceInfos", instanceInfos);
ArrayList<Map<String, Object>> instanceInfos = new ArrayList<>();
appData.put("instanceInfos", instanceInfos);
for (Iterator<Map.Entry<InstanceInfo.InstanceStatus, List<Pair<String,String>>>> iter =
instancesByStatus.entrySet().iterator(); iter.hasNext();) {
Map.Entry<InstanceInfo.InstanceStatus, List<Pair<String,String>>> entry = iter.next();
List<Pair<String, String>> value = entry.getValue();
InstanceInfo.InstanceStatus status = entry.getKey();
for (Iterator<Map.Entry<InstanceInfo.InstanceStatus, List<Pair<String, String>>>> iter = instancesByStatus
.entrySet().iterator(); iter.hasNext();) {
Map.Entry<InstanceInfo.InstanceStatus, List<Pair<String, String>>> entry = iter
.next();
List<Pair<String, String>> value = entry.getValue();
InstanceInfo.InstanceStatus status = entry.getKey();
LinkedHashMap<String, Object> instanceData = new LinkedHashMap<>();
instanceInfos.add(instanceData);
LinkedHashMap<String, Object> instanceData = new LinkedHashMap<>();
instanceInfos.add(instanceData);
instanceData.put("status", entry.getKey());
ArrayList<Map<String, Object>> instances = new ArrayList<>();
instanceData.put("instances", instances);
instanceData.put("isNotUp", status != InstanceInfo.InstanceStatus.UP);
instanceData.put("status", entry.getKey());
ArrayList<Map<String, Object>> instances = new ArrayList<>();
instanceData.put("instances", instances);
instanceData.put("isNotUp", status != InstanceInfo.InstanceStatus.UP);
/*if(status != InstanceInfo.InstanceStatus.UP){
buf.append("<font color=red size=+1><b>");
}
buf.append("<b>").append(status.name()).append("</b> (").append(value.size()).append(") - ");
if(status != InstanceInfo.InstanceStatus.UP){
buf.append("</font></b>");
}*/
/*
* if(status != InstanceInfo.InstanceStatus.UP){
* buf.append("<font color=red size=+1><b>"); }
* buf.append("<b>").append(status
* .name()).append("</b> (").append(value.size()).append(") - ");
* if(status != InstanceInfo.InstanceStatus.UP){
* buf.append("</font></b>"); }
*/
for(Pair<String,String> p : value) {
LinkedHashMap<String, Object> instance = new LinkedHashMap<>();
instances.add(instance);
instance.put("id", p.first());
instance.put("url", p.second());
instance.put("isHref", p.second().startsWith("http"));
/*String id = p.first();
String url = p.second();
if(url != null && url.startsWith("http")){
buf.append("<a href=\"").append(url).append("\">");
}else {
url = null;
}
buf.append(id);
if(url != null){
buf.append("</a>");
}
buf.append(", ");*/
}
}
//out.println("<td>" + buf.toString() + "</td></tr>");
}
for (Pair<String, String> p : value) {
LinkedHashMap<String, Object> instance = new LinkedHashMap<>();
instances.add(instance);
instance.put("id", p.first());
instance.put("url", p.second());
instance.put("isHref", p.second().startsWith("http"));
/*
* String id = p.first(); String url = p.second(); if(url != null &&
* url.startsWith("http")){
* buf.append("<a href=\"").append(url).append("\">"); }else { url =
* null; } buf.append(id); if(url != null){ buf.append("</a>"); }
* buf.append(", ");
*/
}
}
// out.println("<td>" + buf.toString() + "</td></tr>");
}
model.put("apps", apps);
}
model.put("apps", apps);
}
private void populateInstanceInfo(Map<String, Object> model, StatusInfo statusInfo) {
InstanceInfo instanceInfo = statusInfo.getInstanceInfo();
private void populateInstanceInfo(Map<String, Object> model, StatusInfo statusInfo) {
InstanceInfo instanceInfo = statusInfo.getInstanceInfo();
Map<String,String> instanceMap = new HashMap<>();
instanceMap.put("ipAddr", instanceInfo.getIPAddr());
instanceMap.put("status", instanceInfo.getStatus().toString());
if(instanceInfo.getDataCenterInfo().getName() == DataCenterInfo.Name.Amazon) {
AmazonInfo info = (AmazonInfo) instanceInfo.getDataCenterInfo();
instanceMap.put("availability-zone", info.get(AmazonInfo.MetaDataKey.availabilityZone));
instanceMap.put("public-ipv4", info.get(AmazonInfo.MetaDataKey.publicIpv4));
instanceMap.put("instance-id", info.get(AmazonInfo.MetaDataKey.instanceId));
instanceMap.put("public-hostname", info.get(AmazonInfo.MetaDataKey.publicHostname));
instanceMap.put("ami-id", info.get(AmazonInfo.MetaDataKey.amiId));
instanceMap.put("instance-type", info.get(AmazonInfo.MetaDataKey.instanceType));
}
Map<String, String> instanceMap = new HashMap<>();
instanceMap.put("ipAddr", instanceInfo.getIPAddr());
instanceMap.put("status", instanceInfo.getStatus().toString());
if (instanceInfo.getDataCenterInfo().getName() == DataCenterInfo.Name.Amazon) {
AmazonInfo info = (AmazonInfo) instanceInfo.getDataCenterInfo();
instanceMap.put("availability-zone",
info.get(AmazonInfo.MetaDataKey.availabilityZone));
instanceMap.put("public-ipv4", info.get(AmazonInfo.MetaDataKey.publicIpv4));
instanceMap.put("instance-id", info.get(AmazonInfo.MetaDataKey.instanceId));
instanceMap.put("public-hostname",
info.get(AmazonInfo.MetaDataKey.publicHostname));
instanceMap.put("ami-id", info.get(AmazonInfo.MetaDataKey.amiId));
instanceMap.put("instance-type",
info.get(AmazonInfo.MetaDataKey.instanceType));
}
model.put("instanceInfo", instanceMap);
}
model.put("instanceInfo", instanceMap);
}
}

View File

@@ -15,24 +15,24 @@
*/
package org.springframework.cloud.netflix.eureka.server;
import org.springframework.boot.context.properties.ConfigurationProperties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Configuration properties for the Eureka dashboard (UI).
* Configuration properties for the Eureka dashboard (UI).
* @author Dave Syer
*
*/
@ConfigurationProperties("eureka.dashboard")
@Data
public class EurekaDashboardProperties {
/**
* The path to the Eureka dashboard (relative to the servlet path). Defaults to "/".
*/
private String path = "/";
/**
* FLag to enable the Eureka dashboard. Default true.
*/

View File

@@ -117,22 +117,32 @@ public class EurekaServerInitializerConfiguration implements ServletContextAware
// ignore
}
LoggingConfiguration.getInstance().configure();
EurekaServerConfigurationManager.getInstance()
.setConfiguration(eurekaServerConfig);
XmlXStream.getInstance().setMarshallingStrategy(
new DataCenterAwareMarshallingStrategy(applicationContext));
JsonXStream.getInstance().setMarshallingStrategy(
new DataCenterAwareMarshallingStrategy(applicationContext));
EurekaServerConfigurationManager
.getInstance()
.setConfiguration(
EurekaServerInitializerConfiguration.this.eurekaServerConfig);
XmlXStream
.getInstance()
.setMarshallingStrategy(
new DataCenterAwareMarshallingStrategy(
EurekaServerInitializerConfiguration.this.applicationContext));
JsonXStream
.getInstance()
.setMarshallingStrategy(
new DataCenterAwareMarshallingStrategy(
EurekaServerInitializerConfiguration.this.applicationContext));
// PeerAwareInstanceRegistry.getInstance();
applicationContext
EurekaServerInitializerConfiguration.this.applicationContext
.publishEvent(new EurekaRegistryAvailableEvent(
eurekaServerConfig));
EurekaServerInitializerConfiguration.this.eurekaServerConfig));
}
}.contextInitialized(new ServletContextEvent(servletContext));
}.contextInitialized(new ServletContextEvent(
EurekaServerInitializerConfiguration.this.servletContext));
logger.info("Started Eureka Server");
running = true;
applicationContext.publishEvent(new EurekaServerStartedEvent(
eurekaServerConfig));
EurekaServerInitializerConfiguration.this.running = true;
EurekaServerInitializerConfiguration.this.applicationContext
.publishEvent(new EurekaServerStartedEvent(
EurekaServerInitializerConfiguration.this.eurekaServerConfig));
}
catch (Exception e) {
// Help!
@@ -144,12 +154,12 @@ public class EurekaServerInitializerConfiguration implements ServletContextAware
@Override
public void stop() {
running = false;
this.running = false;
}
@Override
public boolean isRunning() {
return running;
return this.running;
}
@Override
@@ -169,7 +179,7 @@ public class EurekaServerInitializerConfiguration implements ServletContextAware
@Override
public int getOrder() {
return order;
return this.order;
}
@Configuration
@@ -189,8 +199,8 @@ public class EurekaServerInitializerConfiguration implements ServletContextAware
@Override
public void onApplicationEvent(EurekaRegistryAvailableEvent event) {
if (instance == null) {
instance = PeerAwareInstanceRegistry.getInstance();
if (this.instance == null) {
this.instance = PeerAwareInstanceRegistry.getInstance();
safeInit();
replaceInstance(getProxyForInstance());
expectRegistrations(1);
@@ -198,9 +208,10 @@ public class EurekaServerInitializerConfiguration implements ServletContextAware
}
private void safeInit() {
Method method = ReflectionUtils.findMethod(InstanceRegistry.class, "postInit");
Method method = ReflectionUtils
.findMethod(InstanceRegistry.class, "postInit");
ReflectionUtils.makeAccessible(method);
ReflectionUtils.invokeMethod(method, instance);
ReflectionUtils.invokeMethod(method, this.instance);
}
private void replaceInstance(Object proxy) {
@@ -221,7 +232,7 @@ public class EurekaServerInitializerConfiguration implements ServletContextAware
private Object getProxyForInstance() {
// Wrap the instance registry...
ProxyFactory factory = new ProxyFactory(instance);
ProxyFactory factory = new ProxyFactory(this.instance);
// ...with the LeaseManagerMessageBroker
factory.addAdvice(new PiggybackMethodInterceptor(leaseManagerMessageBroker(),
LeaseManagerLite.class));
@@ -243,9 +254,9 @@ public class EurekaServerInitializerConfiguration implements ServletContextAware
try {
// Awful ugly hack to work around lack of DI in eureka
field.setAccessible(true);
int value = (int) ReflectionUtils.getField(field, instance);
int value = (int) ReflectionUtils.getField(field, this.instance);
if (value == 0 && count > 0) {
ReflectionUtils.setField(field, instance, count);
ReflectionUtils.setField(field, this.instance, count);
}
}
catch (Exception e) {
@@ -262,7 +273,7 @@ public class EurekaServerInitializerConfiguration implements ServletContextAware
* hasn't sent any renewals recently. This happens for a standalone server. It
* seems like a bad default, so we set it to the smallest non-zero value we can,
* so that any instances that subsequently register can bump up the threshold.
*
*
* @author Dave Syer
*
*/

Some files were not shown because too many files have changed in this diff Show More