diff --git a/docs/src/main/asciidoc/spring-cloud-netflix.adoc b/docs/src/main/asciidoc/spring-cloud-netflix.adoc
index 8aaa3504..b87a3008 100644
--- a/docs/src/main/asciidoc/spring-cloud-netflix.adoc
+++ b/docs/src/main/asciidoc/spring-cloud-netflix.adoc
@@ -264,6 +264,34 @@ not be started yet). It is initialized in a `SmartLifecycle` (with
another `SmartLifecycle` with higher phase.
====
+==== EurekaClient without Jersey
+
+By default, EurekaClient uses Jersey for HTTP communication. If you wish
+to avoid dependencies from Jersey, you can exclude it from your dependencies.
+Spring Cloud will auto configure a transport client based on Spring
+`RestTemplate`.
+
+----
+
+ org.springframework.cloud
+ spring-cloud-starter-eureka
+
+
+ com.sun.jersey
+ jersey-client
+
+
+ com.sun.jersey
+ jersey-core
+
+
+ com.sun.jersey.contribs
+ jersey-apache-client4
+
+
+
+----
+
=== Alternatives to the native Netflix EurekaClient
You don't have to use the raw Netflix `EurekaClient` and usually it
diff --git a/spring-cloud-netflix-eureka-client/pom.xml b/spring-cloud-netflix-eureka-client/pom.xml
index ffc08ead..dfd1750a 100644
--- a/spring-cloud-netflix-eureka-client/pom.xml
+++ b/spring-cloud-netflix-eureka-client/pom.xml
@@ -118,11 +118,22 @@
compile
true
+
+ org.springframework.boot
+ spring-boot-starter-security
+ test
+
org.springframework.boot
spring-boot-starter-test
test
+
+ org.springframework.cloud
+ spring-cloud-commons
+ test-jar
+ test
+
org.springframework.retry
spring-retry
diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/CloudEurekaClient.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/CloudEurekaClient.java
index 79a164f3..74db0b83 100644
--- a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/CloudEurekaClient.java
+++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/CloudEurekaClient.java
@@ -29,6 +29,7 @@ import org.springframework.util.ReflectionUtils;
import com.netflix.appinfo.ApplicationInfoManager;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.appinfo.InstanceInfo.InstanceStatus;
+import com.netflix.discovery.AbstractDiscoveryClientOptionalArgs;
import com.netflix.discovery.DiscoveryClient;
import com.netflix.discovery.EurekaClientConfig;
import com.netflix.discovery.shared.transport.EurekaHttpClient;
@@ -55,7 +56,7 @@ public class CloudEurekaClient extends DiscoveryClient {
public CloudEurekaClient(ApplicationInfoManager applicationInfoManager,
EurekaClientConfig config,
- DiscoveryClientOptionalArgs args,
+ AbstractDiscoveryClientOptionalArgs> args,
ApplicationEventPublisher publisher) {
super(applicationInfoManager, config, args);
this.applicationInfoManager = applicationInfoManager;
diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java
index 2c7829ea..170acc8a 100644
--- a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java
+++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java
@@ -17,6 +17,8 @@
package org.springframework.cloud.netflix.eureka;
+import static org.springframework.cloud.commons.util.IdUtils.getDefaultInstanceId;
+
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -47,6 +49,7 @@ import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationP
import org.springframework.cloud.client.serviceregistry.ServiceRegistryAutoConfiguration;
import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.cloud.context.scope.refresh.RefreshScope;
+import org.springframework.cloud.netflix.eureka.config.DiscoveryClientOptionalArgsConfiguration;
import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaAutoServiceRegistration;
import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaRegistration;
import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaServiceRegistry;
@@ -54,6 +57,7 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertyResolver;
@@ -63,9 +67,10 @@ import com.netflix.appinfo.ApplicationInfoManager;
import com.netflix.appinfo.EurekaInstanceConfig;
import com.netflix.appinfo.HealthCheckHandler;
import com.netflix.appinfo.InstanceInfo;
-import com.netflix.discovery.DiscoveryClient.DiscoveryClientOptionalArgs;
+import com.netflix.discovery.AbstractDiscoveryClientOptionalArgs;
import com.netflix.discovery.EurekaClient;
import com.netflix.discovery.EurekaClientConfig;
+
import static org.springframework.cloud.commons.util.IdUtils.getDefaultInstanceId;
/**
@@ -74,10 +79,12 @@ import static org.springframework.cloud.commons.util.IdUtils.getDefaultInstanceI
* @author Jon Schneider
* @author Matt Jenkins
* @author Ryan Baxter
+ * @author Daniel Lavoie
*/
@Configuration
@EnableConfigurationProperties
@ConditionalOnClass(EurekaClientConfig.class)
+@Import(DiscoveryClientOptionalArgsConfiguration.class)
@ConditionalOnBean(EurekaDiscoveryClientConfiguration.Marker.class)
@ConditionalOnProperty(value = "eureka.client.enabled", matchIfMissing = true)
@AutoConfigureBefore({ NoopDiscoveryClientAutoConfiguration.class,
@@ -177,12 +184,6 @@ public class EurekaClientAutoConfiguration {
return new EurekaAutoServiceRegistration(context, registry, registration);
}
- @Bean
- @ConditionalOnMissingBean(value = DiscoveryClientOptionalArgs.class, search = SearchStrategy.CURRENT)
- public MutableDiscoveryClientOptionalArgs discoveryClientOptionalArgs() {
- return new MutableDiscoveryClientOptionalArgs();
- }
-
@Configuration
@ConditionalOnMissingRefreshScope
protected static class EurekaClientConfiguration {
@@ -190,8 +191,8 @@ public class EurekaClientAutoConfiguration {
@Autowired
private ApplicationContext context;
- @Autowired(required = false)
- private DiscoveryClientOptionalArgs optionalArgs;
+ @Autowired
+ private AbstractDiscoveryClientOptionalArgs> optionalArgs;
@Bean(destroyMethod = "shutdown")
@ConditionalOnMissingBean(value = EurekaClient.class, search = SearchStrategy.CURRENT)
@@ -216,8 +217,8 @@ public class EurekaClientAutoConfiguration {
@Autowired
private ApplicationContext context;
- @Autowired(required = false)
- private DiscoveryClientOptionalArgs optionalArgs;
+ @Autowired
+ private AbstractDiscoveryClientOptionalArgs> optionalArgs;
@Bean(destroyMethod = "shutdown")
@ConditionalOnMissingBean(value = EurekaClient.class, search = SearchStrategy.CURRENT)
diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/config/DiscoveryClientOptionalArgsConfiguration.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/config/DiscoveryClientOptionalArgsConfiguration.java
new file mode 100644
index 00000000..d0439afb
--- /dev/null
+++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/config/DiscoveryClientOptionalArgsConfiguration.java
@@ -0,0 +1,48 @@
+/*
+ * 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.netflix.eureka.config;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
+import org.springframework.boot.autoconfigure.condition.SearchStrategy;
+import org.springframework.cloud.netflix.eureka.MutableDiscoveryClientOptionalArgs;
+import org.springframework.cloud.netflix.eureka.http.RestTemplateDiscoveryClientOptionalArgs;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import com.netflix.discovery.AbstractDiscoveryClientOptionalArgs;
+
+/**
+ * @author Daniel Lavoie
+ */
+@Configuration
+public class DiscoveryClientOptionalArgsConfiguration {
+ @Bean
+ @ConditionalOnMissingClass("com.sun.jersey.api.client.filter.ClientFilter")
+ @ConditionalOnMissingBean(value = AbstractDiscoveryClientOptionalArgs.class, search = SearchStrategy.CURRENT)
+ public RestTemplateDiscoveryClientOptionalArgs restTemplateDiscoveryClientOptionalArgs() {
+ return new RestTemplateDiscoveryClientOptionalArgs();
+ }
+
+ @Bean
+ @ConditionalOnClass(name = "com.sun.jersey.api.client.filter.ClientFilter")
+ @ConditionalOnMissingBean(value = AbstractDiscoveryClientOptionalArgs.class, search = SearchStrategy.CURRENT)
+ public MutableDiscoveryClientOptionalArgs discoveryClientOptionalArgs() {
+ return new MutableDiscoveryClientOptionalArgs();
+ }
+}
diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/EurekaApplications.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/EurekaApplications.java
new file mode 100644
index 00000000..44906b1b
--- /dev/null
+++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/EurekaApplications.java
@@ -0,0 +1,40 @@
+/*
+ * 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.netflix.eureka.http;
+
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.netflix.discovery.shared.Application;
+import com.netflix.discovery.shared.Applications;
+
+/**
+ * A simple wrapper class for {@link Applications} that insure proprer Jackson
+ * serialization through the JsonPropert overwrites.
+ *
+ * @author Daniel Lavoie
+ */
+public class EurekaApplications extends com.netflix.discovery.shared.Applications {
+
+ @JsonCreator
+ public EurekaApplications(@JsonProperty("apps__hashcode") String appsHashCode,
+ @JsonProperty("versions__delta") Long versionDelta,
+ @JsonProperty("application") List registeredApplications) {
+ super(appsHashCode, versionDelta, registeredApplications);
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateDiscoveryClientOptionalArgs.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateDiscoveryClientOptionalArgs.java
new file mode 100644
index 00000000..b0eba96f
--- /dev/null
+++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateDiscoveryClientOptionalArgs.java
@@ -0,0 +1,29 @@
+/*
+ * 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.netflix.eureka.http;
+
+import com.netflix.discovery.AbstractDiscoveryClientOptionalArgs;
+
+/**
+ * @author Daniel Lavoie
+ */
+public class RestTemplateDiscoveryClientOptionalArgs
+ extends AbstractDiscoveryClientOptionalArgs {
+ public RestTemplateDiscoveryClientOptionalArgs() {
+ setTransportClientFactories(new RestTemplateTransportClientFactories());
+ }
+}
diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateEurekaHttpClient.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateEurekaHttpClient.java
new file mode 100644
index 00000000..12f205b4
--- /dev/null
+++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateEurekaHttpClient.java
@@ -0,0 +1,227 @@
+/*
+ * 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.netflix.eureka.http;
+
+import static com.netflix.discovery.shared.transport.EurekaHttpResponse.anEurekaHttpResponse;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.client.RestTemplate;
+
+import com.netflix.appinfo.InstanceInfo;
+import com.netflix.appinfo.InstanceInfo.InstanceStatus;
+import com.netflix.discovery.shared.Application;
+import com.netflix.discovery.shared.Applications;
+import com.netflix.discovery.shared.transport.EurekaHttpClient;
+import com.netflix.discovery.shared.transport.EurekaHttpResponse;
+import com.netflix.discovery.shared.transport.EurekaHttpResponse.EurekaHttpResponseBuilder;
+import com.netflix.discovery.util.StringUtil;
+
+/**
+ * @author Daniel Lavoie
+ */
+public class RestTemplateEurekaHttpClient implements EurekaHttpClient {
+
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ private RestTemplate restTemplate;
+ private String serviceUrl;
+
+ public RestTemplateEurekaHttpClient(RestTemplate restTemplate, String serviceUrl) {
+ this.restTemplate = restTemplate;
+ this.serviceUrl = serviceUrl;
+ }
+
+ @Override
+ public EurekaHttpResponse register(InstanceInfo info) {
+ String urlPath = serviceUrl + "apps/" + info.getAppName();
+
+ HttpHeaders headers = new HttpHeaders();
+ headers.add(HttpHeaders.ACCEPT_ENCODING, "gzip");
+ headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
+
+ ResponseEntity response = restTemplate.exchange(urlPath, HttpMethod.POST,
+ new HttpEntity(info, headers), Void.class);
+
+ return anEurekaHttpResponse(response.getStatusCodeValue())
+ .headers(headersOf(response)).build();
+ }
+
+ @Override
+ public EurekaHttpResponse cancel(String appName, String id) {
+ String urlPath = serviceUrl + "apps/" + appName + '/' + id;
+
+ ResponseEntity response = restTemplate.exchange(urlPath, HttpMethod.DELETE,
+ null, Void.class);
+
+ return anEurekaHttpResponse(response.getStatusCodeValue())
+ .headers(headersOf(response)).build();
+ }
+
+ @Override
+ public EurekaHttpResponse sendHeartBeat(String appName, String id,
+ InstanceInfo info, InstanceStatus overriddenStatus) {
+ String urlPath = serviceUrl + "apps/" + appName + '/' + id + "?status="
+ + info.getStatus().toString() + "&lastDirtyTimestamp="
+ + info.getLastDirtyTimestamp().toString() + (overriddenStatus != null
+ ? "&overriddenstatus=" + overriddenStatus.name() : "");
+
+ ResponseEntity response = restTemplate.exchange(urlPath,
+ HttpMethod.PUT, null, InstanceInfo.class);
+
+ EurekaHttpResponseBuilder eurekaResponseBuilder = anEurekaHttpResponse(
+ response.getStatusCodeValue(), InstanceInfo.class)
+ .headers(headersOf(response));
+
+ if (response.hasBody())
+ eurekaResponseBuilder.entity(response.getBody());
+
+ return eurekaResponseBuilder.build();
+ }
+
+ @Override
+ public EurekaHttpResponse statusUpdate(String appName, String id,
+ InstanceStatus newStatus, InstanceInfo info) {
+ String urlPath = serviceUrl + "apps/" + appName + '/' + id + "?status="
+ + newStatus.name() + "&lastDirtyTimestamp="
+ + info.getLastDirtyTimestamp().toString();
+
+ ResponseEntity response = restTemplate.exchange(urlPath, HttpMethod.PUT,
+ null, Void.class);
+
+ return anEurekaHttpResponse(response.getStatusCodeValue())
+ .headers(headersOf(response)).build();
+ }
+
+ @Override
+ public EurekaHttpResponse deleteStatusOverride(String appName, String id,
+ InstanceInfo info) {
+ String urlPath = serviceUrl + "apps/" + appName + '/' + id
+ + "/status?lastDirtyTimestamp=" + info.getLastDirtyTimestamp().toString();
+
+ ResponseEntity response = restTemplate.exchange(urlPath, HttpMethod.DELETE,
+ null, Void.class);
+
+ return anEurekaHttpResponse(response.getStatusCodeValue())
+ .headers(headersOf(response)).build();
+ }
+
+ @Override
+ public EurekaHttpResponse getApplications(String... regions) {
+ return getApplicationsInternal("apps/", regions);
+ }
+
+ private EurekaHttpResponse getApplicationsInternal(String urlPath,
+ String[] regions) {
+ String url = serviceUrl + urlPath;
+
+ if (regions != null && regions.length > 0)
+ urlPath = (urlPath.contains("?") ? "&" : "?") + "regions="
+ + StringUtil.join(regions);
+
+ ResponseEntity response = restTemplate.exchange(url,
+ HttpMethod.GET, null, EurekaApplications.class);
+
+ return anEurekaHttpResponse(response.getStatusCodeValue(),
+ response.getStatusCode().value() == HttpStatus.OK.value()
+ && response.hasBody() ? (Applications) response.getBody() : null)
+ .headers(headersOf(response)).build();
+ }
+
+ @Override
+ public EurekaHttpResponse getDelta(String... regions) {
+ return getApplicationsInternal("apps/delta", regions);
+ }
+
+ @Override
+ public EurekaHttpResponse getVip(String vipAddress, String... regions) {
+ return getApplicationsInternal("vips/" + vipAddress, regions);
+ }
+
+ @Override
+ public EurekaHttpResponse getSecureVip(String secureVipAddress,
+ String... regions) {
+ return getApplicationsInternal("svips/" + secureVipAddress, regions);
+ }
+
+ @Override
+ public EurekaHttpResponse getApplication(String appName) {
+ String urlPath = serviceUrl + "apps/" + appName;
+
+ ResponseEntity response = restTemplate.exchange(urlPath,
+ HttpMethod.GET, null, Application.class);
+
+ Application application = response.getStatusCodeValue() == HttpStatus.OK.value()
+ && response.hasBody() ? response.getBody() : null;
+
+ return anEurekaHttpResponse(response.getStatusCodeValue(), application)
+ .headers(headersOf(response)).build();
+ }
+
+ @Override
+ public EurekaHttpResponse getInstance(String appName, String id) {
+ return getInstanceInternal("apps/" + appName + '/' + id);
+ }
+
+ @Override
+ public EurekaHttpResponse getInstance(String id) {
+ return getInstanceInternal("instances/" + id);
+ }
+
+ private EurekaHttpResponse getInstanceInternal(String urlPath) {
+ urlPath = serviceUrl + urlPath;
+
+ ResponseEntity response = restTemplate.exchange(urlPath,
+ HttpMethod.GET, null, InstanceInfo.class);
+
+ return anEurekaHttpResponse(response.getStatusCodeValue(),
+ response.getStatusCodeValue() == HttpStatus.OK.value()
+ && response.hasBody() ? response.getBody() : null)
+ .headers(headersOf(response)).build();
+ }
+
+ @Override
+ public void shutdown() {
+ // Nothing to do
+ }
+
+ private static Map headersOf(ResponseEntity> response) {
+ HttpHeaders httpHeaders = response.getHeaders();
+ if (httpHeaders == null || httpHeaders.isEmpty()) {
+ return Collections.emptyMap();
+ }
+ Map headers = new HashMap<>();
+ for (Entry> entry : httpHeaders.entrySet()) {
+ if (!entry.getValue().isEmpty()) {
+ headers.put(entry.getKey(), entry.getValue().get(0));
+ }
+ }
+ return headers;
+ }
+}
diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateTransportClientFactories.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateTransportClientFactories.java
new file mode 100644
index 00000000..f2877be7
--- /dev/null
+++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateTransportClientFactories.java
@@ -0,0 +1,46 @@
+/*
+ * 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.netflix.eureka.http;
+
+import java.util.Collection;
+
+import com.netflix.appinfo.InstanceInfo;
+import com.netflix.discovery.EurekaClientConfig;
+import com.netflix.discovery.shared.transport.TransportClientFactory;
+import com.netflix.discovery.shared.transport.jersey.EurekaJerseyClient;
+import com.netflix.discovery.shared.transport.jersey.TransportClientFactories;
+
+/**
+ * @author Daniel Lavoie
+ */
+public class RestTemplateTransportClientFactories
+ implements TransportClientFactories {
+
+ @Override
+ public TransportClientFactory newTransportClientFactory(
+ Collection additionalFilters, EurekaJerseyClient providedJerseyClient) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public TransportClientFactory newTransportClientFactory(
+ EurekaClientConfig clientConfig, Collection additionalFilters,
+ InstanceInfo myInstanceInfo) {
+ return new RestTemplateTransportClientFactory();
+ }
+
+}
diff --git a/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateTransportClientFactory.java b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateTransportClientFactory.java
new file mode 100644
index 00000000..00c8f9d3
--- /dev/null
+++ b/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateTransportClientFactory.java
@@ -0,0 +1,98 @@
+/*
+ * 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.netflix.eureka.http;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.springframework.http.client.support.BasicAuthorizationInterceptor;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
+import org.springframework.web.client.RestTemplate;
+
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.PropertyNamingStrategy;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.netflix.discovery.shared.resolver.EurekaEndpoint;
+import com.netflix.discovery.shared.transport.EurekaHttpClient;
+import com.netflix.discovery.shared.transport.TransportClientFactory;
+
+/**
+ * Provides the custom {@link RestTemplate} required by the
+ * {@link RestTemplateEurekaHttpClient}. Relies on Jackson for serialization and
+ * deserialization.
+ *
+ * @author Daniel Lavoie
+ */
+public class RestTemplateTransportClientFactory implements TransportClientFactory {
+
+ @Override
+ public EurekaHttpClient newClient(EurekaEndpoint serviceUrl) {
+ return new RestTemplateEurekaHttpClient(restTemplate(serviceUrl.getServiceUrl()),
+ serviceUrl.getServiceUrl());
+ }
+
+ private RestTemplate restTemplate(String serviceUrl) {
+ RestTemplate restTemplate = new RestTemplate();
+ try {
+ URI serviceURI = new URI(serviceUrl);
+ if (serviceURI.getUserInfo() != null) {
+ String[] credentials = serviceURI.getUserInfo().split(":");
+ if (credentials.length == 2) {
+ restTemplate.getInterceptors().add(new BasicAuthorizationInterceptor(
+ credentials[0], credentials[1]));
+ }
+ }
+ }
+ catch (URISyntaxException ignore) {
+
+ }
+
+ restTemplate.getMessageConverters().add(0, mappingJacksonHttpMessageConverter());
+
+ return restTemplate;
+ }
+
+ /**
+ * Provides the serialization configurations required by the Eureka Server. JSON
+ * content exchanged with eureka requires a root node matching the entity being
+ * serialized or deserialized. Achived with
+ * {@link SerializationFeature.WRAP_ROOT_VALUE} and
+ * {@link DeserializationFeature.UNWRAP_ROOT_VALUE}.
+ * {@link PropertyNamingStrategy.SnakeCaseStrategy} is applied to the underlying
+ * {@link ObjectMapper}.
+ *
+ *
+ * @return
+ */
+ public MappingJackson2HttpMessageConverter mappingJacksonHttpMessageConverter() {
+ MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
+ converter.setObjectMapper(new ObjectMapper()
+ .setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE));
+
+ converter.getObjectMapper().configure(SerializationFeature.WRAP_ROOT_VALUE, true);
+ converter.getObjectMapper().configure(DeserializationFeature.UNWRAP_ROOT_VALUE,
+ true);
+
+ return converter;
+ }
+
+ @Override
+ public void shutdown() {
+ }
+
+}
diff --git a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/config/JerseyOptionalArgsConfigurationTest.java b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/config/JerseyOptionalArgsConfigurationTest.java
new file mode 100644
index 00000000..ed2930a1
--- /dev/null
+++ b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/config/JerseyOptionalArgsConfigurationTest.java
@@ -0,0 +1,45 @@
+/*
+ * 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.netflix.eureka.config;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.cloud.netflix.eureka.sample.EurekaSampleApplication;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import com.netflix.discovery.DiscoveryClient.DiscoveryClientOptionalArgs;
+
+/**
+ * @author Daniel Lavoie
+ */
+@DirtiesContext
+@RunWith(SpringJUnit4ClassRunner.class)
+@SpringBootTest(classes = EurekaSampleApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT)
+public class JerseyOptionalArgsConfigurationTest {
+ @Autowired
+ private DiscoveryClientOptionalArgs optionalArgs;
+
+ @Test
+ public void contextLoads() {
+ Assert.assertNotNull(optionalArgs);
+ }
+}
diff --git a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/config/RestTemplateOptionalArgsConfigurationTest.java b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/config/RestTemplateOptionalArgsConfigurationTest.java
new file mode 100644
index 00000000..f993dbce
--- /dev/null
+++ b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/config/RestTemplateOptionalArgsConfigurationTest.java
@@ -0,0 +1,46 @@
+/*
+ * 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.netflix.eureka.config;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.cloud.ClassPathExclusions;
+import org.springframework.cloud.FilteredClassPathRunner;
+import org.springframework.cloud.netflix.eureka.http.RestTemplateDiscoveryClientOptionalArgs;
+import org.springframework.cloud.netflix.eureka.sample.EurekaSampleApplication;
+import org.springframework.context.ConfigurableApplicationContext;
+
+/**
+ * @author Daniel Lavoie
+ */
+@RunWith(FilteredClassPathRunner.class)
+@ClassPathExclusions({ "jersey-client-*", "jersey-core-*", "jersey-apache-client4-*" })
+@SpringBootTest(classes = EurekaSampleApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT)
+public class RestTemplateOptionalArgsConfigurationTest {
+ @Test
+ public void contextLoads() {
+ try (ConfigurableApplicationContext context = new SpringApplicationBuilder()
+ .web(false).sources(EurekaSampleApplication.class).run()) {
+ Assert.assertNotNull(
+ context.getBean(RestTemplateDiscoveryClientOptionalArgs.class));
+ }
+ }
+}
diff --git a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/EurekaServerMockApplication.java b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/EurekaServerMockApplication.java
new file mode 100644
index 00000000..50ee6263
--- /dev/null
+++ b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/EurekaServerMockApplication.java
@@ -0,0 +1,117 @@
+/*
+ * 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.netflix.eureka.http;
+
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.netflix.appinfo.InstanceInfo;
+import com.netflix.discovery.shared.Application;
+import com.netflix.discovery.shared.Applications;
+
+/**
+ * Mocked Eureka Server
+ *
+ * @author Daniel Lavoie
+ */
+@Configuration
+@RestController
+@SpringBootApplication
+public class EurekaServerMockApplication {
+ private static final InstanceInfo INFO = new InstanceInfo(null, null, null, null,
+ null, null, null, null, null, null, null, null, null, 0, null, null, null,
+ null, null, null, null, 0l, 0l, null, null);
+
+ /**
+ * Simulates Eureka Server own's serialization.
+ * @return
+ */
+ @Bean
+ public MappingJackson2HttpMessageConverter mappingJacksonHttpMessageConverter() {
+ return new RestTemplateTransportClientFactory()
+ .mappingJacksonHttpMessageConverter();
+ }
+
+ @ResponseStatus(HttpStatus.OK)
+ @PostMapping("/apps/{appName}")
+ public void register(@PathVariable String appName,
+ @RequestBody InstanceInfo instanceInfo) {
+ // Nothing to do
+ }
+
+ @ResponseStatus(HttpStatus.OK)
+ @DeleteMapping("/apps/{appName}/{id}")
+ public void cancel(@PathVariable String appName, @PathVariable String id) {
+
+ }
+
+ @ResponseStatus(HttpStatus.OK)
+ @PutMapping(value = "/apps/{appName}/{id}", params = { "status",
+ "lastDirtyTimestamp" })
+ public InstanceInfo sendHeartBeat(@PathVariable String appName,
+ @PathVariable String id, @RequestParam String status,
+ @RequestParam String lastDirtyTimestamp,
+ @RequestParam(required = false) String overriddenstatus) {
+ return new InstanceInfo(null, null, null, null, null, null, null, null, null,
+ null, null, null, null, 0, null, null, null, null, null, null, null, 0l,
+ 0l, null, null);
+ }
+
+ @ResponseStatus(HttpStatus.OK)
+ @PutMapping(value = "/apps/{appName}/{id}/status", params = { "value",
+ "lastDirtyTimestamp" })
+ public void statusUpdate(@PathVariable String appName, @PathVariable String id,
+ @RequestParam String value, @RequestParam String lastDirtyTimestamp) {
+
+ }
+
+ @ResponseStatus(HttpStatus.OK)
+ @DeleteMapping(value = "/apps/{appName}/{id}/status", params = "lastDirtyTimestamp")
+ public void deleteStatusOverride(@PathVariable String appName,
+ @PathVariable String id, @RequestParam String lastDirtyTimestamp) {
+
+ }
+
+ @GetMapping(value = { "/apps", "/apps/delta", "/vips/{address}", "/svips/{address}" })
+ public Applications getApplications(@PathVariable(required = false) String address,
+ @RequestParam(required = false) String regions) {
+ return new Applications();
+ }
+
+ @GetMapping(value = "/apps/{appName}")
+ public Application getApplication(@PathVariable String appName) {
+ return new Application();
+ }
+
+ @GetMapping(value = { "/apps/{appName}/{id}", "/instances/{id}" })
+ public InstanceInfo getInstance(@PathVariable(required = false) String appName,
+ @PathVariable String id) {
+ return INFO;
+ }
+}
diff --git a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/RestTemplateEurekaHttpClientTest.java b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/RestTemplateEurekaHttpClientTest.java
new file mode 100644
index 00000000..e02f50f3
--- /dev/null
+++ b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/RestTemplateEurekaHttpClientTest.java
@@ -0,0 +1,139 @@
+/*
+ * 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.netflix.eureka.http;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.cloud.commons.util.InetUtils;
+import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean;
+import org.springframework.http.HttpStatus;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import com.netflix.appinfo.InstanceInfo;
+import com.netflix.appinfo.InstanceInfo.InstanceStatus;
+import com.netflix.appinfo.providers.EurekaConfigBasedInstanceInfoProvider;
+import com.netflix.discovery.shared.resolver.DefaultEndpoint;
+import com.netflix.discovery.shared.transport.EurekaHttpClient;
+
+/**
+ * @author Daniel Lavoie
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@SpringBootTest(classes = EurekaServerMockApplication.class, properties = { "debug=true",
+ "security.basic.enabled=true" }, webEnvironment = WebEnvironment.RANDOM_PORT)
+@DirtiesContext
+public class RestTemplateEurekaHttpClientTest {
+ @Autowired
+ private InetUtils inetUtils;
+
+ @Value("http://${security.user.name}:${security.user.password}@localhost:${local.server.port}")
+ private String serviceUrl;
+
+ private EurekaHttpClient eurekaHttpClient;
+ private InstanceInfo info;
+
+ @Before
+ public void setup() {
+ eurekaHttpClient = new RestTemplateTransportClientFactory()
+ .newClient(new DefaultEndpoint(serviceUrl));
+
+ EurekaInstanceConfigBean config = new EurekaInstanceConfigBean(inetUtils);
+
+ String appname = "customapp";
+ config.setIpAddress("127.0.0.1");
+ config.setHostname("localhost");
+ config.setAppname(appname);
+ config.setVirtualHostName(appname);
+ config.setSecureVirtualHostName(appname);
+ config.setNonSecurePort(4444);
+ config.setInstanceId("127.0.0.1:customapp:4444");
+
+ info = new EurekaConfigBasedInstanceInfoProvider(config).get();
+ }
+
+ @Test
+ public void testRegister() {
+ Assert.assertEquals(HttpStatus.OK.value(),
+ eurekaHttpClient.register(info).getStatusCode());
+ }
+
+ @Test
+ public void testCancel() {
+ Assert.assertEquals(HttpStatus.OK.value(),
+ eurekaHttpClient.cancel("test", "test").getStatusCode());
+ }
+
+ @Test
+ public void testSendHeartBeat() {
+ Assert.assertEquals(HttpStatus.OK.value(), eurekaHttpClient
+ .sendHeartBeat("test", "test", info, null).getStatusCode());
+ }
+
+ @Test
+ public void testStatusUpdate() {
+ Assert.assertEquals(HttpStatus.OK.value(), eurekaHttpClient
+ .statusUpdate("test", "test", InstanceStatus.UP, info).getStatusCode());
+ }
+
+ @Test
+ public void testDeleteStatusOverride() {
+ Assert.assertEquals(HttpStatus.OK.value(), eurekaHttpClient
+ .deleteStatusOverride("test", "test", info).getStatusCode());
+ }
+
+ @Test
+ public void testGetApplications() {
+ Assert.assertNotNull(eurekaHttpClient.getApplications().getEntity());
+ Assert.assertNotNull(eurekaHttpClient.getApplications("us", "eu").getEntity());
+ }
+
+ @Test
+ public void testGetDelta() {
+ eurekaHttpClient.getDelta().getEntity();
+ eurekaHttpClient.getDelta("us", "eu").getEntity();
+ }
+
+ @Test
+ public void testGetVips() {
+ eurekaHttpClient.getVip("test");
+ eurekaHttpClient.getVip("test", "us", "eu");
+ }
+
+ @Test
+ public void testGetSecureVip() {
+ eurekaHttpClient.getSecureVip("test");
+ eurekaHttpClient.getSecureVip("test", "us", "eu");
+ }
+
+ @Test
+ public void testGetApplication() {
+ eurekaHttpClient.getApplication("test");
+ }
+
+ @Test
+ public void testGetInstance() {
+ eurekaHttpClient.getInstance("test");
+ eurekaHttpClient.getInstance("test", "test");
+ }
+}
diff --git a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/RestTemplateTransportClientFactoriesTest.java b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/RestTemplateTransportClientFactoriesTest.java
new file mode 100644
index 00000000..88d02636
--- /dev/null
+++ b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/RestTemplateTransportClientFactoriesTest.java
@@ -0,0 +1,29 @@
+/*
+ * 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.netflix.eureka.http;
+
+import org.junit.Test;
+
+/**
+ * @author Daniel Lavoie
+ */
+public class RestTemplateTransportClientFactoriesTest {
+ @Test(expected = UnsupportedOperationException.class)
+ public void testJerseyIsUnsuported() {
+ new RestTemplateTransportClientFactories().newTransportClientFactory(null, null);
+ }
+}
diff --git a/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/RestTemplateTransportClientFactoryTest.java b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/RestTemplateTransportClientFactoryTest.java
new file mode 100644
index 00000000..50de78ae
--- /dev/null
+++ b/spring-cloud-netflix-eureka-client/src/test/java/org/springframework/cloud/netflix/eureka/http/RestTemplateTransportClientFactoryTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.netflix.eureka.http;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.netflix.discovery.shared.resolver.DefaultEndpoint;
+
+/**
+ * @author Daniel Lavoie
+ */
+public class RestTemplateTransportClientFactoryTest {
+ private RestTemplateTransportClientFactory transportClientFatory;
+
+ @Before
+ public void setup() {
+ transportClientFatory = new RestTemplateTransportClientFactory();
+ }
+
+ @Test
+ public void testWithoutUserInfo() {
+ transportClientFatory.newClient(new DefaultEndpoint("http://localhost:8761"));
+ }
+
+ @Test
+ public void testInvalidUserInfo() {
+ transportClientFatory
+ .newClient(new DefaultEndpoint("http://test@localhost:8761"));
+ }
+
+ @Test
+ public void testUserInfo() {
+ transportClientFatory
+ .newClient(new DefaultEndpoint("http://test:test@localhost:8761"));
+ }
+
+ @After
+ public void shutdown() {
+ transportClientFatory.shutdown();
+ }
+}
diff --git a/spring-cloud-netflix-eureka-client/src/test/resources/application.yml b/spring-cloud-netflix-eureka-client/src/test/resources/application.yml
index 7423d1f9..3e83e31a 100644
--- a/spring-cloud-netflix-eureka-client/src/test/resources/application.yml
+++ b/spring-cloud-netflix-eureka-client/src/test/resources/application.yml
@@ -2,4 +2,11 @@
foo3:
ribbon:
NFLoadBalancerPingClassName: com.netflix.loadbalancer.DummyPing
- NIWSServerListClassName: com.netflix.loadbalancer.ConfigurationBasedServerList
\ No newline at end of file
+ NIWSServerListClassName: com.netflix.loadbalancer.ConfigurationBasedServerList
+
+security:
+ basic:
+ enabled: false
+ user:
+ name: test
+ password: test
\ No newline at end of file