Skip to content

Property placeholders are not replaced when used in name attribute of <springProfile> #13450

@sergeyandrusevich

Description

@sergeyandrusevich

Use case:

Application on certain environments should write logs into the file. In order to turn this on/off we provide property in application.yml configuration which tells for which spring profile it is allowed or not allowed (like '!prod' for example).

The logback-spring.xml configuration for such case looks as follows:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>    <include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
    <springProperty scope="context" name="allowed-profiles" source="logback.allowed-profiles"/>    <springProfile name="${allowed-profiles}">
        <appender name="ROLLING-FILE"
                  class="ch.qos.logback.core.rolling.RollingFileAppender">
            <encoder>
                <pattern>${FILE_LOG_PATTERN}</pattern>
            </encoder>
            <file>${LOG_FILE}</file>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.log</fileNamePattern>
            </rollingPolicy>
        </appender>
    </springProfile>

    <root>
        <appender-ref ref="CONSOLE"/>
        <springProfile name="${allowed-profiles}">
            <appender-ref ref="ROLLING-FILE"/>
        </springProfile>
    </root></configuration>

In the Spring-Boot version 1.5.x it doesn't work. From the source code (org.springframework.boot.logging.logback.SpringProfileAction) there is a piece of logic which isn't applied:

private boolean acceptsProfiles(InterpretationContext ic, Attributes attributes) { 
     String[] profileNames = StringUtils.trimArrayElements(StringUtils .commaDelimitedListToStringArray(attributes.getValue(NAME_ATTRIBUTE))); 
    if (profileNames.length != 0) { 
        for (String profileName : profileNames) {
            OptionHelper.substVars(profileName, ic, this.context);
        }

        return this.environment != null && 
             this.environment.acceptsProfiles(profileNames); 
    }
    return false; 
}

Here OptionHelper.substVars(profileName, ic, this.context) should return substituted value from the properties or from environment variables. But it isn't assigned to anything and in the next check where environment accepts profiles it still passes expression but not actual value.

The change like that could fix it:

String[] profiles = new String[profileNames.length]; 
for (int i = 0; i < profileNames.length; i++) { 
    profiles[i] = OptionHelper.substVars(profileNames[i], ic, this.context); 
} 
return this.environment != null &&   
    this.environment.acceptsProfiles(profiles);

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions