[
https://issues.apache.org/jira/browse/FINERACT-2671?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Abhishek Chaudhary resolved FINERACT-2671.
------------------------------------------
Resolution: Fixed
> Client family member and GSIM account lookups return HTTP 500 instead of 404
> when the record does not exist
> -----------------------------------------------------------------------------------------------------------
>
> Key: FINERACT-2671
> URL: https://issues.apache.org/jira/browse/FINERACT-2671
> Project: Apache Fineract
> Issue Type: Bug
> Components: Client, Savings
> Affects Versions: 1.14.0
> Reporter: Abhishek Chaudhary
> Priority: Major
> Labels: bug
>
> *Observed behavior*
> Two read endpoints return a raw HTTP 500 due to an unhandled
> {{EmptyResultDataAccessException}} when the requested resource does not exist:
> {noformat}
> GET
> /fineract-provider/api/v1/clients/{clientId}/familymembers/{familyMemberId}
> GET /fineract-provider/api/v1/groups/{groupId}/gsimaccounts?parentGSIMId={id}
> {noformat}
> This can be reproduced on the current {{develop}} branch and is also present
> in {{1.14.0}}.
> *Root cause*
> * {{ClientFamilyMembersReadPlatformServiceImpl.getClientFamilyMember()}}
> calls {{jdbcTemplate.queryForObject(...)}} without handling the case where no
> rows are returned.
> * {{GSIMReadPlatformServiceImpl.findGSIMAccountByGSIMId()}} follows the same
> pattern. It is invoked from {{GroupsApiResource.retrieveGsimAccounts()}}
> whenever the {{parentGSIMId}} query parameter is supplied.
> When {{JdbcTemplate.queryForObject()}} finds no matching row, Spring throws
> {{EmptyResultDataAccessException}}. Since there is no dedicated exception
> mapper for it under
> {{org.apache.fineract.infrastructure.core.exceptionmapper}}, it falls through
> to {{DefaultExceptionMapper}}, resulting in an HTTP 500 instead of a 404.
> *Additional defect (Family Members)*
> The family-member lookup does not validate the {{clientId}} path parameter.
> The query filters only by {{fmb.id}}, meaning requests such as:
> {noformat}
> GET /clients/999/familymembers/5
> {noformat}
> can return a family member belonging to a different client.
> The lookup should instead be scoped as:
> {code:sql}
> WHERE fmb.client_id = ? AND fmb.id = ?
> {code}
> If the family member does not belong to the client specified in the path, the
> endpoint should return HTTP 404.
> *Expected behavior*
> Both endpoints should return HTTP 404 with the standard platform error
> payload when the requested resource does not exist.
> This should follow the existing Fineract pattern:
> * Catch {{EmptyResultDataAccessException}}.
> * Throw a domain-specific exception extending
> {{AbstractPlatformResourceNotFoundException}}.
> * Let {{PlatformResourceNotFoundExceptionMapper}} translate it into an HTTP
> 404 response.
> *Steps to reproduce*
> # Call:
> {noformat}
> GET /fineract-provider/api/v1/clients/1/familymembers/999999
> {noformat}
> Current: HTTP 500
> Expected: HTTP 404
> # Call:
> {noformat}
> GET /fineract-provider/api/v1/groups/1/gsimaccounts?parentGSIMId=999999
> {noformat}
> Current: HTTP 500
> Expected: HTTP 404
> # Create Client A with a family member M and Client B. Then call:
> {noformat}
> GET /clients/{B}/familymembers/{M}
> {noformat}
> Current: Returns the family member belonging to Client A.
> Expected: HTTP 404.
> *Proposed fix*
> * Introduce {{FamilyMemberNotFoundException}} and
> {{GSIMAccountNotFoundException}}, both extending
> {{AbstractPlatformResourceNotFoundException}}.
> * Catch {{EmptyResultDataAccessException}} in the corresponding read-platform
> service methods and rethrow the appropriate domain-specific exception.
> * Scope the family-member lookup by both {{client_id}} and {{familyMemberId}}.
> * Add integration tests covering:
> ** Non-existent family member → HTTP 404.
> ** Non-existent GSIM account → HTTP 404.
> ** Family member belonging to a different client → HTTP 404.
> I found this issue while reviewing the read-platform services and would like
> to work on it. Please assign it to me.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)