Skip to content

FINERACT-2538: Fix String Locale compiler warning in EnumValueValidator#5595

Open
hms2186 wants to merge 1 commit intoapache:developfrom
hms2186:fix-string-locale
Open

FINERACT-2538: Fix String Locale compiler warning in EnumValueValidator#5595
hms2186 wants to merge 1 commit intoapache:developfrom
hms2186:fix-string-locale

Conversation

@hms2186
Copy link

@hms2186 hms2186 commented Mar 7, 2026

Description

Describe the changes made and why they were made. (Ignore if these details are present on the associated Apache Fineract JIRA ticket.)

This PR resolves a [StringCaseLocaleUsage] compiler warning found in EnumValueValidator.java during the build process.

Calling String.toLowerCase() without specifying a Locale relies on the system's default locale, which can cause unexpected behavior on internationalized servers (such as the Turkish "I" issue).

Fix: Explicitly set Locale.ROOT on lines 33 and 39 to ensure consistent, locale-insensitive character mapping for the enum validation.

Checklist

Please make sure these boxes are checked before submitting your pull request - thanks!

  • Write the commit message as per our guidelines
  • Acknowledge that we will not review PRs that are not passing the build ("green") - it is your responsibility to get a proposed PR to pass the build, not primarily the project's maintainers.
  • Create/update unit or integration tests for verifying the changes made.
  • Follow our coding conventions.
  • Add required Swagger annotation and update API documentation at fineract-provider/src/main/resources/static/legacy-docs/apiLive.htm with details of any API changes
  • This PR must not be a "code dump". Large changes can be made in a branch, with assistance. Ask for help on the developer mailing list.

Your assigned reviewer(s) will follow our guidelines for code reviews.

Copy link
Contributor

@IOhacker IOhacker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review my comments

@adamsaghy
Copy link
Contributor

@hms2186 Please rebase and fix the conflicts.

@hms2186 hms2186 force-pushed the fix-string-locale branch from cdf3ca0 to 720e507 Compare March 16, 2026 05:29
@hms2186 hms2186 changed the title Fix: Specify Locale in String toLowerCase to resolve compiler warnings FINERACT-2538: Fix String Locale compiler warning in EnumValueValidator Mar 16, 2026
@hms2186 hms2186 force-pushed the fix-string-locale branch from 720e507 to 6e09733 Compare March 16, 2026 05:46
@hms2186
Copy link
Author

hms2186 commented Mar 16, 2026

@adamsaghy I have rebased the branch, resolved all conflicts, and squashed the changes into a single commit. I've also created the Jira ticket FINERACT-2538 and updated the PR title accordingly. Ready for re-review

@hms2186 hms2186 force-pushed the fix-string-locale branch from 6e09733 to 4bd69b5 Compare March 16, 2026 06:32
@hms2186
Copy link
Author

hms2186 commented Mar 16, 2026

@adamsaghy It looks like the CI pipeline finished, but E2E Tests (Shard 8) failed during the Loan/EMI calculation feature tests. Since my change is restricted to resolving a compiler warning in EnumValueValidator, this appears to be an environment timeout or a flaky test. Could you please re-trigger the failed job when you have a moment?

