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

Adam Saghy resolved FINERACT-2315.
----------------------------------
    Resolution: Fixed

> Error Reading SMS Campaing Reports e.g. Pending or Sent SMS
> -----------------------------------------------------------
>
>                 Key: FINERACT-2315
>                 URL: https://issues.apache.org/jira/browse/FINERACT-2315
>             Project: Apache Fineract
>          Issue Type: Bug
>            Reporter: Peter Thua
>            Priority: Major
>         Attachments: image-2025-06-19-09-26-39-710.png
>
>
> {color:#0000ff}# SMS Campaign Reports API Returns 500 Internal Server 
> Error{color}
> {color:#0000ff}## Summary{color}
> {color:#000000}API endpoint for retrieving SMS campaign reports by status 
> returns a 500 Internal Server Error due to HK2 dependency injection failure 
> with record-based parameter classes.{color}
> {color:#0000ff}## Environment{color}
> {color:#0000ff}- {color}{color:#000000}{*}{{*}}API 
> Endpoint:{{*}}{*}{color}{color:#000000} 
> {color}{color:#001188}`/fineract-provider/api/v1/sms/\{id}/messageByStatus`{color}
> {color:#0000ff}- 
> {color}{color:#000000}{*}{{*}}Framework:{{*}}{*}{color}{color:#000000} Jersey 
> with HK2 dependency injection{color}
> {color:#0000ff}- {color}{color:#000000}{*}{{*}}Java 
> Version:{{*}}{*}{color}{color:#000000} 21{color}
> {color:#0000ff}## Steps to Reproduce{color}
> {color:#0000ff}### Prerequisites{color}
> {color:#0000ff}- {color}{color:#000000}Access to Fineract SMS API{color}
> {color:#0000ff}- {color}{color:#000000}Valid SMS campaign ID{color}
> {color:#0000ff}- {color}{color:#000000}API authentication credentials{color}
> {color:#0000ff}### Reproduction Steps{color}
> {color:#0000ff}1. {color}{color:#000000}{*}{{*}}Create or identify an 
> existing SMS campaign{{*}}{*}{color}
> {color:#0000ff}   - {color}{color:#000000}Ensure the campaign has sent 
> messages{color}
> {color:#0000ff}   - {color}{color:#000000}Note the campaign ID (e.g., 
> {color}{color:#001188}`2`{color}{color:#000000}){color}
> {color:#0000ff}2. {color}{color:#000000}{*}{{*}}Make API request to retrieve 
> campaign reports{{*}}{*}{color}
> {color:#a31515}   ```bash{color}
> {color:#000000}   GET 
> [https://localhost:8443/fineract-provider/api/v1/sms/\|https://localhost:8443/fineract-provider/api/v1/sms/]{{{}id{}}}/messageByStatus?status=100&locale=en&dateFormat=dd
>  MMMM yyyy&fromDate=01 June 2025&toDate=17 June 2025{color}
> {color:#000000}   {color}{color:#a31515}```{color}
> {color:#000000}   {color}
> {color:#000000}   Replace 
> {color}{color:#001188}`{{{}id{}}}`{color}{color:#000000} with your actual 
> campaign ID.{color}
> {color:#0000ff}3. {color}{color:#000000}{*}{{*}}Sample query 
> parameters:{{*}}{*}{color}
> {color:#0000ff}   - {color}{color:#001188}`status=100`{color}{color:#000000} 
> (or any valid status code){color}
> {color:#0000ff}   - {color}{color:#001188}`locale=en`{color}
> {color:#0000ff}   - {color}{color:#001188}`dateFormat=dd MMMM yyyy`{color}
> {color:#0000ff}   - {color}{color:#001188}`fromDate=01 June 
> 2025`{color}{color:#000000} (adjust date as needed){color}
> {color:#0000ff}   - {color}{color:#001188}`toDate=17 June 
> 2025`{color}{color:#000000} (adjust date as needed){color}
> {color:#0000ff}4. {color}{color:#000000}{*}{{*}}Execute the 
> request{{*}}{*}{color}
> {color:#0000ff}   - {color}{color:#000000}Use any HTTP client (Postman, curl, 
> browser, etc.){color}
> {color:#0000ff}   - {color}{color:#000000}Include necessary authentication 
> headers{color}
> {color:#0000ff}### Expected Result{color}
> {color:#000000}API should return SMS message data filtered by the specified 
> status and date range.{color}
> {color:#0000ff}### Actual Result{color}
> {color:#000000}API returns a 500 Internal Server Error with the following 
> response:{color}
> {color:#a31515}```json{color}
> {color:#000000}{{color}
> {color:#000000}  "timestamp": "2025-06-17T12:06:20.745Z",{color}
> {color:#000000}  "status": 500,{color}
> {color:#000000}  "error": "Internal Server Error",{color}
> {color:#000000}  "path": 
> "/fineract-provider/api/v1/sms/2/messageByStatus"{color}
> {color:#000000}}
> ```
> {color:#0000ff}## Error Details{color}
> {color:#0000ff}### Server Console Error{color}
> {color:#a31515}```{color}
> {color:#001188}org.glassfish.hk2.api.MultiException: A MultiException has 2 
> exceptions. They are:{color}
> {color:#001188}1. java.lang.NoSuchMethodException: Could not find a suitable 
> constructor in org.apache.fineract.infrastructure.sms.param.SmsRequestParam 
> class.{color}
> {color:#001188}2. java.lang.IllegalArgumentException: Errors were discovered 
> while reifying SystemDescriptor(...){color}
> {color:#a31515}```{color}
> {color:#0000ff}### Error Analysis{color}
> {color:#000000}The error occurs in the following sequence:{color}
> {color:#0000ff}1. {color}{color:#000000}Jersey receives the HTTP request with 
> query parameters{color}
> {color:#0000ff}2. {color}{color:#000000}Jersey attempts to create an instance 
> of {color}{color:#001188}`SmsRequestParam`{color}{color:#000000} (annotated 
> with {color}{color:#001188}`@BeanParam`{color}{color:#000000}){color}
> {color:#0000ff}3. {color}{color:#000000}HK2 dependency injection container 
> tries to instantiate the parameter class{color}
> {color:#0000ff}4. {color}{color:#000000}HK2 fails to find a suitable 
> constructor in the record-based 
> {color}{color:#001188}`SmsRequestParam`{color}{color:#000000} class{color}
> {color:#0000ff}5. 
> {color}{color:#001188}`NoSuchMethodException`{color}{color:#000000} is 
> thrown, causing the 500 error{color}
> {color:#0000ff}## Root Cause{color}
> {color:#0000ff}### Technical Details{color}
> {color:#0000ff}- {color}{color:#000000}{*}{{*}}Framework 
> Incompatibility:{{*}}{*}{color}{color:#000000} Jersey uses HK2 for dependency 
> injection, which requires classes to have default constructors for 
> instantiation{color}
> {color:#0000ff}- {color}{color:#000000}{*}{{*}}Record 
> Limitation:{{*}}{*}{color}{color:#000000} Java records only provide 
> constructors that accept all declared parameters; they do not have default 
> (no-argument) constructors{color}
> {color:#0000ff}- {color}{color:#000000}{*}{{*}}Parameter Binding 
> Process:{{*}}{*}{color}{color:#000000} The 
> {color}{color:#001188}`@BeanParam`{color}{color:#000000} annotation instructs 
> Jersey to:{color}
> {color:#0000ff}  1. {color}{color:#000000}Create an instance of the parameter 
> class using dependency injection{color}
> {color:#0000ff}  2. {color}{color:#000000}Populate the instance fields using 
> query parameter values{color}
> {color:#0000ff}  3. {color}{color:#000000}Pass the populated instance to the 
> endpoint method{color}
> {color:#0000ff}### Why Records Don't Work{color}
> {color:#000000}Records are immutable data carriers that:{color}
> {color:#0000ff}- {color}{color:#000000}Automatically generate constructors 
> requiring all parameters{color}
> {color:#0000ff}- {color}{color:#000000}Do not provide default 
> constructors{color}
> {color:#0000ff}- {color}{color:#000000}Cannot be instantiated without 
> providing all field values upfront{color}
> {color:#000000}This conflicts with HK2's instantiation process, which expects 
> to create empty instances first and then populate them through setter methods 
> or field injection.{color}
> {color:#0000ff}## Solution Implemented{color}
> {color:#0000ff}### Code Changes{color}
> {color:#000000}Converted 
> {color}{color:#001188}`SmsRequestParam`{color}{color:#000000} from a record 
> to a regular class with:{color}
> {color:#000000}{*}{{*}}Before (Record):{{*}}{*}{color}
> {color:#a31515}```java{color}
> {color:#0000ff}public{color}{color:#000000} 
> {color}{color:#0000ff}record{color}{color:#000000} SmsRequestParam(Long 
> status, DateParam fromDate, DateParam toDate, String locale, String 
> rawDateFormat, Integer offset,{color}
> {color:#000000}        Integer limit, String orderBy, String sortOrder) 
> {}{color}
> {color:#a31515}```{color}
> {color:#000000}{*}{{*}}After (Regular Class):{{*}}{*}{color}
> {color:#a31515}```java{color}
> {color:#808080}@Data{color}
> {color:#808080}@NoArgsConstructor{color}
> {color:#0000ff}public{color}{color:#000000} 
> {color}{color:#0000ff}class{color}{color:#000000} SmsRequestParam {{color}
> {color:#000000}    
> {color}{color:#808080}@QueryParam{color}{color:#000000}({color}{color:#a31515}"status"{color}{color:#000000}){color}
> {color:#000000}    {color}{color:#0000ff}private{color}{color:#000000} Long 
> status;{color}
> {color:#000000}    
> {color}{color:#808080}@QueryParam{color}{color:#000000}({color}{color:#a31515}"fromDate"{color}{color:#000000}){color}
> {color:#000000}    {color}{color:#0000ff}private{color}{color:#000000} 
> DateParam fromDate;{color}
> {color:#000000}    
> {color}{color:#808080}@QueryParam{color}{color:#000000}({color}{color:#a31515}"toDate"{color}{color:#000000}){color}
> {color:#000000}    {color}{color:#0000ff}private{color}{color:#000000} 
> DateParam toDate;{color}
> {color:#000000}    
> {color}{color:#808080}@QueryParam{color}{color:#000000}({color}{color:#a31515}"locale"{color}{color:#000000}){color}
> {color:#000000}    {color}{color:#0000ff}private{color}{color:#000000} String 
> locale;{color}
> {color:#000000}    
> {color}{color:#808080}@QueryParam{color}{color:#000000}({color}{color:#a31515}"dateFormat"{color}{color:#000000}){color}
> {color:#000000}    {color}{color:#0000ff}private{color}{color:#000000} String 
> rawDateFormat;{color}
> {color:#000000}    
> {color}{color:#808080}@QueryParam{color}{color:#000000}({color}{color:#a31515}"offset"{color}{color:#000000}){color}
> {color:#000000}    {color}{color:#0000ff}private{color}{color:#000000} 
> Integer offset;{color}
> {color:#000000}    
> {color}{color:#808080}@QueryParam{color}{color:#000000}({color}{color:#a31515}"limit"{color}{color:#000000}){color}
> {color:#000000}    {color}{color:#0000ff}private{color}{color:#000000} 
> Integer limit;{color}
> {color:#000000}    
> {color}{color:#808080}@QueryParam{color}{color:#000000}({color}{color:#a31515}"orderBy"{color}{color:#000000}){color}
> {color:#000000}    {color}{color:#0000ff}private{color}{color:#000000} String 
> orderBy;{color}
> {color:#000000}    
> {color}{color:#808080}@QueryParam{color}{color:#000000}({color}{color:#a31515}"sortOrder"{color}{color:#000000}){color}
> {color:#000000}    {color}{color:#0000ff}private{color}{color:#000000} String 
> sortOrder;{color}
> {color:#000000}}
> ```
> {color:#0000ff}### How the Fix Works{color}
> {color:#0000ff}1. {color}{color:#000000}{*}{{*}}Default 
> Constructor:{{*}}{*}{color}{color:#000000} Allows HK2 to create an empty 
> instance{color}
> {color:#0000ff}2. {color}{color:#000000}{*}{{*}}Setter 
> Methods:{{*}}{*}{color}{color:#000000} Enable Jersey to populate fields with 
> query parameter values{color}
> {color:#0000ff}3. {color}{color:#000000}{*}{{*}}Field 
> Annotations:{{*}}{*}{color}{color:#000000} 
> {color}{color:#001188}`@QueryParam`{color}{color:#000000} annotations 
> directly map HTTP parameters to class fields{color}
> {color:#0000ff}4. {color}{color:#000000}{*}{{*}}Dependency 
> Injection:{{*}}{*}{color}{color:#000000} HK2 can now successfully instantiate 
> and populate the parameter object{color}
> {color:#0000ff}## Verification{color}
> {color:#000000}After implementing the fix:{color}
> {color:#0000ff}1. {color}{color:#000000}The API endpoint successfully 
> processes requests{color}
> {color:#0000ff}2. {color}{color:#000000}Query parameters are correctly mapped 
> to the parameter object{color}
> {color:#0000ff}3. {color}{color:#000000}SMS campaign reports are returned as 
> expected{color}
> {color:#0000ff}4. {color}{color:#000000}No more 500 Internal Server Error 
> responses{color}
> {color:#0000ff}## Impact{color}
> {color:#0000ff}- 
> {color}{color:#000000}{*}{{*}}Severity:{{*}}{*}{color}{color:#000000} High - 
> API endpoint completely non-functional{color}
> {color:#0000ff}- {color}{color:#000000}{*}{{*}}Affected 
> Users:{{*}}{*}{color}{color:#000000} All users attempting to retrieve SMS 
> campaign reports{color}
> {color:#0000ff}- 
> {color}{color:#000000}{*}{{*}}Workaround:{{*}}{*}{color}{color:#000000} None 
> available before fix implementation{color}
> {color:#0000ff}## Related Issues{color}
> {color:#0000ff}- {color}{color:#000000}Consider reviewing other record-based 
> parameter classes in the codebase{color}
> {color:#0000ff}- {color}{color:#000000}Evaluate compatibility of Java records 
> with Jersey/HK2 framework combination{color}
> {color:#0000ff}- {color}{color:#000000}Document best practices for parameter 
> binding in the project{color}



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

Reply via email to