Dominic
Dominic

Reputation: 4972

Update Vaadin 8 UI from Spring EventListener

I have a Spring Boot Vaadin application with a long-running thread in the service layer (which is triggered from the UI). While the thread is running, I'd like to give updates on the progress back to the View class and display it to the user.

I thought I could use the Spring Event mechanism (ApplicationEventPublisher, EventListener) to send events from the service layer and react accordingly in the UI.

However, the Service cannot publish the event to the view, as Scope 'vaadin-ui' is not active for the current thread:

View:

@SpringView
public class CustomView extends Composite implements View {
    private void triggerService() {
        new Thread(() -> service.executeLongRunningOperation()).start();
    }

    @EventListener
    private void onUpdate(UpdateEvent event) {
        getUI().access(() -> doSomething...);
    }
}

Service:

@Service
public class CustomService {
    @Autowired
    private ApplicationEventPublisher publisher;

    @Transactional
    public void executeLongRunningOperation() {
        // Some operation
        publisher.publishEvent(new UpdateEvent());
    }
}

My UI class is annotated with @Push.

Exception:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'viewCache': Scope 'vaadin-ui' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No VaadinSession bound to current thread
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:362)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:224)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1015)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:339)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:334)
    at com.vaadin.spring.internal.ViewScopeImpl$BeanFactoryContextViewCacheRetrievalStrategy.getViewCache(ViewScopeImpl.java:132)
    at com.vaadin.spring.internal.ViewScopeImpl.getViewCache(ViewScopeImpl.java:109)
    at com.vaadin.spring.internal.ViewScopeImpl.get(ViewScopeImpl.java:77)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:350)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)

What am I missing? Would another way be more appropriate?

My setup:

Upvotes: 0

Views: 612

Answers (1)

Tatu Lund
Tatu Lund

Reputation: 10643

It looks like you are firing the event from background thread, which is not spawned from main UI thread, e.g. using executors, @Async. Thus you get error about UI not bound to thread. And as consequence View cannot be determined. Thus I think this is sibbling of the similar issue that has been filed on our CDI add-on here https://github.com/vaadin/cdi/issues/226 As a workaround I would recommend to use event bus instead.

Upvotes: 1

Related Questions