Could not resolve placeholder in string value
Categories:
Resolving 'Could not resolve placeholder' in Spring Applications

Understand and fix the common 'Could not resolve placeholder' error in Spring applications, often caused by missing configuration or incorrect property loading.
The 'Could not resolve placeholder' error is a common issue encountered by developers working with Spring Framework. It typically indicates that Spring is unable to find a value for a property defined using the ${...}
syntax within your application's configuration. This article will delve into the root causes of this error and provide comprehensive solutions to help you resolve it efficiently.
Understanding Spring's Property Resolution
Spring applications heavily rely on externalized configuration, allowing you to define environment-specific settings without modifying code. This is achieved through property placeholders, which are resolved at runtime. Spring's Environment
abstraction and PropertySource
hierarchy are responsible for finding and injecting these values. When a placeholder cannot be matched to an available property source, this error occurs.
flowchart TD A[Spring Application Context Startup] --> B{Scan for @PropertySource annotations & application.properties/yml} B --> C{Load PropertySources into Environment} C --> D{Process @Value annotations & XML placeholders} D --> E{Attempt to resolve ${placeholder}} E -- Placeholder Found --> F[Value Injected] E -- Placeholder NOT Found --> G["Error: Could not resolve placeholder"] G --> H[Application Fails to Start]
Spring Property Resolution Flow
Common Causes and Solutions
Several factors can lead to unresolved placeholders. Identifying the exact cause is the first step towards a solution. Below are the most frequent scenarios and their corresponding fixes.
1. Missing or Incorrect Property Files
The most straightforward reason for this error is that Spring cannot find the property file containing the definition for your placeholder. This could be due to the file being absent, incorrectly named, or not located in a path accessible to Spring.
# application.properties
my.service.url=http://localhost:8080/api
Example application.properties
file
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class MyServiceConfig {
@Value("${my.service.url}")
private String serviceUrl;
public String getServiceUrl() {
return serviceUrl;
}
}
Java component using @Value
annotation
Ensure your application.properties
(or application.yml
) file is in the src/main/resources
directory. If you're using custom property files, you need to explicitly tell Spring where to find them using @PropertySource
.
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@PropertySource("classpath:custom.properties")
public class AppConfig {
// ... bean definitions
}
Loading a custom property file using @PropertySource
2. Incorrect Profile Activation
If you're using Spring profiles to manage different configurations (e.g., application-dev.properties
, application-prod.properties
), an unresolved placeholder might mean the correct profile isn't active, or the property is missing from the active profile's configuration.
# application-dev.properties
database.url=jdbc:h2:mem:testdb
# application-prod.properties
database.url=jdbc:postgresql://prod-db:5432/mydb
Profile-specific property files
To activate a profile, you can use the spring.profiles.active
property. For example, when running your application, you can pass it as a JVM argument:
java -jar myapp.jar --spring.profiles.active=dev
Activating the 'dev' profile via command line
3. Order of PropertySource Loading
Spring loads property sources in a specific order. If a property is defined in multiple places, the one loaded later takes precedence. If your placeholder is defined in a lower-priority source and overridden by a higher-priority source that doesn't define it, it can appear as unresolved.
PropertySource
loading in Spring Boot is: Devtools global settings, @TestPropertySource
, @SpringBootTest
properties, command line arguments, SPRING_APPLICATION_JSON
, Servlet config init parameters, Servlet context init parameters, JNDI, System.getProperties()
, OS environment variables, RandomValuePropertySource
, application-specific properties (e.g., application.properties
), @PropertySource
annotations, and finally, default properties.4. Using Default Values
To prevent application startup failures due to missing optional properties, you can provide a default value directly in the placeholder syntax. This ensures that if Spring cannot resolve the primary property, it falls back to a sensible default.
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class FeatureToggleConfig {
@Value("${feature.enabled:false}") // Default to false if feature.enabled is not found
private boolean featureEnabled;
public boolean isFeatureEnabled() {
return featureEnabled;
}
}
Using a default value for a placeholder
In the example above, if feature.enabled
is not found in any property source, featureEnabled
will be set to false
instead of throwing an error.
5. Programmatic Property Resolution
For more complex scenarios or when you need to resolve properties dynamically at runtime, you can inject the Environment
object and resolve properties programmatically.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
@Component
public class DynamicPropertyResolver {
private final Environment environment;
@Autowired
public DynamicPropertyResolver(Environment environment) {
this.environment = environment;
}
public String getProperty(String key) {
return environment.getProperty(key);
}
public String getPropertyWithDefault(String key, String defaultValue) {
return environment.getProperty(key, defaultValue);
}
}
Programmatic property resolution using Environment
@Value
for static property injection where possible.Troubleshooting Steps
When faced with this error, follow these systematic steps to diagnose and resolve the issue:
1. Verify Property Key Spelling
Ensure the placeholder key (e.g., my.service.url
) exactly matches the key in your property file. Typos are common.
2. Check Property File Existence and Location
Confirm that application.properties
(or application.yml
) is in src/main/resources
. If using custom files, verify the @PropertySource
path is correct and the file exists.
3. Inspect Active Profiles
If using profiles, ensure the correct profile is active and that the property is defined within that profile's configuration.
4. Review PropertySource Order
Consider if a higher-priority property source might be overriding or omitting the property you expect to be resolved.
5. Add Default Values
For non-critical properties, add a default value using ${key:defaultValue}
to allow the application to start and identify missing properties later.
6. Enable Debug Logging
Increase logging levels for org.springframework.core.env
to DEBUG
to see how Spring loads and resolves properties. This can provide valuable insights into which property sources are being consulted.