Причина возникновения исключения NullPointerException
Хотя это и не указано явно в вопросе, предоставленная трассировка стека показывает, что служба «запускается» в рамках модульного теста.
Кроме того, трассировка стека показывает, что используется OsgiContext
, что не обеспечивает реализацию ResourceResolverFactory
.
Поскольку ResourceResolverFactory
не зарегистрировано в фиктивном контексте OSGi, @Reference
не может быть введено при регистрации и активации службы. Когда ResourceResolverFactory
вызывается в методе активации, ссылка null
и, следовательно, NullPointerException
выбрасывается.
Предлагаемое решение
Поэтому я бы посоветовал использовать превосходный AemContext
, который предоставляется wcm.io aem-mock framework или, по крайней мере, SlingContext
, предоставленный sling-mocks .
Модульный тест будет выглядеть так:
public class MyUnitTest {
@Rule
public AemContext context;
@Test
public void someTest() {
MyTest service = context.registerInjectActivateService(new MyTest());
[... additional test code ...]
}
}
Поскольку в AemContext
уже зарегистрирован функционал ResourceResolverFactory
(макет), код модульного теста не должен создавать макет и регистрировать его. Когда вызывается метод registerInjectActivateService()
, создается новый экземпляр класса MyTest
и вставляется ссылка ResourceResolverFactory
.
Дополнительное примечание
Пожалуйста, не создавайте для всей службы ResourceResolvers
. Это плохая практика. ResourceResolver
должно быть недолгим. Это означает, что они используются только для нескольких «операций» (например, чтение ресурса), а затем отбрасываются.
Лучший способ сделать это - использовать выражение try-with-resource
, например:
public class MyTest {
private static final SERVICE_NAME = "MyTestService";
private static final Map<String, Object> authenticationInfo = Collections.singletonMap(ResourceResolverFactory.SUBSERVICE, SERVICE_NAME);
@Reference
private ResourceResolverFactory resourceResolverFactory;
public void someMethod() {
try (ResourceResolver resolver = getResourceResolver()) {
[... use resolver to do stuff in JCR ...]
}
}
private ResourceResolver getResourceResolver() {
try {
return resourceResolverFactory.getServiceResourceResolver(authenticationInfo);
} catch (LoginException cause) {
throw new IllegalStateException("Unable to obtain ResourceResolver!", cause)
}
}
}
Я решил создать отдельный метод для создания ResourceResolver
, чтобы избежать беспорядка someMethod()
с обработкой исключений. Но это, очевидно, то, что можно изменить.
Поскольку административный ResourceResolver
устарел, я также решил воспользоваться услугой ResourceResolver
. Для их использования необходимо создать службу сопоставления пользователей. Вы можете узнать больше об этом в документации .