OpenRewrite: Automatic Code Refactoring and Maintenance

As software engineers and architects, we often face the challenge of upgrading dependencies, security patches, and framework upgrades to the latest versions. Enterprise organizations often have legacy code developed and maintained for a long time.

Updating dependency versions in the build file in many build files in the software projects, and implementing large framework upgrades can be a daunting task for developers, who must manually inspect and modify class files, properties, and the build files such as pom.xml or build.gradle or any other build files.

The OpenRewrite library will alleviate this problem among a number of tools available to us.

In this article, we will understand how the OpenRewrite library addresses these developer challenges.

Source: OpenReWrite


What is OpenRewrite?

The OpenRewrite documentation defines itself as follows:

OpenRewrite enables large-scale distributed source code refactoring for framework migrations, vulnerability patches, and API migrations.

While the original focus was on Java, OpenRewrite continuously expands language and framework coverage.

Its key feature is that it will automatically refactor source code by applying recipes to your project. These recipes are written in Java code and include in the build process using the OpenRewrite Maven or Gradle plugin. It cannot only refactor Java code but also Maven’s pom.xml, Gradle’s build.gradle, and property files( or application.yml).

Alternatively, you can also run recipes on your codebase without including them in your build process in command line interface.

mvn -U org.openrewrite.maven:rewrite-maven-plugin:run

This process will involve the refactoring of both Java code and build files such as pom.xml or build.gradle, and or application.yml. Refactoring will takes place main branch itself, without creating a feature branch a separate CI pipeline or build profile.

OpenRewrite offers a plethora of modules that are readily available for code maintenance and framework upgrades, for example

Upgrading Spring Boot

Rectifying the code smells identified by Static Analysis Tools

Migrating to JDK11 or JDK 17

Upgrading from JUnit4 to JUnit5

Automated resolution to checkstyle violations

Migrate to SL4J from Log4j

Automating Maven Dependency Management

Migrate to Quarkus 2 from Quarkus 1

Migrate to Micronaut 3 from Micronaut 2

and many more

A comprehensive inventory of all recipes is available in the recipe catalogue. In the Popular Recipe Guides section, you’ll find guides for the most popular recipes.

How does OpenRewrite work Internally?

When implementing a recipe on the code base, OpenRewrite will generate a tree representation of the code that is an extended version of the Abstract Syntax Tree(AST). This tree representation furnishes fundamental information to the compiler during the compilation process and possesses various structural properties.

A “Lossless Semantic Tree” or LST is a tree structure that possesses the below properties.

The preservation of the original formatting of the code when executing the recipes through the utilization of the whitespace before and after tree elements

The source file does not expressly define encompassing types for all elements.

Markers will be associated with tree elements. Markers essentially provide metadata information.

For instance, Build markers, record the type and version of the build too that generated the LST

For instance, Java markers, such as NamedStyles comprise a named collection of styles that represent code/style formatting and associated configuration options.

The tree possesses complete serialization, notwithstanding the presence of cyclic elements. This feature enables the tree to be pre-generate in JSON format and preserved for subsequent processing.

Let’s understand above mentioned description with a pragmatic approach.

Consider the following simple example

package com.bsmlabs;

public class HelloOpenRewrite {
public String welcome() {
return “Welcome to OpenRewrite!”;

When generating the LST for this class, we will get the following output:

|—J.Modifier | “public”
|—J.Identifier | “HelloOpenRewrite”
|—J.Modifier | “public”
|—J.Identifier | “String”
|—J.Identifier | “welcome”
| —#JRightPadded
| —J.Empty
—J.Return | “return “Welcome to OpenRewrite!””

In the following example, the JavaVisitor defines the relevant visitor methods in a general class.

class JavaVisitor<P> extends TreeVisitor<J, P> {

public J visitClassDeclaration(J.ClassDeclaration classDecl, P p) {…}
public J visitIdentifier(J.Identifier ident, P p) {…}
public J visitBlock(J.Block block, P p) {…}
public J visitMethodDeclaration(J.MethodDeclaration method, P p) {…}
public J visitReturn(J.Return retrn, P p) {…}


Each of the methods available allows accessing and, crucially, modifying metadata information pertaining to the respective LST element to effect transformations in the source code. However, note that not all LST elements possess a corresponding visitor method. For instance, the J.Modifier element can solely be accessed via its parent element, namely J.ClassDeclaration or J.MethodDeclaration.

We can implement the preceding class and can develop custom refactoring recipe. In the subsequent section, we shall comprehend the methodology for executing this refactoring code in action.

OpenRewrite in Action

You can accomplish the integration of OpenRewrite into the build process with ease by utilizing either the OpenRewrite Maven or Gradle plugin. In the configuration section of the plugin, you can specify which recipes to activate for the current project.

For Maven, add the below OpenRewrite Maven Plugin in pom.xml

<!– Define the recipes available in the catalogue or to the name custom defined in rewrite.yml –>

<!– It is necessary to declare dependencies for recipes that are not included in the OpenRewrite bundle. –>


It is recommended to take a precautionary measure by executing the command mvn rewrite:dryrun. This command will generate a set of differences solely for the modifications made within the /target/rewrite directory, which will be saved in the rewrite.patch.

During the dryRun phase, if one is sufficiently confident in the modifications made, the command mvn rewrite:run may be executed for the code base. Upon completion, the system will generate a collection of changed source files, which the user can review and commit if they deem them satisfactory.

For Gradle, add the below OpenRewrite Gradle Plugin in build.gradle

plugins {
id ‘java’
id ‘maven-publish’
id ‘org.openrewrite.rewrite’ version ‘6.2.4’

rewrite {
// Define the recipes available in the catalogue or to the name custom defined in rewrite.yml
// for running external recipe modules
dependencies {
// It is necessary to declare dependencies for recipes that are not included in the OpenRewrite bundle.

And also if you want to add custom related changes you can add it rewrite.yml and place it under the root of the project (or in /META-INF/rewrite). In this file, you can add as many number of recipes as you desired, For instance, if you wanted to run the ChangePackage recipe to change to, you can add a rewrite.yml file that looks like this:

name: com.bsmlabs.ChangePackageExample
displayName: Rename package name example
oldPackageName: com.bsmlabs.openaccount
newPackageName: com.bsmlabs.account
recursive: null

Having defined com.bsmlabs.ChangePackageExample, it is now imperative to activate it in your build file.

For Maven


For Gradle

plugins {
id(“org.openrewrite.rewrite”) version(“6.2.4”)

rewrite {

repositories {


OpenRewrite is a potent instrument that facilitates the systematic maintenance of numerous software projects within an organization. It offers a plethora of refactoring recipes that automate various maintenance tasks, including dependency updates and resolution of issues identified by static code analysis tools. Nonetheless, given that OpenRewrite is still in the developmental phase, the stability of the recipes may not be guaranteed. It is recommended to utilize the latest versions of both OpenRewrite and the recipes whenever feasible.

In the next blog post, I will show you how to migrate Java and Spring Boot projects using OpenRewrite recipes.

The post OpenRewrite: Automatic Code Refactoring and Maintenance appeared first on foojay.