Hi,

the new support for prefixes in property sources added by a8592f36d425fa6b9faff59a45e1936e87b2ec9d has broken the tests, I think.

In case no prefix is specified, the PrefixedIterableConfigurationPropertySource actually filtered a bit too much, because isAncestorOf should be true in all those cases.

The alternative would be to check for the empty prefix when the property source is created in the first place, but the check inside the actual source felt a little safer for eventual callers outside the Spring-Boot source code itself. But I can change that if you'd like me to.

Cheers, Christoph

Comment From: wilkinsona

Thanks, @dreis2211. The changes in https://github.com/spring-projects/spring-boot/commit/a8592f36d425fa6b9faff59a45e1936e87b2ec9d build cleanly for me. Can you share a bit more about the failures that you were seeing please?

Comment From: dreis2211

See https://ci.spring.io/builds/146826 for example. Same locally. Your build scan seems to have skipped those - maybe Docker not being up?

Comment From: wilkinsona

Thanks. I'd assumed those were just Docker being unstable on CI as it is from time-to-time. I'll run them locally.

Comment From: dreis2211

Funny enough I was working on them to improve things a little and was wondering why they failed all of a sudden only to notice that things have been failing since the mentioned commit.

Comment From: wilkinsona

Interestingly, the deployment tests only seem to fail on Liberty. I can't explain why that's the case at the moment. This is the failure:

09:58:15.502 [Default Executor-thread-16] DEBUG org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter - Application failed to start due to an exception
org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'spring.config.name' to java.lang.String[]
    at org.springframework.boot.context.properties.bind.Binder.handleBindError(Binder.java:364)
    at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:324)
    at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:309)
    at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:239)
    at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:200)
    at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:187)
    at org.springframework.boot.context.config.StandardConfigDataLocationResolver.getConfigNames(StandardConfigDataLocationResolver.java:91)
    at org.springframework.boot.context.config.StandardConfigDataLocationResolver.<init>(StandardConfigDataLocationResolver.java:86)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at org.springframework.boot.util.Instantiator.instantiate(Instantiator.java:115)
    at org.springframework.boot.util.Instantiator.instantiate(Instantiator.java:100)
    at org.springframework.boot.util.Instantiator.instantiate(Instantiator.java:90)
    at org.springframework.boot.context.config.ConfigDataLocationResolvers.<init>(ConfigDataLocationResolvers.java:80)
    at org.springframework.boot.context.config.ConfigDataLocationResolvers.<init>(ConfigDataLocationResolvers.java:56)
    at org.springframework.boot.context.config.ConfigDataEnvironment.createConfigDataLocationResolvers(ConfigDataEnvironment.java:161)
    at org.springframework.boot.context.config.ConfigDataEnvironment.<init>(ConfigDataEnvironment.java:151)
    at org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor.getConfigDataEnvironment(ConfigDataEnvironmentPostProcessor.java:108)
    at org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor.postProcessEnvironment(ConfigDataEnvironmentPostProcessor.java:97)
    at org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor.postProcessEnvironment(ConfigDataEnvironmentPostProcessor.java:89)
    at org.springframework.boot.env.EnvironmentPostProcessorApplicationListener.onApplicationEnvironmentPreparedEvent(EnvironmentPostProcessorApplicationListener.java:100)
    at org.springframework.boot.env.EnvironmentPostProcessorApplicationListener.onApplicationEvent(EnvironmentPostProcessorApplicationListener.java:86)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:131)
    at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:82)
    at org.springframework.boot.SpringApplicationRunListeners.lambda$environmentPrepared$2(SpringApplicationRunListeners.java:63)
    at org.springframework.boot.SpringApplicationRunListeners$$Lambda$40/0000000078191920.accept(Unknown Source)
    at java.util.ArrayList.forEach(ArrayList.java:1259)
    at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:117)
    at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:111)
    at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:62)
    at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:364)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:322)
    at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:173)
    at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:153)
    at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:95)
    at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:174)
    at com.ibm.ws.webcontainer.webapp.WebApp.initializeServletContainerInitializers(WebApp.java:2546)
    at com.ibm.ws.webcontainer.webapp.WebApp.initialize(WebApp.java:1027)
    at com.ibm.ws.webcontainer.webapp.WebApp.initialize(WebApp.java:6663)
    at com.ibm.ws.webcontainer.osgi.DynamicVirtualHost.startWebApp(DynamicVirtualHost.java:470)
    at com.ibm.ws.webcontainer.osgi.DynamicVirtualHost.startWebApplication(DynamicVirtualHost.java:465)
    at com.ibm.ws.webcontainer.osgi.WebContainer.startWebApplication(WebContainer.java:1178)
    at com.ibm.ws.webcontainer.osgi.WebContainer.access$100(WebContainer.java:109)
    at com.ibm.ws.webcontainer.osgi.WebContainer$3.run(WebContainer.java:975)
    at com.ibm.ws.threading.internal.ExecutorServiceImpl$RunnableWrapper.run(ExecutorServiceImpl.java:239)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:823)
