Skip to content

How to resolve 'could not resolve placeholder xxx in value ${xxx}' when using spring cloud config client with profiles

Problem

When using Spring Cloud Config Server/Client with profiles, you might encounter the following error:

Terminal window
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'message' in value "${message}"

This error occurs when the Spring application cannot resolve a property placeholder, such as ${message}, from the configuration files.

Environment

  • Spring Boot 2.3
  • Spring Cloud Config Server 2.2.3.RELEASE
  • Spring Cloud Version: Hoxton.SR6

Configuration Files and Code

The Config Server

The configuration server uses a local directory as its repository. For example, the repository is located at /Users/bswen/bswen-github/configs. The application.properties file for the config server is configured as follows:

application.properties
spring.cloud.config.server.composite.type=composite
spring.cloud.config.server.native.search-locations=file://///Users/bswen/bswen-github/configs/{application}

Inside the repository, there are subdirectories for different profiles of the config client (app1). For example:

  • ./app1/dev/app1.properties
  • ./app1/prod/app1.properties

The content of ./app1/dev/app1.properties is:

app1-dev.properties
message=hellodev

The content of ./app1/prod/app1.properties is:

app1-prod.properties
message=helloprod

The Config Client

The bootstrap.properties file for the config client (app1) is configured as follows:

bootstrap.properties
spring.application.name=app1
spring.cloud.config.uri=http://localhost:8888
spring.main.web-application-type=NONE
spring.profiles.active=prod

The code that injects the message property from the config server is:

App1Application.java
@SpringBootApplication
public class App1Application {
private static final Logger log = LoggerFactory.getLogger(App1Application.class);
public static void main(String[] args) {
SpringApplication.run(App1Application.class,args);
}
@Value("${message}")
private String message;
@Bean
public CommandLineRunner run(RestTemplate restTemplate) throws Exception {
log.info("got message {}",message);
}
}

Despite the configuration, the application throws the error:

Terminal window
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'message' in value "${message}"

Reason

The Spring Cloud Config Server expects the configuration files to be in a specific directory structure:

file://///Users/bswen/bswen-github/configs/{application}/{application}-{profile}.properties

In this case, the correct file paths should be:

  • /Users/bswen/bswen-github/configs/app1/app1-dev.properties
  • /Users/bswen/bswen-github/configs/app1/app1-prod.properties

Solution

To resolve the issue, move the configuration files to the correct directories:

  • /Users/bswen/bswen-github/configs/app1/app1-dev.properties
  • /Users/bswen/bswen-github/configs/app1/app1-prod.properties

After making this change, restart the Spring Cloud Config Client application. The application should now correctly resolve the message property.

Summary

This post demonstrated how to resolve the “could not resolve placeholder” error when using Spring Cloud Config Client with profiles. The key takeaway is to ensure that the configuration files are placed in the correct directory structure and follow the required naming convention. By organizing the files properly, the Spring Cloud Config Server can successfully resolve the properties, and the application will function as expected.

Final Words + More Resources

My intention with this article was to help others who might be considering solving such a problem. So I hope that’s been the case here. If you still have any questions, don’t hesitate to ask me by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!