Skip to main content

Proof of value (POV) process

Moderne automates code maintenance tasks like framework migrations, security vulnerability fixes, and code quality improvements. Work that traditionally takes months can be completed in minutes, freeing developers to focus on delivering business value.

This guide walks through a typical proof of value (POV) process to help you evaluate Moderne's capabilities. We recommend starting with lower-risk tasks like code quality improvements before moving to more complex migrations.

Progression from simple to complex automation tasks

Proof of value steps

  1. Platform provisioning - Moderne provisions an isolated platform in your chosen cloud provider and region (takes ~1 hour).

  2. Mass Ingest - Your team sets up an ingestion pipeline to build and publish LST artifacts for your repositories. You should start with 100 or more diverse repositories for best results. This step does not require you to make any changes to the repositories themselves (such as installing build plugins).

  3. Agent setup - Your team sets up the Moderne agent following our on-premise agent configuration doc. The agent runs as a Docker image or JAR and connects to your source code manager (SCM) and artifact repository using read-only service accounts (takes less than 1 hour with accounts ready).

  4. Run recipes - With everything set up, you can now run recipes against your code. We strongly recommend starting with simple code quality improvement recipes before progressing to complex migrations. You can find our recommended recipes to run and examples of what they do in the next section of this doc.

  5. Study results - After you've run a recipe, you should generate data tables and visualizations to learn more about what happened.

note

The recipes below progress from simple to complex. Links go to the public Moderne Platform where you can test on open-source repositories. You can also run these recipes using the CLI commands provided in each section.

Code quality recipes

Common static analysis issues

Resolves common static analysis issues (SAST issues) to improve code quality, fix mistakes, eliminate legacy patterns, and resolve performance issues.

CLI commands

mod run . --recipe org.openrewrite.staticanalysis.CommonStaticAnalysis
mod study . --last-recipe-run --data-table SourcesFileResults

Recipe results

Static analysis fixes

Code search and impact analysis

Many developers use Moderne every day for code search. Need to plan a refactor? Want to understand how an API is used? Trying to assess security concerns? All of these questions can be answered by running search recipes across your repositories.

This is possible because Moderne treats your code like a data warehouse. Our type-aware search capabilities go far beyond simple text searches. They understand your code's structure, inheritance hierarchies, and semantic relationships. It's effectively like running a database query across your entire codebase.

One of the most powerful applications of search is impact analysis – understanding what will be affected before you make changes. The search recipes below help you assess the scope and impact of potential transformations, giving you confidence before running large-scale refactors or migrations.

To see learn more about impact analysis and how to automate it, check out this video:

Find types

Identifies classes, interfaces, or enums matching a type pattern. Crucial for understanding class usage and inheritance hierarchies before performing refactoring or migrations.

tip

If you don't remember the exact type, try replacing parts of the expression with * as a wildcard and go from there.

CLI commands

# Example: Find all uses of Apache Commons StringUtils across your codebase
mod run . --recipe org.openrewrite.java.search.FindTypes \
-P "fullyQualifiedTypeName=org.apache.commons.lang3.StringUtils" \
-P "checkAssignability=true"

mod study . --last-recipe-run --data-table SourcesFileResults

Recipe results

find-types-example.png
Discovering type usage patterns across repositories

Find methods

Locates method invocations matching a method pattern, even when methods are imported in different ways or invoked on subclasses. Essential for understanding API usage before refactoring.

tip

Unsure how to accurately identify methods? Check out our documentation on method patterns.

CLI commands

# Example: Find all uses of methods in org.apache.commons
mod run . --recipe org.openrewrite.java.search.FindMethods \
-P "methodPattern=org.apache.commons..*#*(..)" \
-P "matchOverrides=true"

mod study . --last-recipe-run --data-table SourcesFileResults

Recipe results

Finding method usage across repositories

Find sensitive API endpoints

Discovers REST API endpoints that handle sensitive data. Essential for security audits, understanding data exposure, and planning privacy improvements.

