You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@fineract.apache.org by "Ashhar Ahmad Khan (Jira)" <ji...@apache.org> on 2026/08/25 13:36:00 UTC
[jira] [Created] (FINERACT-2786) EmailMessage.pendingEmail() throws NullPointerException on /v1/email CREATE due to hardcoded null emailCampaign
Ashhar Ahmad Khan created FINERACT-2786:
-------------------------------------------
Summary: EmailMessage.pendingEmail() throws NullPointerException on /v1/email CREATE due to hardcoded null emailCampaign
Key: FINERACT-2786
URL: https://issues.apache.org/jira/browse/FINERACT-2786
Project: Apache Fineract
Issue Type: Bug
Reporter: Ashhar Ahmad Khan
What is broken
EmailMessageAssembler.assembleFromJson(), the method that builds an EmailMessage from a /v1/email CREATE request, calls EmailMessage.pendingEmail(group, client, staff, null, emailSubject, message, emailAddress, null), passing emailCampaign as a hardcoded null. pendingEmail()'s body unconditionally calls .setStatusType(emailCampaign.getStatus()) with no null check, so it throws NullPointerException on every single /v1/email CREATE request, regardless of which valid fields are supplied. This makes /v1/email CREATE completely unusable today, independent of and in addition to the validator bug fixed in FINERACT-2785.
Why it's broken
Runtime confirmed with a Mockito test calling assembleFromJson() with a valid clientId and emailMessage payload. The call throws NullPointerException from inside pendingEmail(), not from anywhere in EmailMessageAssembler itself.
Grepped every caller of pendingEmail() across the codebase. Found three other call sites, two in EmailCampaignWritePlatformCommandHandlerImpl and one in UpdateEmailOutboundWithCampaignMessageTasklet, and all three always pass a real, non-null EmailCampaign. The /v1/email assembler is the only caller that passes null. The email_campaign_id column itself is nullable at the JPA/DB level, confirming the schema always intended campaign-less emails to be valid. pendingEmail() was just never written to handle that case because nothing called it that way until /v1/email's assembler was added.
EmailMessage.java already contains a second factory method, instance(), sitting right next to pendingEmail(), which takes statusType as an explicit parameter instead of deriving it from emailCampaign.getStatus(), so it is null safe by construction. Grep confirms zero production callers currently used instance() before this fix, it was dead code with the right shape, not an established pattern.
Changes made
* EmailMessageAssembler.assembleFromJson() now calls EmailMessage.instance(group, client, staff, null, EmailMessageStatusType.PENDING, emailSubject, message, null, emailAddress, null) instead of pendingEmail(...). This required zero changes to EmailMessage.java itself, so it carries zero risk to the three working campaign driven callers of pendingEmail().
* Added EmailMessageAssemblerTest.java, a regression test confirming assembleFromJson() no longer throws and produces a PENDING EmailMessage when only clientId is supplied.
Related
FINERACT-2785 (validator fix, separate bug, same resource, found during the same investigation)
--
This message was sent by Atlassian Jira
(v8.20.10#820010)