Search code examples
springspring-bootspring-cloudspring-cloud-configspring-cloud-config-server

Default profile values are not returned when specific profile selected in Spring Cloud Config


I'm moving from a local application.yml configuration file to a config server managed configuration.

My application.yml file contains 2 (or more) profiles in the same file, in the format:

spring.application.name: config-client
app.myvar1: "Var 1 in default profile"
app.myvar2: "Var 2 in default profile"
---
spring.config.activate.on-profile: docker
app.myvar1: "Var 1 in docker profile"

When I test this configuration file in a NOT config-server environment, I the result reading from the specific profile, and if not found, reading from default. Sample

Correct result when I test without config-server

Profile: docker
MyVar1=Var 1 in docker profile
MyVar2=Var 2 in default profile

For testing I'm using a simple program:

package com.bthinking.configclient;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class ConfigClientApplication {

    @Autowired
    private Environment environment;

    @Value("${app.myvar1:MyVar1 not found}")
    String myVar1;
    @Value("${app.myvar2:MyVar2 not found}")
    String myVar2;

    public static void main(String[] args) {
        SpringApplication.run(ConfigClientApplication.class, args);
    }

    @RequestMapping("/")
    public String index() {
        StringBuffer b = new StringBuffer();
        for (String profile : environment.getActiveProfiles()) {
            b.append(String.format("Profile: %s</br>", profile));
        }
        b.append(String.format("MyVar1=%s</br>", myVar1));
        b.append(String.format("MyVar2=%s</br>", myVar2));
        return b.toString();
    }
}

And I start the program with (I use gradle):

gradle :config-client:bootRun --args='--spring.profiles.active=docker'

But, when I migrate to config server, moving the file to a config-repo (I'm using file based repor), I get the invalid result (it's unable to read the variable in the default section). I have also tried with --spring.profiles.active=docker,default with no change

Profile: docker
MyVar1=Var 1 in docker profile
MyVar2=MyVar2 not found

For reference, my config-server has the following configuration:

server.port: 8888

spring.application.name: config-server

spring.cloud.config.server.native.searchLocations: file:${PWD}/config-repo
# spring.cloud.config.server.native.searchLocations: file:/Users/jmalbarran/Projects/BTH/BTH/SPB_SpringBoot/bugs/config/config-repo

logging.level:
  root: debug
---
spring.config.activate.on-profile: docker
spring.cloud.config.server.native.searchLocations: file:/config-repo

The main class

package com.bthinking.configserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;

@EnableConfigServer
@SpringBootApplication
public class ConfigServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication.class, args);
    }

}

And the build.gradle

plugins {
    id 'org.springframework.boot' version '2.4.1'
    id 'io.spring.dependency-management' version '1.0.10.RELEASE'
    id 'java'
}

group = 'com.b-thinking'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
    mavenCentral()
    maven { url 'https://repo.spring.io/milestone' }
}

ext {
    set('springCloudVersion', "2020.0.0")
}

dependencies {
    implementation 'org.springframework.cloud:spring-cloud-config-server'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
    }
}

test {
    useJUnitPlatform()
}

And I start it with:

gradle :config-server:bootRun --args='--spring.profiles.active=native'

NOTE: As I think this a bug, I have also created an issue in github. Check in Issue


Solution

  • After the @spencergibb (Thanks!) comment, I tried with the version 3.0.1, and it solves the problem.

    This is now my build.gradle

    plugins {
        id 'org.springframework.boot' version '2.4.1'
        id 'io.spring.dependency-management' version '1.0.10.RELEASE'
        id 'java'
    }
    
    group = 'com.b-thinking'
    version = '0.0.1-SNAPSHOT'
    sourceCompatibility = '1.8'
    
    repositories {
        mavenCentral()
        maven { url 'https://repo.spring.io/milestone' }
    }
    
    ext {
        set('springCloudVersion', "2020.0.0")
    }
    
    dependencies {
        implementation 'org.springframework.cloud:spring-cloud-config-server:3.0.1'
        testImplementation 'org.springframework.boot:spring-boot-starter-test'
    }
    
    dependencyManagement {
        imports {
            mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
        }
    }
    
    test {
        useJUnitPlatform()
    }
    

    It's amazing, because the version 3.0.1 is reported solving the opposite bug (the default configuration override the specific), but I imagine that the review solved both.

    For references, this were the related issues

    Issue#1777 Profile not correct with SpringBoot 2.4.1 + Ilford 2020.0.0 (working with 2.4.1 + Ilford 2020.0.0-RC1)

    Issue@1778 multidocument files from config server have the same property name