diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-metadata/src/main/java/org/springframework/boot/configurationmetadata/SimpleConfigurationMetadataRepository.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-metadata/src/main/java/org/springframework/boot/configurationmetadata/SimpleConfigurationMetadataRepository.java index 5becb4d6906d..1d9a2553495e 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-configuration-metadata/src/main/java/org/springframework/boot/configurationmetadata/SimpleConfigurationMetadataRepository.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-metadata/src/main/java/org/springframework/boot/configurationmetadata/SimpleConfigurationMetadataRepository.java @@ -117,4 +117,17 @@ private void putIfAbsent(Map map, String key, V value) { } } +/* +Uncomment this code to fix issue revealed by ConfigurationMetadataRepositoryJsonBuilderTests#severalRepositoriesIdenticalGroups3() + + private void putIfAbsent(Map sources, String name, + ConfigurationMetadataSource source) { + ConfigurationMetadataSource existing = sources.get(name); + if (existing == null) { + sources.put(name, source); + } else { + source.getProperties().forEach((k, v) -> putIfAbsent(existing.getProperties(), k, v)); + } + } +*/ } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-metadata/src/test/java/org/springframework/boot/configurationmetadata/ConfigurationMetadataRepositoryJsonBuilderTests.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-metadata/src/test/java/org/springframework/boot/configurationmetadata/ConfigurationMetadataRepositoryJsonBuilderTests.java index 0706b9036d17..b22da1be4708 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-configuration-metadata/src/test/java/org/springframework/boot/configurationmetadata/ConfigurationMetadataRepositoryJsonBuilderTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-metadata/src/test/java/org/springframework/boot/configurationmetadata/ConfigurationMetadataRepositoryJsonBuilderTests.java @@ -113,6 +113,102 @@ void severalRepositoriesIdenticalGroups() throws IOException { } } + + /* + * A rewrite of severalRepositoriesIdenticalGroups() using "containsOnlyKeys" to show actual vs. expected when assert fails. + */ + @Test + void severalRepositoriesIdenticalGroups_rewritten() throws IOException { + try (InputStream foo = getInputStreamFor("foo")) { + try (InputStream foo2 = getInputStreamFor("foo2")) { + ConfigurationMetadataRepository repo = ConfigurationMetadataRepositoryJsonBuilder.create(foo, foo2) + .build(); + + // assert all properties are found + assertThat(repo.getAllProperties()).containsOnlyKeys( + "spring.foo.name", + "spring.foo.description", + "spring.foo.counter", + "spring.foo.enabled", + "spring.foo.type"); + + // we have a single group containing all properties + assertThat(repo.getAllGroups()).containsOnlyKeys("spring.foo"); + + ConfigurationMetadataGroup group = repo.getAllGroups().get("spring.foo"); + assertThat(group.getProperties()).containsOnlyKeys( + "spring.foo.name", + "spring.foo.description", + "spring.foo.counter", + "spring.foo.enabled", + "spring.foo.type"); + + // the group contains 3 different sources + assertThat(group.getSources()).containsOnlyKeys( + "org.acme.Foo", "org.acme.Foo2", "org.springframework.boot.FooProperties"); + + assertThat(group.getSources().get("org.acme.Foo").getProperties()).containsOnlyKeys( + "spring.foo.name", + "spring.foo.description"); + + assertThat(group.getSources().get("org.acme.Foo2").getProperties()).containsOnlyKeys( + "spring.foo.enabled", + "spring.foo.type"); + + assertThat(group.getSources().get("org.springframework.boot.FooProperties").getProperties()).containsOnlyKeys( + "spring.foo.name", + "spring.foo.counter"); + } + } + } + + /* + * "foo3" contains the same properties as "foo2" except they refer to a group that already exists in + * "foo1" (same NAME, same TYPE). + * + * This test shows that the union of properties collected from the sources is less than what the group actually + * contains (some properties are missing). + */ + @Test + void severalRepositoriesIdenticalGroups3() throws IOException { + try (InputStream foo = getInputStreamFor("foo")) { + try (InputStream foo3 = getInputStreamFor("foo3")) { + ConfigurationMetadataRepository repo = ConfigurationMetadataRepositoryJsonBuilder.create(foo, foo3) + .build(); + + assertThat(repo.getAllProperties()).containsOnlyKeys( + "spring.foo.name", + "spring.foo.description", + "spring.foo.counter", + "spring.foo.enabled", + "spring.foo.type"); + + assertThat(repo.getAllGroups()).containsOnlyKeys("spring.foo"); + + ConfigurationMetadataGroup group = repo.getAllGroups().get("spring.foo"); + assertThat(group.getProperties()).containsOnlyKeys( + "spring.foo.name", + "spring.foo.description", + "spring.foo.counter", + "spring.foo.enabled", + "spring.foo.type"); + + + assertThat(group.getSources()).containsOnlyKeys("org.acme.Foo", "org.springframework.boot.FooProperties"); + assertThat(group.getSources().get("org.acme.Foo").getProperties()).containsOnlyKeys( + "spring.foo.name", + "spring.foo.description", + "spring.foo.enabled", // <-- missing although present in repo.getAllProperties() + "spring.foo.type"); // <-- missing although present in repo.getAllProperties() + + assertThat(group.getSources().get("org.springframework.boot.FooProperties").getProperties()).containsOnlyKeys( + "spring.foo.name", + "spring.foo.counter"); + } + } + } + + @Test void emptyGroups() throws IOException { try (InputStream in = getInputStreamFor("empty-groups")) { diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-metadata/src/test/resources/metadata/configuration-metadata-foo3.json b/spring-boot-project/spring-boot-tools/spring-boot-configuration-metadata/src/test/resources/metadata/configuration-metadata-foo3.json new file mode 100644 index 000000000000..417cf5d613ed --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-metadata/src/test/resources/metadata/configuration-metadata-foo3.json @@ -0,0 +1,23 @@ +{ + "groups": [ + { + "name": "spring.foo", + "type": "org.acme.Foo", + "sourceType": "org.acme.config.FooApp", + "sourceMethod": "foo2()", + "description": "This is Foo." + } + ], + "properties": [ + { + "name": "spring.foo.enabled", + "type": "java.lang.Boolean", + "sourceType": "org.acme.Foo" + }, + { + "name": "spring.foo.type", + "type": "java.lang.String", + "sourceType": "org.acme.Foo" + } + ] +} \ No newline at end of file