Allow to filter available Spring Boot versions

This commit adds a new InitializrMetadataUpdateStrategy callback
interface that can be used to customize what should happen when the
metadata has to be refreshed.

Closes gh-816
This commit is contained in:
Stephane Nicoll 2019-02-08 16:42:45 +01:00
parent fe4d05d1f6
commit cbb60c45e1
10 changed files with 324 additions and 164 deletions

View File

@ -124,18 +124,15 @@ details, {spring-boot-reference}/#boot-features-restclient-customization[check t
documentation]. documentation].
If you don't want the version to be upgraded automatically, you need to override the If you don't want the version to be upgraded automatically, you need to override the
`InitializrMetadataProvider` bean to provide your own metadata for the service. For `InitializrMetadataUpdateStrategy` bean to provide your own strategy when the metadata has
instance, you could swap to an implementation that always returns the contents of static to be refreshed. For instance, you could swap to an implementation that always returns the
`application.yml`: contents of static `application.yml`:
[source,java,indent=0] [source,java,indent=0]
---- ----
@Bean @Bean
public InitializrMetadataProvider initializrMetadataProvider( public InitializrMetadataUpdateStrategy initializrMetadataUpdateStrategy() {
InitializrProperties properties) { return (metadata) -> metadata;
InitializrMetadata metadata = InitializrMetadataBuilder
.fromInitializrProperties(properties).build();
return new SimpleInitializrMetadataProvider(metadata);
} }
---- ----

View File

@ -38,6 +38,8 @@ import io.spring.initializr.web.project.ProjectGenerationInvoker;
import io.spring.initializr.web.project.ProjectRequestToDescriptionConverter; import io.spring.initializr.web.project.ProjectRequestToDescriptionConverter;
import io.spring.initializr.web.support.DefaultDependencyMetadataProvider; import io.spring.initializr.web.support.DefaultDependencyMetadataProvider;
import io.spring.initializr.web.support.DefaultInitializrMetadataProvider; import io.spring.initializr.web.support.DefaultInitializrMetadataProvider;
import io.spring.initializr.web.support.DefaultInitializrMetadataUpdateStrategy;
import io.spring.initializr.web.support.InitializrMetadataUpdateStrategy;
import io.spring.initializr.web.ui.UiController; import io.spring.initializr.web.ui.UiController;
import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.ObjectProvider;
@ -106,15 +108,23 @@ public class InitializrAutoConfiguration {
return new NoOpCache("templates"); return new NoOpCache("templates");
} }
@Bean
@ConditionalOnMissingBean
public InitializrMetadataUpdateStrategy initializrMetadataUpdateStrategy(
RestTemplateBuilder restTemplateBuilder, ObjectMapper objectMapper) {
return new DefaultInitializrMetadataUpdateStrategy(restTemplateBuilder.build(),
objectMapper);
}
@Bean @Bean
@ConditionalOnMissingBean(InitializrMetadataProvider.class) @ConditionalOnMissingBean(InitializrMetadataProvider.class)
public InitializrMetadataProvider initializrMetadataProvider( public InitializrMetadataProvider initializrMetadataProvider(
InitializrProperties properties, ObjectMapper objectMapper, InitializrProperties properties,
RestTemplateBuilder restTemplateBuilder) { InitializrMetadataUpdateStrategy initializrMetadataUpdateStrategy) {
InitializrMetadata metadata = InitializrMetadataBuilder InitializrMetadata metadata = InitializrMetadataBuilder
.fromInitializrProperties(properties).build(); .fromInitializrProperties(properties).build();
return new DefaultInitializrMetadataProvider(metadata, objectMapper, return new DefaultInitializrMetadataProvider(metadata,
restTemplateBuilder.build()); initializrMetadataUpdateStrategy);
} }
@Bean @Bean

View File

