Java 8 to Java 21 Modernization for a US Professional Membership Academy: 9 Security Vulnerabilities Resolved, 266 Tests Delivered from Zero

266

Tests Delivered from Zero

9

Security Vulnerabilities Resolved

Java 21

From End-of-Life Java 8

A US-based professional membership academy was running a Java 8 identity management suite of 17 CLI programs, 6,105 lines of code, and zero automated tests, with nine unresolved security vulnerabilities, including SSL certificate validation completely bypassed across all Active Directory connections, hardcoded passwords sent over unencrypted LDAP, and a 1,777-line god class with cyclomatic complexity of 285. Legacyleap executed a structured 7-phase modernization to Java 21 LTS: resolved every critical and high-severity security issue, decomposed the god class into 7 focused service classes, delivered 266 tests from scratch, and established a full GitHub Actions CI/CD pipeline. SpotBugs: 0 findings. Checkstyle: 0 violations. Build passes clean.

Results at a Glance

MetricResult
Security issues resolved9 (critical + high + medium)
Tests delivered from zero266 across 14 test classes
God class eliminated1,777 LOC decomposed into 7 services
Static analysis0 SpotBugs findings, 0 Checkstyle violations

Engagement Snapshot

IndustryNon-profit / Professional Membership Association
LocationUnited States
System typeIdentity management — Active Directory + OpenLDAP member provisioning
Legacy stackJava 8 (EOL March 2025), 24 source files, 6,105 LOC
Target stackJava 21 LTS, 28 source files, GitHub Actions CI/CD
Scope17 CLI programs, 1 god class (CC=285), zero tests, zero CI/CD
Delivery modelStructured 7-phase execution — assessment → security → decomposition → testing → quality gates → CI/CD → validation

About the Client

The client is a prominent US-based professional membership academy managing member accounts for thousands of fellows across multiple academy divisions. Their identity management infrastructure (a Java 8 CLI batch suite called NAS-LDAP-Utilities) synchronized member records from their Impexium membership database into Microsoft Active Directory and OpenLDAP, handling account creation, lifecycle changes, group assignments, and credential email dispatch.

The system had operated reliably for years, but had accumulated critical security debt that could not be deferred: Java 8 reached end-of-life in March 2025, the codebase had no tests and no CI/CD, and multiple high-severity security vulnerabilities were present in production.

Challenge

The modernization required resolving four compounding categories of risk simultaneously, on a live identity system with no test coverage to validate changes against.

End-of-Life Runtime with Active Security Vulnerabilities

Java 8 reached end-of-life in March 2025, meaning no further security patches. The codebase carried nine unresolved security issues on top of the EOL risk: SSL certificate validation was completely disabled across all 9 Active Directory connections via TrustAllTrustManager, making MITM attacks technically possible. All 7 OpenLDAP connections ran on plain unencrypted LDAP port 389, transmitting bind credentials and passwords in cleartext. Two programs contained hardcoded plaintext passwords (“start123”, “startnewpass”). Initial member passwords were derived from a deterministic algorithm using name and member ID, predictable if the algorithm was known.

1,777-Line God Class with Cyclomatic Complexity of 285

All 44 LDAP, AD, SMTP, and utility operations were concentrated in a single static Operations.java class of 1,777 lines of code, with a cyclomatic complexity score of 285. Every one of the 17 CLI programs called into it. Any change to Operations carried the risk of unintentionally breaking unrelated functionality across the entire suite. This made safe refactoring nearly impossible without a test suite, and building a test suite nearly impossible without refactoring the god class first.

Zero Tests, Zero CI/CD on a Production Identity System

The codebase had no automated tests whatsoever – not unit tests, not integration tests, not even smoke tests. There was no CI/CD pipeline. Changes were validated manually before deployment. With 24 source files and 6,105 lines of code managing live member account provisioning, deceased account handling, group synchronization, and credential email dispatch, there was no safety net for the modernization work.

Non-Functional Stubs, Dead Code, and Copy-Paste Artifacts in Production

ldapDeleteGroup, a program that operators could invoke to delete LDAP groups, was a non-functional stub: the deletion logic was commented out, so invoking it produced no error and no deletion. adDeleteDeceased and adEnableAccounts both performed operations without pre-validating account state.

Three CLI programs contained a copy-paste artifact (new ldapImport() at startup with no functional effect). Dead code blocks, including an unused Derby database connection layer, an unreferenced trust manager, and dead password encoding methods, added maintenance surface with no operational value.

How Legacyleap Executed the Modernization

