Skip to content

Commit 3d47d9b

Browse files
rismehtaArmaan Gupta
authored andcommitted
feat: handling NPE when fragment path is not valid (#1778)
1 parent ff6291f commit 3d47d9b

File tree

3 files changed

+79
-1
lines changed

3 files changed

+79
-1
lines changed

bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FragmentImpl.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ public String getFragmentPath() {
123123
}
124124

125125
protected <T> Map<String, T> getChildrenModels(@Nullable SlingHttpServletRequest request, @NotNull Class<T> modelClass) {
126+
if (fragmentContainer == null) {
127+
return new LinkedHashMap<>();
128+
}
126129
List<Resource> filteredChildrenResources = getFilteredChildrenResources(fragmentContainer);
127130
SlingHttpServletRequest wrappedSlingHttpServletRequest = null;
128131
if (request != null) {
@@ -170,7 +173,7 @@ public Object getAttribute(String attrName) {
170173
private @Nonnull I18n getFragmentContainerI18n(@Nonnull String localeLang) {
171174
// Get the locale from the lang setter
172175
ResourceBundle resourceBundle = null;
173-
if (localeLang != null) {
176+
if (localeLang != null && fragmentContainer != null) {
174177
Locale desiredLocale = new Locale(localeLang);
175178
// Get the resource resolver from the fragment container
176179
ResourceResolver resourceResolver = fragmentContainer.getResourceResolver();

bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FragmentImplTest.java

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ public class FragmentImplTest {
6464
private static final String PATH_FRAGMENT_DAMPATH = CONTENT_ROOT + "/fragment-dampath";
6565
private static final String PATH_FRAGMENT_WITHOUT_FIELDTYPE = CONTENT_ROOT + "/fragment-without-fieldtype";
6666
private static final String PATH_FRAGMENT_WITH_FRAGMENT_PATH = CONTENT_ROOT + "/fragment-with-fragment-path";
67+
private static final String PATH_FRAGMENT_WITH_INVALID_PATH = CONTENT_ROOT + "/fragment-with-invalid-path";
6768
private final AemContext context = FormsCoreComponentTestContext.newAemContext();
6869

6970
@BeforeEach
@@ -273,4 +274,64 @@ void testGetFragmentContainerI18n() throws Exception {
273274
I18n result5 = (I18n) getFragmentContainerI18nMethod.invoke(fragmentImpl, "");
274275
Assertions.assertNotNull(result5, "getFragmentContainerI18n should handle empty string localeLang");
275276
}
277+
278+
@Test
279+
void testNullFragmentContainerHandling() throws Exception {
280+
// This test verifies the fix when fragmentContainer is null
281+
Fragment fragment = Utils.getComponentUnderTest(PATH_FRAGMENT_WITH_INVALID_PATH, Fragment.class, context);
282+
FragmentImpl fragmentImpl = (FragmentImpl) fragment;
283+
284+
// Verify that fragmentContainer is null due to invalid path
285+
Assertions.assertNull(fragmentImpl.getFragmentContainer(),
286+
"Fragment container should be null for invalid fragment path");
287+
288+
// Test that getChildrenModels returns empty map instead of throwing NPE
289+
Map<String, ComponentExporter> childrenModels = fragmentImpl.getChildrenModels(context.request(),
290+
ComponentExporter.class);
291+
Assertions.assertNotNull(childrenModels, "getChildrenModels should return non-null map even with null fragmentContainer");
292+
Assertions.assertTrue(childrenModels.isEmpty(),
293+
"getChildrenModels should return empty map when fragmentContainer is null");
294+
295+
// Test that getExportedItems doesn't throw NPE
296+
Map<String, ? extends ComponentExporter> exportedItems = fragmentImpl.getExportedItems();
297+
Assertions.assertNotNull(exportedItems, "getExportedItems should return non-null map even with null fragmentContainer");
298+
Assertions.assertTrue(exportedItems.isEmpty(),
299+
"getExportedItems should return empty map when fragmentContainer is null");
300+
301+
// Test that getExportedItemsOrder doesn't throw NPE
302+
String[] exportedItemsOrder = fragmentImpl.getExportedItemsOrder();
303+
Assertions.assertNotNull(exportedItemsOrder, "getExportedItemsOrder should return non-null array even with null fragmentContainer");
304+
Assertions.assertEquals(0, exportedItemsOrder.length,
305+
"getExportedItemsOrder should return empty array when fragmentContainer is null");
306+
307+
// Test getFragmentContainerI18n with null fragmentContainer
308+
Method getFragmentContainerI18nMethod = FragmentImpl.class.getDeclaredMethod("getFragmentContainerI18n", String.class);
309+
getFragmentContainerI18nMethod.setAccessible(true);
310+
311+
// Should not throw NPE and should return non-null I18n object
312+
I18n result = (I18n) getFragmentContainerI18nMethod.invoke(fragmentImpl, "en");
313+
Assertions.assertNotNull(result,
314+
"getFragmentContainerI18n should return non-null I18n object even when fragmentContainer is null");
315+
}
316+
317+
@Test
318+
void testNullFragmentContainerWithNullRequest() throws Exception {
319+
// Test with null request to cover both code paths
320+
Resource resource = context.resourceResolver().getResource(PATH_FRAGMENT_WITH_INVALID_PATH);
321+
Fragment fragment = resource.adaptTo(Fragment.class);
322+
Assertions.assertNotNull(fragment, "Fragment should be created even with invalid path");
323+
324+
FragmentImpl fragmentImpl = (FragmentImpl) fragment;
325+
326+
// Verify that fragmentContainer is null
327+
Assertions.assertNull(fragmentImpl.getFragmentContainer(),
328+
"Fragment container should be null for invalid fragment path");
329+
330+
// Test that getChildrenModels with null request returns empty map instead of throwing NPE
331+
Map<String, TextInput> childrenModels = fragmentImpl.getChildrenModels(null, TextInput.class);
332+
Assertions.assertNotNull(childrenModels,
333+
"getChildrenModels should return non-null map with null request and null fragmentContainer");
334+
Assertions.assertTrue(childrenModels.isEmpty(),
335+
"getChildrenModels should return empty map when fragmentContainer is null and request is null");
336+
}
276337
}

bundles/af-core/src/test/resources/form/fragment/test-content.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,20 @@
5656
"fragmentPath": "/content/affragment",
5757
"customProp": "customPropValue"
5858
},
59+
"fragment-with-invalid-path": {
60+
"jcr:primaryType": "nt:unstructured",
61+
"wrapData": true,
62+
"jcr:title": "Fragment with Invalid Path",
63+
"minOccur": "0",
64+
"jcr:lastModifiedBy": "admin",
65+
"name": "fragment-456",
66+
"maxOccur": "4",
67+
"jcr:lastModified": "Fri Jun 02 2023 12:34:24 GMT+0530",
68+
"repeatable": true,
69+
"sling:resourceType": "core/fd/components/form/fragment/v1/fragment",
70+
"fieldType": "panel",
71+
"fragmentPath": "/content/nonexistent/fragment"
72+
},
5973
"affragment": {
6074
"jcr:primaryType": "nt:unstructured",
6175
"jcr:title": "AF Fragment (v2)",

0 commit comments

Comments
 (0)