NotTwoTimes
NotTwoTimes

Reputation: 1

Posting an event from different thread with Guava EventBus

I'm using Guava Eventbus in Vaadin+Spring project and started to have a problem with posting an event from background thread.

Eventbus is instantiated in wrapper class. Objects communicate with the eventbus using static method defined in main UI class to obtain the eventbus object. It is the same way as proposed in Vaadin Dashboard example (DashboardEventBus).

public class MainUI extends UI implements ViewDisplay
{
    private EventBusWrapper eventbus_ = new EventBusWrapper();

    public static EventBusWrapper GetEventBusWrapper()
    {
        return ((MainUI) getCurrent()).eventbus_;
    }
}

Problem appears in presenter/services classes where I create new thread class and start the thread. Inside Runnable implemenation of run method I create another object which makes some job.

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();
        }
    }
}

It performs some validation/checking and creates other helper classes.

public class DefaultSearch implements Search
{
    private final Scraper scraper_;
    ...

    @Override
    public void Search()
    {
        if(!scraper_.IsConfigured())
            return;
        ...
        scraper_.FindElements();
    }
}

Then inside scraper's FindElements body I try to post an event using static post method defined in EventBusWrapper.

public class HttpElementScraper extends WebScraper
{
    ...

        @Override
        public Collection<Element> FindElements()
        {
            ...
            Element elem = ...
            Event.UserSearchElementFound e = new Event.UserSearchElementFound(elem);
            EventBusWrapper.post(e);

            return foundelements;
        }
    }

At this moment the NullPointerException is thrown and I cannot solve and help myself with the problem.

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)

// I ommited not important lines of code and annotations. Most of the components and services connected with them are UIscoped.

Upvotes: 0

Views: 702

Answers (1)

Henri Kerola
Henri Kerola

Reputation: 4967

Vaadin assumes that access to Vaadin component (and related) instances is synchronized properly. When using the traditional single-threaded request-response cycle to access components it's synchronized automatically.

When using external threads, you need to synchronize code accessing your Vaadin components by using UI.access(). For example:

getUI().access(() -> label.setValue("Hello"));

Upvotes: 4

Related Questions