Channels / #fineract / 2026 / 08 / 03

#fineract 2026-08-03

Mon 07:30Victor Romero
Hello Apache Fineract community,

I would like to propose upgrading the project from Java 21 LTS to Java 25 LTS (it is a NFR change). This change is proposed because the following reasons:
  • Java 25 is the current LTS (it was released September 2025).
  • Java 25 has improvements about performance, language features, security, longer support window, alignment with Spring Boot upgrades or dependencies.
  • Java 21 will eventually move out of free support and it will become less convenient for new contributors and adopters.
  • Evergreening compliance is required by Institutions that run the software on production environments
  • It is a best practice for having the technology aligned to the EOL of the base framework/product.

The changes that contains the PR are:
  • Gradle toolchain languageVersion = 25
  • Jib base image update (azul/zulu-openjdk-alpine:25) so then the Docker Hub images dev tag will be updated to java 25 (arm and amd64).
  • Modernizer module and ResolutionHelperTest required fixes
  • CI / GitHub Actions updates
  • Documentation (MD files).
  • Existing functionalities are working (green flag/checks after running the Github Actions)

As any technology upgrade there are risks and compatibility issues that must be highlighted
  • Requires JDK 25 to build and run (The developer will require to upgrade the Java version and also the running environment will require the upgrade)
  • If you have developed third-party libraries and plugins they may need to be upgraded to Java 25

These are the tickets for your review:
JIRA ticket: FINERACT-2734 issues.apache.org/jira/browse/FINERACT-2734
PR ticket: github.com/apache/fineract/pull/6215

I welcome feedback about any concerns and especially your help with testing on different environments (MariaDB, PostgreSQL, different Operating Systems and/or multi-tenant setups).
Thank you in advance!
Victor Romero
Mon 08:17Aleksandar Vidakovic
Hi Victor... first: 👍 👍 👍 for this change... the whole ecosystem is moving fast (JDK releases every 6 months, Spring/Boot pretty much the same in the future), so we should too... other benefits I see:
  • there are really considerable performance improvements between JDK releases and Oracle is paranoid about testing backwards compatibility; this should be in general low risk
  • we could upgrade Gradle to the latest (upcoming) 9.7 release with some major caching and performance improvements (compared to our 8.x use)
  • we can move away from our JDK 8 compatible Java syntax style and gradually adopt a more modern use of Java (e.g. just the "var" keyword is such a great boilerplate saver!)
... on the counter side the only thing that comes to mind: there could be community members who have internal company policies that prevent them to just nilly willy switch JDK versions... but maybe we can come up with a solution for this... I think we shouldn't hold back with these updates for too long, we don't have to follow every release cycle of Oracle and/or Spring, but it should not be 5 years (exaggeration) apart either...

My 2 cents
👍 1
reply Mon 17:03Victor Romero
I think that the policies should be aware about the changes of the licensing of JDK 21 about the extended support....
reply Mon 17:46Aleksandar Vidakovic
I agree
reply Mon 17:46Aleksandar Vidakovic
... maybe @Adam Saghy has also a perspective on this...
reply Mon 20:16Adam Saghy
@Victor Romero in my understanding - except oracle - jdk 21 support will be there for years still.
reply Mon 20:29Victor Romero
This is the reference published by Azul which is the vendor of the JDK used by Apache Fineract
reply Mon 20:33Victor Romero
so then... if it is build by Azul Zulu... it will be free...
reply Mon 22:20Adam Saghy
yeah. just like i said. except oracle distro all others are still providing free support for this for years :)
reply Mon 23:54TomD
Surely this is a sensible suggestion i.e. to move to a later JDK release and JDK from 2025 seems sensible. The discussion raises another more general question "what is the desirable release cadence/adoption cadence from JDK releases ?" Surely staying on something too many years old is undesirable , as perhaps is being on the "bleeding edge". I would think that adopting a policy of updating JDK releases (and maybe similarly Spring) every "2-3" years would be sensible , perhaps some policy that says fineract should "make every attempt" to within a year or 2 of the latest stable and well regarded release. The alternative to this is to get "stuck" and encounter lots of tech debt and potentially increases security risks.
Mon 09:56Surya Kumar
Hi team,

Subject: Bug in ph-ee-connector-ams-mifos: NullPointerException on all account-lookup routes (confirmed in v1.17.3)

We're implementing a payment engine on PH-EE and, as part of our Phase 1 validation, are running the reference ph-ee-connector-ams-mifos connector against Fineract before building our own AMS connector.

Issue
All five account-lookup REST routes in AccountsRouteBuilder fail with a NullPointerException:

GET /ams/accounts/{IdentifierType}/{IdentifierId}/status
GET /ams/accounts/{IdentifierType}/{IdentifierId}/accountname
GET /ams/accounts/{IdentifierType}/{IdentifierId}/balance
GET /ams/accounts/{IdentifierType}/{IdentifierId}/transactions
GET /ams/accounts/{IdentifierType}/{IdentifierId}/statemententries

Stack trace (balance endpoint, representative of all five):
java.lang.NullPointerException
at java.base/java.lang.String.replace(String.java:2165)
at org.mifos.connector.ams.interop.AmsFinXService.getSavingsAccount(AmsFinXService.java:53)
...

Root cause
AccountsRouteBuilder sets the inbound identifier as an exchange property named PARTY_ID:
e.setProperty(PARTY_ID, IdentifierId);

But AmsFinXService.getSavingsAccount reads a differently-named property:
headers.put(HTTP_PATH, amsInteropAccountsPath.replace("{externalAccountId}", e.getProperty(EXTERNAL_ACCOUNT_ID, String.class)));

Since PARTY_ID and EXTERNAL_ACCOUNT_ID are never the same property, the value is always null when getSavingsAccount runs, and String.replace() throws on the null argument. The same pattern affects getSavingsAccountsTransactions as well.

Confirmed scope
We verified this is not specific to an unreleased build on our end — we reproduced it both on the :latest / 1.0.0-SNAPSHOT image and, after checking out the official v1.17.3 tag directly, confirmed the same property mismatch exists there too.

@TomD, @Aleksandar Vidakovic, could you please help us fix this or point us where we are going wrong.