Why does @Value sometimes fail to inject properties?

Why does @Value sometimes fail to inject properties?

@Value failing to inject properties is one of the most confusing Spring problems because it often fails silently or only in specific environments.

The reason is not “Spring is broken” — it’s always due to how and when property sources are loaded and how the bean is created.

Let’s go deep from internals → real-world failure patterns → professional fixes.


1. How @Value Actually Works (Internal Mechanism)

@Value is handled by:

PropertySourcesPlaceholderConfigurer

It runs during:

Bean definition post-processing phase

Not during normal runtime.

Image

Image

Image

So if properties are not available at that exact phase, injection fails.


2. The 8 Most Common Reasons @Value Fails


2.1 Bean Created Before Property Loader

This is the #1 real-world cause.

Example:

@Bean
public MyService myService() {
   return new MyService();
}

If MyService is created before:

@PropertySource("classpath:app.properties")

Then:

@Value("${timeout}")
private int timeout; // null / 0

Because property source not loaded yet.


2.2 Using @Value in Static Fields

@Value("${url}")
private static String url; // will always be null

Spring cannot inject into static fields.

Because:

Injection happens on instances, not classes.


2.3 Property Key Does Not Exist

@Value("${server.timeout}")

But in file:

server.timeOut=30

Case mismatch = not found.

Result:

Could not resolve placeholder

Or worse:

Injects empty string.


2.4 Profile-Specific Properties Not Loaded

spring.profiles.active=prod

But property exists in:

application-dev.properties

So in prod:

@Value("${api.key}") // fails

Because file not loaded.


2.5 Missing PropertySource

If not using Boot:

@Value("${app.name}")

But no:

@PropertySource("classpath:application.properties")

Then:

Spring has no idea where to look.


2.6 YAML Indentation / Structure Errors

app:
 name: myApp

But:

@Value("${app.name}")

If indentation is wrong:

app:
   name: myApp
    port: 8080  # invalid

Entire block ignored.


2.7 Using @Value in @Configuration Constructor

@Configuration
public class Config {
  public Config(@Value("${x}") String x) { }
}

Fails because:

@Configuration is processed before placeholders resolved.

This one is very subtle.


2.8 Wrong Environment / Docker / K8s

In containers:

ENV API_KEY=123

But using:

@Value("${api.key}")

Spring maps env vars:

API_KEY -> api.key

But only if:

relaxed binding is enabled

Misconfig = null.


3. Silent Failure Patterns (Most Dangerous)

Pattern Result
primitive int injects 0
boolean injects false
String injects “”
wrapper types null

No exception.
Bug detected in production.


4. Why @Value Is Considered Fragile

Because:

  • No type safety
  • No compile-time validation
  • No grouping
  • No documentation

It’s just:

String replacement at startup.


5. The Professional Replacement: @ConfigurationProperties

@ConfigurationProperties(prefix="app")
public class AppConfig {
  private int timeout;
  private String name;
}

Advantages:

  • Strong typing
  • Validated
  • Fails fast
  • IDE support

6. Debugging @Value Failures Like a Pro

Step 1 – Dump property sources

@Autowired
Environment env;

env.getPropertySources().forEach(System.out::println);

Step 2 – Check resolved value

env.getProperty("api.key");

If null → source not loaded.


7. Force Spring to Fail Fast

spring.main.fail-on-missing-placeholder=true

Now:

App crashes immediately if property missing.

No silent bugs.


8. Internal Ordering (Advanced)

Property resolution order:

  1. Command line args
  2. OS environment
  3. application.properties
  4. @PropertySource
  5. Default values

So:

--timeout=10

Overrides everything.


9. Interview-Grade Answer (For You, Nimai)

“@Value fails when the property source is not loaded at the time of placeholder resolution, such as with wrong profiles, missing PropertySource, static fields, early bean creation, or incorrect keys. Since it works during bean definition phase, timing and environment configuration are the main causes.”


Final Mental Model

Think of @Value as:

Text substitution during container bootstrap

If the text is not available at that moment, Spring cannot go back later.


Golden Rule

Use @Value only for:

  • One-off constants
  • Feature flags

For everything else:

Use @ConfigurationProperties or you will debug ghosts in production.

Leave a Reply