[
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)