@ -16,74 +16,35 @@
package io.spring.initializr.web.support; package io.spring.initializr.web.support;
import java.util.List;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.spring.initializr.metadata.DefaultMetadataElement;
import io.spring.initializr.metadata.InitializrMetadata; import io.spring.initializr.metadata.InitializrMetadata;
import io.spring.initializr.metadata.InitializrMetadataProvider; import io.spring.initializr.metadata.InitializrMetadataProvider;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Cacheable;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
/** /**
* A default {@link InitializrMetadataProvider} that is able to refresh the metadata with * A default {@link InitializrMetadataProvider} that caches the {@link InitializrMetadata
* the status of the main spring.io site. * metadata} and invokes a {@link InitializrMetadataUpdateStrategy} whenever the cache
* expires.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
*/ */
public class DefaultInitializrMetadataProvider implements InitializrMetadataProvider { public class DefaultInitializrMetadataProvider implements InitializrMetadataProvider {
private static final Log logger = LogFactory private InitializrMetadata metadata;
.getLog(DefaultInitializrMetadataProvider.class);
private final InitializrMetadata metadata; private final InitializrMetadataUpdateStrategy initializrMetadataUpdateStrategy;
private final ObjectMapper objectMapper;
private final RestTemplate restTemplate;
public DefaultInitializrMetadataProvider(InitializrMetadata metadata, public DefaultInitializrMetadataProvider(InitializrMetadata metadata,
ObjectMapper objectMapper, RestTemplate restTemplate) { InitializrMetadataUpdateStrategy initializrMetadataUpdateStrategy) {
this.metadata = metadata; this.metadata = metadata;
this.objectMapper = objectMapper; this.initializrMetadataUpdateStrategy = initializrMetadataUpdateStrategy;
this.restTemplate = restTemplate;
} }
@Override @Override
@Cacheable(value = "initializr.metadata", key = "'metadata'") @Cacheable(value = "initializr.metadata", key = "'metadata'")
public InitializrMetadata get() { public InitializrMetadata get() {
updateInitializrMetadata(this.metadata); this.metadata = this.initializrMetadataUpdateStrategy.update(this.metadata);
return this.metadata; return this.metadata;
} }
protected void updateInitializrMetadata(InitializrMetadata metadata) {
List<DefaultMetadataElement> bootVersions = fetchBootVersions();
if (bootVersions != null && !bootVersions.isEmpty()) {
if (bootVersions.stream().noneMatch(DefaultMetadataElement::isDefault)) {
// No default specified
bootVersions.get(0).setDefault(true);
}
metadata.updateSpringBootVersions(bootVersions);
}
}
protected List<DefaultMetadataElement> fetchBootVersions() {
String url = this.metadata.getConfiguration().getEnv().getSpringBootMetadataUrl();
if (StringUtils.hasText(url)) {
try {
logger.info("Fetching boot metadata from " + url);
return new SpringBootMetadataReader(this.objectMapper, this.restTemplate,
url).getBootVersions();
}
catch (Exception ex) {
logger.warn("Failed to fetch spring boot metadata", ex);
}
}
return null;
}
} }

View File

@ -0,0 +1,85 @@
/*
* Copyright 2012-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
*
* 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.web.support;
import java.util.List;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.spring.initializr.metadata.DefaultMetadataElement;
import io.spring.initializr.metadata.InitializrMetadata;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
/**
* A {@link InitializrMetadataUpdateStrategy} that refreshes the metadata with the status
* of the main spring.io site.
*
* @author Stephane Nicoll
*/
public class DefaultInitializrMetadataUpdateStrategy
implements InitializrMetadataUpdateStrategy {
private static final Log logger = LogFactory
.getLog(DefaultInitializrMetadataUpdateStrategy.class);
private final RestTemplate restTemplate;
private final ObjectMapper objectMapper;
public DefaultInitializrMetadataUpdateStrategy(RestTemplate restTemplate,
ObjectMapper objectMapper) {
this.restTemplate = restTemplate;
this.objectMapper = objectMapper;
}
@Override
public InitializrMetadata update(InitializrMetadata current) {
String url = current.getConfiguration().getEnv().getSpringBootMetadataUrl();
List<DefaultMetadataElement> bootVersions = fetchSpringBootVersions(url);
if (bootVersions != null && !bootVersions.isEmpty()) {
if (bootVersions.stream().noneMatch(DefaultMetadataElement::isDefault)) {
// No default specified
bootVersions.get(0).setDefault(true);
}
current.updateSpringBootVersions(bootVersions);
}
return current;
}
/**
* Fetch the available Spring Boot versions using the specified service url.
* @param url the url to the spring-boot project metadata
* @return the spring boot versions metadata.
*/
protected List<DefaultMetadataElement> fetchSpringBootVersions(String url) {
if (StringUtils.hasText(url)) {
try {
logger.info("Fetching Spring Boot metadata from " + url);
return new SpringBootMetadataReader(this.objectMapper, this.restTemplate,
url).getBootVersions();
}
catch (Exception ex) {
logger.warn("Failed to fetch Spring Boot metadata", ex);
}
}
return null;
}
}