The engagement followed a structured 7-phase execution designed to address security first, then structural debt, then quality gates, with each phase building the foundation for the next.

Phase 1: Assessment and dependency mapping

Legacyleap’s AI-powered assessment tool analyzed all 24 source files, producing a full Application Overview documenting architecture, workflows, data model, security risks, and technical debt. Every CLI program, every call path into Operations.java, and every dead code block was mapped before a single line was changed.

Phase 2: Security remediation

Every critical and high-severity security issue was addressed: NaiveTrustManager rewritten with TrustManagerFactory delegation and custom KeyStore support; TrustAllTrustManager eliminated from all 9 AD CLIs; hardcoded passwords externalized to environment variables via ConfigService; ConnectionFactory created with StartTLS for all OpenLDAP connections; SMTP upgraded to SMTP AUTH + STARTTLS; CLI credential exposure mitigated by env var/properties resolution as primary path.

Phase 3: God class decomposition

Operations.java (1,777 LOC, CC=285) was decomposed into 7 focused service classes: LdapUserService (user lifecycle), LdapGroupService (group management), NotificationService (email), ConfigService (configuration), PasswordService (SecureRandom generation), ConnectionFactory (LDAP connection), and AuditService (structured execution summaries as Java 21 records). All 17 CLI callers were updated. Operations.java was deleted.

Phase 4: Dead code removal and CLI modernization

NASConstants, Derby DB methods, dead password chain, copy-paste artifacts, and wrong constructors were removed. All 17 CLI programs received try-with-resources, parameterized logging, and StandardCharsets.UTF_8 for all file I/O, and pre-validation added to adDeleteDeceased and adEnableAccounts. Java version bumped to 21 LTS with var type inference throughout.

Phase 5: Test suite built from scratch

266 tests across 14 test classes, covering integration tests via InMemoryDirectoryServer for LDAP operations, unit tests for all service classes, DTOs, CSV I/O, and configuration resolution chains. Tests cover duplicate detection, username collision, accountExpires logic, the validUser bug fix, SecureRandom password generation, SMTP AUTH contract, and the full ConfigService env var → properties → CLI arg precedence chain.

Phase 6: Quality gates established

SpotBugs (effort=MAX, reportLevel=HIGH) reduced from 19 findings to 0. Checkstyle reduced from 15 violations to 0. All 8 runtime dependencies upgraded, including a 13-version Java jump, UnboundID LDAP SDK major upgrade, and javax.mail → angus-mail 2.0.5 namespace migration. JaCoCo added for test coverage reporting.

Phase 7: CI/CD pipeline and structural validation

GitHub Actions workflow established: triggers on push to main/develop and PRs to main, runs clean build → spotbugsMain → checkstyleMain, uploads test/JaCoCo/SpotBugs/Checkstyle reports as artifacts. Structural validation confirmed: 24 → 41 entity nodes, 150 → 400 behaviour nodes, USES edges into Operations.java reduced from 1,965 to 0.

Security Issues Resolved

IssueSeverityWhat Was FoundWhat Was Done
SSL bypass (9 AD CLIs)CriticalTrustAllTrustManager disabled all certificate validationTrustManagerFactory delegation implemented; custom KeyStore via env var
Hardcoded “start123”CriticalPlaintext password literal in setPassCn.javaExternalized via ConfigService with fail-safe exit if unset
Hardcoded “startnewpass”CriticalApplied to every new OpenLDAP user in ldapImportSame externalization pattern — refuses to proceed without configured password
Deterministic initial passwordsCriticalUppercaseFirstInitial + lowercaseLastInitial + memberID algorithmPasswordService.generateSecurePassword() using SecureRandom
Plaintext LDAP (7 CLIs)HighPort 389, cleartext bind credentials and passwordsConnectionFactory with StartTLSExtendedRequest on all connections
CLI credential exposureHighBind DN/password visible in process listings and shell historyConfigService resolves from env var / properties first; CLI args as fallback only
Unauthenticated SMTPMediumPort 25, no authentication, no TLSNotificationService with SMTP AUTH and STARTTLS
validUser bugMediumsetValidUser(true) set before null check on search entryMoved inside if (entry != null) block
Default file encodingLowFileReader without charset — platform-dependentStandardCharsets.UTF_8 applied across all 17 CLIs

Results

