Vaadin Grid接收Spring事件后未刷新,订阅Mono更新数据无显示如何解决
问题排查与解决方案
核心原因
- 响应式流回调线程未持有Vaadin UI锁:Vaadin所有UI组件的更新操作必须在UI线程上下文中执行,你直接在WebFlux的subscribe回调中调用
setItems,默认回调运行在Reactor调度线程上,不属于当前UI会话的线程,Vaadin不会将这次更新推送到前端,因此看不到变化也不会抛出异常,完全符合你描述的现象。 - SearchResultModel 字段赋值缺失:你初始化Grid列时指定了
subscriptionNumber作为第一列,但构建SearchResultModel实例时没有给该字段赋值,即使更新生效也会出现首列空白的问题。
修复方案
修改onApplicationEvent方法,将UI更新操作包裹在UI.access中执行,同时补全缺失的字段赋值即可:
@Override public void onApplicationEvent(FetchBySubscriptionNumberAction action) { log.info(action.getSubscriptionNumber()); // 先获取当前组件绑定的UI实例,避免会话过期空指针 UI currentUi = getUI().orElse(null); if (currentUi == null) { log.warn("当前组件未绑定到任何UI会话,忽略更新"); return; } sumoCmMemberService .fetchBySubscriptionNumber(action.getSubscriptionNumber()) .doOnError(e -> log.error("error in webflux: " + e.getMessage())) .subscribe(sumoCmMemberDto -> { SumoSubscriptionDto sumoSubscriptionDto = sumoCmMemberDto.getSumoSubscription(); SearchResultModel searchResultModel = SearchResultModel .builder() // 补全缺失的subscriptionNumber字段 .subscriptionNumber(action.getSubscriptionNumber()) .mnr(sumoCmMemberDto.getMnumber()) .firstName(sumoSubscriptionDto.getFirstName()) .lastName(sumoSubscriptionDto.getLastName()) .street(sumoSubscriptionDto.getStreet()) .houseNumber(sumoSubscriptionDto.getHouseNumber()) .box(sumoSubscriptionDto.getBox()) .active(sumoCmMemberDto.isActive()) .build(); searchResultModels = List.of(searchResultModel); // UI更新操作必须放到UI.access中执行 currentUi.access(() -> { setItems(searchResultModels); }); }); }
额外注意事项
- 因为你使用了
SCOPE_PROTOTYPE作用域,每次从Spring上下文获取该组件都会新建实例,请确认监听事件的实例就是当前前端页面渲染的实例,否则也会出现更新无效的问题。
内容的提问来源于stack exchange,提问作者Trace
相关产品推荐
相关产品推荐