View File

@ -0,0 +1,37 @@
/*
* Copyright 2012-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
*
* 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.web.support;
import io.spring.initializr.metadata.InitializrMetadata;
/**
* A strategy interface for updating the {@link InitializrMetadata metadata} on a running
* instance.
*
* @author Stephane Nicoll
*/
@FunctionalInterface
public interface InitializrMetadataUpdateStrategy {
/**
* Update the current {@link InitializrMetadata}.
* @param current the metadata to update
* @return the updated metadata, or {@code current} (never {@code null})
*/
InitializrMetadata update(InitializrMetadata current);
}

View File

@ -33,7 +33,7 @@ import org.springframework.web.client.RestTemplate;
* *
* @author Stephane Nicoll * @author Stephane Nicoll
*/ */
public class SpringBootMetadataReader { class SpringBootMetadataReader {
private final JsonNode content; private final JsonNode content;
@ -44,7 +44,7 @@ public class SpringBootMetadataReader {
* @param url the metadata URL * @param url the metadata URL
* @throws IOException on load error * @throws IOException on load error
*/ */
public SpringBootMetadataReader(ObjectMapper objectMapper, RestTemplate restTemplate, SpringBootMetadataReader(ObjectMapper objectMapper, RestTemplate restTemplate,
String url) throws IOException { String url) throws IOException {
this.content = objectMapper this.content = objectMapper
.readTree(restTemplate.getForObject(url, String.class)); .readTree(restTemplate.getForObject(url, String.class));

View File

@ -29,13 +29,9 @@ import java.util.List;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import io.spring.initializr.generator.spring.test.ProjectAssert; import io.spring.initializr.generator.spring.test.ProjectAssert;
import io.spring.initializr.metadata.InitializrMetadata;
import io.spring.initializr.metadata.InitializrMetadataBuilder;
import io.spring.initializr.metadata.InitializrMetadataProvider;
import io.spring.initializr.metadata.InitializrProperties;
import io.spring.initializr.web.AbstractInitializrIntegrationTests.Config; import io.spring.initializr.web.AbstractInitializrIntegrationTests.Config;
import io.spring.initializr.web.mapper.InitializrMetadataVersion; import io.spring.initializr.web.mapper.InitializrMetadataVersion;
import io.spring.initializr.web.support.DefaultInitializrMetadataProvider; import io.spring.initializr.web.support.InitializrMetadataUpdateStrategy;
import org.apache.tools.ant.Project; import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Expand; import org.apache.tools.ant.taskdefs.Expand;
import org.apache.tools.ant.taskdefs.Untar; import org.apache.tools.ant.taskdefs.Untar;
@ -294,17 +290,10 @@ public abstract class AbstractInitializrIntegrationTests {
@EnableAutoConfiguration @EnableAutoConfiguration
public static class Config { public static class Config {
// Disable metadata fetching from spring.io
@Bean @Bean
public InitializrMetadataProvider initializrMetadataProvider( public InitializrMetadataUpdateStrategy initializrMetadataUpdateStrategy() {
InitializrProperties properties) { return (metadata) -> metadata;
return new DefaultInitializrMetadataProvider(InitializrMetadataBuilder
.fromInitializrProperties(properties).build(), new ObjectMapper(),
new RestTemplate()) {
@Override
protected void updateInitializrMetadata(InitializrMetadata metadata) {
// Disable metadata fetching from spring.io
}
};
} }
} }

View File

@ -22,6 +22,8 @@ import io.spring.initializr.metadata.InitializrMetadataProvider;
import io.spring.initializr.web.project.MainController; import io.spring.initializr.web.project.MainController;
import io.spring.initializr.web.project.ProjectGenerationInvoker; import io.spring.initializr.web.project.ProjectGenerationInvoker;
import io.spring.initializr.web.project.ProjectRequestToDescriptionConverter; import io.spring.initializr.web.project.ProjectRequestToDescriptionConverter;
import io.spring.initializr.web.support.DefaultInitializrMetadataUpdateStrategy;
import io.spring.initializr.web.support.InitializrMetadataUpdateStrategy;
import io.spring.initializr.web.ui.UiController; import io.spring.initializr.web.ui.UiController;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.Mockito; import org.mockito.Mockito;
@ -73,6 +75,24 @@ class InitializrAutoConfigurationTests {
}); });
} }
@Test
void autoConfigRegistersInitializrMetadataUpdateStrategy() {
this.contextRunner.run((context) -> assertThat(context)
.hasSingleBean(InitializrMetadataUpdateStrategy.class));
}
@Test
void autoConfigWhenInitializrMetadataUpdateStrategyPresentDoesNotRegisterInitializrMetadataUpdateStrategy() {
this.contextRunner
.withUserConfiguration(
CustomInitializrMetadataUpdateStrategyConfiguration.class)
.run((context) -> {
assertThat(context)
.hasSingleBean(InitializrMetadataUpdateStrategy.class);
assertThat(context).hasBean("testInitializrMetadataUpdateStrategy");
});
}
@Test @Test
void autoConfigRegistersInitializrMetadataProvider() { void autoConfigRegistersInitializrMetadataProvider() {
this.contextRunner.run((context) -> assertThat(context) this.contextRunner.run((context) -> assertThat(context)
@ -111,10 +131,12 @@ class InitializrAutoConfigurationTests {
void customRestTemplateBuilderIsUsed() { void customRestTemplateBuilderIsUsed() {
this.contextRunner.withUserConfiguration(CustomRestTemplateConfiguration.class) this.contextRunner.withUserConfiguration(CustomRestTemplateConfiguration.class)
.run((context) -> { .run((context) -> {
assertThat(context).hasSingleBean(InitializrMetadataProvider.class); assertThat(context)
.hasSingleBean(DefaultInitializrMetadataUpdateStrategy.class);
RestTemplate restTemplate = (RestTemplate) new DirectFieldAccessor( RestTemplate restTemplate = (RestTemplate) new DirectFieldAccessor(
context.getBean(InitializrMetadataProvider.class)) context.getBean(
.getPropertyValue("restTemplate"); DefaultInitializrMetadataUpdateStrategy.class))
.getPropertyValue("restTemplate");
assertThat(restTemplate.getErrorHandler()) assertThat(restTemplate.getErrorHandler())
.isSameAs(CustomRestTemplateConfiguration.errorHandler); .isSameAs(CustomRestTemplateConfiguration.errorHandler);
}); });
@ -184,6 +206,16 @@ class InitializrAutoConfigurationTests {
} }
@Configuration
static class CustomInitializrMetadataUpdateStrategyConfiguration {
@Bean
public InitializrMetadataUpdateStrategy testInitializrMetadataUpdateStrategy() {
return Mockito.mock(InitializrMetadataUpdateStrategy.class);
}
}
@Configuration @Configuration
static class CustomInitializrMetadataProviderConfiguration { static class CustomInitializrMetadataProviderConfiguration {

View File

@ -16,103 +16,32 @@
package io.spring.initializr.web.support; package io.spring.initializr.web.support;
import java.util.List;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.spring.initializr.generator.spring.test.InitializrMetadataTestBuilder;
import io.spring.initializr.metadata.DefaultMetadataElement;
import io.spring.initializr.metadata.InitializrMetadata; import io.spring.initializr.metadata.InitializrMetadata;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.test.web.client.MockRestServiceServer;
import org.springframework.web.client.RestTemplate;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; import static org.mockito.Mockito.mock;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus; import static org.mockito.Mockito.verify;
/** /**
* Tests for {@link DefaultInitializrMetadataProvider}.
*
* @author Stephane Nicoll * @author Stephane Nicoll
*/ */
class DefaultInitializrMetadataProviderTests { class DefaultInitializrMetadataProviderTests {
private static final ObjectMapper objectMapper = new ObjectMapper();
private RestTemplate restTemplate;
private MockRestServiceServer mockServer;
@BeforeEach
public void setUp() {
this.restTemplate = new RestTemplate();
this.mockServer = MockRestServiceServer.createServer(this.restTemplate);
}
@Test @Test
void bootVersionsAreReplaced() { void strategyIsInvokedOnGet() {
InitializrMetadata metadata = new InitializrMetadataTestBuilder() InitializrMetadata metadata = mock(InitializrMetadata.class);
.addBootVersion("0.0.9.RELEASE", true) InitializrMetadata updatedMetadata = mock(InitializrMetadata.class);
.addBootVersion("0.0.8.RELEASE", false).build(); InitializrMetadataUpdateStrategy updateStrategy = mock(
assertThat(metadata.getBootVersions().getDefault().getId()) InitializrMetadataUpdateStrategy.class);
.isEqualTo("0.0.9.RELEASE"); given(updateStrategy.update(metadata)).willReturn(updatedMetadata);
DefaultInitializrMetadataProvider provider = new DefaultInitializrMetadataProvider( DefaultInitializrMetadataProvider provider = new DefaultInitializrMetadataProvider(
metadata, objectMapper, this.restTemplate); metadata, updateStrategy);
expectJson(metadata.getConfiguration().getEnv().getSpringBootMetadataUrl(), assertThat(provider.get()).isEqualTo(updatedMetadata);
"metadata/sagan/spring-boot.json"); verify(updateStrategy).update(metadata);
InitializrMetadata updatedMetadata = provider.get();
assertThat(updatedMetadata.getBootVersions()).isNotNull();
List<DefaultMetadataElement> updatedBootVersions = updatedMetadata
.getBootVersions().getContent();
assertThat(updatedBootVersions).hasSize(4);
assertBootVersion(updatedBootVersions.get(0), "1.4.1 (SNAPSHOT)", false);
assertBootVersion(updatedBootVersions.get(1), "1.4.0", true);
assertBootVersion(updatedBootVersions.get(2), "1.3.8 (SNAPSHOT)", false);
assertBootVersion(updatedBootVersions.get(3), "1.3.7", false);
}
@Test
void defaultBootVersionIsAlwaysSet() {
InitializrMetadata metadata = new InitializrMetadataTestBuilder()
.addBootVersion("0.0.9.RELEASE", true)
.addBootVersion("0.0.8.RELEASE", false).build();
assertThat(metadata.getBootVersions().getDefault().getId())
.isEqualTo("0.0.9.RELEASE");
DefaultInitializrMetadataProvider provider = new DefaultInitializrMetadataProvider(
metadata, objectMapper, this.restTemplate);
expectJson(metadata.getConfiguration().getEnv().getSpringBootMetadataUrl(),
"metadata/sagan/spring-boot-no-default.json");
InitializrMetadata updatedMetadata = provider.get();
assertThat(updatedMetadata.getBootVersions()).isNotNull();
List<DefaultMetadataElement> updatedBootVersions = updatedMetadata
.getBootVersions().getContent();
assertThat(updatedBootVersions).hasSize(4);
assertBootVersion(updatedBootVersions.get(0), "1.3.1 (SNAPSHOT)", true);
assertBootVersion(updatedBootVersions.get(1), "1.3.0", false);
assertBootVersion(updatedBootVersions.get(2), "1.2.6 (SNAPSHOT)", false);
assertBootVersion(updatedBootVersions.get(3), "1.2.5", false);
}
private static void assertBootVersion(DefaultMetadataElement actual, String name,
boolean defaultVersion) {
assertThat(actual.getName()).isEqualTo(name);
assertThat(actual.isDefault()).isEqualTo(defaultVersion);
}
private void expectJson(String url, String bodyPath) {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
this.mockServer.expect(requestTo(url)).andExpect(method(HttpMethod.GET))
.andRespond(withStatus(HttpStatus.OK)
.body(new ClassPathResource(bodyPath)).headers(httpHeaders));
} }
} }

View File

@ -0,0 +1,120 @@
/*
* Copyright 2012-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
*
* 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.web.support;
import java.util.List;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.spring.initializr.generator.spring.test.InitializrMetadataTestBuilder;
import io.spring.initializr.metadata.DefaultMetadataElement;
import io.spring.initializr.metadata.InitializrMetadata;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.test.web.client.MockRestServiceServer;
import org.springframework.web.client.RestTemplate;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus;
/**
* Tests for {@link DefaultInitializrMetadataUpdateStrategy}.
*
* @author Stephane Nicoll
*/
class DefaultInitializrMetadataUpdateStrategyTests {
private static final ObjectMapper objectMapper = new ObjectMapper();
private RestTemplate restTemplate;
private MockRestServiceServer mockServer;
@BeforeEach
public void setUp() {
this.restTemplate = new RestTemplate();
this.mockServer = MockRestServiceServer.createServer(this.restTemplate);
}
@Test
void bootVersionsAreReplaced() {
InitializrMetadata metadata = new InitializrMetadataTestBuilder()
.addBootVersion("0.0.9.RELEASE", true)
.addBootVersion("0.0.8.RELEASE", false).build();
assertThat(metadata.getBootVersions().getDefault().getId())
.isEqualTo("0.0.9.RELEASE");
DefaultInitializrMetadataUpdateStrategy provider = new DefaultInitializrMetadataUpdateStrategy(
this.restTemplate, objectMapper);
expectJson(metadata.getConfiguration().getEnv().getSpringBootMetadataUrl(),
"metadata/sagan/spring-boot.json");
InitializrMetadata updatedMetadata = provider.update(metadata);
assertThat(updatedMetadata.getBootVersions()).isNotNull();
List<DefaultMetadataElement> updatedBootVersions = updatedMetadata
.getBootVersions().getContent();
assertThat(updatedBootVersions).hasSize(4);
assertBootVersion(updatedBootVersions.get(0), "1.4.1 (SNAPSHOT)", false);
assertBootVersion(updatedBootVersions.get(1), "1.4.0", true);
assertBootVersion(updatedBootVersions.get(2), "1.3.8 (SNAPSHOT)", false);
assertBootVersion(updatedBootVersions.get(3), "1.3.7", false);
}
@Test
void defaultBootVersionIsAlwaysSet() {
InitializrMetadata metadata = new InitializrMetadataTestBuilder()
.addBootVersion("0.0.9.RELEASE", true)
.addBootVersion("0.0.8.RELEASE", false).build();
assertThat(metadata.getBootVersions().getDefault().getId())
.isEqualTo("0.0.9.RELEASE");
DefaultInitializrMetadataUpdateStrategy provider = new DefaultInitializrMetadataUpdateStrategy(
this.restTemplate, objectMapper);
expectJson(metadata.getConfiguration().getEnv().getSpringBootMetadataUrl(),
"metadata/sagan/spring-boot-no-default.json");
InitializrMetadata updatedMetadata = provider.update(metadata);
assertThat(updatedMetadata.getBootVersions()).isNotNull();
List<DefaultMetadataElement> updatedBootVersions = updatedMetadata
.getBootVersions().getContent();
assertThat(updatedBootVersions).hasSize(4);
assertBootVersion(updatedBootVersions.get(0), "1.3.1 (SNAPSHOT)", true);
assertBootVersion(updatedBootVersions.get(1), "1.3.0", false);
assertBootVersion(updatedBootVersions.get(2), "1.2.6 (SNAPSHOT)", false);
assertBootVersion(updatedBootVersions.get(3), "1.2.5", false);
}
private static void assertBootVersion(DefaultMetadataElement actual, String name,
boolean defaultVersion) {
assertThat(actual.getName()).isEqualTo(name);
assertThat(actual.isDefault()).isEqualTo(defaultVersion);
}
private void expectJson(String url, String bodyPath) {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
this.mockServer.expect(requestTo(url)).andExpect(method(HttpMethod.GET))
.andRespond(withStatus(HttpStatus.OK)
.body(new ClassPathResource(bodyPath)).headers(httpHeaders));
}
}