Hey devs ๐,
A few years back (around 3–4 years ago), I got a chance to work on a project involving Spring Cron Scheduler — using both XML configuration and Java annotations.
The requirement was pretty standard:
✅ Trigger a job every day at a particular time
✅ Fetch data from a table maintained by another team
✅ Process that data further
Everything worked well at first — in lower environments and even after initial production deployment.
But then... something strange started happening ๐ฌ
๐จ The Weird Behavior
After 4-5 days in production, the scheduled method started behaving oddly:
❌ It triggered twice at the same time
❌ Then later, three times, then four...
๐ต Restarting the application fixed it — but only temporarily.
After a few more days, it would go back to calling multiple times again.
It was as if my @Scheduled
method had cloned itself and started a party! ๐ฅด
⏳ Take 10 Seconds... Can You Guess the Root Cause?
You probably thought of:
-
Duplicate entries in the cron config? ❌
-
Bad server clock sync? ❌
-
Parallel jobs? ❌
Nope. The real issue was deeper... and sneakier.
๐ง Root Cause Analysis (RCA)
After some serious debugging and log tracing, I found the actual cause:
๐ Multiple ApplicationContext initializations inside the codebase!
Here’s what was happening:
-
Some report functionality / test utility code was programmatically initializing ApplicationContext like this:
-
Every time that functionality was triggered, a new context was created.
-
That context would load the scheduler bean again.
-
Result? Your scheduled job now existed multiple times in memory!
So if the test method ran 5 times, there were 5 instances of your scheduler bean — all firing at the scheduled time. ๐ฅ
๐ What is ApplicationContext?
Let’s take a quick refresher.
Concept | Description |
---|---|
๐ง What | It's the central container in Spring that manages the lifecycle of beans |
๐ ️ Why | Handles bean creation, dependency injection, and configuration |
⏱️ When | It should be initialized once during application startup |
❌ Don’t | Manually create it inside business logic or methods |
❌ What Went Wrong
⚠️ A helper method used in reports/tests was initializing ApplicationContext
again
⚠️ This reloaded the @Scheduled
beans
⚠️ Now multiple scheduler beans existed simultaneously
⚠️ Each was independently triggering at the same cron time ๐จ
✅ The Fix: Singleton ApplicationContext
To fix this, we made sure:
✅ ApplicationContext
is initialized once only at app startup
✅ All scheduler beans are defined only in the main Spring context
✅ No dynamic or hidden context initialization is done in any logic layer
Here's what a proper scheduler looks like:
Let Spring manage this as a singleton, not you!
๐ก Best Practices
๐ Never initialize ApplicationContext
manually in code
๐ Use @SpringBootApplication
to bootstrap your context
๐ Ensure all scheduler classes are under component scan paths
๐ Use dependency injection — not manual context fetching
๐ Wrapping Up
This post hopefully saves you from chasing vague errors across layers.
The moment your @Scheduled
method starts behaving like a haunted loop — think ApplicationContext. ๐ป
Have you dealt with weird Spring behavior like this before?
Drop your stories in the comments or reach out!
Until next time,
– Anand ☕ @ Java Bean Bag
Comments
Post a Comment