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?
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