From 564c524d3498e0c542109c84bebf3882c26cee02 Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Fri, 8 Mar 2024 13:40:16 +0100 Subject: [PATCH] Add support for customizable application properties Closes gh-1516 --- ...urationProjectGenerationConfiguration.java | 10 +-- .../ApplicationPropertiesContributor.java | 37 --------- .../properties/ApplicationProperties.java | 81 ++++++++++++++++++ .../ApplicationPropertiesContributor.java | 58 +++++++++++++ .../ApplicationPropertiesCustomizer.java | 33 ++++++++ ...pertiesProjectGenerationConfiguration.java | 44 ++++++++++ .../spring/properties/package-info.java | 20 +++++ .../main/resources/META-INF/spring.factories | 1 + .../configuration/application.properties | 1 - ...ApplicationPropertiesContributorTests.java | 23 ++++-- .../ApplicationPropertiesTests.java | 82 +++++++++++++++++++ 11 files changed, 338 insertions(+), 52 deletions(-) delete mode 100644 initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/configuration/ApplicationPropertiesContributor.java create mode 100644 initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/properties/ApplicationProperties.java create mode 100644 initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/properties/ApplicationPropertiesContributor.java create mode 100644 initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/properties/ApplicationPropertiesCustomizer.java create mode 100644 initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/properties/ApplicationPropertiesProjectGenerationConfiguration.java create mode 100644 initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/properties/package-info.java delete mode 100644 initializr-generator-spring/src/main/resources/configuration/application.properties rename initializr-generator-spring/src/test/java/io/spring/initializr/generator/spring/{configuration => properties}/ApplicationPropertiesContributorTests.java (57%) create mode 100644 initializr-generator-spring/src/test/java/io/spring/initializr/generator/spring/properties/ApplicationPropertiesTests.java diff --git a/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/configuration/ApplicationConfigurationProjectGenerationConfiguration.java b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/configuration/ApplicationConfigurationProjectGenerationConfiguration.java index 5fa5e55384..54a0c20cc4 100644 --- a/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/configuration/ApplicationConfigurationProjectGenerationConfiguration.java +++ b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/configuration/ApplicationConfigurationProjectGenerationConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2024 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. @@ -26,17 +26,13 @@ * Configuration for application-related contributions to a generated project. * * @author Stephane Nicoll + * @author Moritz Halbritter */ @ProjectGenerationConfiguration public class ApplicationConfigurationProjectGenerationConfiguration { @Bean - public ApplicationPropertiesContributor applicationPropertiesContributor() { - return new ApplicationPropertiesContributor(); - } - - @Bean - public WebFoldersContributor webFoldersContributor(Build build, InitializrMetadata metadata) { + WebFoldersContributor webFoldersContributor(Build build, InitializrMetadata metadata) { return new WebFoldersContributor(build, metadata); } diff --git a/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/configuration/ApplicationPropertiesContributor.java b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/configuration/ApplicationPropertiesContributor.java deleted file mode 100644 index f87e948566..0000000000 --- a/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/configuration/ApplicationPropertiesContributor.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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 - * - * 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 io.spring.initializr.generator.spring.configuration; - -import io.spring.initializr.generator.project.contributor.SingleResourceProjectContributor; - -/** - * A {@link SingleResourceProjectContributor} that contributes a - * {@code application.properties} file to a project. - * - * @author Stephane Nicoll - */ -public class ApplicationPropertiesContributor extends SingleResourceProjectContributor { - - public ApplicationPropertiesContributor() { - this("classpath:configuration/application.properties"); - } - - public ApplicationPropertiesContributor(String resourcePattern) { - super("src/main/resources/application.properties", resourcePattern); - } - -} diff --git a/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/properties/ApplicationProperties.java b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/properties/ApplicationProperties.java new file mode 100644 index 0000000000..8a79367f50 --- /dev/null +++ b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/properties/ApplicationProperties.java @@ -0,0 +1,81 @@ +/* + * Copyright 2012-2024 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 io.spring.initializr.generator.spring.properties; + +import java.io.PrintWriter; +import java.util.HashMap; +import java.util.Map; + +import org.springframework.util.Assert; + +/** + * Application properties. + * + * @author Moritz Halbritter + */ +public class ApplicationProperties { + + private final Map properties = new HashMap<>(); + + /** + * Adds a new property. + * @param key the key of the property + * @param value the value of the property + */ + public void add(String key, long value) { + add(key, (Object) value); + } + + /** + * Adds a new property. + * @param key the key of the property + * @param value the value of the property + */ + public void add(String key, boolean value) { + add(key, (Object) value); + } + + /** + * Adds a new property. + * @param key the key of the property + * @param value the value of the property + */ + public void add(String key, double value) { + add(key, (Object) value); + } + + /** + * Adds a new property. + * @param key the key of the property + * @param value the value of the property + */ + public void add(String key, String value) { + add(key, (Object) value); + } + + void writeTo(PrintWriter writer) { + for (Map.Entry entry : this.properties.entrySet()) { + writer.printf("%s=%s%n", entry.getKey(), entry.getValue()); + } + } + + private void add(String key, Object value) { + Assert.state(!this.properties.containsKey(key), () -> "Property '%s' already exists".formatted(key)); + this.properties.put(key, value); + } + +} diff --git a/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/properties/ApplicationPropertiesContributor.java b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/properties/ApplicationPropertiesContributor.java new file mode 100644 index 0000000000..290d4de1de --- /dev/null +++ b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/properties/ApplicationPropertiesContributor.java @@ -0,0 +1,58 @@ +/* + * Copyright 2012-2024 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 io.spring.initializr.generator.spring.properties; + +import java.io.IOException; +import java.io.PrintWriter; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; + +import io.spring.initializr.generator.project.contributor.ProjectContributor; + +/** + * A {@link ProjectContributor} that contributes a {@code application.properties} file to + * a project. + * + * @author Stephane Nicoll + * @author Moritz Halbritter + */ +public class ApplicationPropertiesContributor implements ProjectContributor { + + private static final String FILE = "src/main/resources/application.properties"; + + private final ApplicationProperties properties; + + public ApplicationPropertiesContributor(ApplicationProperties properties) { + this.properties = properties; + } + + @Override + public void contribute(Path projectRoot) throws IOException { + Path output = projectRoot.resolve(FILE); + if (!Files.exists(output)) { + Files.createDirectories(output.getParent()); + Files.createFile(output); + } + try (PrintWriter writer = new PrintWriter(Files.newOutputStream(output, StandardOpenOption.APPEND), false, + StandardCharsets.UTF_8)) { + this.properties.writeTo(writer); + } + } + +} diff --git a/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/properties/ApplicationPropertiesCustomizer.java b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/properties/ApplicationPropertiesCustomizer.java new file mode 100644 index 0000000000..4eafce92c6 --- /dev/null +++ b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/properties/ApplicationPropertiesCustomizer.java @@ -0,0 +1,33 @@ +/* + * Copyright 2012-2024 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 io.spring.initializr.generator.spring.properties; + +/** + * Callback for customizing a project's {@link ApplicationProperties}. + * + * @author Moritz Halbritter + */ +@FunctionalInterface +public interface ApplicationPropertiesCustomizer { + + /** + * Customizes the project's {@link ApplicationProperties}. + * @param properties the properties to customize + */ + void customize(ApplicationProperties properties); + +} diff --git a/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/properties/ApplicationPropertiesProjectGenerationConfiguration.java b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/properties/ApplicationPropertiesProjectGenerationConfiguration.java new file mode 100644 index 0000000000..e56a777252 --- /dev/null +++ b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/properties/ApplicationPropertiesProjectGenerationConfiguration.java @@ -0,0 +1,44 @@ +/* + * Copyright 2012-2024 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 io.spring.initializr.generator.spring.properties; + +import io.spring.initializr.generator.project.ProjectGenerationConfiguration; + +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.context.annotation.Bean; + +/** + * Configuration for application properties related contributions to a generated project. + * + * @author Moritz Halbritter + */ +@ProjectGenerationConfiguration +class ApplicationPropertiesProjectGenerationConfiguration { + + @Bean + ApplicationProperties applicationProperties(ObjectProvider customizers) { + ApplicationProperties properties = new ApplicationProperties(); + customizers.orderedStream().forEach((customizer) -> customizer.customize(properties)); + return properties; + } + + @Bean + ApplicationPropertiesContributor applicationPropertiesContributor(ApplicationProperties applicationProperties) { + return new ApplicationPropertiesContributor(applicationProperties); + } + +} diff --git a/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/properties/package-info.java b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/properties/package-info.java new file mode 100644 index 0000000000..b894115064 --- /dev/null +++ b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/properties/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-2024 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. + */ + +/** + * Support for application properties. + */ +package io.spring.initializr.generator.spring.properties; diff --git a/initializr-generator-spring/src/main/resources/META-INF/spring.factories b/initializr-generator-spring/src/main/resources/META-INF/spring.factories index 5641de4825..a1e4a4395e 100644 --- a/initializr-generator-spring/src/main/resources/META-INF/spring.factories +++ b/initializr-generator-spring/src/main/resources/META-INF/spring.factories @@ -8,4 +8,5 @@ io.spring.initializr.generator.spring.code.java.JavaProjectGenerationConfigurati io.spring.initializr.generator.spring.code.kotlin.KotlinProjectGenerationConfiguration,\ io.spring.initializr.generator.spring.configuration.ApplicationConfigurationProjectGenerationConfiguration,\ io.spring.initializr.generator.spring.documentation.HelpDocumentProjectGenerationConfiguration,\ +io.spring.initializr.generator.spring.properties.ApplicationPropertiesProjectGenerationConfiguration,\ io.spring.initializr.generator.spring.scm.git.GitProjectGenerationConfiguration diff --git a/initializr-generator-spring/src/main/resources/configuration/application.properties b/initializr-generator-spring/src/main/resources/configuration/application.properties deleted file mode 100644 index 8b13789179..0000000000 --- a/initializr-generator-spring/src/main/resources/configuration/application.properties +++ /dev/null @@ -1 +0,0 @@ - diff --git a/initializr-generator-spring/src/test/java/io/spring/initializr/generator/spring/configuration/ApplicationPropertiesContributorTests.java b/initializr-generator-spring/src/test/java/io/spring/initializr/generator/spring/properties/ApplicationPropertiesContributorTests.java similarity index 57% rename from initializr-generator-spring/src/test/java/io/spring/initializr/generator/spring/configuration/ApplicationPropertiesContributorTests.java rename to initializr-generator-spring/src/test/java/io/spring/initializr/generator/spring/properties/ApplicationPropertiesContributorTests.java index 2873857a6f..89664ccc24 100644 --- a/initializr-generator-spring/src/test/java/io/spring/initializr/generator/spring/configuration/ApplicationPropertiesContributorTests.java +++ b/initializr-generator-spring/src/test/java/io/spring/initializr/generator/spring/properties/ApplicationPropertiesContributorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -14,10 +14,9 @@ * limitations under the License. */ -package io.spring.initializr.generator.spring.configuration; +package io.spring.initializr.generator.spring.properties; import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Path; import io.spring.initializr.generator.test.project.ProjectStructure; @@ -30,6 +29,7 @@ * Tests for {@link ApplicationPropertiesContributor}. * * @author Stephane Nicoll + * @author Moritz Halbritter */ class ApplicationPropertiesContributorTests { @@ -38,11 +38,20 @@ class ApplicationPropertiesContributorTests { @Test void applicationConfigurationWithDefaultSettings() throws IOException { - Path projectDir = Files.createTempDirectory(this.directory, "project-"); - new ApplicationPropertiesContributor().contribute(projectDir); - assertThat(new ProjectStructure(projectDir)).textFile("src/main/resources/application.properties") - .lines() + new ApplicationPropertiesContributor(new ApplicationProperties()).contribute(this.directory); + assertThat(new ProjectStructure(this.directory)).textFile("src/main/resources/application.properties") .isEmpty(); } + @Test + void shouldAddStringProperty() throws IOException { + ApplicationProperties properties = new ApplicationProperties(); + properties.add("spring.application.name", "test"); + ApplicationPropertiesContributor contributor = new ApplicationPropertiesContributor(properties); + contributor.contribute(this.directory); + assertThat(new ProjectStructure(this.directory)).textFile("src/main/resources/application.properties") + .lines() + .contains("spring.application.name=test"); + } + } diff --git a/initializr-generator-spring/src/test/java/io/spring/initializr/generator/spring/properties/ApplicationPropertiesTests.java b/initializr-generator-spring/src/test/java/io/spring/initializr/generator/spring/properties/ApplicationPropertiesTests.java new file mode 100644 index 0000000000..c23d88785c --- /dev/null +++ b/initializr-generator-spring/src/test/java/io/spring/initializr/generator/spring/properties/ApplicationPropertiesTests.java @@ -0,0 +1,82 @@ +/* + * Copyright 2012-2024 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 io.spring.initializr.generator.spring.properties; + +import java.io.PrintWriter; +import java.io.StringWriter; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatIllegalStateException; + +/** + * Tests for {@link ApplicationProperties}. + * + * @author Moritz Halbritter + */ +class ApplicationPropertiesTests { + + @Test + void stringProperty() { + ApplicationProperties properties = new ApplicationProperties(); + properties.add("test", "string"); + String written = write(properties); + assertThat(written).isEqualToIgnoringNewLines("test=string"); + } + + @Test + void longProperty() { + ApplicationProperties properties = new ApplicationProperties(); + properties.add("test", 1); + String written = write(properties); + assertThat(written).isEqualToIgnoringNewLines("test=1"); + } + + @Test + void doubleProperty() { + ApplicationProperties properties = new ApplicationProperties(); + properties.add("test", 0.1); + String written = write(properties); + assertThat(written).isEqualToIgnoringNewLines("test=0.1"); + } + + @Test + void booleanProperty() { + ApplicationProperties properties = new ApplicationProperties(); + properties.add("test", false); + String written = write(properties); + assertThat(written).isEqualToIgnoringNewLines("test=false"); + } + + @Test + void shouldFailOnExistingProperty() { + ApplicationProperties properties = new ApplicationProperties(); + properties.add("test", 1); + assertThatIllegalStateException().isThrownBy(() -> properties.add("test", 2)) + .withMessage("Property 'test' already exists"); + } + + private String write(ApplicationProperties properties) { + StringWriter stringWriter = new StringWriter(); + try (PrintWriter writer = new PrintWriter(stringWriter)) { + properties.writeTo(writer); + } + return stringWriter.toString(); + } + +}