CLI commands

# Find endpoints handling personal data fields like names and emails
mod run . --recipe org.openrewrite.java.security.search.FindSensitiveApiEndpoints \
-P "fieldNames=firstName,lastName,email,emailAddress" \
-P "transitive=true"

mod study . --last-recipe-run --data-table SourcesFileResults

Recipe results

find-sensitive-api-endpoints-1.png
Identifying sensitive API endpoints for security review

find-sensitive-api-endpoints-2.png
Sensitive values can be found on super classes of types used in API endpoints

Find SQL statements

Identifies SQL statements in your codebase, including those constructed through string concatenation. Useful for understanding database dependencies, finding potential SQL injection vulnerabilities, and planning schema changes.

CLI commands

# Find all SQL statements, particularly useful for identifying dynamic SQL construction
mod run . --recipe org.openrewrite.sql.FindSql

mod study . --last-recipe-run --data-table DatabaseColumnsUsed

Recipe results

find-sql-example.png
Discovering SQL statements across the codebase

Logging improvements

Parameterize SLF4J logging statements

Converts string concatenation in log statements to parameterized logging for significant performance boosts, especially when log levels are disabled.

CLI commands

mod run . --recipe org.openrewrite.java.logging.slf4j.ParameterizedLogging
mod study . --last-recipe-run --data-table SourcesFileResults

Recipe results

Logging improvements

Complete exception logging

Ensures exceptions are logged with full stack traces rather than just messages. Many exception types lack useful messages, and stack traces are critical for debugging.

CLI commands

mod run . --recipe org.openrewrite.java.logging.slf4j.CompleteExceptionLogging
mod study . --last-recipe-run --data-table SourcesFileResults

Recipe results

Adding useful exceptions to logs

Dependency management

Dependency insight for Gradle and Maven

Finds all dependencies (including transitive) across Gradle and Maven projects. Useful for identifying version inconsistencies that can cause runtime issues.

CLI commands

# Example: Find all Jackson library versions
mod run . --recipe org.openrewrite.java.dependencies.DependencyInsight \
-P "groupIdPattern=com.fasterxml.jackson.*" \
-P "artifactIdPattern=*" \
-P "scope=runtime"

mod study . --last-recipe-run --data-table DependenciesInUse

Recipe results

A data table that includes information about what repositories use the dependency we specified above.

A visualization generated from the recipe results that shows the different versions of the specified dependencies across the selected repositories.

Update Gradle wrapper

Updates Gradle wrapper to the latest version, querying services.gradle.org for available releases while respecting your artifact repository configuration.

CLI commands

mod run . --recipe org.openrewrite.gradle.UpdateGradleWrapper
mod study . --last-recipe-run --data-table SourcesFileResults

Recipe results

Updating the Gradle wrapper

Update Gradle plugins

Updates Gradle plugins by ID to newer versions.

CLI commands

# Update specific plugin - adjust parameters for your plugins
mod run . --recipe org.openrewrite.gradle.plugins.UpgradePluginVersion \
--recipe-option "pluginIdPattern=org.springframework.boot" \
--recipe-option "newVersion=3.4.x"

mod study . --last-recipe-run --data-table SourcesFileResults

Recipe results

An example build.gradle change.

Security

Find secrets

Locates secrets like passwords, API keys, and tokens stored in plain text.

CLI commands

mod run . --recipe org.openrewrite.java.security.secrets.FindSecrets
mod study . --last-recipe-run --data-table SourcesFileResults

Recipe results

Example of a secret being found in the code.

Use secure random

Replaces java.util.Random with cryptographically secure java.security.SecureRandom.

CLI commands

mod run . --recipe org.openrewrite.java.security.SecureRandom
mod study . --last-recipe-run --data-table SourcesFileResults

Recipe results

Example demonstrating Random being replaced with SecureRandom.

Java security best practices

