Naman Rathi created FINERACT-2884:
-------------------------------------

             Summary: DataValidatorBuilder.validateForBooleanValue() throws 
NullPointerException when value is null and ignoreIfNull() is not set
                 Key: FINERACT-2884
                 URL: https://issues.apache.org/jira/browse/FINERACT-2884
             Project: Apache Fineract
          Issue Type: Bug
    Affects Versions: 1.16.0
            Reporter: Naman Rathi


DataValidatorBuilder.validateForBooleanValue() delegates to the private 
validateStringFor(...). That method only returns early for a null value when 
ignoreIfNull() was called. Otherwise it goes on to call this.value.toString() 
and throws a NullPointerException. The class's value-format checks (e.g. 
validateCronExpression, inMinMaxRange, positiveAmount) skip null and leave 
missing-value reporting to notNull()/notBlank().

Observed in a unit test on develop (386ee1523f):

java.lang.NullPointerException: Cannot invoke "Object.toString()" because 
"this.value" is null
    at 
org.apache.fineract.infrastructure.core.data.DataValidatorBuilder.validateStringFor(DataValidatorBuilder.java:962)
    at 
org.apache.fineract.infrastructure.core.data.DataValidatorBuilder.validateForBooleanValue(DataValidatorBuilder.java:978)

h3. Affected callers

*Jobs (reproduced on a running server).* Against a locally running Fineract 
instance (devRun, pre-fix build), PUT /v1/jobs/{jobId}:
* {"active": null} returns HTTP 500 Internal Server Error (observed).
* {"active": ""} returns HTTP 500 Internal Server Error (observed).

JobDetailDataValidator reads the value with extractStringNamed(), which returns 
null for both inputs. It then calls .notBlank().validateForBooleanValue(): 
notBlank() records the "cannot.be.blank" error, and the NPE is thrown before 
that error can be returned as an HTTP 400.

*Code values and entity datatable checks (from reading the code, not reproduced 
against a running server).* An explicit JSON null makes the extractor return 
null, and the validator then throws.
* Code value create/update with {"isActive": null} 
(CodeValueCommandFromApiJsonDeserializer).
* Entity datatable check create with {"systemDefined": null} 
(EntityDatatableChecksDataValidator).

h3. Relation to FINERACT-1013

FINERACT-1013 (closed as "Not A Problem", Dec 2025) was also about 
validateForBooleanValue(). It was closed because extractBooleanNamed() 
pre-parses the value via Boolean.parseBoolean(), so invalid strings never reach 
the method. That reasoning doesn't hold here, for three reasons:

* It only covers non-null strings. An explicit JSON null is a JsonNull, not a 
JsonPrimitive, so extractBooleanNamed() returns null without parsing anything. 
The null reaches validateForBooleanValue() and fails at this.value.toString().
* Two of the three callers don't use extractBooleanNamed() at all. 
JobDetailDataValidator and EntityDatatableChecksDataValidator use 
extractStringNamed(), so nothing pre-parses the value. A non-boolean value such 
as "yes" reaches the method and is rejected with value.should.true.or.false. 
The method is not dead code on these paths. A new unit test confirms the method 
rejects "yes"; that the value arrives there unparsed comes from reading the 
code.
* Empty strings take the same route. extractStringNamed() also returns null for 
"" and whitespace-only values. This is observed on the jobs path: PUT 
/v1/jobs/{jobId} with {"active": ""} returned HTTP 500 on a running pre-fix 
instance.

h3. Expected

A null value is skipped by validateForBooleanValue(), the same way the other 
value-format checks handle null, so callers get their normal validation errors 
(HTTP 400) instead of an NPE.

h3. Related issues

Relates to FINERACT-2694: same defect family (a queued DataValidatorBuilder 
validation error is bypassed by a null dereference, giving a 500 instead of a 
400), but a different call path (.intValue()/fromInt(), not 
validateForBooleanValue()).



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

Reply via email to