diff --git a/docs/src/main/asciidoc/spring-cloud-commons.adoc b/docs/src/main/asciidoc/spring-cloud-commons.adoc
index b9921306..0dc29a29 100644
--- a/docs/src/main/asciidoc/spring-cloud-commons.adoc
+++ b/docs/src/main/asciidoc/spring-cloud-commons.adoc
@@ -487,3 +487,16 @@ spring:
inetutils:
useOnlySiteLocalInterfaces: true
----
+
+[[http-clients]]
+=== HTTP Client Factories
+
+Spring Cloud Commons provides beans for creating both Apache HTTP clients (`ApacheHttpClientFactory`)
+as well as OK HTTP clients (`OkHttpClientFactory`). The `OkHttpClientFactory` bean will only be created
+if the OK HTTP jar is on the classpath. In addition, Spring Cloud Commons provides beans for creating
+the connection managers used by both clients, `ApacheHttpClientConnectionManagerFactory` for the Apache
+HTTP client and `OkHttpClientConnectionPoolFactory` for the OK HTTP client. You can provide
+your own implementation of these beans if you would like to customize how the HTTP clients are created
+in downstream projects. You can also disable the creation of these beans by setting
+`spring.cloud.httpclientfactories.apache.enabled` or `spring.cloud.httpclientfactories.ok.enabled` to
+`false`.
\ No newline at end of file
diff --git a/spring-cloud-commons/pom.xml b/spring-cloud-commons/pom.xml
index 7d7ab076..afb1f682 100644
--- a/spring-cloud-commons/pom.xml
+++ b/spring-cloud-commons/pom.xml
@@ -13,6 +13,10 @@
jar
Spring Cloud Commons
Spring Cloud Commons
+
+ 3.6.0
+ 4.5.1
+
org.springframework.boot
@@ -75,11 +79,22 @@
true
- org.projectlombok
- lombok
- compile
+ com.squareup.okhttp3
+ okhttp
+ ${okhttp3.version}
true
+
+ com.squareup.okhttp3
+ logging-interceptor
+ ${okhttp3.version}
+ true
+
+
+ org.apache.httpcomponents
+ httpclient
+ ${apachehttpclient.version}
+
org.springframework.boot
spring-boot-starter-test
diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/DefaultServiceInstance.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/DefaultServiceInstance.java
index 566a1228..d7e710c2 100644
--- a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/DefaultServiceInstance.java
+++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/DefaultServiceInstance.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013-2015 the original author or authors.
+ * Copyright 2013-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,20 +16,17 @@
package org.springframework.cloud.client;
+
import java.net.URI;
import java.util.LinkedHashMap;
import java.util.Map;
-
-import lombok.Data;
-import lombok.RequiredArgsConstructor;
+import java.util.Objects;
/**
* Default implementation of {@link ServiceInstance}.
*
* @author Spencer Gibb
*/
-@Data
-@RequiredArgsConstructor
public class DefaultServiceInstance implements ServiceInstance {
private final String serviceId;
@@ -42,6 +39,15 @@ public class DefaultServiceInstance implements ServiceInstance {
private final Map metadata;
+ public DefaultServiceInstance(String serviceId, String host, int port, boolean secure,
+ Map metadata) {
+ this.serviceId = serviceId;
+ this.host = host;
+ this.port = port;
+ this.secure = secure;
+ this.metadata = metadata;
+ }
+
public DefaultServiceInstance(String serviceId, String host, int port,
boolean secure) {
this(serviceId, host, port, secure, new LinkedHashMap());
@@ -68,4 +74,52 @@ public class DefaultServiceInstance implements ServiceInstance {
instance.getPort());
return URI.create(uri);
}
+
+ @Override
+ public String getServiceId() {
+ return serviceId;
+ }
+
+ @Override
+ public String getHost() {
+ return host;
+ }
+
+ @Override
+ public int getPort() {
+ return port;
+ }
+
+ @Override
+ public boolean isSecure() {
+ return secure;
+ }
+
+ @Override
+ public String toString() {
+ return "DefaultServiceInstance{" +
+ "serviceId='" + serviceId + '\'' +
+ ", host='" + host + '\'' +
+ ", port=" + port +
+ ", secure=" + secure +
+ ", metadata=" + metadata +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ DefaultServiceInstance that = (DefaultServiceInstance) o;
+ return port == that.port &&
+ secure == that.secure &&
+ Objects.equals(serviceId, that.serviceId) &&
+ Objects.equals(host, that.host) &&
+ Objects.equals(metadata, that.metadata);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(serviceId, host, port, secure, metadata);
+ }
}
diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/actuator/FeaturesEndpoint.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/actuator/FeaturesEndpoint.java
index 7e6e19c4..319e27c6 100644
--- a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/actuator/FeaturesEndpoint.java
+++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/actuator/FeaturesEndpoint.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package org.springframework.cloud.client.actuator;
import java.util.ArrayList;
@@ -10,7 +26,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
-import lombok.Value;
/**
* @author Spencer Gibb
@@ -75,17 +90,47 @@ public class FeaturesEndpoint extends AbstractEndpoint enabled = new ArrayList<>();
- List disabled = new ArrayList<>();
+ final List enabled = new ArrayList<>();
+ final List disabled = new ArrayList<>();
+
+ public List getEnabled() {
+ return enabled;
+ }
+
+ public List getDisabled() {
+ return disabled;
+ }
}
- @Value
+
class Feature {
final String type;
final String name;
final String version;
final String vendor;
+
+ public Feature(String type, String name, String version, String vendor) {
+ this.type = type;
+ this.name = name;
+ this.version = version;
+ this.vendor = vendor;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public String getVendor() {
+ return vendor;
+ }
}
}
diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/actuator/NamedFeature.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/actuator/NamedFeature.java
index f5062052..572263e0 100644
--- a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/actuator/NamedFeature.java
+++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/actuator/NamedFeature.java
@@ -1,12 +1,38 @@
+/*
+ * Copyright 2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package org.springframework.cloud.client.actuator;
-import lombok.Value;
/**
* @author Spencer Gibb
*/
-@Value
public class NamedFeature {
private final String name;
private final Class> type;
+
+ public NamedFeature(String name, Class> type) {
+ this.name = name;
+ this.type = type;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Class> getType() {
+ return type;
+ }
}
diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/health/DiscoveryClientHealthIndicator.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/health/DiscoveryClientHealthIndicator.java
index 75ec4a2b..8f86a386 100644
--- a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/health/DiscoveryClientHealthIndicator.java
+++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/health/DiscoveryClientHealthIndicator.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013-2015 the original author or authors.
+ * Copyright 2013-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +19,8 @@ package org.springframework.cloud.client.discovery.health;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.Status;
import org.springframework.cloud.client.discovery.DiscoveryClient;
@@ -26,12 +28,10 @@ import org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.Ordered;
-import lombok.extern.apachecommons.CommonsLog;
/**
* @author Spencer Gibb
*/
-@CommonsLog
public class DiscoveryClientHealthIndicator implements DiscoveryHealthIndicator, Ordered,
ApplicationListener> {
@@ -42,6 +42,8 @@ public class DiscoveryClientHealthIndicator implements DiscoveryHealthIndicator,
private final DiscoveryClient discoveryClient;
private final DiscoveryClientHealthIndicatorProperties properties;
+ private final Log log = LogFactory.getLog(DiscoveryClientHealthIndicator.class);
+
@Deprecated
public DiscoveryClientHealthIndicator(DiscoveryClient discoveryClient) {
this(discoveryClient, new DiscoveryClientHealthIndicatorProperties());
diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/noop/NoopDiscoveryClientAutoConfiguration.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/noop/NoopDiscoveryClientAutoConfiguration.java
index 6dd788b6..9548485d 100644
--- a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/noop/NoopDiscoveryClientAutoConfiguration.java
+++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/noop/NoopDiscoveryClientAutoConfiguration.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013-2014 the original author or authors.
+ * Copyright 2013-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,6 +21,8 @@ import java.net.UnknownHostException;
import javax.annotation.PostConstruct;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@@ -36,8 +38,6 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.env.Environment;
-import lombok.extern.apachecommons.CommonsLog;
-
/**
*
* @deprecated Use
@@ -48,7 +48,6 @@ import lombok.extern.apachecommons.CommonsLog;
@Configuration
@EnableConfigurationProperties
@ConditionalOnMissingBean(DiscoveryClient.class)
-@CommonsLog
@Deprecated
public class NoopDiscoveryClientAutoConfiguration
implements ApplicationListener {
@@ -67,6 +66,8 @@ public class NoopDiscoveryClientAutoConfiguration
private DefaultServiceInstance serviceInstance;
+ private final Log log = LogFactory.getLog(NoopDiscoveryClientAutoConfiguration.class);
+
@PostConstruct
public void init() {
String host = "localhost";
diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/hypermedia/CloudHypermediaAutoConfiguration.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/hypermedia/CloudHypermediaAutoConfiguration.java
index a30f4f0c..8f31161e 100644
--- a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/hypermedia/CloudHypermediaAutoConfiguration.java
+++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/hypermedia/CloudHypermediaAutoConfiguration.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 the original author or authors.
+ * Copyright 2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,7 +15,6 @@
*/
package org.springframework.cloud.client.hypermedia;
-import lombok.Data;
import java.util.Collections;
import java.util.List;
@@ -50,17 +49,39 @@ public class CloudHypermediaAutoConfiguration {
properties.getRefresh().getInitialDelay());
}
- @Data
@ConfigurationProperties(prefix = "spring.cloud.hypermedia")
public static class CloudHypermediaProperties {
private Refresh refresh = new Refresh();
- @Data
+ public Refresh getRefresh() {
+ return refresh;
+ }
+
+ public void setRefresh(Refresh refresh) {
+ this.refresh = refresh;
+ }
+
public static class Refresh {
private int fixedDelay = 5000;
private int initialDelay = 10000;
+
+ public int getFixedDelay() {
+ return fixedDelay;
+ }
+
+ public void setFixedDelay(int fixedDelay) {
+ this.fixedDelay = fixedDelay;
+ }
+
+ public int getInitialDelay() {
+ return initialDelay;
+ }
+
+ public void setInitialDelay(int initialDelay) {
+ this.initialDelay = initialDelay;
+ }
}
}
}
diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/hypermedia/DiscoveredResource.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/hypermedia/DiscoveredResource.java
index 6a9737a1..cae5a18e 100644
--- a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/hypermedia/DiscoveredResource.java
+++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/hypermedia/DiscoveredResource.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 the original author or authors.
+ * Copyright 2015-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,12 +15,10 @@
*/
package org.springframework.cloud.client.hypermedia;
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-
import java.net.URI;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.MediaTypes;
@@ -35,15 +33,22 @@ import org.springframework.web.client.RestTemplate;
*
* @author Oliver Gierke
*/
-@Slf4j
-@RequiredArgsConstructor
public class DiscoveredResource implements RemoteResource {
private final ServiceInstanceProvider provider;
private final TraversalDefinition traversal;
+
private RestOperations restOperations = new RestTemplate();
- private @Getter Link link = null;
+ private Link link = null;
+
+ private final Logger log = LoggerFactory.getLogger(DiscoveredResource.class);
+
+
+ public DiscoveredResource(ServiceInstanceProvider provider, TraversalDefinition traversal) {
+ this.provider = provider;
+ this.traversal = traversal;
+ }
/**
* Configures the {@link RestOperations} to use to execute the traversal and verifying HEAD calls.
@@ -54,6 +59,27 @@ public class DiscoveredResource implements RemoteResource {
this.restOperations = restOperations == null ? new RestTemplate() : restOperations;
}
+ public ServiceInstanceProvider getProvider() {
+ return provider;
+ }
+
+ public TraversalDefinition getTraversal() {
+ return traversal;
+ }
+
+ public RestOperations getRestOperations() {
+ return restOperations;
+ }
+
+ @Override
+ public Link getLink() {
+ return link;
+ }
+
+ public void setLink(Link link) {
+ this.link = link;
+ }
+
/**
* Verifies the link to the current
*/
diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/hypermedia/DynamicServiceInstanceProvider.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/hypermedia/DynamicServiceInstanceProvider.java
index 7f33015a..fa32769c 100644
--- a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/hypermedia/DynamicServiceInstanceProvider.java
+++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/hypermedia/DynamicServiceInstanceProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 the original author or authors.
+ * Copyright 2015-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,8 +15,6 @@
*/
package org.springframework.cloud.client.hypermedia;
-import lombok.RequiredArgsConstructor;
-
import java.util.List;
import org.springframework.cloud.client.ServiceInstance;
@@ -28,16 +26,20 @@ import org.springframework.cloud.client.discovery.DiscoveryClient;
*
* @author Oliver Gierke
*/
-@RequiredArgsConstructor
public class DynamicServiceInstanceProvider implements ServiceInstanceProvider {
private final DiscoveryClient client;
private final String serviceName;
+ public DynamicServiceInstanceProvider(DiscoveryClient client, String serviceName) {
+ this.client = client;
+ this.serviceName = serviceName;
+ }
+
/*
- * (non-Javadoc)
- * @see example.customers.integration.ServiceInstanceProvider#getServiceInstance()
- */
+ * (non-Javadoc)
+ * @see example.customers.integration.ServiceInstanceProvider#getServiceInstance()
+ */
@Override
public ServiceInstance getServiceInstance() {
diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/hypermedia/RemoteResourceRefresher.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/hypermedia/RemoteResourceRefresher.java
index d3effdad..f167d57a 100644
--- a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/hypermedia/RemoteResourceRefresher.java
+++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/hypermedia/RemoteResourceRefresher.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 the original author or authors.
+ * Copyright 2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,8 +15,6 @@
*/
package org.springframework.cloud.client.hypermedia;
-import lombok.RequiredArgsConstructor;
-
import java.util.List;
import org.springframework.scheduling.config.ContextLifecycleScheduledTaskRegistrar;
@@ -29,16 +27,21 @@ import org.springframework.scheduling.config.ScheduledTaskRegistrar;
*
* @author Oliver Gierke
*/
-@RequiredArgsConstructor
public class RemoteResourceRefresher extends ContextLifecycleScheduledTaskRegistrar {
private final List discoveredResources;
private final int fixedDelay, initialDelay;
+ public RemoteResourceRefresher(List discoveredResources, int fixedDelay, int initialDelay) {
+ this.discoveredResources = discoveredResources;
+ this.fixedDelay = fixedDelay;
+ this.initialDelay = initialDelay;
+ }
+
/*
- * (non-Javadoc)
- * @see org.springframework.scheduling.config.ContextLifecycleScheduledTaskRegistrar#afterPropertiesSet()
- */
+ * (non-Javadoc)
+ * @see org.springframework.scheduling.config.ContextLifecycleScheduledTaskRegistrar#afterPropertiesSet()
+ */
@Override
public void afterPropertiesSet() {
diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/hypermedia/StaticServiceInstanceProvider.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/hypermedia/StaticServiceInstanceProvider.java
index dfebb846..1dc7715a 100644
--- a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/hypermedia/StaticServiceInstanceProvider.java
+++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/hypermedia/StaticServiceInstanceProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 the original author or authors.
+ * Copyright 2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,8 +15,6 @@
*/
package org.springframework.cloud.client.hypermedia;
-import lombok.RequiredArgsConstructor;
-
import org.springframework.cloud.client.ServiceInstance;
/**
@@ -24,15 +22,18 @@ import org.springframework.cloud.client.ServiceInstance;
*
* @author Oliver Gierke
*/
-@RequiredArgsConstructor
public class StaticServiceInstanceProvider implements ServiceInstanceProvider {
private final ServiceInstance instance;
+ public StaticServiceInstanceProvider(ServiceInstance instance) {
+ this.instance = instance;
+ }
+
/*
- * (non-Javadoc)
- * @see example.customers.integration.ServiceInstanceProvider#getServiceInstance()
- */
+ * (non-Javadoc)
+ * @see example.customers.integration.ServiceInstanceProvider#getServiceInstance()
+ */
@Override
public ServiceInstance getServiceInstance() {
return instance;
diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/httpclient/ApacheHttpClientConnectionManagerFactory.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/httpclient/ApacheHttpClientConnectionManagerFactory.java
new file mode 100644
index 00000000..5c97d8e6
--- /dev/null
+++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/httpclient/ApacheHttpClientConnectionManagerFactory.java
@@ -0,0 +1,47 @@
+/*
+ *
+ * * Copyright 2013-2016 the original author or authors.
+ * *
+ * * Licensed under the Apache License, Version 2.0 (the "License");
+ * * you may not use this file except in compliance with the License.
+ * * You may obtain a copy of the License at
+ * *
+ * * http://www.apache.org/licenses/LICENSE-2.0
+ * *
+ * * Unless required by applicable law or agreed to in writing, software
+ * * distributed under the License is distributed on an "AS IS" BASIS,
+ * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * * See the License for the specific language governing permissions and
+ * * limitations under the License.
+ *
+ */
+
+package org.springframework.cloud.commons.httpclient;
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.conn.HttpClientConnectionManager;
+
+/**
+ * Interface for creating an {@link HttpClientConnectionManager}.
+ * @author Ryan Baxter
+ */
+public interface ApacheHttpClientConnectionManagerFactory {
+ public static final String HTTP_SCHEME = "http";
+ public static final String HTTPS_SCHEME = "https";
+
+ /**
+ * Creates a new {@link HttpClientConnectionManager}.
+ * @param disableSslValidation True to disable SSL validation, false otherwise
+ * @param maxTotalConnections The total number of connections
+ * @param maxConnectionsPerRoute The total number of connections per route
+ * @param timeToLive The time a connection is allowed to exist
+ * @param timeUnit The time unit for the time to live value
+ * @param registryBuilder The {@link RegistryBuilder} to use in the connection manager
+ * @return A new {@link HttpClientConnectionManager}
+ */
+ public HttpClientConnectionManager newConnectionManager(boolean disableSslValidation,
+ int maxTotalConnections, int maxConnectionsPerRoute, long timeToLive,
+ TimeUnit timeUnit, RegistryBuilder registryBuilder);
+}
diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/httpclient/ApacheHttpClientFactory.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/httpclient/ApacheHttpClientFactory.java
new file mode 100644
index 00000000..7ef38395
--- /dev/null
+++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/httpclient/ApacheHttpClientFactory.java
@@ -0,0 +1,37 @@
+/*
+ *
+ * * Copyright 2013-2016 the original author or authors.
+ * *
+ * * Licensed under the Apache License, Version 2.0 (the "License");
+ * * you may not use this file except in compliance with the License.
+ * * You may obtain a copy of the License at
+ * *
+ * * http://www.apache.org/licenses/LICENSE-2.0
+ * *
+ * * Unless required by applicable law or agreed to in writing, software
+ * * distributed under the License is distributed on an "AS IS" BASIS,
+ * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * * See the License for the specific language governing permissions and
+ * * limitations under the License.
+ *
+ */
+
+package org.springframework.cloud.commons.httpclient;
+
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.conn.HttpClientConnectionManager;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+
+/**
+ * Factory for creating a new {@link CloseableHttpClient}.
+ * @author Ryan Baxter
+ */
+public interface ApacheHttpClientFactory {
+
+ /**
+ * Creates an {@link HttpClientBuilder} that can be used to create a new {@link CloseableHttpClient}.
+ * @return A {@link HttpClientBuilder}
+ */
+ public HttpClientBuilder createBuilder();
+}
diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/httpclient/DefaultApacheHttpClientConnectionManagerFactory.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/httpclient/DefaultApacheHttpClientConnectionManagerFactory.java
new file mode 100644
index 00000000..136ce607
--- /dev/null
+++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/httpclient/DefaultApacheHttpClientConnectionManagerFactory.java
@@ -0,0 +1,85 @@
+package org.springframework.cloud.commons.httpclient;
+
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.concurrent.TimeUnit;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import org.apache.commons.logging.LogFactory;
+import org.apache.http.config.Registry;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.conn.HttpClientConnectionManager;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.conn.socket.PlainConnectionSocketFactory;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.apache.commons.logging.Log;
+
+/**
+ * Default implementation of {@link ApacheHttpClientConnectionManagerFactory}.
+ * @author Ryan Baxter
+ */
+public class DefaultApacheHttpClientConnectionManagerFactory
+ implements ApacheHttpClientConnectionManagerFactory {
+
+ private static final Log LOG = LogFactory
+ .getLog(DefaultApacheHttpClientConnectionManagerFactory.class);
+
+ public HttpClientConnectionManager newConnectionManager(boolean disableSslValidation,
+ int maxTotalConnections, int maxConnectionsPerRoute) {
+ return newConnectionManager(disableSslValidation, maxTotalConnections,
+ maxConnectionsPerRoute, -1, TimeUnit.MILLISECONDS, null);
+ }
+
+ @Override
+ public HttpClientConnectionManager newConnectionManager(boolean disableSslValidation,
+ int maxTotalConnections, int maxConnectionsPerRoute, long timeToLive,
+ TimeUnit timeUnit, RegistryBuilder registryBuilder) {
+ if (registryBuilder == null) {
+ registryBuilder = RegistryBuilder. create()
+ .register(HTTP_SCHEME, PlainConnectionSocketFactory.INSTANCE);
+ }
+ if (disableSslValidation) {
+ try {
+ final SSLContext sslContext = SSLContext.getInstance("SSL");
+ sslContext.init(null, new TrustManager[] { new X509TrustManager() {
+ @Override
+ public void checkClientTrusted(X509Certificate[] x509Certificates,
+ String s) throws CertificateException {
+ }
+
+ @Override
+ public void checkServerTrusted(X509Certificate[] x509Certificates,
+ String s) throws CertificateException {
+ }
+
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ return null;
+ }
+ } }, new SecureRandom());
+ registryBuilder.register(HTTPS_SCHEME, new SSLConnectionSocketFactory(
+ sslContext, NoopHostnameVerifier.INSTANCE));
+ }
+ catch (NoSuchAlgorithmException e) {
+ LOG.warn("Error creating SSLContext", e);
+ }
+ catch (KeyManagementException e) {
+ LOG.warn("Error creating SSLContext", e);
+ }
+ }
+ final Registry registry = registryBuilder.build();
+
+ PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(
+ registry, null, null, null, timeToLive, timeUnit);
+ connectionManager.setMaxTotal(maxTotalConnections);
+ connectionManager.setDefaultMaxPerRoute(maxConnectionsPerRoute);
+
+ return connectionManager;
+ }
+}
diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/httpclient/DefaultApacheHttpClientFactory.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/httpclient/DefaultApacheHttpClientFactory.java
new file mode 100644
index 00000000..66827bd8
--- /dev/null
+++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/httpclient/DefaultApacheHttpClientFactory.java
@@ -0,0 +1,23 @@
+package org.springframework.cloud.commons.httpclient;
+
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.conn.HttpClientConnectionManager;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+
+/**
+ * Default implementation of {@link ApacheHttpClientFactory}.
+ * @author Ryan Baxter
+ */
+public class DefaultApacheHttpClientFactory implements ApacheHttpClientFactory {
+
+ /**
+ * A default {@link HttpClientBuilder}. The {@link HttpClientBuilder} returned will
+ * have content compression disabled, cookie management disabled, and use system properties.
+ */
+ @Override
+ public HttpClientBuilder createBuilder() {
+ return HttpClientBuilder.create().disableContentCompression()
+ .disableCookieManagement().useSystemProperties();
+ }
+}
diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/httpclient/DefaultOkHttpClientConnectionPoolFactory.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/httpclient/DefaultOkHttpClientConnectionPoolFactory.java
new file mode 100644
index 00000000..9c09dfcc
--- /dev/null
+++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/httpclient/DefaultOkHttpClientConnectionPoolFactory.java
@@ -0,0 +1,17 @@
+package org.springframework.cloud.commons.httpclient;
+
+import okhttp3.ConnectionPool;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Default implementation of {@link OkHttpClientConnectionPoolFactory}.
+ * @author Ryan Baxter
+ */
+public class DefaultOkHttpClientConnectionPoolFactory implements OkHttpClientConnectionPoolFactory {
+
+ @Override
+ public ConnectionPool create(int maxIdleConnections, long keepAliveDuration, TimeUnit timeUnit) {
+ return new ConnectionPool(maxIdleConnections, keepAliveDuration, timeUnit);
+ }
+}
diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/httpclient/DefaultOkHttpClientFactory.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/httpclient/DefaultOkHttpClientFactory.java
new file mode 100644
index 00000000..7ea0aad8
--- /dev/null
+++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/httpclient/DefaultOkHttpClientFactory.java
@@ -0,0 +1,47 @@
+package org.springframework.cloud.commons.httpclient;
+
+import okhttp3.ConnectionPool;
+import okhttp3.OkHttpClient;
+
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.util.concurrent.TimeUnit;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Default implementation of {@link OkHttpClientFactory}.
+ * @author Ryan Baxter
+ */
+public class DefaultOkHttpClientFactory implements OkHttpClientFactory {
+
+ private static final Log LOG = LogFactory.getLog(DefaultOkHttpClientFactory.class);
+
+ @Override
+ public OkHttpClient.Builder createBuilder(boolean disableSslValidation) {
+ OkHttpClient.Builder builder = new OkHttpClient.Builder();
+ if (disableSslValidation) {
+ try {
+ X509TrustManager disabledTrustManager = new DisableValidationTrustManager();
+ TrustManager[] trustManagers = new TrustManager[1];
+ trustManagers[0] = disabledTrustManager;
+ SSLContext sslContext = SSLContext.getInstance("SSL");
+ sslContext.init(null, trustManagers, new java.security.SecureRandom());
+ SSLSocketFactory disabledSSLSocketFactory = sslContext.getSocketFactory();
+ builder.sslSocketFactory(disabledSSLSocketFactory, disabledTrustManager);
+ builder.hostnameVerifier(new TrustAllHostnames());
+ }
+ catch (NoSuchAlgorithmException e) {
+ LOG.warn("Error setting SSLSocketFactory in OKHttpClient", e);
+ }
+ catch (KeyManagementException e) {
+ LOG.warn("Error setting SSLSocketFactory in OKHttpClient", e);
+ }
+ }
+ return builder;
+ }
+}
diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/httpclient/HttpClientConfiguration.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/httpclient/HttpClientConfiguration.java
new file mode 100644
index 00000000..df3de178
--- /dev/null
+++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/httpclient/HttpClientConfiguration.java
@@ -0,0 +1,51 @@
+package org.springframework.cloud.commons.httpclient;
+
+import okhttp3.OkHttpClient;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author Ryan Baxter
+ */
+@Configuration
+public class HttpClientConfiguration {
+
+ @Configuration
+ @ConditionalOnProperty(name = "spring.cloud.httpclientfactories.apache.enabled", matchIfMissing = true)
+ static class ApacheHttpClientConfiguration {
+
+ @Bean
+ @ConditionalOnMissingBean
+ public ApacheHttpClientConnectionManagerFactory connManFactory() {
+ return new DefaultApacheHttpClientConnectionManagerFactory();
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public ApacheHttpClientFactory apacheHttpClientFactory() {
+ return new DefaultApacheHttpClientFactory();
+ }
+ }
+
+ @Configuration
+ @ConditionalOnProperty(name = "spring.cloud.httpclientfactories.ok.enabled", matchIfMissing = true)
+ @ConditionalOnClass(OkHttpClient.class)
+ static class OkHttpClientConfiguration {
+
+ @Bean
+ @ConditionalOnMissingBean
+ public OkHttpClientConnectionPoolFactory connPoolFactory() {
+ return new DefaultOkHttpClientConnectionPoolFactory();
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public OkHttpClientFactory okHttpClientFactory() {
+ return new DefaultOkHttpClientFactory();
+ }
+ }
+}
diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/httpclient/OkHttpClientConnectionPoolFactory.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/httpclient/OkHttpClientConnectionPoolFactory.java
new file mode 100644
index 00000000..d7682cc1
--- /dev/null
+++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/httpclient/OkHttpClientConnectionPoolFactory.java
@@ -0,0 +1,21 @@
+package org.springframework.cloud.commons.httpclient;
+
+import okhttp3.ConnectionPool;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Creates {@link ConnectionPool}s for {@link okhttp3.OkHttpClient}s
+ * @author Ryan Baxter
+ */
+public interface OkHttpClientConnectionPoolFactory {
+
+ /**
+ * Creates a new {@link ConnectionPool}.
+ * @param maxIdleConnections number of max idle connections to allow
+ * @param keepAliveDuration amount of time to keep connections alive
+ * @param timeUnit the time unit for the keep alive duration
+ * @return A new {@link ConnectionPool}
+ */
+ public ConnectionPool create(int maxIdleConnections, long keepAliveDuration, TimeUnit timeUnit);
+}
diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/httpclient/OkHttpClientFactory.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/httpclient/OkHttpClientFactory.java
new file mode 100644
index 00000000..e4323ca0
--- /dev/null
+++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/httpclient/OkHttpClientFactory.java
@@ -0,0 +1,54 @@
+package org.springframework.cloud.commons.httpclient;
+
+import okhttp3.ConnectionPool;
+import okhttp3.OkHttpClient;
+
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.concurrent.TimeUnit;
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.X509TrustManager;
+
+/**
+ * Creates new {@link OkHttpClient}s.
+ * @author Ryan Baxter
+ */
+public interface OkHttpClientFactory {
+
+ /**
+ * Creates a {@link OkHttpClient.Builder} used to build an {@link OkHttpClient}.
+ * @param disableSslValidation Disables SSL validation
+ * @return A new {@link OkHttpClient.Builder}
+ */
+ public OkHttpClient.Builder createBuilder(boolean disableSslValidation);
+
+ /**
+ * A {@link X509TrustManager} that does not validate SSL certificates.
+ */
+ public static class DisableValidationTrustManager implements X509TrustManager {
+
+ @Override
+ public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {}
+
+ @Override
+ public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {}
+
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ return new X509Certificate[0];
+ }
+ }
+
+ /**
+ * A {@link HostnameVerifier} that does not validate any hostnames.
+ */
+ public static class TrustAllHostnames implements HostnameVerifier {
+
+ @Override
+ public boolean verify(String s, SSLSession sslSession) {
+ return true;
+ }
+ }
+}
diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/util/InetUtils.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/util/InetUtils.java
index e8de986f..34f31a30 100644
--- a/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/util/InetUtils.java
+++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/util/InetUtils.java
@@ -31,20 +31,21 @@ import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
-import lombok.Data;
-import lombok.extern.apachecommons.CommonsLog;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
/**
* @author Spencer Gibb
*/
-@CommonsLog
public class InetUtils implements Closeable {
// TODO: maybe shutdown the thread pool if it isn't being used?
private final ExecutorService executorService;
private final InetUtilsProperties properties;
private static final InetUtils instance = new InetUtils(new InetUtilsProperties());
-
+
+ private final Log log = LogFactory.getLog(InetUtils.class);
+
public InetUtils(final InetUtilsProperties properties) {
this.properties = properties;
this.executorService = Executors
@@ -200,7 +201,6 @@ public class InetUtils implements Closeable {
return new HostInfo(host).getIpAddressAsInt();
}
- @Data
public static class HostInfo {
public boolean override;
private String ipAddress;
@@ -227,6 +227,30 @@ public class InetUtils implements Closeable {
}
return ByteBuffer.wrap(inetAddress.getAddress()).getInt();
}
+
+ public boolean isOverride() {
+ return override;
+ }
+
+ public void setOverride(boolean override) {
+ this.override = override;
+ }
+
+ public String getIpAddress() {
+ return ipAddress;
+ }
+
+ public void setIpAddress(String ipAddress) {
+ this.ipAddress = ipAddress;
+ }
+
+ public String getHostname() {
+ return hostname;
+ }
+
+ public void setHostname(String hostname) {
+ this.hostname = hostname;
+ }
}
}
diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/util/InetUtilsProperties.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/util/InetUtilsProperties.java
index 7fae030f..d4ec4613 100644
--- a/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/util/InetUtilsProperties.java
+++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/util/InetUtilsProperties.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package org.springframework.cloud.commons.util;
import java.net.InetAddress;
@@ -7,12 +23,9 @@ import java.util.List;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
-import lombok.Data;
-
/**
* @author Spencer Gibb
*/
-@Data
@ConfigurationProperties(InetUtilsProperties.PREFIX)
public class InetUtilsProperties {
public static final String PREFIX = "spring.cloud.inetutils";
@@ -47,4 +60,56 @@ public class InetUtilsProperties {
* List of Java regex expressions for network addresses that will be preferred.
*/
private List preferredNetworks = new ArrayList<>();
+
+ public static String getPREFIX() {
+ return PREFIX;
+ }
+
+ public String getDefaultHostname() {
+ return defaultHostname;
+ }
+
+ public void setDefaultHostname(String defaultHostname) {
+ this.defaultHostname = defaultHostname;
+ }
+
+ public String getDefaultIpAddress() {
+ return defaultIpAddress;
+ }
+
+ public void setDefaultIpAddress(String defaultIpAddress) {
+ this.defaultIpAddress = defaultIpAddress;
+ }
+
+ public int getTimeoutSeconds() {
+ return timeoutSeconds;
+ }
+
+ public void setTimeoutSeconds(int timeoutSeconds) {
+ this.timeoutSeconds = timeoutSeconds;
+ }
+
+ public List getIgnoredInterfaces() {
+ return ignoredInterfaces;
+ }
+
+ public void setIgnoredInterfaces(List ignoredInterfaces) {
+ this.ignoredInterfaces = ignoredInterfaces;
+ }
+
+ public boolean isUseOnlySiteLocalInterfaces() {
+ return useOnlySiteLocalInterfaces;
+ }
+
+ public void setUseOnlySiteLocalInterfaces(boolean useOnlySiteLocalInterfaces) {
+ this.useOnlySiteLocalInterfaces = useOnlySiteLocalInterfaces;
+ }
+
+ public List getPreferredNetworks() {
+ return preferredNetworks;
+ }
+
+ public void setPreferredNetworks(List preferredNetworks) {
+ this.preferredNetworks = preferredNetworks;
+ }
}
diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/util/SpringFactoryImportSelector.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/util/SpringFactoryImportSelector.java
index 3e72e5f9..ccc8d00e 100644
--- a/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/util/SpringFactoryImportSelector.java
+++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/commons/util/SpringFactoryImportSelector.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013-2015 the original author or authors.
+ * Copyright 2013-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,8 @@ import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.DeferredImportSelector;
@@ -30,7 +32,6 @@ import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.Assert;
-import lombok.extern.apachecommons.CommonsLog;
/**
* Selects configurations to load defined by the generic type T. Loads implementations
@@ -39,7 +40,6 @@ import lombok.extern.apachecommons.CommonsLog;
* @author Spencer Gibb
* @author Dave Syer
*/
-@CommonsLog
public abstract class SpringFactoryImportSelector
implements DeferredImportSelector, BeanClassLoaderAware, EnvironmentAware {
@@ -49,6 +49,8 @@ public abstract class SpringFactoryImportSelector
private Environment environment;
+ private final Log log = LogFactory.getLog(SpringFactoryImportSelector.class);
+
@SuppressWarnings("unchecked")
protected SpringFactoryImportSelector() {
this.annotationClass = (Class) GenericTypeResolver
diff --git a/spring-cloud-commons/src/main/resources/META-INF/spring.factories b/spring-cloud-commons/src/main/resources/META-INF/spring.factories
index 874eb1fc..01dc663a 100644
--- a/spring-cloud-commons/src/main/resources/META-INF/spring.factories
+++ b/spring-cloud-commons/src/main/resources/META-INF/spring.factories
@@ -8,7 +8,8 @@ org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration,\
org.springframework.cloud.client.serviceregistry.ServiceRegistryAutoConfiguration,\
org.springframework.cloud.commons.util.UtilAutoConfiguration,\
org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClientAutoConfiguration,\
-org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration
+org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration,\
+org.springframework.cloud.commons.httpclient.HttpClientConfiguration
# Environment Post Processors
diff --git a/spring-cloud-commons/src/test/java/org/springframework/cloud/client/loadbalancer/AbstractLoadBalancerAutoConfigurationTests.java b/spring-cloud-commons/src/test/java/org/springframework/cloud/client/loadbalancer/AbstractLoadBalancerAutoConfigurationTests.java
index 52f5a290..9e8184a9 100644
--- a/spring-cloud-commons/src/test/java/org/springframework/cloud/client/loadbalancer/AbstractLoadBalancerAutoConfigurationTests.java
+++ b/spring-cloud-commons/src/test/java/org/springframework/cloud/client/loadbalancer/AbstractLoadBalancerAutoConfigurationTests.java
@@ -1,20 +1,33 @@
+/*
+ * Copyright 2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package org.springframework.cloud.client.loadbalancer;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.hasSize;
-import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import java.io.IOException;
import java.net.URI;
import java.util.Collection;
-import java.util.List;
import java.util.Map;
import java.util.Random;
-import lombok.SneakyThrows;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
@@ -25,7 +38,6 @@ import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
-import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.web.client.RestTemplate;
/**
@@ -138,15 +150,21 @@ public abstract class AbstractLoadBalancerAutoConfigurationTests {
}
@Override
- @SneakyThrows
public T execute(String serviceId, LoadBalancerRequest request) {
- return request.apply(choose(serviceId));
+ try {
+ return request.apply(choose(serviceId));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
}
@Override
- @SneakyThrows
public T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest request) throws IOException {
- return request.apply(choose(serviceId));
+ try {
+ return request.apply(choose(serviceId));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
}
@Override
diff --git a/spring-cloud-commons/src/test/java/org/springframework/cloud/client/loadbalancer/AsyncLoadBalancerAutoConfigurationTests.java b/spring-cloud-commons/src/test/java/org/springframework/cloud/client/loadbalancer/AsyncLoadBalancerAutoConfigurationTests.java
index 1d66d9ed..e270f5ee 100644
--- a/spring-cloud-commons/src/test/java/org/springframework/cloud/client/loadbalancer/AsyncLoadBalancerAutoConfigurationTests.java
+++ b/spring-cloud-commons/src/test/java/org/springframework/cloud/client/loadbalancer/AsyncLoadBalancerAutoConfigurationTests.java
@@ -1,6 +1,21 @@
+/*
+ * Copyright 2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package org.springframework.cloud.client.loadbalancer;
-import lombok.SneakyThrows;
import org.hamcrest.MatcherAssert;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
@@ -140,15 +155,21 @@ public class AsyncLoadBalancerAutoConfigurationTests {
}
@Override
- @SneakyThrows
public T execute(String serviceId, LoadBalancerRequest request) {
- return request.apply(choose(serviceId));
+ try {
+ return request.apply(choose(serviceId));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
}
@Override
- @SneakyThrows
public T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest request) throws IOException {
- return request.apply(choose(serviceId));
+ try {
+ return request.apply(choose(serviceId));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
}
@Override
diff --git a/spring-cloud-commons/src/test/java/org/springframework/cloud/commons/httpclient/CustomHttpClientConfigurationTests.java b/spring-cloud-commons/src/test/java/org/springframework/cloud/commons/httpclient/CustomHttpClientConfigurationTests.java
new file mode 100644
index 00000000..51a1189d
--- /dev/null
+++ b/spring-cloud-commons/src/test/java/org/springframework/cloud/commons/httpclient/CustomHttpClientConfigurationTests.java
@@ -0,0 +1,142 @@
+package org.springframework.cloud.commons.httpclient;
+
+import okhttp3.ConnectionPool;
+import okhttp3.OkHttpClient;
+
+import java.util.concurrent.TimeUnit;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.X509TrustManager;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.conn.HttpClientConnectionManager;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Ryan Baxter
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = CustomApplication.class, properties = {"spring.cloud.httpclient.ok.enabled: true"})
+public class CustomHttpClientConfigurationTests {
+
+ @Autowired
+ ApacheHttpClientFactory httpClientFactory;
+
+ @Autowired
+ ApacheHttpClientConnectionManagerFactory connectionManagerFactory;
+
+ @Autowired
+ OkHttpClientFactory okHttpClientFactory;
+
+ @Autowired
+ OkHttpClientConnectionPoolFactory okHttpClientConnectionPoolFactory;
+
+ @Test
+ public void connManFactory() throws Exception {
+ assertTrue(ApacheHttpClientConnectionManagerFactory.class
+ .isInstance(connectionManagerFactory));
+ assertTrue(CustomApplication.MyApacheHttpClientConnectionManagerFactory.class
+ .isInstance(connectionManagerFactory));
+ }
+
+ @Test
+ public void apacheHttpClientFactory() throws Exception {
+ assertTrue(ApacheHttpClientFactory.class.isInstance(httpClientFactory));
+ assertTrue(CustomApplication.MyApacheHttpClientFactory.class
+ .isInstance(httpClientFactory));
+ }
+
+ @Test
+ public void connectionPoolFactory() throws Exception {
+ assertTrue(OkHttpClientConnectionPoolFactory.class.isInstance(okHttpClientConnectionPoolFactory));
+ assertTrue(CustomApplication.MyOkHttpConnectionPoolFactory.class.isInstance(okHttpClientConnectionPoolFactory));
+ }
+
+ @Test
+ public void okHttpClientFactory() throws Exception {
+ assertTrue(OkHttpClientFactory.class.isInstance(okHttpClientFactory));
+ assertTrue(CustomApplication.MyOkHttpClientFactory.class.isInstance(okHttpClientFactory));
+ }
+
+}
+
+@Configuration
+@EnableAutoConfiguration
+class CustomApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(MyApplication.class, args);
+ }
+
+ @Configuration
+ static class MyConfig {
+
+ @Bean
+ public ApacheHttpClientFactory clientFactory() {
+ return new MyApacheHttpClientFactory();
+ }
+
+ @Bean
+ public ApacheHttpClientConnectionManagerFactory connectionManagerFactory() {
+ return new MyApacheHttpClientConnectionManagerFactory();
+ }
+
+ @Bean
+ public OkHttpClientConnectionPoolFactory connectionPoolFactory() {
+ return new MyOkHttpConnectionPoolFactory();
+ }
+
+ @Bean
+ public OkHttpClientFactory okHttpClientFactory() {
+ return new MyOkHttpClientFactory();
+ }
+
+ }
+
+ static class MyApacheHttpClientFactory implements ApacheHttpClientFactory {
+
+ @Override
+ public HttpClientBuilder createBuilder() {
+ return HttpClientBuilder.create();
+ }
+ }
+
+ static class MyApacheHttpClientConnectionManagerFactory
+ implements ApacheHttpClientConnectionManagerFactory {
+
+ @Override
+ public HttpClientConnectionManager newConnectionManager(
+ boolean disableSslValidation, int maxTotalConnections,
+ int maxConnectionsPerRoute, long timeToLive, TimeUnit timeUnit,
+ RegistryBuilder registryBuilder) {
+ return null;
+ }
+ }
+
+ static class MyOkHttpClientFactory implements OkHttpClientFactory {
+ @Override
+ public OkHttpClient.Builder createBuilder(boolean disableSslValidation) {
+ return new OkHttpClient.Builder();
+ }
+ }
+
+ static class MyOkHttpConnectionPoolFactory implements OkHttpClientConnectionPoolFactory {
+
+ @Override
+ public ConnectionPool create(int maxIdleConnections, long keepAliveDuration, TimeUnit timeUnit) {
+ return null;
+ }
+ }
+}
diff --git a/spring-cloud-commons/src/test/java/org/springframework/cloud/commons/httpclient/DefaultApacheHttpClientConnectionManagerFactoryTests.java b/spring-cloud-commons/src/test/java/org/springframework/cloud/commons/httpclient/DefaultApacheHttpClientConnectionManagerFactoryTests.java
new file mode 100644
index 00000000..4b2f535b
--- /dev/null
+++ b/spring-cloud-commons/src/test/java/org/springframework/cloud/commons/httpclient/DefaultApacheHttpClientConnectionManagerFactoryTests.java
@@ -0,0 +1,53 @@
+package org.springframework.cloud.commons.httpclient;
+
+import java.lang.reflect.Field;
+import java.util.concurrent.TimeUnit;
+import org.apache.http.conn.HttpClientConnectionManager;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.junit.Test;
+import org.springframework.util.ReflectionUtils;
+
+import static org.junit.Assert.assertEquals;
+
+
+/**
+ * @author Ryan Baxter
+ */
+public class DefaultApacheHttpClientConnectionManagerFactoryTests {
+ @Test
+ public void newConnectionManager() throws Exception {
+ HttpClientConnectionManager connectionManager = new DefaultApacheHttpClientConnectionManagerFactory()
+ .newConnectionManager(false, 2, 6);
+ assertEquals(6, ((PoolingHttpClientConnectionManager) connectionManager)
+ .getDefaultMaxPerRoute());
+ assertEquals(2,
+ ((PoolingHttpClientConnectionManager) connectionManager).getMaxTotal());
+ Object pool = getField(((PoolingHttpClientConnectionManager) connectionManager),
+ "pool");
+ assertEquals(-1l, ((Long)getField(pool, "timeToLive")).longValue());
+ TimeUnit timeUnit = getField(pool, "tunit");
+ assertEquals(TimeUnit.MILLISECONDS, timeUnit);
+ }
+
+ @Test
+ public void newConnectionManagerWithTTL() throws Exception {
+ HttpClientConnectionManager connectionManager = new DefaultApacheHttpClientConnectionManagerFactory()
+ .newConnectionManager(false, 2, 6, 56l, TimeUnit.DAYS, null);
+ assertEquals(6, ((PoolingHttpClientConnectionManager) connectionManager)
+ .getDefaultMaxPerRoute());
+ assertEquals(2,
+ ((PoolingHttpClientConnectionManager) connectionManager).getMaxTotal());
+ Object pool = getField(((PoolingHttpClientConnectionManager) connectionManager),
+ "pool");
+ assertEquals(56l, ((Long)getField(pool, "timeToLive")).longValue());
+ TimeUnit timeUnit = getField(pool, "tunit");
+ assertEquals(TimeUnit.DAYS, timeUnit);
+ }
+
+ protected T getField(Object target, String name) {
+ Field field = ReflectionUtils.findField(target.getClass(), name);
+ ReflectionUtils.makeAccessible(field);
+ Object value = ReflectionUtils.getField(field, target);
+ return (T) value;
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-commons/src/test/java/org/springframework/cloud/commons/httpclient/DefaultApacheHttpClientFactoryTests.java b/spring-cloud-commons/src/test/java/org/springframework/cloud/commons/httpclient/DefaultApacheHttpClientFactoryTests.java
new file mode 100644
index 00000000..3a69ea72
--- /dev/null
+++ b/spring-cloud-commons/src/test/java/org/springframework/cloud/commons/httpclient/DefaultApacheHttpClientFactoryTests.java
@@ -0,0 +1,42 @@
+package org.springframework.cloud.commons.httpclient;
+
+import java.lang.reflect.Field;
+import org.apache.http.client.config.CookieSpecs;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.Configurable;
+import org.apache.http.conn.HttpClientConnectionManager;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.springframework.util.ReflectionUtils;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+
+/**
+ * @author Ryan Baxter
+ */
+public class DefaultApacheHttpClientFactoryTests {
+ @Test
+ public void createClient() throws Exception {
+ final RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(100)
+ .setConnectTimeout(200).setCookieSpec(CookieSpecs.IGNORE_COOKIES).build();
+ CloseableHttpClient httpClient = new DefaultApacheHttpClientFactory().createBuilder().
+ setConnectionManager(mock(HttpClientConnectionManager.class)).
+ setDefaultRequestConfig(requestConfig).build();
+ Assertions.assertThat(httpClient).isInstanceOf(Configurable.class);
+ RequestConfig config = ((Configurable) httpClient).getConfig();
+ assertEquals(100, config.getSocketTimeout());
+ assertEquals(200, config.getConnectTimeout());
+ assertEquals(CookieSpecs.IGNORE_COOKIES, config.getCookieSpec());
+ }
+
+ protected T getField(Object target, String name) {
+ Field field = ReflectionUtils.findField(target.getClass(), name);
+ ReflectionUtils.makeAccessible(field);
+ Object value = ReflectionUtils.getField(field, target);
+ return (T) value;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-cloud-commons/src/test/java/org/springframework/cloud/commons/httpclient/DefaultHttpClientConfigurationTests.java b/spring-cloud-commons/src/test/java/org/springframework/cloud/commons/httpclient/DefaultHttpClientConfigurationTests.java
new file mode 100644
index 00000000..d3f7d04f
--- /dev/null
+++ b/spring-cloud-commons/src/test/java/org/springframework/cloud/commons/httpclient/DefaultHttpClientConfigurationTests.java
@@ -0,0 +1,66 @@
+package org.springframework.cloud.commons.httpclient;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author Ryan Baxter
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = MyApplication.class, properties = {"spring.cloud.httpclient.ok.enabled: true"})
+public class DefaultHttpClientConfigurationTests {
+ @Autowired
+ ApacheHttpClientFactory httpClientFactory;
+
+ @Autowired
+ ApacheHttpClientConnectionManagerFactory connectionManagerFactory;
+
+ @Autowired
+ OkHttpClientFactory okHttpClientFactory;
+
+ @Autowired
+ OkHttpClientConnectionPoolFactory okHttpClientConnectionPoolFactory;
+
+ @Test
+ public void connManFactory() throws Exception {
+ assertTrue(ApacheHttpClientConnectionManagerFactory.class
+ .isInstance(connectionManagerFactory));
+ assertTrue(DefaultApacheHttpClientConnectionManagerFactory.class
+ .isInstance(connectionManagerFactory));
+ }
+
+ @Test
+ public void apacheHttpClientFactory() throws Exception {
+ assertTrue(ApacheHttpClientFactory.class.isInstance(httpClientFactory));
+ assertTrue(DefaultApacheHttpClientFactory.class.isInstance(httpClientFactory));
+ }
+
+ @Test
+ public void connPoolFactory() throws Exception {
+ assertTrue(OkHttpClientConnectionPoolFactory.class.isInstance(okHttpClientConnectionPoolFactory));
+ assertTrue(DefaultOkHttpClientConnectionPoolFactory.class.isInstance(okHttpClientConnectionPoolFactory));
+ }
+
+ @Test
+ public void setOkHttpClientFactory() throws Exception {
+ assertTrue(OkHttpClientFactory.class.isInstance(okHttpClientFactory));
+ assertTrue(DefaultOkHttpClientFactory.class.isInstance(okHttpClientFactory));
+ }
+}
+
+@Configuration
+@EnableAutoConfiguration
+class MyApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(MyApplication.class, args);
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-commons/src/test/java/org/springframework/cloud/commons/httpclient/DefaultOkHttpClientConnectionPoolFactoryTest.java b/spring-cloud-commons/src/test/java/org/springframework/cloud/commons/httpclient/DefaultOkHttpClientConnectionPoolFactoryTest.java
new file mode 100644
index 00000000..a7658e3b
--- /dev/null
+++ b/spring-cloud-commons/src/test/java/org/springframework/cloud/commons/httpclient/DefaultOkHttpClientConnectionPoolFactoryTest.java
@@ -0,0 +1,34 @@
+package org.springframework.cloud.commons.httpclient;
+
+import okhttp3.ConnectionPool;
+
+import java.lang.reflect.Field;
+import java.util.concurrent.TimeUnit;
+import org.junit.Test;
+import org.springframework.util.ReflectionUtils;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Ryan Baxter
+ */
+public class DefaultOkHttpClientConnectionPoolFactoryTest {
+ @Test
+ public void create() throws Exception {
+ DefaultOkHttpClientConnectionPoolFactory connectionPoolFactory = new DefaultOkHttpClientConnectionPoolFactory();
+ ConnectionPool connectionPool = connectionPoolFactory.create(2,
+ 3, TimeUnit.MILLISECONDS);
+ int idleConnections = getField(connectionPool, "maxIdleConnections");
+ long keepAliveDuration = getField(connectionPool, "keepAliveDurationNs");
+ assertEquals(2, idleConnections);
+ assertEquals(TimeUnit.MILLISECONDS.toNanos(3), keepAliveDuration);
+ }
+
+ protected T getField(Object target, String name) {
+ Field field = ReflectionUtils.findField(target.getClass(), name);
+ ReflectionUtils.makeAccessible(field);
+ Object value = ReflectionUtils.getField(field, target);
+ return (T) value;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-cloud-commons/src/test/java/org/springframework/cloud/commons/httpclient/DefaultOkHttpClientFactoryTest.java b/spring-cloud-commons/src/test/java/org/springframework/cloud/commons/httpclient/DefaultOkHttpClientFactoryTest.java
new file mode 100644
index 00000000..10c40516
--- /dev/null
+++ b/spring-cloud-commons/src/test/java/org/springframework/cloud/commons/httpclient/DefaultOkHttpClientFactoryTest.java
@@ -0,0 +1,47 @@
+package org.springframework.cloud.commons.httpclient;
+
+import okhttp3.ConnectionPool;
+import okhttp3.OkHttpClient;
+
+import java.lang.reflect.Field;
+import java.util.concurrent.TimeUnit;
+import javax.net.ssl.HostnameVerifier;
+import org.junit.Test;
+import org.springframework.util.ReflectionUtils;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Ryan Baxter
+ */
+public class DefaultOkHttpClientFactoryTest {
+ @Test
+ public void create() throws Exception {
+ DefaultOkHttpClientFactory okHttpClientFactory = new DefaultOkHttpClientFactory();
+ DefaultOkHttpClientConnectionPoolFactory poolFactory = new DefaultOkHttpClientConnectionPoolFactory();
+ ConnectionPool pool = poolFactory.create(4, 5, TimeUnit.DAYS);
+ OkHttpClient httpClient = okHttpClientFactory.createBuilder(true).
+ connectTimeout(2, TimeUnit.MILLISECONDS).
+ readTimeout(3, TimeUnit.HOURS).
+ followRedirects(true).
+ connectionPool(pool).build();
+ int connectTimeout = getField(httpClient, "connectTimeout");
+ assertEquals(2, connectTimeout);
+ int readTimeout = getField(httpClient, "readTimeout");
+ assertEquals(TimeUnit.HOURS.toMillis(3), readTimeout);
+ boolean followRedirects = getField(httpClient, "followRedirects");
+ assertTrue(followRedirects);
+ ConnectionPool poolFromClient = getField(httpClient, "connectionPool");
+ assertEquals(pool, poolFromClient);
+ HostnameVerifier hostnameVerifier = getField(httpClient, "hostnameVerifier");
+ assertTrue(OkHttpClientFactory.TrustAllHostnames.class.isInstance(hostnameVerifier));
+ }
+
+ protected T getField(Object target, String name) {
+ Field field = ReflectionUtils.findField(target.getClass(), name);
+ ReflectionUtils.makeAccessible(field);
+ Object value = ReflectionUtils.getField(field, target);
+ return (T) value;
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-context/src/main/java/org/springframework/cloud/context/environment/EnvironmentManager.java b/spring-cloud-context/src/main/java/org/springframework/cloud/context/environment/EnvironmentManager.java
index 91e625cf..6b4b7639 100644
--- a/spring-cloud-context/src/main/java/org/springframework/cloud/context/environment/EnvironmentManager.java
+++ b/spring-cloud-context/src/main/java/org/springframework/cloud/context/environment/EnvironmentManager.java
@@ -68,9 +68,8 @@ public class EnvironmentManager implements ApplicationEventPublisherAware {
public Map reset() {
Map result = new LinkedHashMap(map);
if (!map.isEmpty()) {
- Set keys = map.keySet();
map.clear();
- publish(new EnvironmentChangeEvent(keys));
+ publish(new EnvironmentChangeEvent(result.keySet()));
}
return result;
}
diff --git a/spring-cloud-context/src/test/java/org/springframework/cloud/context/environment/EnvironmentManagerTest.java b/spring-cloud-context/src/test/java/org/springframework/cloud/context/environment/EnvironmentManagerTest.java
new file mode 100644
index 00000000..518afe74
--- /dev/null
+++ b/spring-cloud-context/src/test/java/org/springframework/cloud/context/environment/EnvironmentManagerTest.java
@@ -0,0 +1,45 @@
+package org.springframework.cloud.context.environment;
+
+
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.mock.env.MockEnvironment;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+public class EnvironmentManagerTest {
+
+ @Test
+ public void testCorrectEvents() {
+ MockEnvironment environment = new MockEnvironment();
+ ApplicationEventPublisher publisher = mock(ApplicationEventPublisher.class);
+ EnvironmentManager environmentManager = new EnvironmentManager(environment);
+ environmentManager.setApplicationEventPublisher(publisher);
+
+ environmentManager.setProperty("foo", "bar");
+
+ assertThat(environment.getProperty("foo")).isEqualTo("bar");
+ ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(ApplicationEvent.class);
+ verify(publisher, times(1)).publishEvent(eventCaptor.capture());
+ assertThat(eventCaptor.getValue()).isInstanceOf(EnvironmentChangeEvent.class);
+ EnvironmentChangeEvent event = (EnvironmentChangeEvent) eventCaptor.getValue();
+ assertThat(event.getKeys()).containsExactly("foo");
+
+ reset(publisher);
+
+ environmentManager.reset();
+ assertThat(environment.getProperty("foo")).isNull();
+ verify(publisher, times(1)).publishEvent(eventCaptor.capture());
+ assertThat(eventCaptor.getValue()).isInstanceOf(EnvironmentChangeEvent.class);
+ event = (EnvironmentChangeEvent) eventCaptor.getValue();
+ assertThat(event.getKeys()).containsExactly("foo");
+ }
+
+}
\ No newline at end of file