Most "I tried Codex on Java" posts use a greenfield todo app. I did the opposite: a Spring Boot monorepo with a real domain model, MapStruct mappers, a Flyway migration history, and a test suite that already existed before the agent showed up.
I ran it for a couple of weeks. What surprised me wasn't where it failed — it was where it looked finished and wasn't.
Codex and Claude Code are different shapes
The first thing to internalise is that "Codex" is two products wearing one name: the open-source CLI in your terminal, and Codex Cloud, the async agent you trigger from a dashboard or by tagging @codex on a GitHub issue.
The mindset gap with Claude Code matters more than the feature gap. Claude Code is interactive — you watch it work and approve the risky steps as they arrive. Codex is built for delegation. You describe a task, walk away, and come back to a diff or a PR. I queue three small tasks, close the laptop, and review after dinner. You don't babysit Codex the way you babysit Claude Code, and you can't fire-and-forget Claude Code the same way. That split is the whole reason I keep both installed.
The one line in AGENTS.md that pays for itself
AGENTS.md is Codex's project-instructions file — the twin of Claude Code's CLAUDE.md. Codex offers to draft one on first run; let it, then throw half away, exactly like /init. Generated instruction files guess at conventions they can't know.
Here's close to what I actually run on a Spring Boot / Java 21 / Maven app:
## Project
- Spring Boot, Java 21, Maven. Use the wrapper: `./mvnw`.
- Layering: controller -> service -> repository. No business logic in controllers.
- MapStruct for DTO mapping. Constructor injection only.
## Conventions
- Records for read DTOs. Validation in the DTO via Bean Validation, not the service.
- Return `ResponseEntity<T>`; route errors through the global
`@RestControllerAdvice`, never inline try/catch in controllers.
- Tests: JUnit 5 + AssertJ; MockMvc for controllers, `@DataJpaTest` for repos.
## Commands
- Build and test: `./mvnw -q test`
- Do NOT run `./mvnw clean` unless I explicitly ask.
## Rules
- After any change, run `./mvnw -q test` and only tell me you are done
if it passes.
- Match the surrounding file style. Do not "modernize" working code to streams.
That last rule — only say done if it passes — is the highest-leverage sentence in the file. Left alone, Codex will hand you a diff it never compiled. One line forces it to find its own compile errors before it talks to you.
Codex also supports cascading AGENTS.md files, so in a multi-module build the payments module can carry tighter rules than the shared library.
Approval modes: why I don't run full-auto on Java
There are three modes: suggest (propose everything), auto-edit (edit files, ask before shell), and full-auto (the whole loop, sandboxed with network off).
Full-auto feels like the future and is how you lose an afternoon. On a real working copy it will decide target is stale, run ./mvnw clean, and then sit there unable to reach your internal Nexus mirror to re-download a dependency. It also can't reach your database, so any test expecting a live datasource fails in the sandbox and Codex reports "tests failed" with no useful reason.
On Java I keep it on suggest. auto-edit is the middle ground for refactoring one module where I trust the edits but want to eyeball the commands.
The cloud sandbox is the best and worst part
The sandbox is the headline safety feature and the biggest Spring Boot gotcha at once.
What bit me: I handed Codex a task whose integration test hit a local Postgres. Green locally. In the sandbox, no Postgres and no network — so the test failed and Codex spent its budget refactoring the test instead of the feature.
The rule I landed on: scope Codex tasks to things covered by @DataJpaTest with an embedded or Testcontainers database, or treat Cloud as a code generator and verify locally yourself. If the task needs your real network or your real database, it is not a Cloud task.
A concrete run: "fix this issue and open a PR"
A teammate filed a bug — pagination on GET /api/orders ignored the sort parameter and silently returned insertion order. I tagged @codex with a one-line brief: sort by createdAt desc when no sort param is given, add a test proving it, open a PR.
Fifteen minutes later: a branch, a three-line controller change, a test that genuinely proved the regression, and a PR description.
What it got wrong: it put the sort inside the controller instead of pushing it into the repository query method — exactly the layering rule my AGENTS.md forbids. The instruction slowed it down but didn't stop it. I moved it down in about a minute and merged.
That's the honest shape of the win. It does the bulk of the mechanical work; I own the last five percent and all of the judgment.
Where it still trips up
- The network wall. Maven mirrors, databases, internal services — none exist in Cloud. Plan around it or run locally.
- Token-metered billing. A Spring Boot build with a long tool-call loop burns credits far faster than flat-rate days did. I watch the dashboard now the way I used to watch my cloud bill.
-
No persistent local state. Each Cloud task starts from a fresh checkout. If the context isn't in
AGENTS.md, you re-explain the terrain every single time. - Business logic it can't see. It will write code that compiles and passes the tests it wrote, then get the business rule subtly wrong. A green build is not correct behaviour, and that part stays on me.
- Weaker enforcement than hooks. The sandbox is coarse: strong isolation, weak "never touch this specific file" control. Claude Code's hooks still win there.
The setup, in five lines
Install the CLI. Write a tight AGENTS.md (build command + the "only done if tests pass" rule). Keep approval on suggest for anything on a real working copy. Verify on your own machine when the task needs a database Cloud can't reach. Review every diff like a stranger wrote it — because a stranger effectively did.
Do that and Codex becomes a reliable junior pair that ships its own PRs. Skip the discipline and it becomes the fastest way yet to merge something that builds green and behaves wrong.
I write about what AI coding agents actually do to real Spring Boot codebases — including the parts where the build goes green and the feature silently isn't there. The longer version of this one, with the full AGENTS.md and the failure logs, is at aikitguides.com/blog/codex-spring-boot.
Top comments (0)