Foo Developer created FINERACT-2865:
---------------------------------------

             Summary: Reading a group's calendars fails with HTTP 500 when it 
has a non-repeating calendar
                 Key: FINERACT-2865
                 URL: https://issues.apache.org/jira/browse/FINERACT-2865
             Project: Apache Fineract
          Issue Type: Bug
          Components: Groups
            Reporter: Foo Developer
            Assignee: Foo Developer


h3. Summary

Reading calendars fails with a {{NullPointerException}} as soon as the entity 
has a *non-repeating* calendar. A non-repeating calendar is stored with 
{{recurrence = NULL}} (by design, see {{Calendar}} constructor and 
{{Calendar.update}}), but the row mappers in 
{{CalendarReadPlatformServiceImpl}} pass that null rule straight into 
{{CalendarUtils}}, which hands it to ical4j's {{RRule}} parser.

h3. Steps to reproduce (stock Fineract)
# Create a group: {{POST /v1/groups}} (any office, active).
# Add a non-repeating, non-collection calendar to it:

{code:json}POST /v1/groups/{groupId}/calendars
{ "title": "One-off meeting", "typeId": 4, "repeating": false, "startDate": "28 
September 2026", "locale": "en", "dateFormat": "dd MMMM yyyy" }
{code}
# Read it back: {{GET /v1/groups/{groupId}/calendars/{calendarId}}}, or list 
{{GET /v1/groups/{groupId}/calendars}}. The same mapper also backs other 
calendar reads, e.g. {{GET 
/v1/loans/template?templateType=jlgbulk&groupId={groupId}}}.

h3. Expected

HTTP 200. The calendar is returned with {{repeating: false}}, no {{frequency}} 
/ {{repeatsOnDay}} / {{repeatsOnNthDayOfMonth}} and {{interval: 0}}, the same 
defaults already used for a rule that cannot be parsed.

h3. Actual

The request fails with HTTP 500 ({{Internal Server Error}}); the server log 
shows a {{NullPointerException}} ({{Cannot invoke "String.split(String)" 
because "aValue" is null}}) thrown from {{CalendarUtils.getICalRecur}} (ical4j 
{{RRule}} with a null rule string), reached from 
{{CalendarReadPlatformServiceImpl$CalendarDataMapper.mapRow}}.

h3. Root cause

Both {{CalendarDataMapper}} and {{CalendarDataFromHistoryMapper}} call 
{{CalendarUtils.getFrequency}}, {{getInterval}}, {{getRepeatsOnDay}}, 
{{getRepeatsOnNthDayOfMonth}} and {{getMonthOnDay}} unconditionally. Each of 
them parses the rule with {{getICalRecur(recurrence)}}, which cannot handle 
{{null}}. The neighbouring {{humanReadable}} computation in the same mappers 
already guards with {{recurrence != null}}; the other five calls do not.

h3. Proposed fix

Guard those five calls with {{recurrence != null}} in both mappers and fall 
back to {{CalendarFrequencyType.INVALID}}, {{0}}, 
{{CalendarWeekDaysType.INVALID}}, {{NthDayType.INVALID}} and {{null}} (which 
{{CalendarEnumerations}} already renders as "no value"). Repeating calendars 
are unaffected.

h3. Test

A unit test {{CalendarReadPlatformServiceImplTest}} maps a non-repeating 
calendar row (null recurrence) through {{retrieveCalendar}} and checks the 
defaults, plus a repeating row to show the rule is still parsed.



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

Reply via email to