Skip to main content

πŸ’₯ "Wait... Why Is It NULL?!?" — When @Value("${...}") Ignores Your Static Field 😡‍πŸ’«

πŸ”  A surprising Spring Boot moment I didn't expect — and the rabbit hole it took me down...

🎬 It All Started With a Simple Idea...

You know how it goes…

You define a config value like this in application.properties:

payment.currency=INR

And then you boldly write this innocent-looking code:

@Component
public class PaymentUtil {

    @Value("${payment.currency}")
    private static String currency; // ✅ Logical! Right?

    public static void printCurrency() {
        System.out.println("Currency: " + currency);
    }
}

You run the app. And BAM πŸ’₯

Currency: null

😡 "Eh? I clearly defined the property. Is it not reading the file? Do I need a restart? Do I need to yell at my laptop?"

🀯 The Shocking Discovery

Spring doesn’t inject values into static fields.

Yes, my friend. Even if you beg it with @Value.

And trust me — it’s not a bug. It’s a feature. πŸ™ƒ

🧠 What Is This Dependency Injection (DI) Sorcery Anyway?

Let’s take a detour (the good kind — not the Bangalore traffic kind).

Spring uses Dependency Injection (DI) to manage your object graph using:

  • πŸ“Œ @Component / @Service / @Repository
  • πŸ“Œ @Autowired / @Value / Constructor injection
  • πŸ“Œ Reflection magic 🎩✨

🚧 Why Static Fields Break the Magic

Spring manages beans as instances — objects in the ApplicationContext.

But static fields belong to the class itself, not an object.

// Instance-level: Works ✔️
@Component
public class ConfigReader {
    @Value("${app.name}")
    private String name;
}

// Static field: No bean owns it ❌
@Value("${app.name}")
private static String name;

So Spring scans the class and goes:

“Aha, no instance variable to inject into? Cool, I’ll move on.” 😎

That’s why:

  • ❌ You get null
  • ❌ Or default values
  • ❌ Or you stare at the screen questioning your life choices 🫠

πŸ› ️ The Correct Fix That Surprised Me

✅ Option 1: Use @PostConstruct to Bridge Static + Instance

@Component
public class PaymentUtil {

    @Value("${payment.currency}")
    private String currency;

    private static String staticCurrency;

    @PostConstruct
    public void init() {
        staticCurrency = currency;
    }

    public static String getCurrency() {
        return staticCurrency;
    }
}

πŸŽ‰ Now currency is injected properly by Spring.

✅ Option 2: Use @ConfigurationProperties — The Cleaner Way

@Component
@ConfigurationProperties(prefix = "payment")
public class PaymentConfig {
    private String currency;

    public String getCurrency() { return currency; }
    public void setCurrency(String currency) { this.currency = currency; }
}
@Component
public class PaymentUtil {
    private final PaymentConfig config;

    public PaymentUtil(PaymentConfig config) {
        this.config = config;
    }

    public void printCurrency() {
        System.out.println("Currency: " + config.getCurrency());
    }
}

🧼 Much cleaner, and easier to unit test!

🧠 But Wait… Why Can’t Spring Just Inject Into Static?

Let’s dig deeper.

  1. πŸ“¦ Create object of the bean (e.g., PaymentUtil)
  2. πŸ” Reflectively access fields
  3. πŸ’‰ Inject values from application context
  4. πŸš€ Initialize the bean

But static fields don’t belong to any bean instance. So Step 2 breaks:

🧡 “Oops! There’s no object for me to inject into.”

It’s like trying to insert a USB drive into a photo of a laptop. πŸ™ƒ

πŸ˜‚ Dumb Interview Question, Smart Answer

Q: "Can Spring inject values into static fields?"

A: "Only if Spring becomes a Jedi and rewrites the Java language spec."

πŸ§ͺ Curious? Try This Yourself!

# application.properties
payment.currency=USD
@Component
public class TestUtil {
    @Value("${payment.currency}")
    private static String currency;

    public static void main(String[] args) {
        System.out.println("Currency = " + currency);
    }
}
Currency = null  // 😐

