Quarkus Mutiny响应式:上游非空持久化DB的Uni类型报错问题
Quarkus Mutiny响应式接口类型不匹配问题解决
问题场景
开发基于Quarkus + MongoDB Reactive + Mutiny的应用时,需要实现为指定人员创建事件的接口:
POST /person/{personId}/event
业务规则:
- 先根据路径参数
personId查询MongoDB中的Person记录 - Person存在则关联保存Event记录,返回成功响应
- Person不存在则返回错误响应
实现过程中出现返回类型不匹配的编译错误,提示要求返回Uni类型但实际类型不符合,尝试transformToUni、onItemOrFailure()等API均未解决。
原有问题代码
public class EventResource { @Inject EventRepository eventRepository; @Inject PersonRepository personRepository; @POST @Path("/{person_id}/event") public Uni<Response> create(Event event, @PathParam("person_id") String personId){ Uni<Person> uniPerson = personRepository.getPersonById(personId); // 该版本仅能捕获创建Event时的异常,无法处理Person不存在的场景 /*return uniPerson.onItem().ifNotNull() .transformToUni(pid -> eventRepository.create(event, pid.getId())) .onItem().transform(e -> Response.ok().entity(e).build()) .onFailure() .recoverWithItem(f-> { AStatus status = createErrorStatus(f.getMessage()); return Response.serverError().entity(status).build(); }); */ // 该版本存在类型不匹配问题 Uni<Response> eventResp = uniPerson.onItem().transform(person -> { if(person==null) return Response.serverError().build(); else{ return eventRepository.create(event, person.getId()) .onItem().transform(event1 -> Response.ok(event1).build()); } }); return eventResp; } }
报错原因
- 错误使用
transform操作符处理异步返回值:onItem().transform()仅支持返回同步普通值,上述代码在person存在分支返回了Uni<Response>,最终流类型变为Uni<Uni<Response>>,和接口要求的Uni<Response>不匹配。 - 未正确处理null分支:注释掉的可用版本没有处理Person查询结果为null的场景,查无数据时不会触发异常,无法进入失败兜底逻辑。
正确实现代码
使用Mutiny内置的空值分支判断+transformToUni处理嵌套异步调用,自动拍平Uni类型:
@POST @Path("/{person_id}/event") public Uni<Response> create(Event event, @PathParam("person_id") String personId){ return personRepository.getPersonById(personId) // 查到Person时执行异步创建Event逻辑 .onItem().ifNotNull().transformToUni(person -> eventRepository.create(event, person.getId()) .onItem().transform(createdEvent -> Response.ok(createdEvent).build()) ) // 未查到Person时直接返回404错误 .onItem().ifNull().continueWith( Response.status(Response.Status.NOT_FOUND) .entity(createErrorStatus("指定人员不存在")) .build() ) // 统一捕获链路中所有异常返回500错误 .onFailure().recoverWithItem(failure -> { AStatus status = createErrorStatus(failure.getMessage()); return Response.serverError().entity(status).build(); }); }
关键操作符说明
onItem().ifNotNull().transformToUni():接收非空的Person对象执行下一段异步操作,会自动将内层Uni展开,避免Uni<Uni<T>>的类型问题onItem().ifNull().continueWith():查询结果为null时直接返回预设的同步响应值,无需额外异步操作onFailure().recoverWithItem():捕获整个响应式链路(查询Person、创建Event)中抛出的所有异常,统一包装为错误响应返回
内容的提问来源于stack exchange,提问作者Dinesh Arora
相关产品推荐
相关产品推荐

