From 77d1d64cdb3868c623b3c4ff3f3b2cae15d3cb1f Mon Sep 17 00:00:00 2001 From: John Blum Date: Mon, 28 Oct 2019 00:36:28 -0700 Subject: [PATCH] DATAGEODE-243 - Introduce RestTemplateConfigurer to configure the RestTemplate used when sending configuration metadata from client to server. --- .../remote/RestHttpGemfireAdminTemplate.java | 96 ++++++++++-- ...ConfiguredAuthenticationConfiguration.java | 19 ++- .../ClusterConfigurationConfiguration.java | 98 +++++++++--- .../EnableClusterConfiguration.java | 25 +++ .../support/RestTemplateConfigurer.java | 38 +++++ ...RestHttpGemfireAdminTemplateUnitTests.java | 49 +++++- ...tpRequestInterceptorsIntegrationTests.java | 103 +++++++++++-- .../EnableClusterConfigurationUnitTests.java | 143 +++++++++++------- ...igurationWithSecurityIntegrationTests.java | 21 +-- 9 files changed, 458 insertions(+), 134 deletions(-) create mode 100644 src/main/java/org/springframework/data/gemfire/config/support/RestTemplateConfigurer.java diff --git a/src/main/java/org/springframework/data/gemfire/config/admin/remote/RestHttpGemfireAdminTemplate.java b/src/main/java/org/springframework/data/gemfire/config/admin/remote/RestHttpGemfireAdminTemplate.java index a6a17371..3ea6a403 100644 --- a/src/main/java/org/springframework/data/gemfire/config/admin/remote/RestHttpGemfireAdminTemplate.java +++ b/src/main/java/org/springframework/data/gemfire/config/admin/remote/RestHttpGemfireAdminTemplate.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.Optional; import org.apache.geode.cache.client.ClientCache; @@ -30,6 +31,7 @@ import org.apache.geode.cache.execute.Function; import org.springframework.data.gemfire.config.admin.GemfireAdminOperations; import org.springframework.data.gemfire.config.schema.definitions.IndexDefinition; import org.springframework.data.gemfire.config.schema.definitions.RegionDefinition; +import org.springframework.data.gemfire.config.support.RestTemplateConfigurer; import org.springframework.data.gemfire.util.ArrayUtils; import org.springframework.data.gemfire.util.CollectionUtils; import org.springframework.data.gemfire.util.NetworkUtils; @@ -100,7 +102,7 @@ public class RestHttpGemfireAdminTemplate extends FunctionGemfireAdminTemplate { /** * Constructs a new instance of {@link RestHttpGemfireAdminTemplate} initialized with the given {@link ClientCache} - * and configured with the default host and port when accessing the Apache Geode or Pivotal GemFire + * and configured with the default HTTP schema, host and port when accessing the Apache Geode or Pivotal GemFire * Management REST API interface. * * @param clientCache reference to the {@link ClientCache}. @@ -117,8 +119,8 @@ public class RestHttpGemfireAdminTemplate extends FunctionGemfireAdminTemplate { /** * Constructs a new instance of {@link RestHttpGemfireAdminTemplate} initialized with the given {@link ClientCache} * and configured with the specified HTTP scheme, host, port, redirects and - * {@link ClientHttpRequestInterceptor ClientHttpRequestInterceptors} when - * accessing the Apache Geode or Pivotal GemFire Management REST API interface. + * {@link ClientHttpRequestInterceptor ClientHttpRequestInterceptors} + * when accessing the Apache Geode or Pivotal GemFire Management REST API interface. * * @param clientCache reference to the {@link ClientCache} * @param scheme {@link String} specifying the HTTP scheme to use (e.g. HTTP or HTTPS). @@ -131,19 +133,47 @@ public class RestHttpGemfireAdminTemplate extends FunctionGemfireAdminTemplate { * @throws IllegalArgumentException if the {@link ClientCache} reference is {@literal null}. * @see org.springframework.http.client.ClientHttpRequestInterceptor * @see org.apache.geode.cache.client.ClientCache - * @see #newClientHttpRequestFactory(boolean) - * @see #newRestOperations(ClientHttpRequestFactory, List) - * @see #resolveManagementRestApiUrl(String, String, int) */ public RestHttpGemfireAdminTemplate(ClientCache clientCache, String scheme, String host, int port, boolean followRedirects, List clientHttpRequestInterceptors) { + this(clientCache, scheme, host, port, followRedirects, clientHttpRequestInterceptors, Collections.emptyList()); + } + + /** + * Constructs a new instance of {@link RestHttpGemfireAdminTemplate} initialized with the given {@link ClientCache} + * and configured with the specified HTTP scheme, host, port, redirects and + * {@link ClientHttpRequestInterceptor ClientHttpRequestInterceptors} + * when accessing the Apache Geode or Pivotal GemFire Management REST API interface. + * + * @param clientCache reference to the {@link ClientCache} + * @param scheme {@link String} specifying the HTTP scheme to use (e.g. HTTP or HTTPS). + * @param host {@link String} containing the hostname of the GemFire/Geode Manager. + * @param port integer value specifying the port on which the GemFire/Geode Manager HTTP Service is listening + * for HTTP clients. + * @param followRedirects boolean indicating whether HTTP Redirects (with HTTP Status Code 3xx) should be followed. + * @param clientHttpRequestInterceptors {@link List} of {@link ClientHttpRequestInterceptor} used to intercept + * and decorate the HTTP request and HTTP response. + * @throws IllegalArgumentException if the {@link ClientCache} reference is {@literal null}. + * @see org.apache.geode.cache.client.ClientCache + * @see org.springframework.data.gemfire.config.support.RestTemplateConfigurer + * @see org.springframework.http.client.ClientHttpRequestInterceptor + * @see #newClientHttpRequestFactory(boolean) + * @see #newRestOperations(ClientHttpRequestFactory, List, List) + * @see #resolveManagementRestApiUrl(String, String, int) + */ + public RestHttpGemfireAdminTemplate(ClientCache clientCache, String scheme, String host, int port, + boolean followRedirects, List clientHttpRequestInterceptors, + List restTemplateConfigurers) { + super(clientCache); ClientHttpRequestFactory clientHttpRequestFactory = newClientHttpRequestFactory(followRedirects); this.managementRestApiUrl = resolveManagementRestApiUrl(scheme, host, port); - this.restTemplate = newRestOperations(clientHttpRequestFactory, clientHttpRequestInterceptors); + + this.restTemplate = + newRestOperations(clientHttpRequestFactory, clientHttpRequestInterceptors, restTemplateConfigurers); } /** @@ -173,13 +203,18 @@ public class RestHttpGemfireAdminTemplate extends FunctionGemfireAdminTemplate { */ @SuppressWarnings("unchecked") protected T newRestOperations(ClientHttpRequestFactory clientHttpRequestFactory, - List clientHttpRequestInterceptors) { + List clientHttpRequestInterceptors, + List restTemplateConfigurers) { RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory); Optional.ofNullable(clientHttpRequestInterceptors) .ifPresent(restTemplate.getInterceptors()::addAll); + CollectionUtils.nullSafeList(restTemplateConfigurers).stream() + .filter(Objects::nonNull) + .forEach(configurer -> configurer.configure(restTemplate)); + return (T) restTemplate; } @@ -283,6 +318,7 @@ public class RestHttpGemfireAdminTemplate extends FunctionGemfireAdminTemplate { private ClientCache clientCache; private final List clientHttpRequestInterceptors = new ArrayList<>(); + private final List restTemplateConfigurers = new ArrayList<>(); private String hostname = DEFAULT_HOST; private String scheme = DEFAULT_SCHEME; @@ -324,15 +360,47 @@ public class RestHttpGemfireAdminTemplate extends FunctionGemfireAdminTemplate { return this; } + /** + * @deprecated use {@link #withInterceptors(ClientHttpRequestInterceptor...)}. + */ + @Deprecated public Builder with(ClientHttpRequestInterceptor... clientHttpRequestInterceptors) { - - clientHttpRequestInterceptors = - ArrayUtils.nullSafeArray(clientHttpRequestInterceptors, ClientHttpRequestInterceptor.class); - - return with(Arrays.asList(clientHttpRequestInterceptors)); + return withInterceptors(clientHttpRequestInterceptors); } + /** + * @deprecated use {@link #withInterceptors(List)}. + */ + @Deprecated public Builder with(List clientHttpRequestInterceptors) { + return withInterceptors(clientHttpRequestInterceptors); + } + + public Builder withConfigurers(RestTemplateConfigurer... restTemplateConfigurers) { + + List restTemplateConfigurerList = + Arrays.asList(ArrayUtils.nullSafeArray(restTemplateConfigurers, RestTemplateConfigurer.class)); + + return withConfigurers(restTemplateConfigurerList); + } + + public Builder withConfigurers(List restTemplateConfigurers) { + + this.restTemplateConfigurers.addAll(CollectionUtils.nullSafeList(restTemplateConfigurers)); + + return this; + } + + public Builder withInterceptors(ClientHttpRequestInterceptor... clientHttpRequestInterceptors) { + + List clientHttpRequestInterceptorList = + Arrays.asList(ArrayUtils.nullSafeArray(clientHttpRequestInterceptors, + ClientHttpRequestInterceptor.class)); + + return withInterceptors(clientHttpRequestInterceptorList); + } + + public Builder withInterceptors(List clientHttpRequestInterceptors) { this.clientHttpRequestInterceptors.addAll(CollectionUtils.nullSafeList(clientHttpRequestInterceptors)); @@ -342,7 +410,7 @@ public class RestHttpGemfireAdminTemplate extends FunctionGemfireAdminTemplate { public RestHttpGemfireAdminTemplate build() { return new RestHttpGemfireAdminTemplate(this.clientCache, this.scheme, this.hostname, this.port, - this.followRedirects, this.clientHttpRequestInterceptors); + this.followRedirects, this.clientHttpRequestInterceptors, this.restTemplateConfigurers); } } diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/AutoConfiguredAuthenticationConfiguration.java b/src/main/java/org/springframework/data/gemfire/config/annotation/AutoConfiguredAuthenticationConfiguration.java index 06cdd31f..ccb9bc4f 100644 --- a/src/main/java/org/springframework/data/gemfire/config/annotation/AutoConfiguredAuthenticationConfiguration.java +++ b/src/main/java/org/springframework/data/gemfire/config/annotation/AutoConfiguredAuthenticationConfiguration.java @@ -38,6 +38,7 @@ import org.springframework.core.annotation.Order; import org.springframework.core.env.Environment; import org.springframework.core.type.AnnotatedTypeMetadata; import org.springframework.data.gemfire.config.annotation.support.AutoConfiguredAuthenticationInitializer; +import org.springframework.data.gemfire.config.support.RestTemplateConfigurer; import org.springframework.data.gemfire.util.CollectionUtils; import org.springframework.http.HttpHeaders; import org.springframework.http.client.ClientHttpRequestInterceptor; @@ -106,9 +107,7 @@ public class AutoConfiguredAuthenticationConfiguration { return authenticator; } - @Bean - @Order(Ordered.LOWEST_PRECEDENCE) - public ClientHttpRequestInterceptor loggingAwareClientHttpRequestInterceptor() { + ClientHttpRequestInterceptor loggingAwareClientHttpRequestInterceptor() { return (request, body, execution) -> { @@ -142,8 +141,12 @@ public class AutoConfiguredAuthenticationConfiguration { } @Bean - @Order(Ordered.HIGHEST_PRECEDENCE) - public ClientHttpRequestInterceptor securityAwareClientHttpRequestInterceptor(Authenticator authenticator) { + @Order(Ordered.LOWEST_PRECEDENCE) + public RestTemplateConfigurer loggingAwareRestTemplateConfigurer() { + return restTemplate -> restTemplate.getInterceptors().add(loggingAwareClientHttpRequestInterceptor()); + } + + ClientHttpRequestInterceptor securityAwareClientHttpRequestInterceptor() { return (request, body, execution) -> { @@ -168,6 +171,12 @@ public class AutoConfiguredAuthenticationConfiguration { }; } + @Bean + @Order(Ordered.HIGHEST_PRECEDENCE) + public RestTemplateConfigurer securityAwareRestTemplateConfigurer(Authenticator authenticator) { + return restTemplate -> restTemplate.getInterceptors().add(securityAwareClientHttpRequestInterceptor()); + } + private boolean isAuthenticationEnabled(String username, char[] password) { return StringUtils.hasText(username) && password != null && password.length > 0; } diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/ClusterConfigurationConfiguration.java b/src/main/java/org/springframework/data/gemfire/config/annotation/ClusterConfigurationConfiguration.java index 11fdbb78..285db1d4 100644 --- a/src/main/java/org/springframework/data/gemfire/config/annotation/ClusterConfigurationConfiguration.java +++ b/src/main/java/org/springframework/data/gemfire/config/annotation/ClusterConfigurationConfiguration.java @@ -57,6 +57,7 @@ import org.springframework.data.gemfire.config.schema.support.IndexCollector; import org.springframework.data.gemfire.config.schema.support.IndexDefiner; import org.springframework.data.gemfire.config.schema.support.RegionDefiner; import org.springframework.data.gemfire.config.support.AbstractSmartLifecycle; +import org.springframework.data.gemfire.config.support.RestTemplateConfigurer; import org.springframework.data.gemfire.util.CacheUtils; import org.springframework.data.gemfire.util.NetworkUtils; import org.springframework.http.client.ClientHttpRequestInterceptor; @@ -93,6 +94,7 @@ import org.springframework.util.StringUtils; public class ClusterConfigurationConfiguration extends AbstractAnnotationConfigSupport implements ImportAware { protected static final boolean DEFAULT_HTTP_FOLLOW_REDIRECTS = false; + protected static final boolean DEFAULT_HTTP_REQUEST_INTERCEPTORS_ENABLED = false; protected static final boolean DEFAULT_MANAGEMENT_USE_HTTP = false; protected static final boolean DEFAULT_MANAGEMENT_REQUIRE_HTTPS = true; @@ -105,6 +107,8 @@ public class ClusterConfigurationConfiguration extends AbstractAnnotationConfigS private static final RegionShortcut DEFAULT_SERVER_REGION_SHORTCUT = RegionDefinition.DEFAULT_REGION_SHORTCUT; + private Boolean enableInterceptors = DEFAULT_HTTP_REQUEST_INTERCEPTORS_ENABLED; + private Boolean followRedirects = DEFAULT_HTTP_FOLLOW_REDIRECTS; private Boolean requireHttps = DEFAULT_MANAGEMENT_REQUIRE_HTTPS; private Boolean useHttp = DEFAULT_MANAGEMENT_USE_HTTP; @@ -116,6 +120,9 @@ public class ClusterConfigurationConfiguration extends AbstractAnnotationConfigS @Autowired(required = false) private List clientHttpRequestInterceptors; + @Autowired(required = false) + private List restTemplateConfigurers; + private RegionShortcut serverRegionShortcut; private String managementHttpHost = DEFAULT_MANAGEMENT_HTTP_HOST; @@ -149,6 +156,30 @@ public class ClusterConfigurationConfiguration extends AbstractAnnotationConfigS return getManagementHttpPort().orElse(DEFAULT_MANAGEMENT_HTTP_PORT); } + protected void setManagementHttpEnableInterceptors(Boolean enableInterceptors) { + this.enableInterceptors = enableInterceptors; + } + + protected Optional getManagementHttpEnableInterceptors() { + return Optional.ofNullable(this.enableInterceptors); + } + + protected boolean resolveManagementHttpEnableInterceptors() { + return getManagementHttpEnableInterceptors().orElse(DEFAULT_HTTP_REQUEST_INTERCEPTORS_ENABLED); + } + + protected void setManagementHttpFollowRedirects(Boolean followRedirects) { + this.followRedirects = followRedirects; + } + + protected Optional getManagementHttpFollowRedirects() { + return Optional.ofNullable(this.followRedirects); + } + + protected boolean resolveManagementHttpFollowRedirects() { + return getManagementHttpFollowRedirects().orElse(DEFAULT_HTTP_FOLLOW_REDIRECTS); + } + protected void setManagementRequireHttps(Boolean requireHttps) { this.requireHttps = requireHttps; } @@ -198,6 +229,12 @@ public class ClusterConfigurationConfiguration extends AbstractAnnotationConfigS setManagementHttpPort(resolveProperty(managementProperty("http.port"), enableClusterConfigurationAttributes.getNumber("port"))); + setManagementHttpEnableInterceptors(resolveProperty(managementProperty("http.enable-interceptors"), + enableClusterConfigurationAttributes.getBoolean("enableInterceptors"))); + + setManagementHttpFollowRedirects(resolveProperty(managementProperty("http.follow-redirects"), + enableClusterConfigurationAttributes.getBoolean("followRedirects"))); + setManagementRequireHttps(resolveProperty(managementProperty("require-https"), enableClusterConfigurationAttributes.getBoolean("requireHttps"))); @@ -228,32 +265,47 @@ public class ClusterConfigurationConfiguration extends AbstractAnnotationConfigS .orElse(null); } + private List resolveBeansOfType(List objects, Class type) { + + return Optional.ofNullable(objects).orElseGet(() -> + Optional.of(getBeanFactory()) + .filter(ListableBeanFactory.class::isInstance) + .map(ListableBeanFactory.class::cast) + .map(beanFactory -> { + + Map beansOfType = beanFactory.getBeansOfType(type, true, false); + + return nullSafeMap(beansOfType).values().stream().collect(Collectors.toList()); + + }) + .orElseGet(Collections::emptyList)); + } + /** * Attempts to resolve a {@link List} of {@link ClientHttpRequestInterceptor} beans in the Spring * {@link ApplicationContext}. * * @return a {@link List} of declared and registered {@link ClientHttpRequestInterceptor} beans. * @see org.springframework.http.client.ClientHttpRequestInterceptor - * @see #getBeanFactory() * @see java.util.List */ - protected List resolveClientHttpRequestInterceptors() { + protected List resolveClientHttpRequestInterceptors(boolean enableInterceptors) { - return Optional.ofNullable(this.clientHttpRequestInterceptors) - .orElseGet(() -> + return enableInterceptors + ? resolveBeansOfType(this.clientHttpRequestInterceptors, ClientHttpRequestInterceptor.class) + : Collections.emptyList(); + } - Optional.of(getBeanFactory()) - .filter(ListableBeanFactory.class::isInstance) - .map(ListableBeanFactory.class::cast) - .map(beanFactory -> { - - Map beansOfType = beanFactory - .getBeansOfType(ClientHttpRequestInterceptor.class, true, false); - - return nullSafeMap(beansOfType).values().stream().collect(Collectors.toList()); - - }) - .orElseGet(Collections::emptyList)); + /** + * Attempts to resolve a {@link List} of {@link RestTemplateConfigurer} beans in the Spring + * {@link ApplicationContext}. + * + * @return a {@link List} of declared and registered {@link RestTemplateConfigurer} beans. + * @see org.springframework.data.gemfire.config.support.RestTemplateConfigurer + * @see java.util.List + */ + protected List resolveRestTemplateConfigurers() { + return resolveBeansOfType(this.restTemplateConfigurers, RestTemplateConfigurer.class); } /** @@ -286,7 +338,7 @@ public class ClusterConfigurationConfiguration extends AbstractAnnotationConfigS * on a GemFire system. * @see org.springframework.data.gemfire.config.admin.GemfireAdminOperations * @see org.apache.geode.cache.client.ClientCache - * @see #resolveClientHttpRequestInterceptors() + * @see #resolveClientHttpRequestInterceptors(boolean) * @see #resolveManagementHttpHost() * @see #resolveManagementHttpPort() * @see #resolveManagementRequireHttps() @@ -296,11 +348,10 @@ public class ClusterConfigurationConfiguration extends AbstractAnnotationConfigS if (resolveManagementUseHttp()) { - boolean setFollowRedirects = - environment.getProperty(HTTP_FOLLOW_REDIRECTS_PROPERTY, Boolean.class, DEFAULT_HTTP_FOLLOW_REDIRECTS); - + boolean enableInterceptors = resolveManagementHttpEnableInterceptors(); + boolean followRedirects = resolveManagementHttpFollowRedirects(); boolean requireHttps = resolveManagementRequireHttps(); - boolean followRedirects = !requireHttps || setFollowRedirects; + boolean resolvedFollowRedirects = !requireHttps || followRedirects; int port = resolveManagementHttpPort(); @@ -308,11 +359,12 @@ public class ClusterConfigurationConfiguration extends AbstractAnnotationConfigS String scheme = requireHttps ? HTTPS_SCHEME : HTTP_SCHEME; return configurePort(new RestHttpGemfireAdminTemplate.Builder() - .with(resolveClientHttpRequestInterceptors()) + .withConfigurers(resolveRestTemplateConfigurers()) + .withInterceptors(resolveClientHttpRequestInterceptors(enableInterceptors)) .with(clientCache) .using(scheme) .on(host) - .followRedirects(followRedirects), port) + .followRedirects(resolvedFollowRedirects), port) .build(); } else { diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/EnableClusterConfiguration.java b/src/main/java/org/springframework/data/gemfire/config/annotation/EnableClusterConfiguration.java index a945a51a..48ed9aed 100644 --- a/src/main/java/org/springframework/data/gemfire/config/annotation/EnableClusterConfiguration.java +++ b/src/main/java/org/springframework/data/gemfire/config/annotation/EnableClusterConfiguration.java @@ -28,6 +28,8 @@ import org.apache.geode.cache.RegionShortcut; import org.apache.geode.cache.client.ClientCache; import org.springframework.context.annotation.Import; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.web.client.RestTemplate; /** * The {@link EnableClusterConfiguration} annotation enables Apache Geode / Pivotal GemFire schema object definitions @@ -78,6 +80,29 @@ public @interface EnableClusterConfiguration { */ int port() default ClusterConfigurationConfiguration.DEFAULT_MANAGEMENT_HTTP_PORT; + /** + * Configures whether to enable {@link ClientHttpRequestInterceptor} bean lookup. + * + * If {@link ClientHttpRequestInterceptor} beans are found in the Spring context, then they will be added to + * the Interceptors on the {@link RestTemplate} when using HTTP. + * + * Alternatively, you can configure this setting using the + * {@literal spring.data.gemfire.management.http.enable-interceptors} property in {@literal application.properties}. + * + * Defaults to {@literal false}. + */ + boolean enableInterceptors() default ClusterConfigurationConfiguration.DEFAULT_HTTP_REQUEST_INTERCEPTORS_ENABLED; + + /** + * Configures whether to follow HTTP redirects when using HTTP. + * + * Alternatively, you can configure this setting using the + * {@literal spring.data.gemfire.management.http.follow-redirects} property in {@literal application.properties}. + * + * Defaults to {@literal false}. + */ + boolean followRedirects() default ClusterConfigurationConfiguration.DEFAULT_HTTP_FOLLOW_REDIRECTS; + /** * Configures whether the HTTP connection between Spring and Apache Geode or Pivotal GemFire should be secure. * That is, whether the HTTP connections uses TLS and results in a secure HTTPS connection rather a plain text diff --git a/src/main/java/org/springframework/data/gemfire/config/support/RestTemplateConfigurer.java b/src/main/java/org/springframework/data/gemfire/config/support/RestTemplateConfigurer.java new file mode 100644 index 00000000..975f7667 --- /dev/null +++ b/src/main/java/org/springframework/data/gemfire/config/support/RestTemplateConfigurer.java @@ -0,0 +1,38 @@ +/* + * Copyright 2019 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 + * + * https://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.data.gemfire.config.support; + +import org.springframework.web.client.RestTemplate; + +/** + * Configurer for a {@link RestTemplate}. + * + * @author John Blum + * @see org.springframework.web.client.RestTemplate + * @since 2.3.0 + */ +@FunctionalInterface +public interface RestTemplateConfigurer { + + /** + * User-defined method and contract for applying custom configuration to the given {@link RestTemplate}. + * + * @param restTemplate {@link RestTemplate} to customize the configuration for. + * @see org.springframework.web.client.RestTemplate + */ + void configure(RestTemplate restTemplate); + +} diff --git a/src/test/java/org/springframework/data/gemfire/config/admin/remote/RestHttpGemfireAdminTemplateUnitTests.java b/src/test/java/org/springframework/data/gemfire/config/admin/remote/RestHttpGemfireAdminTemplateUnitTests.java index bd747ee7..6eb9ef3c 100644 --- a/src/test/java/org/springframework/data/gemfire/config/admin/remote/RestHttpGemfireAdminTemplateUnitTests.java +++ b/src/test/java/org/springframework/data/gemfire/config/admin/remote/RestHttpGemfireAdminTemplateUnitTests.java @@ -19,6 +19,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isA; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -32,19 +33,21 @@ import java.util.Collections; import java.util.List; import java.util.Optional; -import org.apache.geode.cache.Region; -import org.apache.geode.cache.client.ClientCache; -import org.apache.geode.cache.query.Index; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.stubbing.Answer; + +import org.apache.geode.cache.Region; +import org.apache.geode.cache.client.ClientCache; +import org.apache.geode.cache.query.Index; import org.springframework.data.gemfire.IndexType; import org.springframework.data.gemfire.config.schema.definitions.IndexDefinition; import org.springframework.data.gemfire.config.schema.definitions.RegionDefinition; +import org.springframework.data.gemfire.config.support.RestTemplateConfigurer; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; @@ -104,7 +107,8 @@ public class RestHttpGemfireAdminTemplateUnitTests { @Override @SuppressWarnings("unchecked") protected T newRestOperations(ClientHttpRequestFactory clientHttpRequestFactory, - List clientHttpRequestInterceptors) { + List clientHttpRequestInterceptors, + List restTemplateConfigurers) { return (T) mockRestOperations; } @@ -225,7 +229,8 @@ public class RestHttpGemfireAdminTemplateUnitTests { ClientHttpRequestInterceptor mockInterceptorTwo = mock(ClientHttpRequestInterceptor.class); RestTemplate restTemplate = new RestHttpGemfireAdminTemplate(this.mockClientCache) - .newRestOperations(mockClientHttpRequestFactory, Arrays.asList(mockInterceptorOne, mockInterceptorTwo)); + .newRestOperations(mockClientHttpRequestFactory, Arrays.asList(mockInterceptorOne, mockInterceptorTwo), + Collections.emptyList()); assertThat(restTemplate).isNotNull(); assertThat(restTemplate.getInterceptors()).containsExactly(mockInterceptorOne, mockInterceptorTwo); @@ -239,13 +244,43 @@ public class RestHttpGemfireAdminTemplateUnitTests { ClientHttpRequestFactory mockClientHttpRequestFactory = mock(ClientHttpRequestFactory.class); RestTemplate restTemplate = new RestHttpGemfireAdminTemplate(this.mockClientCache) - .newRestOperations(mockClientHttpRequestFactory, Collections.emptyList()); + .newRestOperations(mockClientHttpRequestFactory, Collections.emptyList(), Collections.emptyList()); assertThat(restTemplate).isNotNull(); assertThat(restTemplate.getInterceptors()).isEmpty(); assertThat(restTemplate.getRequestFactory()).isSameAs(mockClientHttpRequestFactory); } + @Test + public void newRestOperationsWithRestTemplateConfigurersApplied() { + + ClientHttpRequestFactory mockClientHttpRequestFactory = mock(ClientHttpRequestFactory.class); + + RestTemplateConfigurer mockRestTemplateConfigurerOne = mock(RestTemplateConfigurer.class); + RestTemplateConfigurer mockRestTemplateConfigurerTwo = mock(RestTemplateConfigurer.class); + + Answer answer = invocation -> { + + assertThat(invocation.getArgument(0, RestTemplate.class)).isInstanceOf(RestTemplate.class); + + return null; + }; + + doAnswer(answer).when(mockRestTemplateConfigurerOne).configure(isA(RestTemplate.class)); + doAnswer(answer).when(mockRestTemplateConfigurerTwo).configure(isA(RestTemplate.class)); + + List mockRestTemplateConfigurers = + Arrays.asList(mockRestTemplateConfigurerOne, null, mockRestTemplateConfigurerTwo); + + RestTemplate restTemplate = new RestHttpGemfireAdminTemplate(this.mockClientCache) + .newRestOperations(mockClientHttpRequestFactory, Collections.emptyList(), mockRestTemplateConfigurers); + + assertThat(restTemplate).isNotNull(); + + verify(mockRestTemplateConfigurerOne, times(1)).configure(eq(restTemplate)); + verify(mockRestTemplateConfigurerTwo, times(1)).configure(eq(restTemplate)); + } + @Test public void resolvesManagementRestApiUrlCorrectly() { diff --git a/src/test/java/org/springframework/data/gemfire/config/annotation/ClusterConfigurationWithClientHttpRequestInterceptorsIntegrationTests.java b/src/test/java/org/springframework/data/gemfire/config/annotation/ClusterConfigurationWithClientHttpRequestInterceptorsIntegrationTests.java index c10116f8..1a4b6e90 100644 --- a/src/test/java/org/springframework/data/gemfire/config/annotation/ClusterConfigurationWithClientHttpRequestInterceptorsIntegrationTests.java +++ b/src/test/java/org/springframework/data/gemfire/config/annotation/ClusterConfigurationWithClientHttpRequestInterceptorsIntegrationTests.java @@ -26,12 +26,12 @@ import java.lang.reflect.Field; import java.util.List; import java.util.Optional; -import org.apache.geode.cache.client.ClientCache; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.apache.geode.cache.client.ClientCache; + import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -40,6 +40,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.core.annotation.Order; import org.springframework.data.gemfire.config.admin.GemfireAdminOperations; import org.springframework.data.gemfire.config.admin.remote.RestHttpGemfireAdminTemplate; +import org.springframework.data.gemfire.config.support.RestTemplateConfigurer; import org.springframework.data.gemfire.test.mock.annotation.EnableGemFireMockObjects; import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.http.client.InterceptingClientHttpRequestFactory; @@ -91,6 +92,20 @@ public class ClusterConfigurationWithClientHttpRequestInterceptorsIntegrationTes @Autowired private List clientHttpRequestInterceptors; + @Autowired + private List restTemplateConfigurers; + + private RestTemplate theRestTemplate; + + @Autowired + @Qualifier("testRestTemplateConfigurerOne") + private RestTemplateConfigurer restTemplateConfigurerOne; + + @Autowired + @Qualifier("testRestTemplateConfigurerTwo") + private RestTemplateConfigurer restTemplateConfigurerTwo; + + // TODO: Replace with STDG @SuppressWarnings("unchecked") private T getFieldValue(Object target, String fieldName) throws NoSuchFieldException { @@ -108,7 +123,7 @@ public class ClusterConfigurationWithClientHttpRequestInterceptorsIntegrationTes } @Before - public void setup() { + public void setupIsCorrect() { assertThat(this.clientCache).isNotNull(); assertThat(this.configuration).isNotNull(); @@ -119,17 +134,18 @@ public class ClusterConfigurationWithClientHttpRequestInterceptorsIntegrationTes assertThat(this.clientHttpRequestInterceptors).hasSize(2); assertThat(this.clientHttpRequestInterceptors) .containsExactly(this.mockClientHttpRequestInterceptorTwo, this.mockClientHttpRequestInterceptorOne); + assertThat(this.restTemplateConfigurerOne).isInstanceOf(TestRestTemplateConfigurer.class); + assertThat(this.restTemplateConfigurerTwo).isInstanceOf(TestRestTemplateConfigurer.class); + assertThat(this.restTemplateConfigurers).isNotNull(); + assertThat(this.restTemplateConfigurers).hasSize(2); + assertThat(this.restTemplateConfigurers) + .containsExactlyInAnyOrder(this.restTemplateConfigurerOne, restTemplateConfigurerTwo); } - @Test - public void configurationWasAutowiredWithUserDefinedClientHttpRequestInterceptors() { + @Before + public void restTemplateWasConfiguredCorrectly() throws Exception { - assertThat(this.configuration.resolveClientHttpRequestInterceptors()) - .isEqualTo(this.clientHttpRequestInterceptors); - } - - @Test - public void clientHttpRequestInterceptorsRegistered() throws Exception { + assertThat(this.initializer).isNotNull(); SchemaObjectContext schemaObjectContext = this.initializer.getSchemaObjectContext(); @@ -140,12 +156,43 @@ public class ClusterConfigurationWithClientHttpRequestInterceptorsIntegrationTes RestHttpGemfireAdminTemplate template = schemaObjectContext.getGemfireAdminOperations(); - RestTemplate restTemplate = getFieldValue(template, "restTemplate"); + this.theRestTemplate = getFieldValue(template, "restTemplate"); - assertThat(restTemplate).isNotNull(); - assertThat(restTemplate.getInterceptors()) - .containsExactly(this.mockClientHttpRequestInterceptorTwo, this.mockClientHttpRequestInterceptorOne); - assertThat(restTemplate.getRequestFactory()).isInstanceOf(InterceptingClientHttpRequestFactory.class); + assertThat(this.theRestTemplate).isNotNull(); + } + + @Test + public void assertRestTemplateConfigurersVisitedAndConfiguredTheClusterConfigurationRestTemplate() { + + assertThat(((TestRestTemplateConfigurer) restTemplateConfigurerOne).getRestTemplate()) + .isEqualTo(this.theRestTemplate); + + assertThat(((TestRestTemplateConfigurer) restTemplateConfigurerTwo).getRestTemplate()) + .isEqualTo(this.theRestTemplate); + } + + @Test + public void assertUserDefinedCustomClientHttpRequestInterceptorsAreNotRegisteredByDefault() { + + assertThat(this.theRestTemplate.getInterceptors()) + .doesNotContain(this.mockClientHttpRequestInterceptorTwo, this.mockClientHttpRequestInterceptorOne); + + assertThat(this.theRestTemplate.getRequestFactory()) + .isNotInstanceOf(InterceptingClientHttpRequestFactory.class); + } + + @Test + public void configurationWasAutowiredWithUserDefinedClientHttpRequestInterceptors() { + + assertThat(this.configuration.resolveClientHttpRequestInterceptors(true)) + .isEqualTo(this.clientHttpRequestInterceptors); + } + + @Test + public void configurationWasAutowiredWithUserDefinedRestTemplateConfigurers() { + + assertThat(this.configuration.resolveRestTemplateConfigurers()) + .isEqualTo(this.restTemplateConfigurers); } @ClientCacheApplication @@ -186,5 +233,29 @@ public class ClusterConfigurationWithClientHttpRequestInterceptorsIntegrationTes ClientHttpRequestInterceptor mockClientHttpRequestInterceptorTwo() { return mock(ClientHttpRequestInterceptor.class); } + + @Bean + TestRestTemplateConfigurer testRestTemplateConfigurerOne() { + return new TestRestTemplateConfigurer(); + } + + @Bean + TestRestTemplateConfigurer testRestTemplateConfigurerTwo() { + return new TestRestTemplateConfigurer(); + } + } + + private static final class TestRestTemplateConfigurer implements RestTemplateConfigurer { + + private volatile RestTemplate restTemplate; + + RestTemplate getRestTemplate() { + return this.restTemplate; + } + + @Override + public void configure(RestTemplate restTemplate) { + this.restTemplate = restTemplate; + } } } diff --git a/src/test/java/org/springframework/data/gemfire/config/annotation/EnableClusterConfigurationUnitTests.java b/src/test/java/org/springframework/data/gemfire/config/annotation/EnableClusterConfigurationUnitTests.java index c2ed5ff8..f7ddf2a8 100644 --- a/src/test/java/org/springframework/data/gemfire/config/annotation/EnableClusterConfigurationUnitTests.java +++ b/src/test/java/org/springframework/data/gemfire/config/annotation/EnableClusterConfigurationUnitTests.java @@ -18,7 +18,6 @@ package org.springframework.data.gemfire.config.annotation; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; @@ -41,13 +40,13 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import org.junit.After; +import org.junit.Test; + import org.apache.geode.cache.Cache; import org.apache.geode.cache.RegionShortcut; import org.apache.geode.cache.client.ClientCache; -import org.junit.After; -import org.junit.Test; - import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.core.env.Environment; @@ -64,7 +63,7 @@ import org.springframework.util.ReflectionUtils; import org.springframework.web.client.RestTemplate; /** - * Unit tests for {@link EnableClusterConfiguration} annotation and the {@link ClusterConfigurationConfiguration} class. + * Unit Tests for {@link EnableClusterConfiguration} annotation and the {@link ClusterConfigurationConfiguration} class. * * @author John Blum * @see org.junit.Test @@ -88,6 +87,7 @@ public class EnableClusterConfigurationUnitTests { System.clearProperty(ClusterConfigurationConfiguration.HTTP_FOLLOW_REDIRECTS_PROPERTY); } + // TODO: Replace with STDG! private ClusterConfigurationConfiguration autowire(ClusterConfigurationConfiguration target, String fieldName, T dependency) throws NoSuchFieldException { @@ -130,6 +130,8 @@ public class EnableClusterConfigurationUnitTests { annotationAttributes.put("host", "skullbox"); annotationAttributes.put("port", 12345); + annotationAttributes.put("enableInterceptors", true); + annotationAttributes.put("followRedirects", true); annotationAttributes.put("requireHttps", false); annotationAttributes.put("serverRegionShortcut", RegionShortcut.PARTITION_PERSISTENT); annotationAttributes.put("useHttp", true); @@ -145,6 +147,8 @@ public class EnableClusterConfigurationUnitTests { assertThat(configuration.getManagementHttpHost().orElse(null)).isEqualTo("skullbox"); assertThat(configuration.getManagementHttpPort().orElse(0)).isEqualTo(12345); + assertThat(configuration.getManagementHttpEnableInterceptors().orElse(false)).isTrue(); + assertThat(configuration.getManagementHttpFollowRedirects().orElse(false)).isTrue(); assertThat(configuration.getManagementRequireHttps().orElse(true)).isFalse(); assertThat(configuration.getManagementUseHttp().orElse(false)).isTrue(); assertThat(configuration.getServerRegionShortcut().orElse(null)).isEqualTo(RegionShortcut.PARTITION_PERSISTENT); @@ -165,6 +169,8 @@ public class EnableClusterConfigurationUnitTests { annotationAttributes.put("host", "skullbox"); annotationAttributes.put("port", 12345); + annotationAttributes.put("enableInterceptors", false); + annotationAttributes.put("followRedirects", false); annotationAttributes.put("requireHttps", true); annotationAttributes.put("serverRegionShortcut", RegionShortcut.PARTITION_PERSISTENT); annotationAttributes.put("useHttp", false); @@ -179,6 +185,8 @@ public class EnableClusterConfigurationUnitTests { when(mockEnvironment.containsProperty(eq("spring.data.gemfire.cluster.region.type"))).thenReturn(true); when(mockEnvironment.containsProperty(eq("spring.data.gemfire.management.http.host"))).thenReturn(true); when(mockEnvironment.containsProperty(eq("spring.data.gemfire.management.http.port"))).thenReturn(true); + when(mockEnvironment.containsProperty(eq("spring.data.gemfire.management.http.enable-interceptors"))).thenReturn(true); + when(mockEnvironment.containsProperty(eq("spring.data.gemfire.management.http.follow-redirects"))).thenReturn(true); when(mockEnvironment.containsProperty(eq("spring.data.gemfire.management.require-https"))).thenReturn(true); when(mockEnvironment.containsProperty(eq("spring.data.gemfire.management.use-http"))).thenReturn(true); @@ -191,6 +199,12 @@ public class EnableClusterConfigurationUnitTests { when(mockEnvironment.getProperty(eq("spring.data.gemfire.management.http.port"), eq(Integer.class), any(Integer.class))) .thenReturn(11235); + when(mockEnvironment.getProperty(eq("spring.data.gemfire.management.http.enable-interceptors"), eq(Boolean.class), any(Boolean.class))) + .thenReturn(true); + + when(mockEnvironment.getProperty(eq("spring.data.gemfire.management.http.follow-redirects"), eq(Boolean.class), any(Boolean.class))) + .thenReturn(true); + when(mockEnvironment.getProperty(eq("spring.data.gemfire.management.require-https"), eq(Boolean.class), any(Boolean.class))) .thenReturn(false); @@ -207,6 +221,8 @@ public class EnableClusterConfigurationUnitTests { assertThat(configuration.getManagementHttpHost().orElse(null)).isEqualTo("cardboardBox"); assertThat(configuration.getManagementHttpPort().orElse(0)).isEqualTo(11235); + assertThat(configuration.getManagementHttpEnableInterceptors().orElse(false)).isTrue(); + assertThat(configuration.getManagementHttpFollowRedirects().orElse(false)).isTrue(); assertThat(configuration.getManagementRequireHttps().orElse(true)).isFalse(); assertThat(configuration.getManagementUseHttp().orElse(false)).isTrue(); assertThat(configuration.getServerRegionShortcut().orElse(null)).isEqualTo(RegionShortcut.LOCAL); @@ -226,6 +242,12 @@ public class EnableClusterConfigurationUnitTests { verify(mockEnvironment, times(1)) .containsProperty(eq("spring.data.gemfire.management.http.port")); + verify(mockEnvironment, times(1)) + .containsProperty(eq("spring.data.gemfire.management.http.enable-interceptors")); + + verify(mockEnvironment, times(1)) + .containsProperty(eq("spring.data.gemfire.management.http.follow-redirects")); + verify(mockEnvironment, times(1)) .containsProperty(eq("spring.data.gemfire.management.require-https")); @@ -237,10 +259,16 @@ public class EnableClusterConfigurationUnitTests { eq(RegionShortcut.PARTITION_PERSISTENT)); verify(mockEnvironment, times(1)) - .getProperty(eq("spring.data.gemfire.management.http.host"), eq(String.class), anyString()); + .getProperty(eq("spring.data.gemfire.management.http.host"), eq(String.class), eq("skullbox")); verify(mockEnvironment, times(1)) - .getProperty(eq("spring.data.gemfire.management.http.port"), eq(Integer.class), anyInt()); + .getProperty(eq("spring.data.gemfire.management.http.port"), eq(Integer.class), eq(12345)); + + verify(mockEnvironment, times(1)) + .getProperty(eq("spring.data.gemfire.management.http.enable-interceptors"), eq(Boolean.class), eq(false)); + + verify(mockEnvironment, times(1)) + .getProperty(eq("spring.data.gemfire.management.http.follow-redirects"), eq(Boolean.class), eq(false)); verify(mockEnvironment, times(1)) .getProperty(eq("spring.data.gemfire.management.require-https"), eq(Boolean.class), eq(true)); @@ -258,6 +286,8 @@ public class EnableClusterConfigurationUnitTests { annotationAttributes.put("host", "postOfficeBox"); annotationAttributes.put("port", 10101); + annotationAttributes.put("enableInterceptors", false); + annotationAttributes.put("followRedirects", false); annotationAttributes.put("requireHttps", false); annotationAttributes.put("serverRegionShortcut", RegionShortcut.REPLICATE); annotationAttributes.put("useHttp", true); @@ -272,9 +302,14 @@ public class EnableClusterConfigurationUnitTests { when(mockEnvironment.containsProperty(eq("spring.data.gemfire.cluster.region.type"))).thenReturn(false); when(mockEnvironment.containsProperty(eq("spring.data.gemfire.management.http.host"))).thenReturn(true); when(mockEnvironment.containsProperty(eq("spring.data.gemfire.management.http.port"))).thenReturn(true); + when(mockEnvironment.containsProperty(eq("spring.data.gemfire.management.http.enable-interceptors"))).thenReturn(false); + when(mockEnvironment.containsProperty(eq("spring.data.gemfire.management.http.follow-redirects"))).thenReturn(true); when(mockEnvironment.containsProperty(eq("spring.data.gemfire.management.require-https"))).thenReturn(false); when(mockEnvironment.containsProperty(eq("spring.data.gemfire.management.use-http"))).thenReturn(false); + when(mockEnvironment.getProperty(eq("spring.data.gemfire.management.http.follow-redirects"), eq(Boolean.class), any(Boolean.class))) + .thenReturn(true); + when(mockEnvironment.getProperty(eq("spring.data.gemfire.management.http.host"), eq(String.class), any(String.class))) .thenReturn("shoebox"); @@ -291,6 +326,8 @@ public class EnableClusterConfigurationUnitTests { assertThat(configuration.getManagementHttpHost().orElse(null)).isEqualTo("shoebox"); assertThat(configuration.getManagementHttpPort().orElse(0)).isEqualTo(12480); + assertThat(configuration.getManagementHttpEnableInterceptors().orElse(true)).isFalse(); + assertThat(configuration.getManagementHttpFollowRedirects().orElse(false)).isTrue(); assertThat(configuration.getManagementRequireHttps().orElse(true)).isFalse(); assertThat(configuration.getManagementUseHttp().orElse(false)).isTrue(); assertThat(configuration.getServerRegionShortcut().orElse(null)).isEqualTo(RegionShortcut.REPLICATE); @@ -321,10 +358,16 @@ public class EnableClusterConfigurationUnitTests { any(RegionShortcut.class)); verify(mockEnvironment, times(1)) - .getProperty(eq("spring.data.gemfire.management.http.host"), eq(String.class), anyString()); + .getProperty(eq("spring.data.gemfire.management.http.host"), eq(String.class), eq("postOfficeBox")); verify(mockEnvironment, times(1)) - .getProperty(eq("spring.data.gemfire.management.http.port"), eq(Integer.class), anyInt()); + .getProperty(eq("spring.data.gemfire.management.http.port"), eq(Integer.class), eq(10101)); + + verify(mockEnvironment, never()) + .getProperty(eq("spring.data.gemfire.management.http.enable-interceptors"), eq(Boolean.class), anyBoolean()); + + verify(mockEnvironment, times(1)) + .getProperty(eq("spring.data.gemfire.management.http.follow-redirects"), eq(Boolean.class), eq(false)); verify(mockEnvironment, never()) .getProperty(eq("spring.data.gemfire.management.require-https"), eq(Boolean.class), anyBoolean()); @@ -364,9 +407,10 @@ public class EnableClusterConfigurationUnitTests { assertThat(schemaObjectContext.getSchemaObjectCollector()).isInstanceOf(ComposableSchemaObjectCollector.class); assertThat(schemaObjectContext.getSchemaObjectDefiner()).isInstanceOf(ComposableSchemaObjectDefiner.class); - verify(configuration, never()).resolveClientHttpRequestInterceptors(); verify(configuration, times(1)) .resolveGemfireAdminOperations(eq(mockEnvironment), eq(mockClientCache)); + verify(configuration, never()).resolveClientHttpRequestInterceptors(anyBoolean()); + verify(configuration, never()).resolveRestTemplateConfigurers(); } @Test @@ -407,7 +451,8 @@ public class EnableClusterConfigurationUnitTests { configuration = autowire(configuration, "clientHttpRequestInterceptors", clientHttpRequestInterceptors); configuration.setBeanFactory(mockBeanFactory); - assertThat(configuration.resolveClientHttpRequestInterceptors()).isEqualTo(clientHttpRequestInterceptors); + assertThat(configuration.resolveClientHttpRequestInterceptors(true)) + .isEqualTo(clientHttpRequestInterceptors); verifyZeroInteractions(mockBeanFactory); } @@ -433,7 +478,7 @@ public class EnableClusterConfigurationUnitTests { configuration.setBeanFactory(mockBeanFactory); List actualClientHttpRequestInterceptors = - configuration.resolveClientHttpRequestInterceptors(); + configuration.resolveClientHttpRequestInterceptors(true); assertThat(actualClientHttpRequestInterceptors).isNotNull(); assertThat(actualClientHttpRequestInterceptors).hasSize(expectedClientHttpRequestInterceptors.size()); @@ -455,7 +500,7 @@ public class EnableClusterConfigurationUnitTests { configuration.setBeanFactory(mockBeanFactory); List clientHttpRequestInterceptors = - configuration.resolveClientHttpRequestInterceptors(); + configuration.resolveClientHttpRequestInterceptors(true); assertThat(clientHttpRequestInterceptors).isNotNull(); assertThat(clientHttpRequestInterceptors).isEmpty(); @@ -496,14 +541,15 @@ public class EnableClusterConfigurationUnitTests { ClientCache mockClientCache = mock(ClientCache.class); + ClusterConfigurationConfiguration configuration = spy(new ClusterConfigurationConfiguration()); + + doReturn(Collections.emptyList()).when(configuration).resolveClientHttpRequestInterceptors(anyBoolean()); + doReturn(Collections.emptyList()).when(configuration).resolveRestTemplateConfigurers(); + Environment mockEnvironment = mock(Environment.class); when(mockEnvironment.getProperty(anyString(), eq(Boolean.class), anyBoolean())).thenReturn(false); - ClusterConfigurationConfiguration configuration = spy(new ClusterConfigurationConfiguration()); - - doReturn(Collections.emptyList()).when(configuration).resolveClientHttpRequestInterceptors(); - configuration.setManagementUseHttp(true); assertThat(configuration.resolveManagementRequireHttps()).isTrue(); @@ -528,29 +574,26 @@ public class EnableClusterConfigurationUnitTests { assertThat(clientHttpRequestFactory.isFollowRedirects()).isFalse(); verifyZeroInteractions(mockClientCache); - - verify(configuration, times(1)).resolveClientHttpRequestInterceptors(); - - verify(mockEnvironment, times(1)) - .getProperty(eq(ClusterConfigurationConfiguration.HTTP_FOLLOW_REDIRECTS_PROPERTY), eq(Boolean.class), - eq(ClusterConfigurationConfiguration.DEFAULT_HTTP_FOLLOW_REDIRECTS)); + verify(configuration, times(1)).resolveClientHttpRequestInterceptors(eq(false)); + verify(configuration, times(1)).resolveRestTemplateConfigurers(); } @Test public void resolvesNewRestHttpGemfireAdminOperationsSetsFollowRedirectsWithProperty() throws Exception { - System.setProperty(ClusterConfigurationConfiguration.HTTP_FOLLOW_REDIRECTS_PROPERTY, Boolean.TRUE.toString()); - ClientCache mockClientCache = mock(ClientCache.class); - Environment environment = spy(new StandardEnvironment()); - ClusterConfigurationConfiguration configuration = spy(new ClusterConfigurationConfiguration()); - doReturn(Collections.emptyList()).when(configuration).resolveClientHttpRequestInterceptors(); + doReturn(Collections.emptyList()).when(configuration).resolveClientHttpRequestInterceptors(anyBoolean()); + doReturn(Collections.emptyList()).when(configuration).resolveRestTemplateConfigurers(); + Environment environment = spy(new StandardEnvironment()); + + configuration.setManagementHttpFollowRedirects(true); configuration.setManagementUseHttp(true); + assertThat(configuration.resolveManagementHttpFollowRedirects()).isTrue(); assertThat(configuration.resolveManagementRequireHttps()).isTrue(); assertThat(configuration.resolveManagementUseHttp()).isTrue(); @@ -572,12 +615,8 @@ public class EnableClusterConfigurationUnitTests { assertThat(clientHttpRequestFactory.isFollowRedirects()).isTrue(); verifyZeroInteractions(mockClientCache); - - verify(configuration, times(1)).resolveClientHttpRequestInterceptors(); - - verify(environment, times(1)) - .getProperty(eq(ClusterConfigurationConfiguration.HTTP_FOLLOW_REDIRECTS_PROPERTY), eq(Boolean.class), - eq(ClusterConfigurationConfiguration.DEFAULT_HTTP_FOLLOW_REDIRECTS)); + verify(configuration, times(1)).resolveClientHttpRequestInterceptors(eq(false)); + verify(configuration, times(1)).resolveRestTemplateConfigurers(); } @Test @@ -591,13 +630,16 @@ public class EnableClusterConfigurationUnitTests { ClientHttpRequestInterceptor mockInterceptorOne = mock(ClientHttpRequestInterceptor.class); ClientHttpRequestInterceptor mockInterceptorTwo = mock(ClientHttpRequestInterceptor.class); - Environment environment = spy(new StandardEnvironment()); - ClusterConfigurationConfiguration configuration = spy(new ClusterConfigurationConfiguration()); - doReturn(Arrays.asList(mockInterceptorOne, mockInterceptorTwo)) - .when(configuration).resolveClientHttpRequestInterceptors(); + Environment environment = spy(new StandardEnvironment()); + doReturn(Arrays.asList(mockInterceptorOne, mockInterceptorTwo)) + .when(configuration).resolveClientHttpRequestInterceptors(anyBoolean()); + + doReturn(Collections.emptyList()).when(configuration).resolveRestTemplateConfigurers(); + + configuration.setManagementHttpEnableInterceptors(true); configuration.setManagementRequireHttps(false); configuration.setManagementUseHttp(true); @@ -622,12 +664,8 @@ public class EnableClusterConfigurationUnitTests { assertThat(clientHttpRequestFactory.isFollowRedirects()).isTrue(); verifyZeroInteractions(mockClientCache); - - verify(configuration, times(1)).resolveClientHttpRequestInterceptors(); - - verify(environment, times(1)) - .getProperty(eq(ClusterConfigurationConfiguration.HTTP_FOLLOW_REDIRECTS_PROPERTY), eq(Boolean.class), - eq(ClusterConfigurationConfiguration.DEFAULT_HTTP_FOLLOW_REDIRECTS)); + verify(configuration, times(1)).resolveClientHttpRequestInterceptors(eq(true)); + verify(configuration, times(1)).resolveRestTemplateConfigurers(); } @Test @@ -635,14 +673,15 @@ public class EnableClusterConfigurationUnitTests { ClientCache mockClientCache = mock(ClientCache.class); + ClusterConfigurationConfiguration configuration = spy(new ClusterConfigurationConfiguration()); + + doReturn(Collections.emptyList()).when(configuration).resolveClientHttpRequestInterceptors(anyBoolean()); + doReturn(Collections.emptyList()).when(configuration).resolveRestTemplateConfigurers(); + Environment environment = mock(Environment.class); when(environment.getProperty(anyString(), eq(Boolean.class), anyBoolean())).thenReturn(false); - ClusterConfigurationConfiguration configuration = spy(new ClusterConfigurationConfiguration()); - - doReturn(Collections.emptyList()).when(configuration).resolveClientHttpRequestInterceptors(); - configuration.setManagementHttpHost("skullbox"); configuration.setManagementHttpPort(-1); configuration.setManagementUseHttp(true); @@ -661,11 +700,7 @@ public class EnableClusterConfigurationUnitTests { .isEqualTo("https://skullbox/gemfire/v1"); verifyZeroInteractions(mockClientCache); - - verify(configuration, times(1)).resolveClientHttpRequestInterceptors(); - - verify(environment, times(1)) - .getProperty(eq(ClusterConfigurationConfiguration.HTTP_FOLLOW_REDIRECTS_PROPERTY), eq(Boolean.class), - eq(ClusterConfigurationConfiguration.DEFAULT_HTTP_FOLLOW_REDIRECTS)); + verify(configuration, times(1)).resolveClientHttpRequestInterceptors(eq(false)); + verify(configuration, times(1)).resolveRestTemplateConfigurers(); } } diff --git a/src/test/java/org/springframework/data/gemfire/config/annotation/EnableClusterConfigurationWithSecurityIntegrationTests.java b/src/test/java/org/springframework/data/gemfire/config/annotation/EnableClusterConfigurationWithSecurityIntegrationTests.java index 9b2c5adb..060f024e 100644 --- a/src/test/java/org/springframework/data/gemfire/config/annotation/EnableClusterConfigurationWithSecurityIntegrationTests.java +++ b/src/test/java/org/springframework/data/gemfire/config/annotation/EnableClusterConfigurationWithSecurityIntegrationTests.java @@ -33,12 +33,12 @@ import java.net.URI; import java.util.Optional; import java.util.Properties; -import org.apache.geode.management.internal.security.ResourceConstants; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.apache.geode.management.internal.security.ResourceConstants; + import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -54,7 +54,6 @@ import org.springframework.data.gemfire.test.mock.annotation.EnableGemFireMockOb import org.springframework.http.HttpHeaders; import org.springframework.http.HttpRequest; import org.springframework.http.client.ClientHttpRequestExecution; -import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.http.client.InterceptingClientHttpRequestFactory; import org.springframework.lang.Nullable; import org.springframework.test.context.ContextConfiguration; @@ -95,16 +94,12 @@ public class EnableClusterConfigurationWithSecurityIntegrationTests { private Authenticator authenticator; @Autowired - @Qualifier("loggingAwareClientHttpRequestInterceptor") - private ClientHttpRequestInterceptor loggingAwareClientHttpRequestInterceptor; - - @Autowired - @Qualifier("securityAwareClientHttpRequestInterceptor") - private ClientHttpRequestInterceptor securityAwareClientHttpRequestInterceptor; + private AutoConfiguredAuthenticationConfiguration configuration; @Autowired private ClusterSchemaObjectInitializer initializer; + // TODO: Replace with STDG. @SuppressWarnings("unchecked") private T getFieldValue(Object target, String fieldName) throws NoSuchFieldException { @@ -123,11 +118,8 @@ public class EnableClusterConfigurationWithSecurityIntegrationTests { @Before public void setup() { - assertThat(this.authenticator).isNotNull(); assertThat(this.initializer).isNotNull(); - assertThat(this.loggingAwareClientHttpRequestInterceptor).isNotNull(); - assertThat(this.securityAwareClientHttpRequestInterceptor).isNotNull(); } @Test @@ -156,8 +148,7 @@ public class EnableClusterConfigurationWithSecurityIntegrationTests { RestTemplate restTemplate = getFieldValue(template, "restTemplate"); assertThat(restTemplate).isNotNull(); - assertThat(restTemplate.getInterceptors()).containsExactly(this.securityAwareClientHttpRequestInterceptor, - this.loggingAwareClientHttpRequestInterceptor); + assertThat(restTemplate.getInterceptors()).hasSize(2); assertThat(restTemplate.getRequestFactory()).isInstanceOf(InterceptingClientHttpRequestFactory.class); } @@ -178,7 +169,7 @@ public class EnableClusterConfigurationWithSecurityIntegrationTests { when(mockHttpRequest.getHeaders()).thenReturn(httpHeaders); when(mockHttpRequest.getURI()).thenReturn(uri); - this.securityAwareClientHttpRequestInterceptor.intercept(mockHttpRequest, body, mockClientHttpRequestExecution); + this.configuration.securityAwareClientHttpRequestInterceptor().intercept(mockHttpRequest, body, mockClientHttpRequestExecution); assertThat(httpHeaders).containsKeys(ResourceConstants.USER_NAME, ResourceConstants.PASSWORD); assertThat(httpHeaders.getFirst(ResourceConstants.USER_NAME)).isEqualTo("skeletor");