Quarkus中@ConsumeEvent返回泛型List时出现ClassNotFound错误如何解决?
根因分析
Quarkus的Vert.x Event Bus扩展在应用构建阶段解析@ConsumeEvent标注方法的返回类型时,对嵌套参数化泛型的处理存在缺陷:它会直接将java.util.List<se.bryderi.events.OfferResponse>这种带泛型参数的完整类型签名作为全限定类名尝试加载,而JVM的泛型擦除机制下根本不存在对应类,因此直接抛出ClassNotFoundException。该问题和类加载器无关,所以dev模式和打包后都会触发。
解决方案(按推荐度排序)
1. 自定义包装类包裹泛型集合(最优)
创建普通POJO类包装List<OfferResponse>,消除方法返回值的嵌套泛型,Quarkus即可正常解析类型,同时保留编译期类型检查,无额外性能损耗。
代码示例:
首先定义包装类:
// 需提供无参构造、getter/setter保证序列化正常 public class OfferResponseResult { private List<OfferResponse> list; public OfferResponseResult() {} public OfferResponseResult(List<OfferResponse> list) { this.list = list; } public List<OfferResponse> getList() { return list; } public void setList(List<OfferResponse> list) { this.list = list; } }
修改消费端代码:
@ConsumeEvent(OfferRequest.ADDRESS) public Uni<OfferResponseResult> onOfferQuery(OfferRequest request) { List<KelkooOffer> offers = getOffers(request.getCategoryId()); List<OfferResponse> responses = new ArrayList<>(); for (KelkooOffer offer : offers) { responses.add(offer.getEventResponse()); } return Uni.createFrom().item(new OfferResponseResult(responses)); }
修改发送端代码:
@Query("offers") public Uni<List<OfferResponse>> getOffers(@PathParam("category") Integer categoryId) { OfferRequest event = new OfferRequest(); event.setCategoryId(categoryId); return bus.<OfferResponseResult>request(OfferRequest.ADDRESS, event) .onItem().transform(resp -> resp.body().getList()); }
2. 移除返回值的嵌套泛型声明(临时兼容)
如果不想新增包装类,可以将消费端返回值声明为Uni<?>,跳过Quarkus的泛型类型校验,发送端自行做类型转换即可:
消费端修改:
@ConsumeEvent(OfferRequest.ADDRESS) public Uni<?> onOfferQuery(OfferRequest request) { // 内部业务逻辑保持不变 List<KelkooOffer> offers = getOffers(request.getCategoryId()); List<OfferResponse> responses = new ArrayList<>(); for (KelkooOffer offer : offers) { responses.add(offer.getEventResponse()); } return Uni.createFrom().item(responses); }
该方案会丢失编译期对返回值的类型校验,不建议长期使用。
3. 升级Quarkus版本
该泛型解析缺陷已在Quarkus 2.10及以上稳定版本修复,若当前使用的Quarkus版本低于2.10,直接升级到最新稳定版即可无需修改业务代码解决问题。
内容的提问来源于stack exchange,提问作者Mattias Johansson
相关产品推荐
相关产品推荐

