Legacy Java apps don’t age gracefully. Java 8 reached end of open-source support in 2019, Spring Boot 2.x followed in November 2023, and yet countless production codebases are still running on them—because upgrading manually is painful, risky, and time-consuming. AWS Transform promises to automate exactly this through agentic AI. I decided to put it to the test on a real Spring Boot petclinic app and document everything: setup, the first error I hit, what the agent changed, and whether the app actually ran afterward.
Spoiler: it worked. The agent made 528 line changes across 18 files, the dashboard showed 100% validation rate, and the petclinic came up clean on Java 21. Here’s the full story.
What is AWS Transform?
AWS Transform is AWS’s platform for enterprise IT modernization powered by agentic AI. It handles mainframe refactoring, VMware migration, Windows modernization, and—the focus here—Custom workloads like Java, Python, and Node.js runtime upgrades.
The platform learns from every transformation, and the numbers on their workspace dashboard reflect the scale of enterprise adoption:
Key Features & Concepts
Before diving in, here are the core building blocks of AWS Transform:
🌐 Workspaces
Containers where you create jobs, store artifacts, and collaborate. Think of them as project folders with an AI agent as the project manager.
🤖 Agentic Job Plans
Multi-step workflows where the agent collects requirements through chat, then hands you a CLI command to execute locally against your codebase.
🔗 Connectors
Outgoing and incoming connectors for cross-account resource access. Useful for multi-account enterprise setups.
🤝 Partner Agents
Third-party transformation agents that plug into your workspace. They get deep access to artifacts and job data, so review security docs before enabling.
📄 Transformation Definitions
AWS-managed recipes for specific upgrade types. AWS/java-version-upgrade handles JDK bump, Jakarta EE migration, database drivers, and Spring ecosystem updates.
💻 CLI (atx)
Runs transformations locally against your codebase. Supports Custom workloads only — Java, Python, Node.js. The actual code changes happen on your machine.
Setting Up AWS Transform
AWS Transform is enabled from inside the AWS console. You need two things: the web application (the chat-based agentic UI) and the CLI (for executing transformations locally).
Step 1 — Enable Capabilities
Navigate to AWS Transform and click Get Started. The capabilities page shows two sections: CLI for Custom workloads, and Web application for the full scope including mainframe and VMware.
⚠️ Note: The CLI supports only Custom workloads. For mainframe, VMware, and Windows, you need the web application.
Step 2 — Choose Your Identity Provider
Enabling the web app requires picking an identity provider: AWS Identity Center or an existing IdP (Microsoft Entra or Okta). This is a one-time irreversible decision.
🚨 One-time decision: You cannot change the identity provider type after enabling. Pick the right one for your org before clicking Enable.
Step 3 — Setup Complete
After enabling, the success screen confirms the web application is live and a service profile has been created.
Step 4 — Install the CLI
curl -fsSL https://desktop-release.transform.us-east-1.api.aws/install.sh | bash
✅ Requirements: Node 20+ must be installed. Does not run natively on Windows (use WSL). Configure AWS credentials with required IAM policies before running any atx commands.
The App: Spring Boot Petclinic on Java 8
I needed a realistic legacy app — not a toy. The Spring Boot petclinic is a well-known demo with real dependencies: Spring Boot 2.7.3, pinned to Java 1.8, with a full stack of libraries that all need updating. Here’s the pom.xml:
<artifactId>spring-petclinic</artifactId> <version>2.7.3</version> <parent> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.3</version> </parent> <java.version>1.8</java.version>
This is a textbook modernization target. Upgrading manually means: bumping the Java version, migrating every javax.* import to jakarta.*, updating database drivers, upgrading Spring Boot to a 3.x line, and resolving cascading dependency conflicts. AWS Transform is supposed to handle all of that autonomously.
Creating a Workspace & Starting a Job
Create a Workspace & Job
In the AWS Transform console, create a workspace, then inside it create a new CustomTransformation job. You’re dropped into the agentic chat interface with a two-step job plan in the sidebar:
Chat with the Agent
I typed exactly what I wanted: "Upgrade the Java 8 Spring Boot application to Java 21."
The agent identified AWS/java-version-upgrade — an AWS-managed transformation definition that handles the full stack: JDK bump, Jakarta EE namespace migration, database drivers, ORM frameworks, and Spring ecosystem updates. I said yes. The agent then generated the CLI command and opened the Monitor panel:
🤖 The web UI has done its job: collected intent, matched a transformation definition, generated a ready-to-run command. Now it moves to the terminal.
Running the Transformation — And Hitting an Error First
I copied the command from the dashboard and ran it. First attempt: I forgot the --configuration flag.
❌ Error: Non-interactive mode requires --configuration with additionalPlanContext — the target language version must be provided before the agent runs headlessly.
Three ways to pass the config:
# Inline flag (what I used)
--configuration "additionalPlanContext=The target Java version to upgrade to is Java 21"
# JSON file
--configuration "file://path/to/config.json"
# { "additionalPlanContext": "The target Java version to upgrade to is Java 21" }
# YAML file
# additionalPlanContext: The target Java version to upgrade to is Java 21
With the flag added, the second attempt ran cleanly:
The full working command:
atx custom def exec \ --code-repository-path ~/petclinic-legacy-demo \ --non-interactive \ --trust-all-tools \ --campaign ced189bc-bafb-4465-8d67-bda247aaf391 \ --repo-name petclinic-legacy-demo \ --add-repo \ --configuration "additionalPlanContext=The target Java version to upgrade to is Java 21"
✅ --trust-all-tools skips per-tool confirmation prompts. Combined with --non-interactive, the agent runs fully autonomously. "Thinking..." means it’s reading the codebase, scanning imports, mapping dependencies.
Under the Hood: What the Agent Does While "Thinking..."
The "Thinking..." state isn’t idle. The agent immediately starts producing artifacts. First it creates a plan.json — a structured JSON file that maps out every step, its goal, target components, and the exact verification command to run after:
It then creates a Transformation Worklog — a running log file tracking the project and every action taken:
With the plan established, the agent starts making targeted edits. Here it is using the editor tool (trusted) to make precise str_replace operations on pom.xml — each one surgical, each one completing in milliseconds:
After each step’s changes pass the build verification, the agent uses the vcs_control tool to commit directly to the staging branch with a structured commit message:
🔎 Full transparency: Every tool call is logged — editor, vcs_control, build runner. You can see exactly what the agent touched and why, file by file and line by line.
The Results: What the Agent Actually Did
The agent didn’t just bump a version number. It worked through the codebase in six structured, independently-committed steps — each one passing its own build validation before the next began.
Estimated Time Saved: 422 Hours
The transformation dashboard calculated 422 hours of manual effort saved, at a baseline of 10 lines of code per developer per day. The dashboard does not update automatically — you ask the agent in chat to refresh it.
100% Validated — 528 Lines, 18 Files
The Full Transformation Summary
At the end of the run, the agent outputs a complete Transformation Summary — every version change, every library migrated, and the final test results:
The Six-Step Commit History
Every step was committed separately by ATX Bot to the atx-result-staging branch, with a build verification before each commit:
🤖 Each step validates the build before committing and moving on. If step 3 had broken the build, the agent would have stopped and reported back rather than silently proceeding to step 4.
What Changed Across Those 18 Files
💾 pom.xml
Java version bumped to 21. Spring Boot parent updated from 2.7.3 → 3.2.12. Maven compiler plugin updated. All dependency versions reconciled.
🔄 javax → jakarta
Every javax.* import across all source files migrated to jakarta.* atomically in a single step. This alone touches dozens of lines across multiple classes.
🖤 Database Drivers
H2, MySQL, and PostgreSQL driver dependencies updated to versions compatible with Jakarta EE and Spring Boot 3.x.
🧩 Spring Ecosystem
Spring Boot starters, Spring Data, Spring MVC — updated as a coordinated set, not individually, avoiding version conflict cascades.
The App Runs on Java 21
The proof that matters: does the app actually work after the transformation? I deployed the transformed code to an EC2 instance and hit it in a browser.
🎉 It works. Java 8 Spring Boot 2.7.3 → Java 21 Spring Boot 3.2.12, running in production on EC2. Zero manual code edits required.
What’s Next — Part 2: Pentesting the Modernized App
The app is live on Java 21. But a modernized app isn’t necessarily a secure app. In Part 2, I’ll walk through how I pentested this exact petclinic deployment using the AWS Security Agent — running vulnerability scans, probing the attack surface, and seeing what AWS’s AI-powered security tooling finds on a freshly modernized Spring Boot application.
🔐 Coming in Part 2: Pentesting the modernized petclinic with AWS Security Agent — what vulnerabilities surface, how the agent reports them, and what a real security posture looks like post-transformation.
Key Takeaways
⚡ Setup is fast
From zero to a running transformation took under 30 minutes including IAM Identity Center setup and CLI installation.
🤖 The agent is genuinely capable
It identified the right transformation definition without prompting, worked through 6 structured steps, validated each build, and produced a working application.
📝 Don’t forget --configuration
In non-interactive mode, --configuration "additionalPlanContext=..." is required. Easy to miss when copying the base command from the dashboard.
🔎 Incremental commits are key
Six separate commits, each with a passing build, means you can review exactly what changed at each stage and roll back to any specific step.
🌟 It goes well beyond pom.xml
The javax→jakarta migration alone touched multiple source files. The agent understood semantic meaning, not just find-and-replace.
⏱ 422 hours is real
Even at a faster LoC/day rate, the coordination cost of a Java 8→21 migration is substantial. The agent handled it in one command.