Search code examples
spring-bootspring-profiles

Could not resolve placeholder spring.profiles.active but at the same time profiles are active


I have a Spring boot console application that is launched with multiple active profiles specified in the command line. The simplified code looks like this:

package tmp;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

import javax.sql.DataSource;

@SpringBootApplication(scanBasePackages = {"tmp"})
@Configuration
public class SampleTool implements CommandLineRunner {

    @Autowired
    private Environment environment;

    @Value("${spring.profiles.active[0]}")
    private String firstProfile;

    // Dummy data source just for the sake of starting JPA 
    @Bean
    public DataSource getDataSource() throws ClassNotFoundException{
        DataSourceBuilder dsBuilder = DataSourceBuilder.create();
        dsBuilder.driverClassName("com.mysql.jdbc.Driver");
        dsBuilder.url("jdbc:mysql://localhost/test");
        dsBuilder.username("...");
        dsBuilder.password("...");
        return dsBuilder.build();
    }
    public void run(String...args) {
        System.exit(0);
    }
    public static void main(String[] args) {
        SpringApplication.run(SampleTool.class, args);
    }
}

The weird thing is that at execution time, I see the following:

2023-02-23 08:34:44.696  INFO 38840 --- [           main] tmp.SampleTool   : The following 2 profiles are active: "local-db", "local-wiki"

and yet the application crashes with

Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'spring.profiles.active[0]' in value "${spring.profiles.active[0]}"

Why woluld Spring not be injecting the active profiles, if they are there?


Solution

  • In your case [0] is considered a part of the property name because the ${...} is the property placeholder syntax which can only be used to dereference properties. But you can use SpEL syntax to extract the first profile as follows:

    @Value("#{'${spring.profiles.active:}'.split(',')[0]}")
    private String firstProfile;
    

    Since spring.profiles.active contains comma-separated profile names, it should be split by a comma before accessing the first element. The : is used to define a default value to prevent java.lang.IllegalArgumentException: Could not resolve placeholder exception if no profile is active.

    For reference: Spring Profiles