Naman Muley
Recommendation Summary
The candidate to implement a more scalable concurrency model in Java and optimize the application's Dockerfile. They to guide the AI's implementation and before accepting it. However, this strong AI collaboration was undermined by , as they committed the final code without any building, testing, or runtime checks.
What went well5
What didn't go well1
Google Chrome
GitHub
iTerm2
Cursor
Cursor AI
macOS Terminal
Optimize Java REST API and Docker Efficiency
Java DeveloperProblem Statement
You are given a fully functional Java Spring Boot REST API for tracking tasks, already containerized using Docker. The API has noticeable response delays and the container image is large with slow rebuilds. The Java code holds completed tasks in an ArrayList that's never cleared (causing high memory usage), and background statistics updates run synchronously, blocking main threads. The Dockerfile uses an oversized base image, copies all source files unnecessarily, and lacks .dockerignore. Your task: Refactor the Java API to (1) clean up memory leaks in task management, (2) implement background stats updates using basic async patterns (ExecutorService), and (3) containerize efficiently with Docker best practices (.dockerignore, slim image, improved build layering, JVM limits). Your improvements should address BOTH Java (concurrency, async patterns, performance) and Docker (image size, build speed, resource control) equally.
- Reduce API response times so requests complete faster and users wait less.
- Stabilize memory use to prevent crashes and keep the service running smoothly.
- Implement asynchronous task handling so background jobs run without slowing the app.
- Make Docker images smaller to speed up deployments and save storage.
- Speed up rebuilds so updates can be tested and released more quickly.
- Tune JVM settings to balance CPU and memory for predictable performance.
- Combine these changes to deliver a reliable, production-ready system for long-term use.
- Write production level clean code with best practices including proper design patterns, naming conventions, exception handling, logging and observability etc.
Candidate Response
Candidate’s submission
Code changes
Steered the AI to a better concurrency model using ExecutorService and accepted a clean multi-stage Dockerfile, but the final Java code contained thread-safety flaws and lacked proper resource management. All changes were committed without any form of building, testing, or verification.
Consistently inspected relevant source files (TaskController.java, TaskService.java, Dockerfile) before prompting for changes. This review, however, was limited to static code analysis; no attempt was made to run the application or its tests to observe runtime behavior.
Successfully diagnosed and resolved an initial git clone authentication failure. More significantly, redirected the AI's architectural approach from Spring's @Async to a more explicit ExecutorService, demonstrating the ability to correct the implementation plan based on technical judgment.
Critically evaluated AI-generated code, identifying the use of Spring's @Async and redirecting the implementation to a more suitable ExecutorService. Further refined the AI's output by specifying the use of a cached thread pool, demonstrating strong technical judgment in steering the assistant.
Made significant changes to both the application's concurrency model and its containerization strategy without any verification. No builds, tests, or application runs were executed to confirm that the changes were correct, functional, or even compiled.
Demonstrated solid technical judgment by directing the AI to use ExecutorService instead of Spring's @Async for concurrency. However, the choice of an unbounded cached thread pool introduced potential scalability risks, and other key issues like a memory leak and thread-safety for shared collections were left unaddressed.
No tests were designed, written, or executed at any point in the session. Changes to the application's concurrency model and container build process were made without any form of automated or manual test to validate their correctness or performance.
While the AI produced a clean multi-stage Dockerfile, the candidate-directed changes to the Java service introduced significant quality issues. The final code uses a non-thread-safe list in a concurrent context, lacks a proper shutdown mechanism for its unbounded thread pool, and leaves a pre-existing memory leak unaddressed.
Highly specific prompts were used to steer the AI through complex Java concurrency changes, including correcting the AI's initial approach and tuning thread pool behavior. The candidate consistently paused to review generated code for both Java and Docker optimizations before accepting changes, maintaining firm control over the implementation.
AI-generated code diffs and explanations were consistently held still for review, with pauses ranging from 10 to 23 seconds. This careful inspection informed key decisions, such as pivoting from Spring's @Async to ExecutorService and understanding Docker multi-stage build optimizations, which was confirmed by a detailed commit message.
Prompts consistently specified exact method targets, architectural choices like substituting Spring @Async with ExecutorService, and detailed logic for handling edge cases like duplicate task IDs. This high level of specificity directly guided the AI to produce precise, desired implementations, even though some later prompts were more general goal-oriented requests.
Context was consistently provided by targeting specific methods like calculateStats and getAll with the relevant files open. More importantly, prompts augmented this with explicit architectural constraints, such as substituting Spring annotations with ExecutorService, and domain rules, like how to handle duplicate task IDs.
Proactive and decisive steering was demonstrated when the candidate immediately pivoted the AI away from a proposed Spring @Async implementation toward an explicit ExecutorService. This was followed by further directional prompts to tune the thread pool and implement specific business logic for handling duplicate tasks, maintaining tight control over the implementation path.
The candidate engaged in some design exploration by asking to replace the AI's initial @Async suggestion with an ExecutorService, which directly altered the technical approach. A later open-ended question about Docker optimization was also posed, though the first suggestion was accepted without further discussion or exploration of alternatives.
Broke the problem down into API performance and Docker optimization phases, handling each sequentially. Iterated effectively on technical challenges like git failures and AI suggestions, but did not create an upfront plan and submitted the final solution without any build, runtime, or test verification.
The problem was broken down into sequential, high-level phases, first addressing API performance and then Docker optimization. Within the API phase, specific bottlenecks like asynchronous calculation and task duplication were isolated and handled incrementally. However, a comprehensive upfront plan covering all requirements was never articulated.
Deliberately rejected the AI's initial suggestion of using Spring's `@Async` annotation, steering instead toward an explicit `ExecutorService`. Further refined this approach by selecting a `newCachedThreadPool` for scalability. However, when optimizing the Dockerfile later, the first solution proposed by the AI was accepted without exploring or comparing alternatives.
Consistently started implementation phases by querying the AI about a specific sub-problem without first creating or verbalizing a comprehensive plan. For both the Java service modifications and the later Docker optimizations, the approach was reactive, following a sequence of prompts or adopting the AI's generated outline as the de facto plan.
When encountering failures, the candidate effectively diagnosed the root cause and applied a correct fix. This was seen early on when resolving a git clone authentication issue and later when a git push failed due to diverged history, which was decisively resolved with a force push.
A significant portion of the session was spent on setup, code review, and generating code with the AI. Time was not budgeted for verification, leading to the session ending with all changes being committed and pushed without any build, test, or runtime validation.
No verification was performed at any stage of the process. Code modifications to the Java service and configuration changes to the Dockerfile were accepted and committed without being compiled, built, or run. The final solution was pushed without any form of testing.
Comments
Loading comments…