Allow for RestTemplate customization

This commit reuses the `RestTemplateBuilder` infrastructure wherever
a `RestTemplate` is required. This allows to customize the rest template
if necessary.

Closes gh-481
This commit is contained in:
Stephane Nicoll
2017-08-14 11:26:34 +02:00
parent 70d224b072
commit 1bf0d0fcde
7 changed files with 263 additions and 40 deletions

View File

@@ -23,9 +23,13 @@ import io.spring.initializr.actuate.stat.ProjectRequestDocumentFactory;
import io.spring.initializr.actuate.stat.StatsProperties;
import io.spring.initializr.metadata.InitializrMetadataProvider;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.retry.backoff.ExponentialBackOffPolicy;
@@ -41,6 +45,7 @@ import org.springframework.retry.support.RetryTemplate;
@Configuration
@EnableConfigurationProperties(StatsProperties.class)
@ConditionalOnProperty("initializr.stats.elastic.uri")
@AutoConfigureAfter(WebClientAutoConfiguration.class)
class InitializrStatsAutoConfiguration {
private final StatsProperties statsProperties;
@@ -50,11 +55,13 @@ class InitializrStatsAutoConfiguration {
}
@Bean
@ConditionalOnBean(InitializrMetadataProvider.class)
public ProjectGenerationStatPublisher projectRequestStatHandler(
InitializrMetadataProvider provider) {
InitializrMetadataProvider provider,
RestTemplateBuilder restTemplateBuilder) {
return new ProjectGenerationStatPublisher(
new ProjectRequestDocumentFactory(provider), statsProperties,
statsRetryTemplate());
restTemplateBuilder, statsRetryTemplate());
}
@Bean

View File

@@ -30,6 +30,7 @@ import org.springframework.http.RequestEntity;
import org.springframework.retry.RetryCallback;
import org.springframework.retry.support.RetryTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
/**
@@ -49,14 +50,20 @@ public class ProjectGenerationStatPublisher {
private final RetryTemplate retryTemplate;
public ProjectGenerationStatPublisher(ProjectRequestDocumentFactory documentFactory,
StatsProperties statsProperties, RetryTemplate retryTemplate) {
StatsProperties statsProperties, RestTemplateBuilder restTemplateBuilder,
RetryTemplate retryTemplate) {
this.documentFactory = documentFactory;
this.statsProperties = statsProperties;
this.objectMapper = createObjectMapper();
this.restTemplate = new RestTemplateBuilder()
.basicAuthorization(statsProperties.getElastic().getUsername(),
statsProperties.getElastic().getPassword())
.build();
StatsProperties.Elastic elastic = statsProperties.getElastic();
if (StringUtils.hasText(elastic.getUsername())) {
this.restTemplate = restTemplateBuilder
.basicAuthorization(elastic.getUsername(),
elastic.getPassword())
.build();
} else {
this.restTemplate = restTemplateBuilder.build();
}
this.retryTemplate = retryTemplate;
}

View File

@@ -0,0 +1,103 @@
/*
* Copyright 2012-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 io.spring.initializr.actuate.autoconfigure;
import io.spring.initializr.actuate.stat.ProjectGenerationStatPublisher;
import io.spring.initializr.metadata.InitializrMetadataProvider;
import io.spring.initializr.web.autoconfigure.InitializrAutoConfiguration;
import io.spring.initializr.web.autoconfigure.InitializrAutoConfigurationTests;
import org.junit.After;
import org.junit.Test;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.boot.web.client.RestTemplateCustomizer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestTemplate;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link InitializrStatsAutoConfiguration}.
*
* @author Stephane Nicoll
*/
public class InitializrStatsAutoConfigurationTests {
private ConfigurableApplicationContext context;
@After
public void close() {
if (this.context != null) {
this.context.close();
}
}
@Test
public void customRestTemplateBuilderIsUsed() {
load(CustomRestTemplateConfiguration.class,
"initializr.stats.elastic.uri=http://localhost:9200");
assertThat(this.context.getBeansOfType(ProjectGenerationStatPublisher.class))
.hasSize(1);
RestTemplate restTemplate = (RestTemplate) new DirectFieldAccessor(
this.context.getBean(ProjectGenerationStatPublisher.class))
.getPropertyValue("restTemplate");
assertThat(restTemplate.getErrorHandler()).isSameAs(
CustomRestTemplateConfiguration.errorHandler);
}
private void load(Class<?> config, String... environment) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(ctx, environment);
if (config != null) {
ctx.register(config);
}
ctx.register(WebClientAutoConfiguration.class,
InitializrStatsAutoConfiguration.class);
ctx.refresh();
this.context = ctx;
}
@Configuration
static class InfrastructureConfiguration {
@Bean
public InitializrMetadataProvider initializrMetadataProvider() {
return mock(InitializrMetadataProvider.class);
}
}
@Configuration
@Import(InfrastructureConfiguration.class)
static class CustomRestTemplateConfiguration {
private static final ResponseErrorHandler errorHandler = mock(ResponseErrorHandler.class);
@Bean
public RestTemplateCustomizer testRestTemplateCustomizer() {
return b -> b.setErrorHandler(errorHandler);
}
}
}

View File

@@ -25,6 +25,7 @@ import io.spring.initializr.generator.ProjectRequest;
import org.junit.Before;
import org.junit.Test;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
@@ -54,7 +55,7 @@ public class ProjectGenerationStatPublisherTests extends AbstractInitializrStatT
new ProjectRequestDocumentFactory(createProvider(getMetadata()));
this.retryTemplate = new RetryTemplate();
this.statPublisher = new ProjectGenerationStatPublisher(documentFactory,
properties, retryTemplate);
properties, new RestTemplateBuilder(), retryTemplate);
mockServer = MockRestServiceServer.createServer(
this.statPublisher.getRestTemplate());
}