Code Transformation with Amazon Q
Tags: aws, tutorial, genai, java
Published: 2024-07-09 09:24:42

## Introduction

An exciting feature of `Amazon Q` is the concept of agents that autonomously perform a complex, multistep task from a single prompt. One of these agents is the "Developer Agent for Code Transformation" which automates the process of upgrading and transforming Java applications from `Java 8` or `Java 11` to `Java 17`, with more language support on the way.

I have previously demonstrated this capability using a simple `Java 8` example. However, when I stumbled upon an old `Java 11` Spring Boot application with thousands of lines of code, the build failed to compile on `Java 17` with various upgrade issues, and it meant a time-consuming process to manually step through all of the problems.

Now, a few months on, I wanted to see whether any step change improvements had been made to the agent, so dug out the old codebase.

## Setting up the Java 11 Bicycle Licence Application

In March 2020, I presented at an online AWS Tech Talk on new features of `Amazon QLDB`. To bring this to life, we built a quick demo using Java 11 and Spring Boot. You can find the code repository on GitHub [here]( https://github.com/mlewis7127/bicycle-licence-ui-master). The repository does require a QLDB Ledger and table to be set up in the `eu-west-2` region, with more details provided in associated `README.md` file.

First create a new QLDB ledger in the `eu-west-2` region:

![QLDB Create Ledger](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pir04argrt50t302w3sz.jpg)

And once created, open up the `PartiQL editor` and run a command to create a new table:

![QLDB Create Table](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m7nrcj5dsh9jm0uhu8sh.jpg)

Then we create a new directory by cloning the repository using the following command:

```shell
git clone https://github.com/mlewis7127/bicycle-licence-ui-master.git
```
We will use the JetBrains Intellij IDEA for this transformation, and choose to open a new project and select the folder created in the previous step.

![Open Project in Intellij](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5s79zimkrgknye6y707r.jpg)

If a pop-up appears, enable annotation processing for Lombok. Make sure to set the project to use version 11 of the `Java SDK`. I am using `Amazon Corretto` for my distribution of the Open Java Development Kit (OpenJDK).

![Set up Java 11 SDK](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zdbshg9uwiba9sck11rd.jpg)

This is set for the project by selected `File --> Project Structure`, and select `Project` under `Project Settings`. Clicking on the SDK dropdown box, allows you to select `Download SDK` where you can specify the version and vendor of the JDK to download.

From here, run a Maven `clean` and then a Maven `compile`. In the screenshot below I am doing this from the Maven plugin, or you can run from the command line. This will compile all of the code successfully as shown below.

![Maven Compile Success](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/398yphdyl23ycr6v1cza.jpg)

Now launch the application by running the `BicycleLicenceApplication` class in a new configuration.

![Application Run Configuration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yuc8tzcxsfxy3mbvjraj.jpg)

This will start the application, which can be accessed in a browser window on `http://localhost:8080/`. I have put together a short video below showing the application running as a `Java 11` application.

{% embed https://youtu.be/LbmzamV9CZA %}

## Using Amazon Q to automatically upgrade to Java 17

Now we have the application successfully running using `Java 11`, we want to upgrade to `Java 17`. We tell `Amazon Q` that we want to use the Code Transformation agent by opening a chat window and typing `/transform` and selecting the agent.

![Transform](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8r5xgdfzrt05fin89229.jpg)

This launches the `Developer Agent for Code Transformation`. The `bicycle-licence-ui` module is automatically selected, and we press confirm to let the agent know we want to upgrade to `Java 17`.

![Code Transformation Agent](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y0hkr99x4z53biu86dsd.jpg)

Once we select transform, the agent takes over. It starts by building the Java module. Then it uploads the project artefacts that it has just built. Once these files have been uploaded, the code transformation job has been accepted, and the agent begins building the code in a secure build environment. Once built, `Amazon Q` begins analysing the code in order to generate a transformation plan.

Once created, you can see a summary of the transformation plan. In this case, we have an application with almost 2500 lines of code, in which we need to replace 2 dependencies, with changes made to 5 files.

![Code Transformation Plan](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r7lh0uxk5gdpcw2qqfm6.jpg)

A summary is also provided of the planned transformation changes.

![Planned Transformation Changes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0wflrgxon5grz46hh59m.jpg)

The transformation plan generated follows a 3 step process:

1. Update JDK version, dependencies and related code
2. Upgrade deprecated code
3. Finalise code changes and generate transformation summary

This is where the massive improvements in code transformation shone. A few months ago, when the build of the application to `Java 17` failed, the automated process abruptly ended. Now, the agent takes the compilation errors, and looks to make changes to fix the errors, before attempting to build the code again. You can see below it took several attempts, making changes each time, before the code could successfully build on `Java 17`. The key point is this was all automated, with no manual input required.

![Step 1 Compilation Errors](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fzvw3m5u63dq2u4q3cjt.jpg)

After just 16 minutes, the code transformation was complete and had succeeded.

![Code Transformation Summary](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x0ynl5h1yxqycrtjpv37.jpg)

`Amazon Q` lets us know about the planned dependency that it updated, with the other identified dependency having been removed.

![Planned Dependencies Replaced](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/in3juu0yeum1g04x95d2.jpg)

As well as a number of additional dependencies that were updated during the upgrade

![Additional Dependencies Updated](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jxsmwl4xychclap81bk9.jpg)

A pop up box allows you to see which files have been changed, and you  can select each file individually and run a side by sided comparison to evaluate the changes.

![Apply Patch](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d7aas6jchnu8d1pn2i0r.jpg)

As an example, I can see that all all references to `javax.servlet.http.HttpServletRequest` have been replaced by `jakarta.servlet.http.HttpServletRequest` as `Spring Boot 3.0` has migrated from `Java EE` to `Jakarta EE` APIs for all dependencies. The agent had also implemented a new interface that was present in the latest Spring Framework version, that had not previously existed.

After this, we accept the automated updates, and run a Maven `clean` and a Maven `compile` before making sure we click on the top left button in the screenshot to reload the latest version of the dependencies:

![Reload Maven Project](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jxa6zf4mjffobg79dew8.jpg)

We can launch and test the application which is now running on `Java 17`.

{% embed https://youtu.be/eKIGflrCQ1s %}

## Final Observations

There has been a **massive improvement** in the capability of the “Developer Agent for Code Transformation” over the past few months. If you had tried and discounted the agent, you should definitely look to give it another go. As the underlying models improve, I think we will see further step change improvements happen in very short timescales on an ongoing basis.

Two areas to call out for me are:

**Unit Testing**
In the video above, the call to verify the digest failed with a `java.lang.NoSuchFieldError` in the logs. This is an example where despite having no compilation errors, we can still experience runtime errors. I have updated the GitHub repository with some unit tests as an example, which demonstrates how Amazon Q executes these tests as part of the code transformation.

![Amazon Q Unit Tests](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1qkkbc9syf39mawmd0ko.jpg)

We were able to fix the error by correcting a version mismatch between AWS SDK modules. This may not be found by unit tests, unless we were able to interact directly with AWS endpoints as part of these tests, and this is something being worked on. Nevertheless, ensuring there are sufficient unit tests to provide coverage of the core functionality will help to reduce examples of code compiling correctly but failing at runtime.

**AWS SDK Upgrades**
Although a number of libraries and frameworks were upgraded such as Spring and Log4j, the AWS SDK itself remained on Java 1.x. A big reason for this is the upgrade to AWS SDK for Java 2.x is a major rewrite that will typically require custom development to make work.

Watch the video below to see the agent in action and the steps it takes as described throughout this post

{% embed https://youtu.be/e7Mvek3wP38 %}