我在Vaadin + Spring项目中使用Guava Eventbus,并开始遇到从后台线程发布事件的问题。
Eventbus在包装器类中实例化。对象使用主UI类中定义的静态方法与eventbus通信,以获取eventbus对象。它与Vaadin Dashboard示例(DashboardEventBus)中提出的方法相同。
public class MainUI extends UI implements ViewDisplay
{
private EventBusWrapper eventbus_ = new EventBusWrapper();
public static EventBusWrapper GetEventBusWrapper()
{
return ((MainUI) getCurrent()).eventbus_;
}
}
在我创建新线程类并启动线程的presenter / services类中出现问题。 在运行方法的Runnable实现中,我创建了另一个可以完成工作的对象。
public class SearchResultsPresenter extends AbstractPresenter<SearchResultView>
{
public SearchResultsPresenter()
{
EventBusWrapper.register(this);
}
@Subscribe
public void UserSearchRequested(Event.UserSearchRequestEvent e)
{
new UpdateContentComponentThread(e.GetSearchElem()).start();
}
@Subscribe
public void UserSearchAppendFoundElement(Event.UserSearchElementFound e)
{
if(e.GetElement().IsValid())
view_.AddElement(e.GetElement());
}
public class UpdateContentComponentThread extends Thread
{
private final Search searcher_;
UpdateContentComponentThread(SearchElement search)
{
searcher_ = new DefaultSearch(search);
}
@Override
public void run()
{
searcher_.Search();
}
}
}
它执行一些验证/检查并创建其他帮助程序类。
public class DefaultSearch implements Search
{
private final Scraper scraper_;
...
@Override
public void Search()
{
if(!scraper_.IsConfigured())
return;
...
scraper_.FindElements();
}
}
然后在scraper的FindElements主体中,我尝试使用EventBusWrapper中定义的静态post方法发布事件。
public class HttpElementScraper extends WebScraper
{
...
@Override
public Collection<Element> FindElements()
{
...
Element elem = ...
Event.UserSearchElementFound e = new Event.UserSearchElementFound(elem);
EventBusWrapper.post(e);
return foundelements;
}
}
此时抛出NullPointerException,我无法解决并帮助解决问题。
Exception in thread "Thread-10" java.lang.NullPointerException
at com.project.MainUI.GetEventBusWrapper(MainUI.java:109)
at com.project.events.EventBusWrapper.register(EventBusWrapper.java:24)
at com.project.service.search.scraper.HttpElementScraper.FindElements(HttpElementScraper.java:92)
at com.project.service.search.DefaultSearch.Search(DefaultSearch.java:38)
at com.project.view.search.SearchResultsPresenter$UpdateContentComponentThread.run(SearchResultsPresenter.java:71)
//我没有提到重要的代码和注释行。与它们相关的大多数组件和服务都是UIscoped。
答案 0 :(得分:3)
Vaadin假设对Vaadin组件(和相关)实例的访问正确同步。使用传统的单线程请求 - 响应周期访问组件时,它会自动同步。
使用外部线程时,您需要使用UI.access()
同步访问Vaadin组件的代码。例如:
getUI().access(() -> label.setValue("Hello"));