Caused by: org.springframework.boot.context.properties.source.InvalidConfigurationPropertyNameException: Configuration property name '.log.file' is not valid
    at org.springframework.boot.context.properties.source.ConfigurationPropertyName.elementsOf(ConfigurationPropertyName.java:569)
    at org.springframework.boot.context.properties.source.ConfigurationPropertyName.elementsOf(ConfigurationPropertyName.java:554)
    at org.springframework.boot.context.properties.source.ConfigurationPropertyName.of(ConfigurationPropertyName.java:545)
    at org.springframework.boot.context.properties.source.ConfigurationPropertyName.of(ConfigurationPropertyName.java:522)
    at org.springframework.boot.context.properties.source.PrefixedIterableConfigurationPropertySource.lambda$stream$0(PrefixedIterableConfigurationPropertySource.java:39)
    at org.springframework.boot.context.properties.source.PrefixedIterableConfigurationPropertySource$$Lambda$82/000000007811FB70.apply(Unknown Source)
    at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
    at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
    at java.util.Spliterators$ArraySpliterator.tryAdvance(Spliterators.java:958)
    at java.util.stream.StreamSpliterators$WrappingSpliterator.lambda$initPartialTraversalState$0(StreamSpliterators.java:295)
    at java.util.stream.StreamSpliterators$WrappingSpliterator$$Lambda$80/000000007811DF30.getAsBoolean(Unknown Source)
    at java.util.stream.StreamSpliterators$AbstractWrappingSpliterator.fillBuffer(StreamSpliterators.java:207)
    at java.util.stream.StreamSpliterators$AbstractWrappingSpliterator.doAdvance(StreamSpliterators.java:162)
    at java.util.stream.StreamSpliterators$WrappingSpliterator.tryAdvance(StreamSpliterators.java:301)
    at java.util.Spliterators$1Adapter.hasNext(Spliterators.java:681)
    at org.springframework.boot.context.properties.bind.IndexedElementsBinder.getKnownIndexedChildren(IndexedElementsBinder.java:122)
    at org.springframework.boot.context.properties.bind.IndexedElementsBinder.bindIndexed(IndexedElementsBinder.java:103)
    at org.springframework.boot.context.properties.bind.IndexedElementsBinder.bindIndexed(IndexedElementsBinder.java:86)
    at org.springframework.boot.context.properties.bind.IndexedElementsBinder.bindIndexed(IndexedElementsBinder.java:70)
    at org.springframework.boot.context.properties.bind.ArrayBinder.bindAggregate(ArrayBinder.java:46)
    at org.springframework.boot.context.properties.bind.AggregateBinder.bind(AggregateBinder.java:56)
    at org.springframework.boot.context.properties.bind.Binder.lambda$bindAggregate$3(Binder.java:415)
    at org.springframework.boot.context.properties.bind.Binder$$Lambda$74/00000000780D1B60.get(Unknown Source)
    at org.springframework.boot.context.properties.bind.Binder$Context.withIncreasedDepth(Binder.java:573)
    at org.springframework.boot.context.properties.bind.Binder$Context.access$100(Binder.java:514)
    at org.springframework.boot.context.properties.bind.Binder.bindAggregate(Binder.java:415)
    at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:376)
    at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:320)
    ... 53 common frames omitted
09:58:15.507 [Default Executor-thread-16] ERROR org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter - 

***************************
APPLICATION FAILED TO START
***************************

Description:

Failed to bind properties under 'spring.config.name' to java.lang.String[]:

    Reason: Configuration property name '.log.file' is not valid

Action:

Update your application's configuration

For future reference, I got the output above by running the container created by the tests using docker run. The output then appears directly in the terminal.

Comment From: dreis2211

Yeah, this is indeed a bit surprising, but the failure shows exactly the problem this PR is fixing. The isAncestorOf check on an empty prefix produces .log.file which is obviously wrong.

Comment From: wilkinsona

Thanks very much, @dreis2211.

Comment From: mbhave

I saw those failures and assumed it was something related to Docker. Thanks for fixing @dreis2211!