Applies multiple security improvements including XML parser XXE vulnerability fixes, secure temporary file creation, Zip slip vulnerability remediation, file descriptor leak prevention, and loop condition safety checks.

CLI commands

mod run . --recipe org.openrewrite.java.security.JavaSecurityBestPractices
mod study . --last-recipe-run --data-table SourcesFileResults

Recipe results

Example demonstrating how this recipe handles security issues such as the Zip slip vulnerability.

OWASP Top Ten

Identifies and remediates vulnerabilities from the OWASP Top Ten including broken access control, cryptographic failures, injection, security misconfiguration, vulnerable components, and data integrity failures.

CLI commands

mod run . --recipe org.openrewrite.java.security.OwaspTopTen
mod study . --last-recipe-run --data-table SourcesFileResults

Recipe results

Example demonstrating how this recipe fixes security issues such as CSRF attacks.

A vulnerability report that includes detailed information about the affected artifact and the corresponding CVEs.

The vulnerablity report also shows the severity of the CVE and the depth (transitivity) of the dependency. ~80% of vulnerable dependencies are transitive.

Find and fix vulnerable dependencies

Software composition analysis (SCA) tool that detects and upgrades dependencies with known CVEs. Uses GitHub Security Advisory Database which aggregates multiple vulnerability databases including the National Vulnerability Database.

CLI commands

mod run . --recipe org.openrewrite.java.dependencies.DependencyVulnerabilityCheck \
-P "scope=runtime" \
-P "overrideTransitive=True" \
-P "maximumUpgradeDelta=patch"

mod study . --last-recipe-run --data-table VulnerabilityReport

Recipe results

Example demonstrating how this recipe updates minor versions to get critical security fixes.

A vulnerability report that includes detailed information about the affected artifact and the corresponding CVEs.

The vulnerablity report also shows the severity of the CVE and the depth (transitivity) of the dependency. ~80% of vulnerable dependencies are transitive.

Test modernization

JUnit Jupiter best practices

Migrates to JUnit 5 and applies best practices to tests. This recipe will: migrate from JUnit 4.x to JUnit Jupiter, statically import JUnit Jupiter assertions, remove the test prefix and public visibility from JUnit 5 tests, add @ParameterizedTest annotations, and improve lifecycle methods – among other things.

CLI commands

mod run . --recipe org.openrewrite.java.testing.junit5.JUnit5BestPractices
mod study . --last-recipe-run --data-table SourcesFileResults

Recipe results

Applying best practices to JUnit tests.

AssertJ best practices

Migrates assertions to AssertJ for better readability. Migrates from JUnit, Hamcrest, Fest, and TestNG assertions, statically imports assertThat, simplifies chained assertions, and adopts type-specific assertions.

CLI commands

mod run . --recipe org.openrewrite.java.testing.assertj.Assertj
mod study . --last-recipe-run --data-table SourcesFileResults

Recipe results

Applying AssertJ best practices to a test class.

Major migrations

Major migrations are complex transformations that typically automate 80-90% of the work, with the remainder requiring manual developer intervention. They are typically composed of multiple, complex recipes.

Migrate to Java 25

Comprehensive migration from Java 8/11 to Java 25. Updates build files for Java 25 target/source, replaces deprecated APIs, adopts new language features, upgrades plugins to Java 25 compatible versions, and updates GitHub Actions configurations.

CLI commands

mod run . --recipe org.openrewrite.java.migrate.UpgradeToJava25
mod study . --last-recipe-run --data-table SourcesFileResults

Recipe results

Updating the Java version

Fixing deprecated methods

Spring Boot 3.5 best practices

Migrates to Spring Boot 3.5 and applies best practices. Includes upgrades from prior Spring Boot versions with configuration updates and dependency alignment.

CLI commands

mod run . --recipe io.moderne.java.spring.boot3.SpringBoot3BestPractices
mod study . --last-recipe-run --data-table SourcesFileResults

Recipe results

Applying Spring Boot best practices to a Java class.