Quarkus 3.22.3+升级后测试出现RequestScoped上下文未激活异常
解决Quarkus 3.22.3+升级后偶发"RequestScoped context was not active"异常
问题定位
从Quarkus 3.22.2升级到3.22.3后出现的偶发上下文异常,大概率和该版本对RESTEasy Reactive上下文管理的优化有关——官方修复了部分上下文泄漏问题,但也导致某些场景下(比如异常处理、异步操作)上下文提前关闭。
具体解决方案
1. 修复RestExceptionMapper的上下文依赖
如果你的RestExceptionMapper中注入了RequestScoped Bean,异常触发时请求上下文可能已经被销毁,此时需要显式激活上下文:
@Provider @Singleton public class RestExceptionMapper implements ExceptionMapper<Throwable> { @Inject RequestContextController requestContextController; // 用Provider延迟获取RequestScoped Bean,避免提前初始化 @Inject Provider<YourRequestScopedBean> requestBeanProvider; @Override public Response toResponse(Throwable exception) { // 显式激活请求上下文 requestContextController.activate(); try { YourRequestScopedBean bean = requestBeanProvider.get(); // 执行异常处理逻辑,比如获取请求信息、构建响应 return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity("Error: " + bean.getRequestId()) .build(); } finally { // 确保上下文最终关闭,避免泄漏 requestContextController.deactivate(); } } }
2. 排查测试并行执行问题
偶发失败通常和测试并发有关,Quarkus测试默认可能开启并行执行,导致上下文隔离失效:
- Maven:修改
pom.xml禁用Surefire插件并行
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <parallel>none</parallel> <forkCount>1</forkCount> </configuration> </plugin>
- Gradle:修改
build.gradle调整测试配置
test { maxParallelForks = 1 }
3. 检查ContainerRequestFilter的异步逻辑
如果过滤器中存在异步操作(比如调用Uni/Multi),需要确保上下文被正确捕获:
@Provider @Singleton public class YourRequestFilter implements ContainerRequestFilter { @Override public void filter(ContainerRequestContext requestContext) { // 异步操作必须调用withContextCapture()传递上下文 someAsyncService.doWork() .withContextCapture() .subscribe().with(result -> { // 处理异步结果 }); } }
4. 验证测试用例的上下文完整性
确保测试中所有异步调用都已完成,避免上下文提前关闭:
@QuarkusTest public class YourTest { @Test public void testEndpoint() { // 调用端点后必须阻塞等待响应完成 given() .when().get("/your/endpoint") .then().statusCode(200); } // 如果是异步端点测试,需显式等待Uni完成 @Test public void testAsyncEndpoint() { Uni<String> response = RestClientBuilder.newBuilder() .baseUri(URI.create("http://localhost:8080")) .build(YourAsyncClient.class) .asyncCall(); // 阻塞直到结果返回 String result = response.await().indefinitely(); assertNotNull(result); } }
补充检查
去Quarkus 3.22.3的Release Notes中确认相关变更,重点关注RESTEasy Reactive、Context Management板块的修复项,排查是否有和你的业务场景匹配的改动。
内容的提问来源于stack exchange,提问作者user31394879
相关产品推荐
相关产品推荐

