Bean Circular Dependency in Spring
What is it?
When two beans depend on each other — neither can be created first.
Bean A needs B → Bean B needs A → 💥
Spring throws: BeanCurrentlyInCreationException:
Requested bean is currently in creation:
Is there an unresolvable circular reference?
3 ways to fix:
1. @Lazy ✅ recommended
Delays bean creation until actually needed — breaks the cycle.
2. Setter Injection
Spring creates both beans first, injects after.
3. Redesign — best long term
Extract shared logic into a third bean. Circular dependency usually signals an architecture problem.
#Java #Spring #Beans #CircularDependency
What is it?
When two beans depend on each other — neither can be created first.
Bean A needs B → Bean B needs A → 💥
Spring throws: BeanCurrentlyInCreationException:
Requested bean is currently in creation:
Is there an unresolvable circular reference?
3 ways to fix:
1. @Lazy ✅ recommended
@Component
public class A {
public A(@Lazy B b) { }
}
Delays bean creation until actually needed — breaks the cycle.
2. Setter Injection
@Autowired
public void setB(B b) { this.b = b; }
Spring creates both beans first, injects after.
3. Redesign — best long term
Extract shared logic into a third bean. Circular dependency usually signals an architecture problem.
#Java #Spring #Beans #CircularDependency
❤1
@Value in Spring
What is it?
Injects values from properties files or expressions directly into fields at runtime.
1. From properties file ${}
2. SpEL expressions #{}
Key difference:
${} reads from properties files
#{} evaluates Java expressions at runtime
#Java #Spring #Value #SpEL #Properties
What is it?
Injects values from properties files or expressions directly into fields at runtime.
1. From properties file ${}
application.yml
app.servers=server1,server2,server3
app.timeout=5000
@Value("${app.servers}")
private String[] servers;
@Value("${app.timeout:5000}") // default if not found
private int timeout;2. SpEL expressions #{}
@Value("#{2 * 3}") // math → 6
private int result;
@Value("#{userService.getDefaultName()}") // method call on a bean
private String name;
@Value("#{T(Math).PI}") // static field
private double pi;Key difference:
${} reads from properties files
#{} evaluates Java expressions at runtime
#Java #Spring #Value #SpEL #Properties
Java 21 Virtual Threads
https://docs.oracle.com/en/java/javase/21/core/virtual-threads.html#GUID-DC4306FC-D6C1-4BCC-AECE-48C32C1A8DAA
#virtual_threads #java_21 #java
https://docs.oracle.com/en/java/javase/21/core/virtual-threads.html#GUID-DC4306FC-D6C1-4BCC-AECE-48C32C1A8DAA
#virtual_threads #java_21 #java
Oracle Help Center
Core Libraries
Virtual threads are lightweight threads that reduce the effort of writing, maintaining, and debugging high-throughput concurrent applications.
Why JVM Doesn't Exit After main() Finishes?
JVM exits only when all non-daemon threads finish. If main() ends but other threads are still running — JVM stays alive.
Common culprits — infinite loop in a thread, ExecutorService not shut down, Timer or ScheduledExecutorService still running, unclosed DB or socket connections holding background threads.
Fix — make background threads daemon with setDaemon(true) so they die automatically when main dies, or properly shut down ExecutorService, or interrupt threads explicitly.
#Java #JVM #Threads #Daemon
JVM exits only when all non-daemon threads finish. If main() ends but other threads are still running — JVM stays alive.
Common culprits — infinite loop in a thread, ExecutorService not shut down, Timer or ScheduledExecutorService still running, unclosed DB or socket connections holding background threads.
Fix — make background threads daemon with setDaemon(true) so they die automatically when main dies, or properly shut down ExecutorService, or interrupt threads explicitly.
#Java #JVM #Threads #Daemon
What Happens if main() is Not Static
When you type java MyApp, the Heap is empty — no objects exist yet. The JVM needs an entry point to start your programme.
If main() were non-static — JVM would need to create an object first. But which constructor? What arguments? What if it throws an exception? JVM has no information to decide.
With static — JVM calls MyApp.main(args) directly on the class level. No object needed, no guessing.
Without static — JVM doesn't even try. You get:
Error: Main method not found, please define as public static void main(String[] args)
Java 21 introduced a preview feature — you can write just void main() without static, without String[] args, without public. JVM handles object creation internally.
#Java #JVM #Static #Main
When you type java MyApp, the Heap is empty — no objects exist yet. The JVM needs an entry point to start your programme.
If main() were non-static — JVM would need to create an object first. But which constructor? What arguments? What if it throws an exception? JVM has no information to decide.
With static — JVM calls MyApp.main(args) directly on the class level. No object needed, no guessing.
Without static — JVM doesn't even try. You get:
Error: Main method not found, please define as public static void main(String[] args)
Java 21 introduced a preview feature — you can write just void main() without static, without String[] args, without public. JVM handles object creation internally.
#Java #JVM #Static #Main
Memory Leaks in Java — yes, even with GC
A lot of devs think "Java has GC, so no memory leaks". I thought the same. Then I spent 3 hours debugging why our app crashed every night at 3am.
Turned out — one unclosed DB connection. That's it.
GC is smart but it's not magic. It removes objects nobody references anymore. The problem is you — you keep referencing objects you forgot about.
Classic examples from real life:
You register a listener and never unregister. You put something in ThreadLocal and move on. You cache objects in a static list and never clean it. You open a connection and "handle it later".
The app doesn't crash immediately. It slows down. Memory grows. GC works harder. Until one night — boom.
The fix isn't a library or a pattern. It's just discipline — close what you open.
#Java #Backend #RealTalk
A lot of devs think "Java has GC, so no memory leaks". I thought the same. Then I spent 3 hours debugging why our app crashed every night at 3am.
Turned out — one unclosed DB connection. That's it.
GC is smart but it's not magic. It removes objects nobody references anymore. The problem is you — you keep referencing objects you forgot about.
Classic examples from real life:
You register a listener and never unregister. You put something in ThreadLocal and move on. You cache objects in a static list and never clean it. You open a connection and "handle it later".
The app doesn't crash immediately. It slows down. Memory grows. GC works harder. Until one night — boom.
The fix isn't a library or a pattern. It's just discipline — close what you open.
#Java #Backend #RealTalk
GC Pauses Increased After a Small Code Change
A small code change caused GC pauses to spike. How?
Most developers add a log line, forget to close a connection, or switch from primitive to wrapper type. Looks innocent. But the chain reaction is brutal.
Too many objects created → Eden fills fast → Minor GC runs constantly → objects survive and get promoted to Old Generation → Old Gen fills up → Major GC kicks in → long Stop The World pause.
Minor GC pauses are short — milliseconds. Major GC pauses are long — hundreds of milliseconds or even seconds. That's the difference between a smooth app and one that freezes randomly.
The culprit is almost always objects living longer than they should — unclosed connections, unbounded caches, forgotten listeners.
#Java #JVM #GC #Performance
A small code change caused GC pauses to spike. How?
Most developers add a log line, forget to close a connection, or switch from primitive to wrapper type. Looks innocent. But the chain reaction is brutal.
Too many objects created → Eden fills fast → Minor GC runs constantly → objects survive and get promoted to Old Generation → Old Gen fills up → Major GC kicks in → long Stop The World pause.
Minor GC pauses are short — milliseconds. Major GC pauses are long — hundreds of milliseconds or even seconds. That's the difference between a smooth app and one that freezes randomly.
The culprit is almost always objects living longer than they should — unclosed connections, unbounded caches, forgotten listeners.
#Java #JVM #GC #Performance
Increasing Heap Size Made Performance Worse
Counterintuitive but real. Here's why.
Bigger heap means more objects can live in memory. GC runs less frequently — sounds good. But when Major GC finally kicks in it has to scan the entire heap.
512MB heap → Major GC → 200ms pause
16GB heap → Major GC → 10 second pause 💀
App doesn't crash. It just freezes for 10 seconds randomly. Users think it's dead.
More heap = less frequent but more painful GC pauses.
The real fix is not throwing more memory at the problem. Fix memory leaks first. Then if you still need large heap — switch to ZGC or Shenandoah which keep pauses under 1ms regardless of heap size.
#Java #JVM #GC #Performance #Heap
Counterintuitive but real. Here's why.
Bigger heap means more objects can live in memory. GC runs less frequently — sounds good. But when Major GC finally kicks in it has to scan the entire heap.
512MB heap → Major GC → 200ms pause
16GB heap → Major GC → 10 second pause 💀
App doesn't crash. It just freezes for 10 seconds randomly. Users think it's dead.
More heap = less frequent but more painful GC pauses.
The real fix is not throwing more memory at the problem. Fix memory leaks first. Then if you still need large heap — switch to ZGC or Shenandoah which keep pauses under 1ms regardless of heap size.
#Java #JVM #GC #Performance #Heap
== vs equals() in Java
== compares memory addresses — are these two variables pointing to the same object in heap?
equals() compares content — are these two objects meaningfully the same?
Default equals() from Object class just does ==. The magic happens when you override it — like String does, comparing character by character.
Two Dogs with the same name are two different objects at different heap addresses. == returns false. Override equals() and it returns true.
Important rule — whenever you override equals() always override hashCode() too. Otherwise HashMap and HashSet break completely.
#Java #CoreJava #Equals #Hashcode
Shallow Copy vs Deep Copy
Shallow copy — copies the object but nested objects are still shared. Change a nested object in the copy and the original changes too.
Deep copy — copies everything completely. Original and copy are fully independent. Change anything in one — the other doesn't care.
Most common approach for deep copy in real projects — copy constructor, or serialize then deserialize, or libraries like ModelMapper.
#Java #CoreJava #DeepCopy #ShallowCopy
Serialization in Java
Serialization converts an object into a byte stream so it can be saved to a file, sent over a network, or stored in cache.
Deserialization is the reverse — byte stream back to object.
Serializable is a marker interface — no methods, just tells JVM this class can be serialized.
Used for — saving object state to file, sending objects between services, storing in Redis, deep copying objects.
The output is binary — not human readable. If you need human readable use JSON instead.
#Java #Serialization #CoreJava
transient vs volatile
Two completely different problems — just both are field modifiers.
volatile — always read fresh value from main memory, bypassing CPU cache. Solves visibility problem between threads.
transient — skip this field during serialization. Field won't be written to file or sent over network. Most common use — sensitive data like passwords and tokens you never want leaving the application.
#Java #CoreJava #Volatile #Transient #Threads
Reflection in Java
Reflection API gives access to private fields, methods, constructors and annotations at runtime — bypassing normal access rules.
Spring uses it heavily — creating beans without you calling new, injecting dependencies into private fields with @Autowired, scanning annotations like @Service and @Transactional.
JUnit finds @Test methods via reflection. Jackson reads object fields to convert to JSON. Hibernate maps fields to database columns.
Downside — slow, breaks encapsulation, and Java 9+ restricts access to internal JDK classes via module system. One of the biggest reasons companies stayed on Java 8 for so long.
#Java #Reflection #CoreJava #Spring
Abstract Class vs Interface
Abstract class — use when classes share common state and behavior. Supports only one extends. Can have instance fields, concrete methods, abstract methods.
Interface — use when unrelated classes share a contract. A class can implement many interfaces. Since Java 8 supports default and static methods too.
Real use case difference — abstract class is what you ARE, interface is what you CAN DO.
Vehicle is an abstract class — Car and Truck share speed, acceleration, fuel logic.
Flyable is an interface — Bird, Airplane, Superman are completely unrelated but all can fly.
#Java #CoreJava #AbstractClass #Interface #OOP
Design Patterns in Java
Patterns are proven solutions to common software design problems. Three categories:
Creational — how objects are created.
Singleton — one instance across entire app. DB connections, Logger, Spring beans by default.
Factory — delegate object creation to a method. Spring BeanFactory, JDBC DriverManager.
Builder — construct complex objects step by step. Lombok @Builder, HTTP request builders.
Structural — how objects are composed.
Proxy, Adapter, Decorator — Spring AOP uses Proxy pattern heavily.
Behavioral — how objects communicate.
Observer, Strategy, Template Method — used everywhere in frameworks.
#Java #DesignPatterns #CoreJava #Spring
== compares memory addresses — are these two variables pointing to the same object in heap?
equals() compares content — are these two objects meaningfully the same?
Default equals() from Object class just does ==. The magic happens when you override it — like String does, comparing character by character.
Two Dogs with the same name are two different objects at different heap addresses. == returns false. Override equals() and it returns true.
Important rule — whenever you override equals() always override hashCode() too. Otherwise HashMap and HashSet break completely.
#Java #CoreJava #Equals #Hashcode
Shallow Copy vs Deep Copy
Shallow copy — copies the object but nested objects are still shared. Change a nested object in the copy and the original changes too.
Deep copy — copies everything completely. Original and copy are fully independent. Change anything in one — the other doesn't care.
Most common approach for deep copy in real projects — copy constructor, or serialize then deserialize, or libraries like ModelMapper.
#Java #CoreJava #DeepCopy #ShallowCopy
Serialization in Java
Serialization converts an object into a byte stream so it can be saved to a file, sent over a network, or stored in cache.
Deserialization is the reverse — byte stream back to object.
Serializable is a marker interface — no methods, just tells JVM this class can be serialized.
Used for — saving object state to file, sending objects between services, storing in Redis, deep copying objects.
The output is binary — not human readable. If you need human readable use JSON instead.
#Java #Serialization #CoreJava
transient vs volatile
Two completely different problems — just both are field modifiers.
volatile — always read fresh value from main memory, bypassing CPU cache. Solves visibility problem between threads.
transient — skip this field during serialization. Field won't be written to file or sent over network. Most common use — sensitive data like passwords and tokens you never want leaving the application.
#Java #CoreJava #Volatile #Transient #Threads
Reflection in Java
Reflection API gives access to private fields, methods, constructors and annotations at runtime — bypassing normal access rules.
Spring uses it heavily — creating beans without you calling new, injecting dependencies into private fields with @Autowired, scanning annotations like @Service and @Transactional.
JUnit finds @Test methods via reflection. Jackson reads object fields to convert to JSON. Hibernate maps fields to database columns.
Downside — slow, breaks encapsulation, and Java 9+ restricts access to internal JDK classes via module system. One of the biggest reasons companies stayed on Java 8 for so long.
#Java #Reflection #CoreJava #Spring
Abstract Class vs Interface
Abstract class — use when classes share common state and behavior. Supports only one extends. Can have instance fields, concrete methods, abstract methods.
Interface — use when unrelated classes share a contract. A class can implement many interfaces. Since Java 8 supports default and static methods too.
Real use case difference — abstract class is what you ARE, interface is what you CAN DO.
Vehicle is an abstract class — Car and Truck share speed, acceleration, fuel logic.
Flyable is an interface — Bird, Airplane, Superman are completely unrelated but all can fly.
#Java #CoreJava #AbstractClass #Interface #OOP
Design Patterns in Java
Patterns are proven solutions to common software design problems. Three categories:
Creational — how objects are created.
Singleton — one instance across entire app. DB connections, Logger, Spring beans by default.
Factory — delegate object creation to a method. Spring BeanFactory, JDBC DriverManager.
Builder — construct complex objects step by step. Lombok @Builder, HTTP request builders.
Structural — how objects are composed.
Proxy, Adapter, Decorator — Spring AOP uses Proxy pattern heavily.
Behavioral — how objects communicate.
Observer, Strategy, Template Method — used everywhere in frameworks.
#Java #DesignPatterns #CoreJava #Spring
🔒 JPA — @Transactional
"The session stays open until the job finishes."
• Guarantees ACID — all or nothing
• Keeps Hibernate session alive for the entire method
• Without it → session closes after first query → LazyInitializationException
• readOnly=true → skips dirty checking → faster reads, no accidental writes
• spring.jpa.open-in-view=true (default) keeps session open till HTTP response — hides real problems, disable it
• Dirty checking: Hibernate tracks changes and auto-flushes at transaction end
💡 Reminder: No @Transactional = no session = no lazy loading.
#Java #JPA #Hibernate #Transactional #ACID #SpringBoot #EPAM
"The session stays open until the job finishes."
• Guarantees ACID — all or nothing
• Keeps Hibernate session alive for the entire method
• Without it → session closes after first query → LazyInitializationException
• readOnly=true → skips dirty checking → faster reads, no accidental writes
• spring.jpa.open-in-view=true (default) keeps session open till HTTP response — hides real problems, disable it
• Dirty checking: Hibernate tracks changes and auto-flushes at transaction end
💡 Reminder: No @Transactional = no session = no lazy loading.
#Java #JPA #Hibernate #Transactional #ACID #SpringBoot #EPAM
🔧 JPA — FETCH JOIN & @EntityGraph
"Tell Hibernate exactly what to load, exactly when you need it."
• FETCH JOIN → collapses N+1 into 1 single SQL query
• @EntityGraph → same idea, but without writing JPQL
• Both keep FetchType LAZY but load eagerly on demand
• Loop after FETCH JOIN = iterating memory, not hitting DB
• Use FETCH JOIN when you KNOW you'll need the children
• Don't use it blindly — fetching unnecessary data is still waste
💡 Reminder: LAZY is the default. FETCH JOIN is your controlled override.
#Java #JPA #Hibernate #FetchJoin #EntityGraph #SpringBoot #EPAM
"Tell Hibernate exactly what to load, exactly when you need it."
• FETCH JOIN → collapses N+1 into 1 single SQL query
• @EntityGraph → same idea, but without writing JPQL
• Both keep FetchType LAZY but load eagerly on demand
• Loop after FETCH JOIN = iterating memory, not hitting DB
• Use FETCH JOIN when you KNOW you'll need the children
• Don't use it blindly — fetching unnecessary data is still waste
💡 Reminder: LAZY is the default. FETCH JOIN is your controlled override.
#Java #JPA #Hibernate #FetchJoin #EntityGraph #SpringBoot #EPAM
🚨 JPA — The N+1 Problem
"You asked for 1 list. Hibernate made 1001 queries."
• 1 query fetches all parents
• N queries fire — one per parent — to fetch their children
• With 1000 users → 1001 DB hits
• Root cause: LAZY loading triggered inside a loop
• Grows silently — works fine in dev, crashes in production
• How to spot it: same query shape repeating in logs with different IDs
• Enable spring.jpa.show-sql=true to see it happening live
💡 Reminder: The loop is not the problem. DB roundtrips inside the loop are.
#Java #JPA #Hibernate #NPlus1 #Performance #SpringBoot #EPAM
"You asked for 1 list. Hibernate made 1001 queries."
• 1 query fetches all parents
• N queries fire — one per parent — to fetch their children
• With 1000 users → 1001 DB hits
• Root cause: LAZY loading triggered inside a loop
• Grows silently — works fine in dev, crashes in production
• How to spot it: same query shape repeating in logs with different IDs
• Enable spring.jpa.show-sql=true to see it happening live
💡 Reminder: The loop is not the problem. DB roundtrips inside the loop are.
#Java #JPA #Hibernate #NPlus1 #Performance #SpringBoot #EPAM
⚡ JPA — FetchType: LAZY vs EAGER
"EAGER loads children when parent is fetched. LAZY loads children only when you actually call them."
• LAZY = load on demand ✅
• EAGER = load everything immediately ⚠️
• Default: @OneToMany → LAZY, @ManyToOne → EAGER, @OneToOne → EAGER
• EAGER with large data = fetching millions of rows you didn't ask for
• Always prefer LAZY, load eagerly only when you explicitly need it
• Use FETCH JOIN or @EntityGraph to control loading, not EAGER
💡 Golden rule: Always LAZY. Load eagerly only when you choose to.
#Java #JPA #Hibernate #SpringBoot #Backend #EPAM
"EAGER loads children when parent is fetched. LAZY loads children only when you actually call them."
• LAZY = load on demand ✅
• EAGER = load everything immediately ⚠️
• Default: @OneToMany → LAZY, @ManyToOne → EAGER, @OneToOne → EAGER
• EAGER with large data = fetching millions of rows you didn't ask for
• Always prefer LAZY, load eagerly only when you explicitly need it
• Use FETCH JOIN or @EntityGraph to control loading, not EAGER
💡 Golden rule: Always LAZY. Load eagerly only when you choose to.
#Java #JPA #Hibernate #SpringBoot #Backend #EPAM