mirror of
https://gitee.com/dcren/initializr.git
synced 2026-01-09 18:04:49 +08:00
Do not fetch latest Spring Boot versions from spring.io by default
Closes gh-1082
This commit is contained in:
@@ -359,33 +359,40 @@ defaults can be overridden as shown below:
|
||||
|
||||
[[create-instance-boot-versions]]
|
||||
=== Configuring available Spring Boot versions
|
||||
If you look at https://projects.spring.io/spring-boot[the project home page for Spring
|
||||
Boot], the latest versions are displayed. And you've probably noticed that they match the
|
||||
drop down list that you automatically get with a default instance of Spring Initializr.
|
||||
The reason for that is that Spring Initializr calls an API on https://spring.io to
|
||||
retrieve the latest versions automatically. This makes sure that you always get the latest
|
||||
available versions.
|
||||
You can configure the available Spring Boot versions the same way you configure other
|
||||
capabilities.
|
||||
|
||||
[source,yaml,indent=0]
|
||||
----
|
||||
initializr:
|
||||
bootVersions:
|
||||
- id: 2.4.0-SNAPSHOT
|
||||
name: 2.4.0 (SNAPSHOT)
|
||||
default: false
|
||||
- id: 2.3.3.BUILD-SNAPSHOT
|
||||
name: 2.3.3 (SNAPSHOT)
|
||||
default: false
|
||||
- id: 2.3.2.RELEASE
|
||||
name: 2.3.2
|
||||
default: true
|
||||
----
|
||||
|
||||
The configuration above provides three versions, with `2.3.2` being used by default. In
|
||||
practice though, you may want to upgrade the available Spring Boot versions without having
|
||||
to redeploy the application every time. Implementing your own
|
||||
`InitializrMetadataUpdateStrategy` bean allows you to update the metadata at runtime.
|
||||
|
||||
If you look at https://spring.io/projects/spring-boot[the project home page for Spring
|
||||
Boot], the latest versions are displayed. `SaganInitializrMetadataUpdateStrategy` is an
|
||||
implementation of that strategy that fetches the latest Spring Boot versions and update
|
||||
the metadata to make sure a running instance always get the latest available versions.
|
||||
|
||||
If you are behind a proxy, or need to customize the `RestTemplate` that is used behind the
|
||||
scenes, you can define a `RestTemplateCustomizer` bean in your configuration. For more
|
||||
details, {spring-boot-reference}/#boot-features-restclient-customization[check the
|
||||
documentation].
|
||||
|
||||
If you don't want the version to be upgraded automatically, you need to override the
|
||||
`InitializrMetadataUpdateStrategy` bean to provide your own strategy when the metadata has
|
||||
to be refreshed. For instance, you could swap to an implementation that always returns the
|
||||
contents of static `application.yml`:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@Bean
|
||||
public InitializrMetadataUpdateStrategy initializrMetadataUpdateStrategy() {
|
||||
return (metadata) -> metadata;
|
||||
}
|
||||
----
|
||||
|
||||
The thing to remember is that, by default, you don't have to worry about upgrading your
|
||||
instance when a new Spring Boot version is released. However, you may need to
|
||||
NOTE: If you opt-in for `SaganInitializrMetadataUpdateStrategy`, you have to
|
||||
<<create-instance-advanced-config-caching,configure caching>> to avoid requesting that
|
||||
service too often.
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ import javax.cache.configuration.MutableConfiguration;
|
||||
import javax.cache.expiry.CreatedExpiryPolicy;
|
||||
import javax.cache.expiry.Duration;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.spring.initializr.generator.io.IndentingWriterFactory;
|
||||
import io.spring.initializr.generator.io.SimpleIndentStrategy;
|
||||
import io.spring.initializr.generator.io.template.MustacheTemplateRenderer;
|
||||
@@ -45,7 +44,6 @@ import io.spring.initializr.web.project.ProjectRequest;
|
||||
import io.spring.initializr.web.project.ProjectRequestPlatformVersionTransformer;
|
||||
import io.spring.initializr.web.support.DefaultDependencyMetadataProvider;
|
||||
import io.spring.initializr.web.support.DefaultInitializrMetadataProvider;
|
||||
import io.spring.initializr.web.support.DefaultInitializrMetadataUpdateStrategy;
|
||||
import io.spring.initializr.web.support.InitializrMetadataUpdateStrategy;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
@@ -58,7 +56,6 @@ import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.bind.Binder;
|
||||
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.support.NoOpCache;
|
||||
@@ -110,19 +107,13 @@ public class InitializrAutoConfiguration {
|
||||
return new NoOpCache("templates");
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public InitializrMetadataUpdateStrategy initializrMetadataUpdateStrategy(RestTemplateBuilder restTemplateBuilder,
|
||||
ObjectMapper objectMapper) {
|
||||
return new DefaultInitializrMetadataUpdateStrategy(restTemplateBuilder.build(), objectMapper);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(InitializrMetadataProvider.class)
|
||||
public InitializrMetadataProvider initializrMetadataProvider(InitializrProperties properties,
|
||||
InitializrMetadataUpdateStrategy initializrMetadataUpdateStrategy) {
|
||||
ObjectProvider<InitializrMetadataUpdateStrategy> initializrMetadataUpdateStrategy) {
|
||||
InitializrMetadata metadata = InitializrMetadataBuilder.fromInitializrProperties(properties).build();
|
||||
return new DefaultInitializrMetadataProvider(metadata, initializrMetadataUpdateStrategy);
|
||||
return new DefaultInitializrMetadataProvider(metadata,
|
||||
initializrMetadataUpdateStrategy.getIfAvailable(() -> (current) -> current));
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.spring.initializr.metadata.DefaultMetadataElement;
|
||||
import io.spring.initializr.metadata.InitializrConfiguration.Env;
|
||||
import io.spring.initializr.metadata.InitializrMetadata;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -28,20 +29,21 @@ 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.
|
||||
* A {@link InitializrMetadataUpdateStrategy} that refreshes the metadata with the latest
|
||||
* state of the Spring Boot project.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @see Env#getSpringBootMetadataUrl()
|
||||
*/
|
||||
public class DefaultInitializrMetadataUpdateStrategy implements InitializrMetadataUpdateStrategy {
|
||||
public class SaganInitializrMetadataUpdateStrategy implements InitializrMetadataUpdateStrategy {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(DefaultInitializrMetadataUpdateStrategy.class);
|
||||
private static final Log logger = LogFactory.getLog(SaganInitializrMetadataUpdateStrategy.class);
|
||||
|
||||
private final RestTemplate restTemplate;
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
public DefaultInitializrMetadataUpdateStrategy(RestTemplate restTemplate, ObjectMapper objectMapper) {
|
||||
public SaganInitializrMetadataUpdateStrategy(RestTemplate restTemplate, ObjectMapper objectMapper) {
|
||||
this.restTemplate = restTemplate;
|
||||
this.objectMapper = objectMapper;
|
||||
}
|
||||
@@ -37,7 +37,6 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.spring.initializr.generator.test.project.ProjectStructure;
|
||||
import io.spring.initializr.web.AbstractInitializrIntegrationTests.Config;
|
||||
import io.spring.initializr.web.mapper.InitializrMetadataVersion;
|
||||
import io.spring.initializr.web.support.InitializrMetadataUpdateStrategy;
|
||||
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
|
||||
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
|
||||
@@ -54,7 +53,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
@@ -366,12 +364,6 @@ public abstract class AbstractInitializrIntegrationTests {
|
||||
@EnableAutoConfiguration
|
||||
public static class Config {
|
||||
|
||||
// Disable metadata fetching from spring.io
|
||||
@Bean
|
||||
public InitializrMetadataUpdateStrategy initializrMetadataUpdateStrategy() {
|
||||
return (metadata) -> metadata;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private enum BitMaskFilePermission {
|
||||
|
||||
@@ -23,11 +23,10 @@ import io.spring.initializr.web.controller.CommandLineMetadataController;
|
||||
import io.spring.initializr.web.controller.ProjectGenerationController;
|
||||
import io.spring.initializr.web.controller.ProjectMetadataController;
|
||||
import io.spring.initializr.web.controller.SpringCliDistributionController;
|
||||
import io.spring.initializr.web.support.DefaultInitializrMetadataUpdateStrategy;
|
||||
import io.spring.initializr.web.support.DefaultInitializrMetadataProvider;
|
||||
import io.spring.initializr.web.support.InitializrMetadataUpdateStrategy;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizer;
|
||||
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
|
||||
@@ -35,11 +34,8 @@ import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfigu
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
||||
import org.springframework.boot.web.client.RestTemplateCustomizer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
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;
|
||||
@@ -55,7 +51,7 @@ class InitializrAutoConfigurationTests {
|
||||
private static final AutoConfigurations BASIC_AUTO_CONFIGURATIONS = AutoConfigurations
|
||||
.of(RestTemplateAutoConfiguration.class, JacksonAutoConfiguration.class, InitializrAutoConfiguration.class);
|
||||
|
||||
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(BASIC_AUTO_CONFIGURATIONS);
|
||||
|
||||
@Test
|
||||
@@ -72,26 +68,23 @@ 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
|
||||
void autoConfigRegistersInitializrMetadataProvider() {
|
||||
void metadataProviderWithNoMetadataUpdateStrategyRegistersDefault() {
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(InitializrMetadataProvider.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void autoConfigWhenInitializrMetadataProviderBeanPresentDoesNotRegisterInitializrMetadataProvider() {
|
||||
void metadataProviderWithCustomInitializrMetadataUpdateStrategyIsRegistered() {
|
||||
this.contextRunner.withUserConfiguration(CustomInitializrMetadataUpdateStrategyConfiguration.class)
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(DefaultInitializrMetadataProvider.class);
|
||||
assertThat(context.getBean(DefaultInitializrMetadataProvider.class)).hasFieldOrPropertyWithValue(
|
||||
"initializrMetadataUpdateStrategy",
|
||||
context.getBean("testInitializrMetadataUpdateStrategy"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void metadataProviderWithCustomInitializrMetadataProvider() {
|
||||
this.contextRunner.withUserConfiguration(CustomInitializrMetadataProviderConfiguration.class).run((context) -> {
|
||||
assertThat(context).hasSingleBean(InitializrMetadataProvider.class);
|
||||
assertThat(context).hasBean("testInitializrMetadataProvider");
|
||||
@@ -111,16 +104,6 @@ class InitializrAutoConfigurationTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void customRestTemplateBuilderIsUsed() {
|
||||
this.contextRunner.withUserConfiguration(CustomRestTemplateConfiguration.class).run((context) -> {
|
||||
assertThat(context).hasSingleBean(DefaultInitializrMetadataUpdateStrategy.class);
|
||||
RestTemplate restTemplate = (RestTemplate) new DirectFieldAccessor(
|
||||
context.getBean(DefaultInitializrMetadataUpdateStrategy.class)).getPropertyValue("restTemplate");
|
||||
assertThat(restTemplate.getErrorHandler()).isSameAs(CustomRestTemplateConfiguration.errorHandler);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void webConfiguration() {
|
||||
WebApplicationContextRunner webContextRunner = new WebApplicationContextRunner()
|
||||
@@ -167,18 +150,6 @@ class InitializrAutoConfigurationTests {
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(JCacheManagerCustomizer.class));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class CustomRestTemplateConfiguration {
|
||||
|
||||
private static final ResponseErrorHandler errorHandler = mock(ResponseErrorHandler.class);
|
||||
|
||||
@Bean
|
||||
RestTemplateCustomizer testRestTemplateCustomizer() {
|
||||
return (b) -> b.setErrorHandler(errorHandler);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class CustomTemplateRendererConfiguration {
|
||||
|
||||
|
||||
@@ -39,11 +39,11 @@ import static org.springframework.test.web.client.match.MockRestRequestMatchers.
|
||||
import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus;
|
||||
|
||||
/**
|
||||
* Tests for {@link DefaultInitializrMetadataUpdateStrategy}.
|
||||
* Tests for {@link SaganInitializrMetadataUpdateStrategy}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class DefaultInitializrMetadataUpdateStrategyTests {
|
||||
class SaganInitializrMetadataUpdateStrategyTests {
|
||||
|
||||
private static final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@@ -62,8 +62,8 @@ class DefaultInitializrMetadataUpdateStrategyTests {
|
||||
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);
|
||||
SaganInitializrMetadataUpdateStrategy provider = new SaganInitializrMetadataUpdateStrategy(this.restTemplate,
|
||||
objectMapper);
|
||||
expectJson(metadata.getConfiguration().getEnv().getSpringBootMetadataUrl(), "metadata/sagan/spring-boot.json");
|
||||
|
||||
InitializrMetadata updatedMetadata = provider.update(metadata);
|
||||
@@ -82,8 +82,8 @@ class DefaultInitializrMetadataUpdateStrategyTests {
|
||||
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);
|
||||
SaganInitializrMetadataUpdateStrategy provider = new SaganInitializrMetadataUpdateStrategy(this.restTemplate,
|
||||
objectMapper);
|
||||
expectJson(metadata.getConfiguration().getEnv().getSpringBootMetadataUrl(),
|
||||
"metadata/sagan/spring-boot-no-default.json");
|
||||
|
||||
Reference in New Issue
Block a user