🧼 So What Did I Learn?

  • 😲 I Did This: @Value on a static field
  • πŸ€” Expected: "INR"
  • ❌ Got: null
  • ✅ Fixed By: @PostConstruct or @ConfigurationProperties
  • πŸ’‘ Lesson: Spring doesn’t inject into static — by design

🌈 Wrapping Up: From "What The Null?!" to "Aha!"

This was a “Why is it null?” moment that led to one of my best Spring learnings:

Spring is smart, but it only manages beans it creates.

Static fields live in their own world — away from the Spring container.

Always remember: With great power comes great bean lifecycle responsibility. πŸ•Έ️

🎀 Over to You!

Ever had a “Null surprise” like this in your config or bean wiring?

πŸ‘‰ Share your moment in the comments — let’s laugh and learn together! πŸ˜„

Comments

Popular posts from this blog

🎭 Spring’s Secret: Why @Transactional & Friends Betray You Silently

πŸ’‘ Lesson Learned — Not a Prod Bug, But a Real Pain No, this wasn’t a production outage. Nobody screamed at me. But I sat for 3 hours wondering: “Why the heck is my @Transactional not rolling back!?” 😡‍πŸ’« “Why is Redis cache not working?” 🀯 Turned out, the issue was one silent villain: 🧱 Self-invocation 🀷 What Is @Transactional ? If you're new: @Transactional = Tells Spring to start a DB transaction when a method is called. It’ll commit if everything’s okay. It’ll rollback if something fails. 🧠 Think of it like wrapping your code in: try { beginTransaction(); // your logic commit(); } catch(Exception e) { rollback(); } πŸ•΅️ Real-Life Analogy — The Gateway Community 🏘️ Let me tell you about my society — it has a strict watchman at the gate. Here’s how it works: πŸ›‚ Watchman = Spring Proxy 🏠 Your apartment = Your service class πŸšͺ Your room = A method inside that class πŸƒ Scenario 1: Outsider Visits Your friend from outside...

🧡 Virtual Threads in Java — The Ultimate Guide with Diagrams, Code & Interview Qs!

πŸš€ “How are Virtual Threads different from Thread Pools?” 😡 “Are they OS threads or JVM threads?” πŸ™ƒ “Should I still use CompletableFuture?” 🀯 “How do I even use them in real-time microservices?” 🧠 What are Virtual Threads? Virtual Threads (introduced in Java 21 as stable πŸŽ‰) are lightweight threads managed by the JVM instead of the OS kernel. πŸ‘‰ They look like normal threads, but don’t hog OS resources like traditional threads. 🧠 What is the OS Kernel? πŸ›️ OS Kernel = The Brain of the Operating System It’s the core part of your OS (Windows, Linux, Mac) that: Manages memory 🧠 Schedules threads πŸ•’ Talks to hardware πŸ’» Handles I/O operations πŸ“¨ When you create a traditional thread in Java, the JVM asks the OS Kernel to create a real OS-level thread. πŸ–Ό️ Imagine This... ┌───────────────────────────┐ │ Your Java Application │ └────────────┬──────────────┘ │ ...

🐱 Tomcat vs ⚡ Netty – Which One Should You Use?

🐱 Tomcat vs ⚡ Netty – Which One Should You Use? So recently I got curious about this too πŸ€”. Everywhere in Spring Boot tutorials we see Tomcat . Then suddenly while exploring Spring WebFlux , the name Netty pops up. And I was like – “Wait, who’s this Netty guy trying to replace Tomcat?” πŸ˜… Let’s break it down with real-time examples , icons , and fun comparisons . 🐱 Tomcat – The Traditional Web Server Type: Servlet Container (blocking I/O) World: Used with Spring MVC Style: Thread-per-request model πŸ‘©‍πŸ’» Pros: Stable, widely used, battle-tested Cons: Struggles with huge concurrent connections πŸ‘‰ Example in real life: Tomcat is like a restaurant with fixed waiters 🍴. - Each customer = one thread/waiter - If too many customers come in at once → waiters run out → customers wait outside πŸšͺ ⚡ Netty – The Reactive Rockstar Type: Asynchronous Event-Driven Network Framework World: Default for Spring WebFlux Style: Event-lo...