Describe the bug I'm using Spring Boot 3.1.4 and Spring Cloud 2022.0.4.

I've configured Spring Cloud Config to use discovery-first. I've put the spring.config.import=configserver: statement in a sub-document of application.properties, activated using spring.config.activate.on-profile=!noconfigserver. I also have a some-profile profile active.

When fetching the some-profile config, the service discovery is used; however, it also fetches the non-profile-specific config without using service discovery. This fails.

Sample

application.properties:

spring.application.name=demo

spring.cloud.config.uri=http://not-discovery:8888/
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.service-id=configuration-service
eureka.client.service-url.default-zone=http://eurekahost:8761

spring.profiles.active=some-profile

#---
spring.config.activate.on-profile=!noconfigserver

spring.config.import=configserver:

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.1.4</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>spring-config-discovery-first-bug</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-config-discovery-first-bug</name>
    <description>Demo project for Spring Config bug</description>
    <properties>
        <java.version>21</java.version>
        <spring-cloud.version>2022.0.4</spring-cloud.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

The following logs are from using a configuration server registered at 127.0.0.1, and adding a not-discovery entry to my hosts file, also pointing at 127.0.0.1 (added for the sake of getting these logs):

2023-10-17T11:59:46.656+01:00  INFO 24856 --- [demo] [           main] SpringConfigDiscoveryFirstBugApplication : The following 1 profile is active: "some-profile"
2023-10-17T11:59:46.675+01:00  INFO 24856 --- [demo] [           main] o.s.c.c.c.ConfigServerConfigDataLoader   : Fetching config from server at : http://127.0.0.1:8888/
2023-10-17T11:59:46.675+01:00  INFO 24856 --- [demo] [           main] o.s.c.c.c.ConfigServerConfigDataLoader   : Located environment: name=demo, profiles=[some-profile], label=null, version=63f3e2b6bd303329ef841d18f99585a5dcef1449, state=null
2023-10-17T11:59:46.675+01:00  INFO 24856 --- [demo] [           main] o.s.c.c.c.ConfigServerConfigDataLoader   : Fetching config from server at : http://not-discovery:8888/
2023-10-17T11:59:46.675+01:00  INFO 24856 --- [demo] [           main] o.s.c.c.c.ConfigServerConfigDataLoader   : Located environment: name=demo, profiles=[default], label=null, version=63f3e2b6bd303329ef841d18f99585a5dcef1449, state=null

You can see that it fetches config for the default profile being active from http://not-discovery:8888/.

This does not happen without the spring.config.activate.on-profile property. I think the issue is that the bootstrapConfigClientProperties in ConfigServerConfigDataLocationResolver.loadProperties have not been initialised by the ConfigServerInstanceMonitor yet when it comes to create the ConfigClientProperties for the non-profile-specific import, because that only happens when the import is processed, and the import is not processed before profile activation.

Comment From: ryanjbaxter

I don't really understand why you have things configured this way.

You can't specify a URI and then use service discovery lookup, you need to choose one or the other.

Comment From: pmahony893

Agreed - the spring.cloud.config.uri property has no place if we're using discovery-first. I only added it to make it really clear in the logs that it isn't using service discovery.

Without that property, everything is the same, except you see the default localhost in the logs instead of not-discovery, which is still wrong, but perhaps less obviously so, as the correct address retrieved using service discovery is 127.0.0.1, as I am running everything locally.

I added that config hoping to make the behaviour more obvious, but it seems I ended up confusing matters - apologies!

Comment From: ryanjbaxter

Is there a reason why the spring.config.import statement is in a document activated by a profile when its required to be set when using discovery first configuration?

Comment From: pmahony893

Sometimes I want my application to fetch config from config server (e.g. when deployed). Sometimes I don't (e.g. when developing locally). My aim is to be able to switch this on or off depending on whether a profile is activated.

With the above application.properties file, if I activate the noconfigserver profile, then config is not fetched from config server. So far, so good. When I don't activate that profile, it is fetched - but incorrectly, as it uses discovery inconsistently.

Comment From: ryanjbaxter

With the above application.properties file, if I activate the noconfigserver profile, then config is not fetched from config server. So far, so good. When I don't activate that profile, it is fetched - but incorrectly, as it uses discovery inconsistently.

Sorry but this doesn't seem to align with the sample applicaiton.properties you supplied. There is no noconfigserver profile specific document, there is a document that is activated as long as the profile is not noconfigserver and when that document is NOT activated the config server will fail to start because there is no spring.config.import.

I think one possible solution to this situation is just have one document and change spring.config.import to optional:configsever: so that if the config server is not available the application does not fail to start.

Comment From: pmahony893

Apologies, I've gone through several iterations before creating an issue here, and I missed something in my initial post. The following document should also be in application.properties. The service does not fail to start with the noconfigserver profile active when this is present.

#---
spring.config.activate.on-profile=noconfigserver

spring.cloud.config.enabled=false

The point is that the configserver: import is in a profile-specific document. To me, this doesn't seem such a strange thing to do. It's even in a suggestion given by a member of the Spring Cloud team here, to get different behaviours between profiles.

I don't want to use optional: because when my application is deployed, it must fetch its config from configserver, otherwise it will be running with incorrect configuration. I want it to fail to start in this case.