Expand my Community achievements bar.

Submissions are now open for the 2026 Adobe Experience Maker Awards.
SOLVED

JUnit NPE issue in Build

Avatar

Level 5

I am struggling a little with JUnits

 

Here's my model impl class - 

@Model(adaptables = SlingHttpServletRequest.class,
adapters = {MultifieldCollectionModel.class},
defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class MultifieldCollectionModelImpl implements MultifieldCollectionModel {

private final String resourcePath;

private final String multifieldName;

private final @NonNull Resource resource;

private final @NonNull List<Resource> multiCollection;

@Inject
public MultifieldCollectionModelImpl(@RequestAttribute(name = "resourcePath") String resourcePath,
@RequestAttribute(name = "multifieldName") String multifieldName,
@Self @Via("resource") @NonNull Resource resource) {
this.resourcePath = resourcePath;
this.multifieldName = multifieldName;
this.resource = resource;
multiCollection = new ArrayList<>();
}

@PostConstruct
public void init() {
if (resourcePath != null && multifieldName != null) {
String multifieldResourcePath = String.join("/", resourcePath, multifieldName);
ResourceResolver resolver = resource.getResourceResolver();
Resource multifieldResource = resolver.getResource(multifieldResourcePath);
if (multifieldResource != null) {
multifieldResource.listChildren().forEachRemaining(multiCollection::add);
}
}
}

@Override
public List<Resource> getMultifieldList() {
return Collections.unmodifiableList(multiCollection);
}

@Override
public int getMultifieldListSize() {
return multiCollection.size();
}
}

This is the test class for it - 

@ExtendWith({AemContextExtension.class, MockitoExtension.class})
class MultifieldCollectionModelImplTest {
private static final String CONTENT = "content";
private static final String CQ_PAGE = "cq:page";
private static final String PAGE_TITLE = "Project Page";
private static final String HYPERLINK = "hyperlink";
private static final String MULTIFIELD_NAME = "multifieldName";
private static final String RESOURCE_PATH = "resourcePath";
private static final String TITLE = "title";
private static final String URL = "url";

private MultifieldCollectionModel model;
@InjectMocks
private MultifieldCollectionModelImpl model1;
private final AemContext context = new AemContext();

@BeforeEach
void setUp() throws WCMException {
context.addModelsForClasses(MultifieldCollectionModel.class);
context.pageManager().create("/", CONTENT, CQ_PAGE, CONTENT);
context.pageManager().create("/content", "brandA", CQ_PAGE, PAGE_TITLE);
Page page = context.pageManager().create("/content/brandA", "en", CQ_PAGE, PAGE_TITLE);
context.currentPage(page);
}

@Test
void shouldReturnEmptyListIfRequestAttributeMultifieldIsNull() throws IllegalAccessException {
writeField(model1, "multifieldName", null, true);
writeField(model1, "resourcePath", "resource", true);
model1.init();
model1.getMultifieldListSize();
assertEquals(Collections.emptyList(), model1.getMultifieldList());
}

@Test
void shouldReturnEmptyListIfRequestAttributeResourceIsNull() throws IllegalAccessException {
writeField(model1, "multifieldName", null, true);
writeField(model1, "resourcePath", null, true);
model1.init();
model1.getMultifieldListSize();
assertEquals(Collections.emptyList(), model1.getMultifieldList());
}

@Test
void shouldReturnEmptyListIfResourceIsNull() {
context.request().setAttribute(RESOURCE_PATH, "/content/brandA/en/jcr:content");
context.request().setAttribute(MULTIFIELD_NAME, HYPERLINK);
model = context.request().adaptTo(MultifieldCollectionModel.class);
assertTrue(model.getMultifieldList().isEmpty());
}

@Test
void shouldReturnEmptyListIfResourceHasNotChildResources() {
context.request().setAttribute(RESOURCE_PATH, "/content/brandA/en/jcr:content");
context.request().setAttribute(MULTIFIELD_NAME, HYPERLINK);
context.create().resource("/content/brandA/en/jcr:content/hyperlink");
model = context.request().adaptTo(MultifieldCollectionModel.class);

assertTrue(model.getMultifieldList().isEmpty());
}

@Test
void shouldReturnMultifieldListIfResourceExist() {
context.request().setAttribute(RESOURCE_PATH, "/content/brandA/en/jcr:content");
context.request().setAttribute(MULTIFIELD_NAME, HYPERLINK);
context.create().resource("/content/brandA/en/jcr:content/hyperlink");
context.create()
.resource("/content/brandA/en/jcr:content/hyperlink/item0", ImmutableMap.<String, Object>builder()
.put(TITLE, "Products")
.put(URL, "/content/products")
.build());
context.create()
.resource("/content/brandA/en/jcr:content/hyperlink/item1", ImmutableMap.<String, Object>builder()
.put(TITLE, "Campaigns")
.put(URL, "/content/campaigns")
.build());
model = context.request().adaptTo(MultifieldCollectionModel.class);

assertEquals("Products", model.getMultifieldList().get(0).getValueMap().get(TITLE, String.class));
assertEquals("/content/products", model.getMultifieldList().get(0).getValueMap().get(URL,
String.class));
assertEquals("Campaigns", model.getMultifieldList().get(1).getValueMap().get(TITLE, String.class));
assertEquals("/content/campaigns", model.getMultifieldList().get(1).getValueMap().get(URL,
String.class));
}

@Test
void shouldReturnMultifieldListSizeIfResourceExist() {
context.request().setAttribute(RESOURCE_PATH, "/content/brandA/en/jcr:content");
context.request().setAttribute(MULTIFIELD_NAME, HYPERLINK);
context.create().resource("/content/brandA/en/jcr:content/hyperlink");
context.create()
.resource("/content/brandA/en/jcr:content/hyperlink/item0", ImmutableMap.<String, Object>builder()
.put(TITLE, "Products")
.put(URL, "/content/products")
.build());
context.create()
.resource("/content/brandA/en/jcr:content/hyperlink/item1", ImmutableMap.<String, Object>builder()
.put(TITLE, "Campaigns")
.put(URL, "/content/campaigns")
.build());
model = context.request().adaptTo(MultifieldCollectionModel.class);

assertEquals(2, model.getMultifieldListSize());
}
}

When I change the model annotation for the impl class to include Component Exporter as shown below - 

@Model(adaptables = SlingHttpServletRequest.class,
adapters = {MultifieldCollectionModel.class, ComponentExporter.class},
defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
@Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION)
public class MultifieldCollectionModelImpl implements MultifieldCollectionModel {

I get the below error in unit tests - 
[ERROR] MultifieldCollectionModelImplTest.shouldReturnEmptyListIfResourceHasNotChildResources:90 NullPointer
[ERROR] MultifieldCollectionModelImplTest.shouldReturnEmptyListIfResourceIsNull:80 NullPointer
[ERROR] MultifieldCollectionModelImplTest.shouldReturnMultifieldListIfResourceExist:110 NullPointer
[ERROR] MultifieldCollectionModelImplTest.shouldReturnMultifieldListSizeIfResourceExist:135 NullPointer

Why does this error come and what is the best way to correct it?

 

Thanks,

Nagesh

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

Hey @NageshRaja, Your implementation class is not implementing ComponentExporter.

  • public class MultifieldCollectionModelImpl implements MultifieldCollectionModel, ComponentExporter {

You will need to add a getExportedType() method.
@Override
public @NonNull String getExportedType() {
return resource.getResourceType();
}

The NPE is just a silent adaptation failure. The cause is primarily because your class does not implement ComponentExporter
Hope this helps!

Regards,
Rohan Garg 

View solution in original post

1 Reply

Avatar

Correct answer by
Community Advisor

Hey @NageshRaja, Your implementation class is not implementing ComponentExporter.

  • public class MultifieldCollectionModelImpl implements MultifieldCollectionModel, ComponentExporter {

You will need to add a getExportedType() method.
@Override
public @NonNull String getExportedType() {
return resource.getResourceType();
}

The NPE is just a silent adaptation failure. The cause is primarily because your class does not implement ComponentExporter
Hope this helps!

Regards,
Rohan Garg