@@ -56,4 +56,5 @@ private static SpringApplicationBuilder configureApplication(SpringApplicationBu
public static void main(String[] args) throws IOException {
configureApplication(new SpringApplicationBuilder(ServerApplication.class)).run(args);
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for the extra line

@@ -30,12 +30,12 @@ public class EnumValueValidator implements ConstraintValidator<EnumValue, String

@Override
public void initialize(EnumValue annotation) {
acceptedValues = Arrays.stream(annotation.enumClass().getEnumConstants()).map(e -> e.name().toLowerCase())
acceptedValues = Arrays.stream(annotation.enumClass().getEnumConstants()).map(e -> e.name().toLowerCase(java.util.Locale.ROOT))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please make sure to check whether this is an issue with other classes? I think you can extend this story and cover all "missing" locale compilation warning in one shot. What do you think?

@hms2186 hms2186 force-pushed the fix-string-locale branch from 4bd69b5 to cb640ea Compare March 16, 2026 14:23
@adamsaghy
Copy link
Contributor

@hms2186 Please rebase this PR.

@hms2186 hms2186 force-pushed the fix-string-locale branch from cb640ea to 377a62b Compare March 16, 2026 15:49
@hms2186
Copy link
Author

hms2186 commented Mar 16, 2026

Hi @adamsaghy, I've completed the project-wide audit and successfully rebased the PR onto the latest develop branch, resolving the conflicts in the Note service implementation.

I've patched multiple instances of .toLowerCase(), .toUpperCase(), and String.format() missing the Locale parameter across fineract-core, fineract-provider, and fineract-investor. I've used java.util.Locale.ROOT to ensure consistent, locale-neutral behavior. The updated, signed commit has been pushed

@adamsaghy
Copy link
Contributor

FAILURE: Build completed with 2 failures.

1: Task failed with an exception.
-----------
* What went wrong:
Execution failed for task ':fineract-core:spotlessJavaCheck'.
> The following files had format violations:
      src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarUtils.java
          @@ -299,10 +299,11 @@
           ················NthDayNameEnum·nthDayName·=·NthDayNameEnum.from(nthDayType.toString());
           ················DayNameEnum·weekdayType·=·DayNameEnum.from(weekDay.getDay().name());
           ················if·(recur.getInterval()·==·1·||·recur.getInterval()·==·-1)·{
          -····················humanReadable·=·"Monthly·on·"·+·nthDayName.getCode().toLowerCase(java.util.Locale.ROOT)·+·"·"·+·weekdayType.getCode().toLowerCase(java.util.Locale.ROOT);
          +····················humanReadable·=·"Monthly·on·"·+·nthDayName.getCode().toLowerCase(java.util.Locale.ROOT)·+·"·"
          +····························+·weekdayType.getCode().toLowerCase(java.util.Locale.ROOT);
           ················}·else·{
          -····················humanReadable·=·"Every·"·+·recur.getInterval()·+·"·months·on·"·+·nthDayName.getCode().toLowerCase(java.util.Locale.ROOT)·+·"·"
          -····························+·weekdayType.getCode().toLowerCase(java.util.Locale.ROOT);
          +····················humanReadable·=·"Every·"·+·recur.getInterval()·+·"·months·on·"·+·nthDayName.getCode().toLowerCase(java.util.Locale.ROOT)
          +····························+·"·"·+·weekdayType.getCode().toLowerCase(java.util.Locale.ROOT);
           ················}
           ············}·else·if·(monthDay·!=·null)·{
           ················if·(monthDay·==·-1)·{
          @@ -756,7 +757,8 @@
           ············if·(nthDayType·==·NthDayType.ONE·||·nthDayType·==·NthDayType.TWO·||·nthDayType·==·NthDayType.THREE
           ····················||·nthDayType·==·NthDayType.FOUR)·{
           ················baseDataValidator.reset().parameter(repeatsOnDayParamName).value(repeatsOnDay).cantBeBlankWhenParameterProvidedIs(
          -························repeatsOnNthDayOfMonthParamName,·NthDayNameEnum.from(nthDayType.toString()).getCode().toLowerCase(java.util.Locale.ROOT));
          +························repeatsOnNthDayOfMonthParamName,
          +························NthDayNameEnum.from(nthDayType.toString()).getCode().toLowerCase(java.util.Locale.ROOT));
           ············}
           ········}
           ····}
      src/main/java/org/apache/fineract/useradministration/domain/AppUser.java
          @@ -551,7 +551,8 @@
           ····}
           
           ····private·void·validateHasPermission(final·String·prefix,·final·String·resourceType)·{
          -········final·String·authorizationMessage·=·"User·has·no·authority·to·"·+·prefix·+·"·"·+·resourceType.toLowerCase(java.util.Locale.ROOT)·+·"s";
          +········final·String·authorizationMessage·=·"User·has·no·authority·to·"·+·prefix·+·"·"·+·resourceType.toLowerCase(java.util.Locale.ROOT)
          +················+·"s";
           ········final·String·matchPermission·=·prefix·+·"_"·+·resourceType.toUpperCase(java.util.Locale.ROOT);
           
           ········if·(!hasNotPermissionForAnyOf("ALL_FUNCTIONS",·"ALL_FUNCTIONS_READ",·matchPermission))·{
  Run './gradlew :fineract-core:spotlessApply' to fix these violations.

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Get more help at https://help.gradle.org./
==============================================================================

2: Task failed with an exception.

-----------
* What went wrong:
Execution failed for task ':fineract-provider:compileJava'.
> Compilation failed; see the compiler output below.
==============================================================================


/home/runner/work/fineract/fineract/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java:135: error: cannot find symbol
    private CommandProcessingResult updateLoanTransactionNote(final JsonCommand command) {
> Task :fineract-provider:compileJava FAILED
                                                                    ^
  symbol:   class JsonCommand
  location: class NoteWritePlatformServiceJpaRepositoryImpl
/home/runner/work/fineract/fineract/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java:135: error: cannot find symbol
    private CommandProcessingResult updateLoanTransactionNote(final JsonCommand command) {
            ^
  symbol:   class CommandProcessingResult
  location: class NoteWritePlatformServiceJpaRepositoryImpl
/home/runner/work/fineract/fineract/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java:162: error: cannot find symbol
    private CommandProcessingResult updateSavingAccountNote(final JsonCommand command) {
                                                                  ^
  symbol:   class JsonCommand
  location: class NoteWritePlatformServiceJpaRepositoryImpl
/home/runner/work/fineract/fineract/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java:162: error: cannot find symbol
    private CommandProcessingResult updateSavingAccountNote(final JsonCommand command) {
            ^
/home/runner/work/fineract/fineract/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java:119: error: cannot find symbol
        final Loan loan = this.loanRepository.findOneWithNotFoundDetection(resourceId);
              ^
  symbol:   class Loan
  location: class NoteWritePlatformServiceJpaRepositoryImpl
/home/runner/work/fineract/fineract/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java:119: error: cannot find symbol
        final Loan loan = this.loanRepository.findOneWithNotFoundDetection(resourceId);
                                                                           ^
  symbol:   variable resourceId
  location: class NoteWritePlatformServiceJpaRepositoryImpl
/home/runner/work/fineract/fineract/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java:120: error: cannot find symbol
        final Note noteForUpdate = this.noteRepository.findByLoanAndId(loan, noteId);
                                                                             ^
  symbol:   variable noteId
  location: class NoteWritePlatformServiceJpaRepositoryImpl
/home/runner/work/fineract/fineract/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java:122: error: cannot find symbol
            throw new NoteNotFoundException(noteId, resourceId, type.name().toLowerCase(java.util.Locale.ROOT));
                                            ^
  symbol:   variable noteId
  location: class NoteWritePlatformServiceJpaRepositoryImpl
/home/runner/work/fineract/fineract/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java:122: error: cannot find symbol
            throw new NoteNotFoundException(noteId, resourceId, type.name().toLowerCase(java.util.Locale.ROOT));
                                                    ^
  symbol:   variable resourceId
  location: class NoteWritePlatformServiceJpaRepositoryImpl
/home/runner/work/fineract/fineract/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java:125: error: cannot find symbol
        final Map<String, Object> changes = noteForUpdate.update(command);
              ^
  symbol:   class Map
  location: class NoteWritePlatformServiceJpaRepositoryImpl
/home/runner/work/fineract/fineract/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java:125: error: cannot find symbol
        final Map<String, Object> changes = noteForUpdate.update(command);
                                                                 ^
  symbol:   variable command
  location: class NoteWritePlatformServiceJpaRepositoryImpl
/home/runner/work/fineract/fineract/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java:131: error: cannot find symbol
        return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(noteForUpdate.getId())
                   ^
  symbol:   class CommandProcessingResultBuilder
  location: class NoteWritePlatformServiceJpaRepositoryImpl
/home/runner/work/fineract/fineract/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java:131: error: cannot find symbol
        return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(noteForUpdate.getId())
                                                                  ^
  symbol:   variable command
  location: class NoteWritePlatformServiceJpaRepositoryImpl
/home/runner/work/fineract/fineract/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java:142: error: cannot find symbol
        final LoanTransaction loanTransaction = this.loanTransactionRepository.findById(resourceId)
              ^
  symbol:   class LoanTransaction
  location: class NoteWritePlatformServiceJpaRepositoryImpl
/home/runner/work/fineract/fineract/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java:144: error: cannot find symbol
        final Loan loan = loanTransaction.getLoan();
              ^
  symbol:   class Loan
  location: class NoteWritePlatformServiceJpaRepositoryImpl
/home/runner/work/fineract/fineract/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java:152: error: cannot find symbol
        final Map<String, Object> changes = noteForUpdate.update(command);
              ^
  symbol:   class Map
  location: class NoteWritePlatformServiceJpaRepositoryImpl
/home/runner/work/fineract/fineract/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java:158: error: cannot find symbol
        return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(noteForUpdate.getId())
                   ^
  symbol:   class CommandProcessingResultBuilder
  location: class NoteWritePlatformServiceJpaRepositoryImpl
/home/runner/work/fineract/fineract/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java:166: error: cannot find symbol
        final SavingsAccount savingAccount = this.savingsAccountRepository.findById(resourceId)
              ^
  symbol:   class SavingsAccount
  location: class NoteWritePlatformServiceJpaRepositoryImpl
/home/runner/work/fineract/fineract/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java:173: error: cannot find symbol
        final Map<String, Object> changes = noteForUpdate.update(command);
              ^
  symbol:   class Map
  location: class NoteWritePlatformServiceJpaRepositoryImpl
/home/runner/work/fineract/fineract/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java:178: error: cannot find symbol
        return new CommandProcessingResultBuilder() //
                   ^
  symbol:   class CommandProcessingResultBuilder
  location: class NoteWritePlatformServiceJpaRepositoryImpl
/home/runner/work/fineract/fineract/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java:238: error: cannot find symbol
        if (noteForUpdate == null) {
            ^
  symbol:   variable noteForUpdate
  location: class NoteWritePlatformServiceJpaRepositoryImpl

@hms2186
Copy link
Author

hms2186 commented Mar 17, 2026

Hi @adamsaghy,
Just a quick update: I've successfully resolved the rebase conflicts in the Note service to align with the new NoteUpdateRequest builder pattern. My original fixes using Locale.ROOT are safely intact within the updated exception handling.
Local compile and Spotless checks are passing cleanly, so the CI pipeline should be completely green now!

- Resolved String.toLowerCase() locale warnings across the codebase.
- Updated Note service implementation to align with NoteUpdateRequest refactoring.

Signed-off-by: Hemanth Madhav <216912024+hms2186@users.noreply.github.com>
@hms2186 hms2186 force-pushed the fix-string-locale branch from fb296fe to 3f29427 Compare March 17, 2026 16:20
@hms2186 hms2186 closed this Mar 17, 2026
@hms2186 hms2186 reopened this Mar 17, 2026
@hms2186
Copy link
Author

hms2186 commented Mar 17, 2026

Hi @l0hacker, I have squashed my changes into a single signed commit as requested and updated the Note service to use the new builder pattern. I'm seeing a failure in the build-core check, but looking at the logs, it appears to be a transient org.eclipse.swt dependency download error rather than a failure in my Java logic. Could you please trigger a re-run of the failed check when you have a moment?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants