[ 
https://issues.apache.org/jira/browse/FINERACT-2665?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Adam Saghy updated FINERACT-2665:
---------------------------------
    Labels: beginner beginner-friendly bug loan  (was: bug loan)

> PUT /loans/{loanId} (modify loan application) fails with a 
> NullPointerException (HTTP 500) when a loan product allows attribute 
> overrides but the request omits the attribute
> -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: FINERACT-2665
>                 URL: https://issues.apache.org/jira/browse/FINERACT-2665
>             Project: Apache Fineract
>          Issue Type: Bug
>          Components: Loan
>            Reporter: Farooq Ayoade
>            Priority: Minor
>              Labels: beginner, beginner-friendly, bug, loan
>
> h3. Observed behavior
> Modifying a submitted-and-pending loan application via {{{}PUT 
> /fineract-provider/api/v1/loans/{loanId{}}}} — when the change triggers a 
> schedule recalculation (e.g. changing {{{}productId{}}}) and the request body 
> does not resend {{interestType}} — returns HTTP 500 with a raw NPE:
>  
>  
> {{java.lang.NullPointerException: Cannot invoke 
> "java.lang.Integer.intValue()" because "selectedMethod" is null
> at 
> org.apache.fineract.portfolio.loanproduct.domain.InterestMethod.fromInt(InterestMethod.java:45)
> at 
> org.apache.fineract.portfolio.loanaccount.loanschedule.service.LoanScheduleAssembler.assembleLoanApplicationTermsFrom(LoanScheduleAssembler.java:238)
> at 
> org.apache.fineract.portfolio.loanaccount.loanschedule.service.LoanScheduleAssembler.assembleLoanTerms(LoanScheduleAssembler.java:178)
> at 
> org.apache.fineract.portfolio.loanaccount.loanschedule.service.LoanScheduleAssembler.assembleLoanScheduleFrom(LoanScheduleAssembler.java:711)
> at 
> org.apache.fineract.portfolio.loanaccount.loanschedule.service.LoanScheduleCalculationPlatformServiceImpl.calculateLoanSchedule(LoanScheduleCalculationPlatformServiceImpl.java:79)
> at 
> org.apache.fineract.portfolio.loanaccount.service.LoanAssemblerImpl.updateFrom(LoanAssemblerImpl.java:866)
> at 
> org.apache.fineract.portfolio.loanaccount.service.LoanApplicationWritePlatformServiceJpaRepositoryImpl.modifyApplication(LoanApplicationWritePlatformServiceJpaRepositoryImpl.java:277)}}
> The same class of NPE occurs for {{amortizationType}} and 
> {{{}interestCalculationPeriodType{}}}, and a null {{repaymentEvery}} is 
> produced, when those overrides are enabled on the product and the field is 
> omitted.
> h3. Expected behavior
> "Allow overriding X" on a loan product means the override is {*}optional{*}. 
> When the modify request omits an override-enabled attribute, the schedule 
> should be (re)built using the *product's configured value* for that attribute 
> — exactly as it already does when the override is _not_ enabled — instead of 
> dereferencing a null and throwing.
> h3. Steps to reproduce
>  # Have a loan product with one or more attribute overrides enabled — i.e. a 
> row in {{m_product_loan_configurable_attributes}} with {{interest_method_enum 
> = 1}} (and/or {{{}amortization_method_enum{}}}, 
> {{{}interest_calculated_in_period_enum{}}}, {{{}repay_every{}}}). A product 
> with *no* row also reproduces, because 
> {{LoanProductConfigurableAttributes.populateDefaultsForConfigurableAttributes()}}
>  defaults every flag to {{{}true{}}}.
>  # Create a loan application (Submitted and pending approval) on some product.
>  # {{{}PUT /fineract-provider/api/v1/loans/{loanId{}}}} changing 
> {{productId}} to an override-enabled product, with a minimal body that omits 
> {{{}interestType{}}}:
>  \{{ { "locale": "en", "dateFormat": "dd MMMM yyyy", "loanType": 
> "individual", "productId": <overrideEnabledId> }
> }}
>  # Observe HTTP 500 and the NPE above. (Re-sending the loan's _current_ 
> product is a no-op — {{{}changes:{}{{}}}}, no recalculation — so it appears 
> to "work"; the failure only manifests once a real change forces the schedule 
> rebuild.)
> h3. Root cause
> {{LoanScheduleAssembler.assembleLoanApplicationTermsFrom(...)}} reads each 
> override-gated attribute from the request JSON when the product allows 
> overriding it, but passes the (possibly {{{}null{}}}) value straight into 
> {{{}XxxMethod.fromInt(...){}}}:
> final Boolean allowOverridingInterestMethod = 
> loanProduct.getLoanConfigurableAttributes().getInterestMethodBoolean();
> final Integer interestType = 
> this.fromApiJsonHelper.extractIntegerWithLocaleNamed("interestType", 
> element); // null on modify when omitted
> final InterestMethod interestMethod = allowOverridingInterestMethod
>         ? InterestMethod.fromInt(interestType)   // line 238 — fromInt(null) 
> → NPE
>         : loanProduct.getLoanProductRelatedDetail().getInterestMethod();
> {{}}



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

Reply via email to