From fd36215d7218f0df4f66069b6379dbdd406b2c5e Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Wed, 23 Feb 2022 14:38:03 +0100 Subject: [PATCH] Omit empty values for AutoConfigureAfter and AutoConfigureBefore As @AutoConfiguration is now meta-annotated with @AutoConfigureAfter and @AutoConfigureBefore, the generated property files have a lot of superfluous lines in the format .AutoConfigureAfter= and .AutoConfigureBefore=. One can now configure in the annotation processor for each property key if empty values should be omitted. This is currently only activated for AutoConfigureAfter and AutoConfigureBefore See gh-29907 --- .../AutoConfigurationSorterTests.java | 13 ++++++--- .../AutoConfigureAnnotationProcessor.java | 28 +++++++++++++++---- ...AutoConfigureAnnotationProcessorTests.java | 13 +++++++++ .../TestAutoConfigurationConfiguration.java | 2 +- ...estAutoConfigurationOnlyConfiguration.java | 27 ++++++++++++++++++ .../TestAutoConfigureAnnotationProcessor.java | 4 +-- ...tMergedAutoConfigurationConfiguration.java | 2 +- 7 files changed, 76 insertions(+), 13 deletions(-) create mode 100644 spring-boot-project/spring-boot-tools/spring-boot-autoconfigure-processor/src/test/java/org/springframework/boot/autoconfigureprocessor/TestAutoConfigurationOnlyConfiguration.java diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/AutoConfigurationSorterTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/AutoConfigurationSorterTests.java index aa60c03afb..fa0284ceb1 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/AutoConfigurationSorterTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/AutoConfigurationSorterTests.java @@ -223,8 +223,10 @@ class AutoConfigurationSorterTests { Map autoConfigureAfter = annotationMetadata .getAnnotationAttributes(AutoConfigureAfter.class.getName(), true); if (autoConfigureAfter != null) { - properties.put(className + ".AutoConfigureAfter", - merge((String[]) autoConfigureAfter.get("value"), (String[]) autoConfigureAfter.get("name"))); + String value = merge((String[]) autoConfigureAfter.get("value"), (String[]) autoConfigureAfter.get("name")); + if (!value.isEmpty()) { + properties.put(className + ".AutoConfigureAfter", value); + } } } @@ -233,8 +235,11 @@ class AutoConfigurationSorterTests { Map autoConfigureBefore = annotationMetadata .getAnnotationAttributes(AutoConfigureBefore.class.getName(), true); if (autoConfigureBefore != null) { - properties.put(className + ".AutoConfigureBefore", - merge((String[]) autoConfigureBefore.get("value"), (String[]) autoConfigureBefore.get("name"))); + String value = merge((String[]) autoConfigureBefore.get("value"), + (String[]) autoConfigureBefore.get("name")); + if (!value.isEmpty()) { + properties.put(className + ".AutoConfigureBefore", value); + } } } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-autoconfigure-processor/src/main/java/org/springframework/boot/autoconfigureprocessor/AutoConfigureAnnotationProcessor.java b/spring-boot-project/spring-boot-tools/spring-boot-autoconfigure-processor/src/main/java/org/springframework/boot/autoconfigureprocessor/AutoConfigureAnnotationProcessor.java index 467541a481..53f5b97cbd 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-autoconfigure-processor/src/main/java/org/springframework/boot/autoconfigureprocessor/AutoConfigureAnnotationProcessor.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-autoconfigure-processor/src/main/java/org/springframework/boot/autoconfigureprocessor/AutoConfigureAnnotationProcessor.java @@ -88,11 +88,11 @@ public class AutoConfigureAnnotationProcessor extends AbstractProcessor { generators.add(PropertyGenerator.of("ConditionalOnWebApplication", "org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication", ValueExtractor.allFrom("type"))); - generators.add(PropertyGenerator.of("AutoConfigureBefore", + generators.add(PropertyGenerator.of("AutoConfigureBefore", true, "org.springframework.boot.autoconfigure.AutoConfigureBefore", ValueExtractor.allFrom("value", "name"), "org.springframework.boot.autoconfigure.AutoConfiguration", ValueExtractor.allFrom("before", "beforeName"))); - generators.add(PropertyGenerator.of("AutoConfigureAfter", + generators.add(PropertyGenerator.of("AutoConfigureAfter", true, "org.springframework.boot.autoconfigure.AutoConfigureAfter", ValueExtractor.allFrom("value", "name"), "org.springframework.boot.autoconfigure.AutoConfiguration", ValueExtractor.allFrom("after", "afterName"))); @@ -284,13 +284,17 @@ public class AutoConfigureAnnotationProcessor extends AbstractProcessor { private final String keyName; + private final boolean omitEmptyValues; + /** * Maps from annotation class name -> {@link ValueExtractor}. */ private final Map valueExtractors; - private PropertyGenerator(String keyName, Map valueExtractors) { + private PropertyGenerator(String keyName, boolean omitEmptyValues, + Map valueExtractors) { this.keyName = keyName; + this.omitEmptyValues = omitEmptyValues; this.valueExtractors = valueExtractors; } @@ -303,6 +307,9 @@ public class AutoConfigureAnnotationProcessor extends AbstractProcessor { } void applyToProperties(Map properties, String className, List annotationValues) { + if (this.omitEmptyValues && annotationValues.isEmpty()) { + return; + } mergeProperties(properties, className + "." + this.keyName, toCommaDelimitedString(annotationValues)); } @@ -329,15 +336,26 @@ public class AutoConfigureAnnotationProcessor extends AbstractProcessor { } static PropertyGenerator of(String keyName, String annotation, ValueExtractor valueExtractor) { - return new PropertyGenerator(keyName, Collections.singletonMap(annotation, valueExtractor)); + return of(keyName, false, annotation, valueExtractor); + } + + static PropertyGenerator of(String keyName, boolean omitEmptyValues, String annotation, + ValueExtractor valueExtractor) { + return new PropertyGenerator(keyName, omitEmptyValues, + Collections.singletonMap(annotation, valueExtractor)); } static PropertyGenerator of(String keyName, String annotation1, ValueExtractor valueExtractor1, String annotation2, ValueExtractor valueExtractor2) { + return of(keyName, false, annotation1, valueExtractor1, annotation2, valueExtractor2); + } + + static PropertyGenerator of(String keyName, boolean omitEmptyValues, String annotation1, + ValueExtractor valueExtractor1, String annotation2, ValueExtractor valueExtractor2) { Map valueExtractors = new LinkedHashMap<>(); valueExtractors.put(annotation1, valueExtractor1); valueExtractors.put(annotation2, valueExtractor2); - return new PropertyGenerator(keyName, valueExtractors); + return new PropertyGenerator(keyName, omitEmptyValues, valueExtractors); } } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-autoconfigure-processor/src/test/java/org/springframework/boot/autoconfigureprocessor/AutoConfigureAnnotationProcessorTests.java b/spring-boot-project/spring-boot-tools/spring-boot-autoconfigure-processor/src/test/java/org/springframework/boot/autoconfigureprocessor/AutoConfigureAnnotationProcessorTests.java index 8eb8b9e2a3..593bf2bbb1 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-autoconfigure-processor/src/test/java/org/springframework/boot/autoconfigureprocessor/AutoConfigureAnnotationProcessorTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-autoconfigure-processor/src/test/java/org/springframework/boot/autoconfigureprocessor/AutoConfigureAnnotationProcessorTests.java @@ -67,6 +67,19 @@ class AutoConfigureAnnotationProcessorTests { + "TestClassConfiguration.ConditionalOnWebApplication", "SERVLET"); } + @Test + void annotatedClassWithOnlyAutoConfiguration() throws Exception { + Properties properties = compile(TestAutoConfigurationOnlyConfiguration.class); + assertThat(properties).containsEntry( + "org.springframework.boot.autoconfigureprocessor.TestAutoConfigurationOnlyConfiguration", ""); + assertThat(properties).doesNotContainEntry( + "org.springframework.boot.autoconfigureprocessor.TestAutoConfigurationOnlyConfiguration.AutoConfigureAfter", + ""); + assertThat(properties).doesNotContainEntry( + "org.springframework.boot.autoconfigureprocessor.TestAutoConfigurationOnlyConfiguration.AutoConfigureBefore", + ""); + } + @Test void annotatedClassWithOnBeanThatHasName() throws Exception { Properties properties = compile(TestOnBeanWithNameClassConfiguration.class); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-autoconfigure-processor/src/test/java/org/springframework/boot/autoconfigureprocessor/TestAutoConfigurationConfiguration.java b/spring-boot-project/spring-boot-tools/spring-boot-autoconfigure-processor/src/test/java/org/springframework/boot/autoconfigureprocessor/TestAutoConfigurationConfiguration.java index b1405ff3f6..76a57b6a11 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-autoconfigure-processor/src/test/java/org/springframework/boot/autoconfigureprocessor/TestAutoConfigurationConfiguration.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-autoconfigure-processor/src/test/java/org/springframework/boot/autoconfigureprocessor/TestAutoConfigurationConfiguration.java @@ -26,6 +26,6 @@ import java.io.OutputStream; */ @TestAutoConfiguration(before = InputStream.class, beforeName = { "test.before1", "test.before2" }, after = OutputStream.class, afterName = { "test.after1", "test.after2" }) -public class TestAutoConfigurationConfiguration { +class TestAutoConfigurationConfiguration { } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-autoconfigure-processor/src/test/java/org/springframework/boot/autoconfigureprocessor/TestAutoConfigurationOnlyConfiguration.java b/spring-boot-project/spring-boot-tools/spring-boot-autoconfigure-processor/src/test/java/org/springframework/boot/autoconfigureprocessor/TestAutoConfigurationOnlyConfiguration.java new file mode 100644 index 0000000000..9faeb61fe9 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-autoconfigure-processor/src/test/java/org/springframework/boot/autoconfigureprocessor/TestAutoConfigurationOnlyConfiguration.java @@ -0,0 +1,27 @@ +/* + * Copyright 2012-2022 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.boot.autoconfigureprocessor; + +/** + * Tests a plain {@code @AutoConfiguration} annotated class. + * + * @author Moritz Halbritter + */ +@TestAutoConfiguration +class TestAutoConfigurationOnlyConfiguration { + +} diff --git a/spring-boot-project/spring-boot-tools/spring-boot-autoconfigure-processor/src/test/java/org/springframework/boot/autoconfigureprocessor/TestAutoConfigureAnnotationProcessor.java b/spring-boot-project/spring-boot-tools/spring-boot-autoconfigure-processor/src/test/java/org/springframework/boot/autoconfigureprocessor/TestAutoConfigureAnnotationProcessor.java index 7bf679ef4e..cd1314922c 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-autoconfigure-processor/src/test/java/org/springframework/boot/autoconfigureprocessor/TestAutoConfigureAnnotationProcessor.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-autoconfigure-processor/src/test/java/org/springframework/boot/autoconfigureprocessor/TestAutoConfigureAnnotationProcessor.java @@ -57,10 +57,10 @@ public class TestAutoConfigureAnnotationProcessor extends AutoConfigureAnnotatio TestConditionalOnSingleCandidate.class.getName(), new OnBeanConditionValueExtractor())); generators.add(PropertyGenerator.of("ConditionalOnWebApplication", TestConditionalOnWebApplication.class.getName(), ValueExtractor.allFrom("type"))); - generators.add(PropertyGenerator.of("AutoConfigureBefore", TestAutoConfigureBefore.class.getName(), + generators.add(PropertyGenerator.of("AutoConfigureBefore", true, TestAutoConfigureBefore.class.getName(), ValueExtractor.allFrom("value", "name"), TestAutoConfiguration.class.getName(), ValueExtractor.allFrom("before", "beforeName"))); - generators.add(PropertyGenerator.of("AutoConfigureAfter", TestAutoConfigureAfter.class.getName(), + generators.add(PropertyGenerator.of("AutoConfigureAfter", true, TestAutoConfigureAfter.class.getName(), ValueExtractor.allFrom("value", "name"), TestAutoConfiguration.class.getName(), ValueExtractor.allFrom("after", "afterName"))); generators.add(PropertyGenerator.of("AutoConfigureOrder", TestAutoConfigureOrder.class.getName(), diff --git a/spring-boot-project/spring-boot-tools/spring-boot-autoconfigure-processor/src/test/java/org/springframework/boot/autoconfigureprocessor/TestMergedAutoConfigurationConfiguration.java b/spring-boot-project/spring-boot-tools/spring-boot-autoconfigure-processor/src/test/java/org/springframework/boot/autoconfigureprocessor/TestMergedAutoConfigurationConfiguration.java index fe5a018800..d5ab4ee577 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-autoconfigure-processor/src/test/java/org/springframework/boot/autoconfigureprocessor/TestMergedAutoConfigurationConfiguration.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-autoconfigure-processor/src/test/java/org/springframework/boot/autoconfigureprocessor/TestMergedAutoConfigurationConfiguration.java @@ -31,6 +31,6 @@ import java.io.OutputStream; @TestAutoConfigureAfter(value = OutputStream.class, name = { "test.after1", "test.after2" }) @TestAutoConfiguration(before = ObjectInputStream.class, beforeName = { "test.before3", "test.before4" }, after = ObjectOutputStream.class, afterName = { "test.after3", "test.after4" }) -public class TestMergedAutoConfigurationConfiguration { +class TestMergedAutoConfigurationConfiguration { }