[ 
https://issues.apache.org/jira/browse/GEODE-10547?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Jinwoo Hwang updated GEODE-10547:
---------------------------------
    Fix Version/s: 2.1.0

> Migrate deprecated commons-lang3 methods with Java standard library 
> equivalents
> -------------------------------------------------------------------------------
>
>                 Key: GEODE-10547
>                 URL: https://issues.apache.org/jira/browse/GEODE-10547
>             Project: Geode
>          Issue Type: Improvement
>            Reporter: Jinwoo Hwang
>            Assignee: Jinwoo Hwang
>            Priority: Major
>             Fix For: 2.1.0
>
>
> h1. Replace deprecated commons-lang3 methods with Java standard library 
> equivalents
> h2. Summary
> Replace deprecated Apache Commons Lang3 utility methods with Java standard 
> library equivalents to eliminate deprecation warnings and improve code 
> maintainability.
> h2. Issue Type
>  * *Type:* Technical Debt / Code Improvement
>  * *Priority:* Medium
>  * *Component:* Code Quality
>  * *Related:* GEODE-10543 (commons-lang3 3.18.0 upgrade for CVE-2025-48924)
> h2. Description
> As part of upgrading to commons-lang3 3.18.0, several utility methods have 
> been deprecated. These methods have direct equivalents in the Java standard 
> library that provide the same functionality with better performance and no 
> external dependencies.
> This task replaces all deprecated commons-lang3 method calls with their Java 
> standard library equivalents across the Apache Geode codebase.
> h3. Deprecated Methods Being Replaced
>  # {{StringUtils.startsWith(String, String)}} → {{String.startsWith(String)}}
>  # {{StringUtils.containsIgnoreCase(String, String)}} → 
> {{String.toLowerCase().contains(String.toLowerCase())}}
>  # {{StringUtils.equals(String, String)}} → {{Objects.equals(Object, Object)}}
>  # {{StringUtils.removeStart(String, String)}} → {{startsWith() + 
> substring()}}
>  # {{LineIterator.nextLine()}} → {{LineIterator.next()}}
> h2. Benefits
>  * *Eliminates deprecation warnings* during compilation
>  * *Reduces external dependencies* by using Java standard library
>  * *Improves performance* - native Java methods are typically faster
>  * *Better null safety* - {{Objects.equals()}} handles null properly
>  * *Future-proof* - Java standard library methods won't be deprecated
>  * *Cleaner code* - removes unnecessary utility wrapper calls
> h2. Implementation Details
> h3. Method Replacement Details
> h4. 1. StringUtils.startsWith() → String.startsWith()
> *Before:*
> {code:java}
> if (StringUtils.startsWith(url, "https")) {
>     // ...
> }
> {code}
> *After:*
> {code:java}
> if (url.startsWith("https")) {
>     // ...
> }
> {code}
> *Considerations:* String.startsWith() throws NullPointerException if the 
> string is null. Ensure proper null checks exist.
> h4. 2. StringUtils.containsIgnoreCase() → toLowerCase().contains()
> *Before:*
> {code:java}
> if (StringUtils.containsIgnoreCase(query, "keyword")) {
>     // ...
> }
> {code}
> *After:*
> {code:java}
> if (query.toLowerCase().contains("keyword".toLowerCase())) {
>     // ...
> }
> {code}
> *Considerations:* Both strings need toLowerCase() for case-insensitive 
> comparison. Requires null check on the source string.
> h4. 3. StringUtils.equals() → Objects.equals()
> *Before:*
> {code:java}
> if (StringUtils.equals(value1, value2)) {
>     // ...
> }
> {code}
> *After:*
> {code:java}
> if (Objects.equals(value1, value2)) {
>     // ...
> }
> {code}
> *Benefits:* {{Objects.equals()}} is null-safe and works for any object type, 
> not just strings.
> h4. 4. StringUtils.removeStart() → startsWith() + substring()
> *Before:*
> {code:java}
> String result = StringUtils.removeStart(text, "prefix");
> {code}
> *After:*
> {code:java}
> String result = text.startsWith("prefix") ? text.substring("prefix".length()) 
> : text;
> {code}
> *Considerations:* Requires explicit logic to handle the case when prefix is 
> not present.
> h4. 5. LineIterator.nextLine() → LineIterator.next()
> *Before:*
> {code:java}
> while (iterator.hasNext()) {
>     String line = iterator.nextLine();
> }
> {code}
> *After:*
> {code:java}
> while (iterator.hasNext()) {
>     String line = iterator.next();
> }
> {code}
> *Note:* {{nextLine()}} is deprecated in commons-io 2.18.0. Use {{next()}} 
> which is the standard Iterator interface method.
> h3. Files Affected
> *geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/ConnectCommand.java*
>  * 
>  ** Line ~126: {{StringUtils.startsWith()}} → {{String.startsWith()}}
> *geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/QueryCommand.java*
>  * 
>  ** {{StringUtils.containsIgnoreCase()}} → {{toLowerCase().contains()}}
> *geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/CreateIndexCommand.java*
>  * 
>  ** {{StringUtils.removeStart()}} → {{startsWith() + substring()}}
> *geode-management/src/main/java/org/apache/geode/management/configuration/Index.java*
>  * 
>  ** {{StringUtils.removeStart()}} → {{startsWith() + substring()}}
> *geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/domain/FixedPartitionAttributesInfo.java*
>  * 
>  ** {{StringUtils.equals()}} → {{Objects.equals()}}
> *geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/domain/RegionAttributesInfo.java*
>  * 
>  ** {{StringUtils.equals()}} → {{Objects.equals()}}
> *geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/domain/PartitionAttributesInfo.java*
>  * 
>  ** {{StringUtils.equals()}} → {{Objects.equals()}}
> *geode-assembly/src/acceptanceTest/java/org/apache/geode/management/internal/cli/commands/StartServerCommandAcceptanceTest.java*
>  * 
>  ** {{LineIterator.nextLine()}} → {{LineIterator.next()}}
> h3. Required Imports
> Add these imports where needed:
> {code:java}
> import java.util.Objects; // For Objects.equals()
> {code}
> Remove if no longer used:
> {code:java}
> import org.apache.commons.lang3.StringUtils;
> {code}
> h2. Testing Strategy
> h3. Verification Steps
> *Compilation:* Ensure no deprecation warnings remain
> {code:bash}
> ./gradlew clean build -Werror
> {code}
> *Unit Tests:* All existing tests should pass
> {code:bash}
> ./gradlew test
> {code}
> *Functionality:* Verify behavior is identical
>  * 
>  ** String comparisons work correctly
>  ** Case-insensitive searches work
>  ** Null handling is proper
>  ** Edge cases are covered
> h3. Risk Assessment
> {panel:title=Low 
> Risk|borderStyle=solid|borderColor=#cccccc|titleBGColor=#dff0d8|bgColor=#dff0d8}
>  * *Low Risk:* These are straightforward method replacements with equivalent 
> functionality
>  * *Well-tested:* All modified code paths have existing unit tests
>  * *Standard library:* Using well-tested Java standard library methods{panel}
> h4. Potential Issues
>  * *Null handling:* {{String}} methods throw {{NullPointerException}} on 
> null, while {{StringUtils}} returns false/empty
>  ** *Mitigation:* Code analysis shows all call sites have proper null checks
>  * *Case sensitivity:* Must ensure {{toLowerCase()}} is applied to both 
> strings in comparisons
>  ** *Mitigation:* Code review verified correct implementation
> h2. Acceptance Criteria
>  *  All deprecated commons-lang3 method calls replaced in production code
>  *  All deprecated commons-io method calls replaced in test code
>  *  No deprecation warnings during compilation
>  *  All unit tests pass without modification
>  *  Build succeeds with {{-Werror}} flag (warnings as errors)
>  *  Code review confirms correct null handling
>  *  No behavioral changes in functionality
> h2. Build Verification
> h4. Commands to Verify
> {code:bash}
> # Clean build with strict warnings
> export JAVA_HOME=$(/usr/libexec/java_home -v 1.8)
> ./gradlew clean build -Werror
> # Verify no deprecation warnings
> ./gradlew compileJava 2>&1 | grep -i "deprecation"
> # Run full test suite
> ./gradlew test
> {code}
> h2. Related Changes
>  * Part of GEODE-10543: commons-lang3 3.18.0 upgrade
>  * Complements CVE-2025-48924 security fix
>  * Coordinates with:
>  ** commons-io 2.18.0 upgrade
>  ** slf4j-api 1.7.36 upgrade
>  ** Log4j 2.25.3 upgrade
> h2. Code Review Checklist
>  *  All {{StringUtils}} methods replaced with Java equivalents
>  *  Proper null checks exist before calling {{String}} instance methods
>  *  Case-insensitive comparisons use {{toLowerCase()}} on both sides
>  * {{Objects.equals()}} imported and used correctly
>  * {{LineIterator.next()}} used instead of {{nextLine()}}
>  *  No unused imports remaining
>  *  Code formatting follows project standards (spotless check passes)
> h2. Documentation
> h4. Migration Guide for Developers
> Future code should use:
>  * {{String.startsWith()}} instead of {{StringUtils.startsWith()}}
>  * {{String.toLowerCase().contains()}} instead of 
> {{StringUtils.containsIgnoreCase()}}
>  * {{Objects.equals()}} instead of {{StringUtils.equals()}}
>  * Ternary with {{startsWith() + substring()}} instead of 
> {{StringUtils.removeStart()}}
>  * {{Iterator.next()}} instead of {{LineIterator.nextLine()}}
> h2. Estimated Effort
>  * Analysis: 2 - 3 days
>  * Implementation: 1 - 2 weeks
>  * Testing: 2 - 3 days
>  



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to