@Activate方法调用ResourceResolverFactory触发RuntimeException求助
首先看错误栈的根因:Caused by: java.lang.NullPointerException at com.Demo.MyTest.activate(MyTest.java:75),这说明在activate方法执行时,resolverFactory字段是null,调用它的方法才触发了空指针异常。而把调用移到公共方法里能正常运行,核心原因和OSGi服务生命周期、你的单元测试环境直接相关,具体拆解如下:
为什么Activate方法里会出现NPE?
从错误栈里的org.apache.sling.testing.mock.osgi相关类能看出,这是单元测试场景下的问题。Sling Mock OSGi框架通过registerInjectActivateService注册你的MyTest服务时,逻辑是先尝试注入所有@Reference标注的依赖,再调用@Activate方法。
但如果你的测试代码里没有提前注册ResourceResolverFactory的模拟实例,框架无法找到这个依赖服务,resolverFactory就会保持null状态,此时执行activate里的调用自然会抛出NPE。
而把调用移到公共方法后能正常运行,大概率是两种情况:
- 测试时,你在调用这个公共方法之前,已经手动注册了
ResourceResolverFactory的mock,此时依赖已经被注入; - 你在真实AEM运行环境中测试,此时
ResourceResolverFactory是OSGi容器中真实存在的服务,依赖注入流程正常。
解决步骤
1. 在单元测试中提前注册ResourceResolverFactory的Mock
用Mockito创建ResourceResolverFactory的模拟实例,先注册到OSGi测试上下文,再注册你的MyTest服务。示例代码:
@RunWith(MockitoJUnitRunner.class) public class MyDemoTest { @Rule public OsgiContext context = new OsgiContext(); @Mock private ResourceResolverFactory mockResolverFactory; @Mock private ResourceResolver mockResolver; @Before public void setUp() throws LoginException { // 模拟getAdministrativeResourceResolver的返回结果 when(mockResolverFactory.getAdministrativeResourceResolver(null)).thenReturn(mockResolver); // 先注册ResourceResolverFactory的mock到测试上下文 context.registerService(ResourceResolverFactory.class, mockResolverFactory); // 再注册MyTest服务 context.registerInjectActivateService(new MyTest()); } // 测试方法... }
2. 替换不推荐的getAdministrativeResourceResolver调用
在AEM中,getAdministrativeResourceResolver(null)这种方式是官方不推荐的(它会使用系统管理员权限,存在安全风险),建议改用**服务用户(Service User)**来获取ResourceResolver:
- 在AEM中创建对应的服务用户,并配置好所需权限;
- 用
getServiceResourceResolver方法替换原有调用,示例代码:
@Activate protected void activate() { final ResourceResolver resolver; try { Map<String, Object> authInfo = new HashMap<>(); // 替换成你配置的服务用户名称 authInfo.put(ResourceResolverFactory.SUBSERVICE, "my-test-service-user"); resolver = resolverFactory.getServiceResourceResolver(authInfo); } catch (LoginException e) { LOG.error("error resolving resource resolver", e); return; } // 后续业务逻辑... }
3. 确保OSGi依赖注入的顺序
在真实AEM运行环境中,OSGi容器会自动处理依赖注入顺序(先确保依赖服务可用,再激活你的服务),但在测试环境中必须手动保证:先注册所有依赖服务的mock,再注册你的MyTest服务。
内容的提问来源于stack exchange,提问作者codeexplorer