MetricBeforeAfter
Java version8 (EOL March 2025)21 LTS (supported to 2028+)
Automated tests0266 across 14 test classes
Critical security issues40
High security issues20
God class1,777 LOC / CC=285 / 44 static methodsDeleted — decomposed into 7 services
SpotBugs findings190
Checkstyle violations150
CI/CD pipelineNoneGitHub Actions (push + PR triggers)
Dead code / stubs5 categories presentAll removed
Source LOC6,1055,761 (−344 dead code removed)
Details

Industry

Research & Academia

LOCATION

United States

Challenge

Modernize a Java 8 identity management suite with nine active security vulnerabilities, zero automated tests, and a 1,777-line god class on a live system controlling member account access for a national academy.

Featured Services

Legacyleap

Why Legacyleap

Legacyleap's Gen AI-powered assessment mapped all 24 source files, 44 god class methods, and every security vulnerability before a single line was changed. A structured 7-phase execution resolved all four critical security issues, including SSL bypass across nine AD connections and cleartext LDAP on seven CLIs, decomposed a 1,777-line god class into seven focused services, and delivered 266 tests from zero. SpotBugs: 0. Checkstyle: 0. Build passes clean.

Running a Java 8 or Java 11 system with security debt and no test coverage?

Get a $0 assessment. Legacyleap maps every vulnerability, every dead code block, and every structural risk before a single line is changed.

No sensitive data leaves your firewall.

Test Legacyleap for Free!

Running a Java 8 or Java 11 system with security debt and no test coverage?

Get a $0 assessment. Legacyleap maps every vulnerability, every dead code block, and every structural risk before a single line is changed.

What You'll Receive:

Legacyleap platform with code analysis, dependency visualization, and modernization summary.

Frequently Asked Questions

Didn't find what you were looking for?

Legacyleap starts with a full AI-powered assessment before any code changes are made. Mapping every class, every call path, and every security risk. For this engagement, that meant documenting all 44 methods in the god class, all 17 CLI programs, and all 9 security issues before writing a single line of new code. Security remediation runs as a parallel workstream to structural decomposition, meaning vulnerabilities are closed while the architecture is being improved. The 266-test suite is built incrementally as each phase completes, creating a safety net that grows throughout the engagement rather than being bolted on at the end.

Both issues require changes at the connection layer, which in a legacy codebase like this one touches every CLI program that establishes a directory connection. For SSL, Legacyleap rewrote the trust manager to use TrustManagerFactory delegation with support for custom KeyStore configuration via environment variable, eliminating the accept-all behavior permanently. For plaintext LDAP, a ConnectionFactory class was created that wraps all connection creation and applies StartTLSExtendedRequest before any bind credentials are transmitted. Because all 17 CLIs now route through ConnectionFactory, both fixes are enforced structurally; there is no way for a new CLI to inadvertently bypass them.

The decomposition and test-writing happen together, not sequentially. Legacyleap begins by extracting the highest-risk, most clearly bounded methods first, in this case, the connection and configuration logic, and writing unit tests for each extracted service before moving to the next. This means the test suite grows in parallel with the decomposition, and each extracted service is validated before it becomes a dependency for other services. By the time the god class is deleted, every method it contained has a new home and a test covering its contract. For this engagement, Operations.java went from 1,965 inbound USES edges to 0, fully migrated, fully tested, then deleted.

The approach is the same regardless of organization type: assess the full codebase first, prioritize security issues by severity, and execute the runtime upgrade as part of a broader structural improvement rather than as a standalone version bump. For membership organizations specifically, identity management systems like this one carry additional risk because they control authentication for the entire member base, meaning security issues in the directory provisioning layer have direct consequences for member account integrity. Legacyleap’s assessment tool documents all risks before any changes begin, giving the organization a clear picture of what they are running and what needs to be fixed.

The version bump is the smallest part of the work. A full modernization engagement includes: security audit and remediation (SSL, encryption, credential management, password policies), structural refactoring (god class decomposition, dead code removal, copy-paste artifact cleanup), a greenfield test suite built to cover all critical workflows, static analysis gates via SpotBugs and Checkstyle brought to zero findings, all dependency upgrades to current stable versions, and a CI/CD pipeline that enforces quality gates on every future commit. The deliverable is not just a codebase running on Java 21. It is a codebase that is safe, tested, and maintainable for the next several years.

Technical Demo

Book a Technical Demo

Explore how Legacyleap’s Gen AI agents analyze, refactor, and modernize your legacy applications, at unparalleled velocity.

Watch how Legacyleap’s Gen AI agents modernize legacy apps ~50-70% faster

Want an Application Modernization Cost Estimate?

Get a detailed and personalized cost estimate based on your unique application portfolio and business goals.