Jersey 3.x注入ServiceLocator遇空指针异常求助
Jersey 3.x + Wildfly 33:ResourceConfig中获取ServiceLocator的正确方式
核心问题
Jersey 3.x(适配Jakarta EE 9+)调整了DI初始化流程,ResourceConfig构造方法执行时,HK2的InjectionManager还未完成注入,直接在无参构造里访问注入字段会触发空指针异常。同时Wildfly 33内置Jersey版本可能和自定义依赖冲突,也会导致注入失败。
解决方案1:构造方法注入InjectionManager(推荐)
将InjectionManager作为构造方法参数注入,Jersey会在DI容器就绪后调用该构造方法,避免空指针:
import jakarta.inject.Inject; import jakarta.ws.rs.ApplicationPath; import org.glassfish.hk2.api.ServiceLocator; import org.glassfish.jersey.internal.inject.InjectionManager; import org.glassfish.jersey.server.ResourceConfig; @ApplicationPath("/") public class MyJerseyConfig extends ResourceConfig { @Inject public MyJerseyConfig(InjectionManager injectionManager) { logger.info(() -> "Bootstrapping Jersey 3.1.x"); packages("..."); // 从InjectionManager获取ServiceLocator ServiceLocator serviceLocator = injectionManager.getInstance(ServiceLocator.class); // 配置HK2 DI register(new MyHk2Config()); // 建立HK2-Guice双向桥接 createBiDirectionalGuiceBridge(serviceLocator, getServletModules(...)); } }
解决方案2:利用事件监听器延迟初始化
如果构造方法注入仍有问题,可通过监听应用初始化完成事件,在容器完全启动后获取ServiceLocator:
import jakarta.ws.rs.ApplicationPath; import org.glassfish.hk2.api.ServiceLocator; import org.glassfish.jersey.internal.inject.InjectionManager; import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.server.monitoring.ApplicationEvent; import org.glassfish.jersey.server.monitoring.ApplicationEventListener; import org.glassfish.jersey.server.monitoring.RequestEvent; @ApplicationPath("/") public class MyJerseyConfig extends ResourceConfig { public MyJerseyConfig() { logger.info(() -> "Bootstrapping Jersey 3.1.x"); packages("..."); register(new MyHk2Config()); // 注册应用初始化监听器 register(new ApplicationEventListener() { @Override public void onEvent(ApplicationEvent event) { // 等待初始化完成后执行桥接 if (event.getType() == ApplicationEvent.Type.INITIALIZATION_FINISHED) { InjectionManager injectionManager = event.getInjectionManager(); ServiceLocator serviceLocator = injectionManager.getInstance(ServiceLocator.class); createBiDirectionalGuiceBridge(serviceLocator, getServletModules(...)); } } @Override public RequestEventListener onRequest(RequestEvent requestEvent) { return null; } }); } }
关键注意事项
- 依赖版本对齐:Wildfly 33内置Jersey 3.x,需将项目中Jersey相关依赖设为
provided范围,避免版本冲突:<dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-servlet-core</artifactId> <version>3.1.5</version> <!-- 与Wildfly内置版本保持一致 --> <scope>provided</scope> </dependency> - Guice与HK2桥接兼容:Guice 7.0.0需搭配
hk2-guice-bridge2.6.1及以上版本,确保桥接逻辑正常:<dependency> <groupId>org.glassfish.hk2</groupId> <artifactId>hk2-guice-bridge</artifactId> <version>2.6.1</version> </dependency> - Jakarta EE包迁移:确保所有
javax.*包替换为jakarta.*(如javax.inject.Inject→jakarta.inject.Inject),混合使用会导致注入失效。
内容的提问来源于stack exchange,提问作者pmguy
相关产品推荐
相关产品推荐

