Java Bug Fix Interview Question - Retry Utility with Silent Failures
Retries That Refuse to Retry...
Scenario
You are building a retry utility in Java for a Spring Boot microservice. The utility accepts a Supplier<T> (lambda) and retries the lambda up to maxAttempts if it throws an exception.
A junior engineer writes a client code like this:
Observed Behavior
When
processItem()fails:Error is logged
Retry does not happen (only 1 attempt)
📢 Join 6,500+ subscribers and get actionable Java/Spring Boot insights every week — from practical code tips to real-world, use-case-based interview questions — and level up your Spring & backend skills with hand-crafted content, no fluff.
First 100 paid subscribers will get the annual membership at $50/year forever that is ~ $4/mo ( 71 already converted to paid, 29 remaining)
Why are retries not happening?
How RetryUtil Works (Key Contract)
return work.get();Retry happens only if
work.get()throws an exceptionIf no exception is thrown → RetryUtil assumes success and returns immediately.
What actually happens inside the code?
RetryUtil.execute(() -> {
try {
processItem(item);
} catch (Exception e) {
log.error(...);
}
return null;
});Step 1: First attempt starts
attempts = 0work.get()is called
Step 2: processItem(item) throws exception
Example:
throw new RuntimeException(”DB failure”);Step 3: Exception is caught inside lambda
catch (Exception e) {
log.error(...);
// swallowed
}This is the critical bug
Exception does NOT escape
It is absorbed locally
Step 4: Lambda completes successfully
return null;From RetryUtil’s perspective:
try {
return work.get(); // no exception thrown
}So:
RetryUtil thinks execution succeeded
It immediately returns
No retry loop is triggered
so the core problem is: We broke the retry contract by swallowing the exception.
Can you write a test that demonstrate this failing behavior? Also fix the original code.
We ca simulate a failing operation and count how many times it runs.
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import java.util.List;
import static org.mockito.Mockito.*;
class ClientProcessTest {
@Test
void should_retry_3_times_when_processItem_fails() {
// Create a spy of the client
TestClient client = Mockito.spy(new TestClient());
// Force processItem to always throw
doThrow(new RuntimeException("fail"))
.when(client).processItem(anyString());
// Call the real process method
client.process(List.of("item1"));
// Verify that processItem was called 3 times due to retry
verify(client, times(3)).processItem("item1");
}
}Fixed code:
We should let the processItem raise the exception if it failed process. By doing so , exception will reach to RetryUtil correctly and try 3 times before raising eventually when out of retries.
That’s it for this one friends! If you like this please help sharing this in your network.
Subscribe | Sponsor us | LinkedIn | Twitter
Happy Coding 🚀
Suraj





