Обновление пользовательского интерфейса Vaadin 8 из Spring EventListener - PullRequest
0 голосов
/ 27 апреля 2018

У меня есть приложение Spring Boot Vaadin с долго работающим потоком на уровне обслуживания (которое запускается из пользовательского интерфейса). Пока поток запущен, я хотел бы предоставить обновления о прогрессе обратно в класс View и показать его пользователю.

Я подумал, что мог бы использовать механизм Spring Event (ApplicationEventPublisher, EventListener), чтобы отправлять события из сервисного уровня и соответствующим образом реагировать в пользовательском интерфейсе.

Однако Служба не может опубликовать событие в представлении, как Scope 'vaadin-ui' is not active for the current thread:

Вид:

@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
public class CustomService {
    @Autowired
    private ApplicationEventPublisher publisher;

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

Мой класс пользовательского интерфейса помечен @Push.

Исключение:

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)

Что мне не хватает? Был бы другой способ более подходящим?

Моя настройка:

  • Ваадин 8.3.3
  • Spring Boot 2.0.1

1 Ответ

0 голосов
/ 27 апреля 2018

Похоже, что вы запускаете событие из фонового потока, который не создается из основного потока пользовательского интерфейса, например используя исполнителей, @Async. Таким образом, вы получаете ошибку об интерфейсе, не связанном с потоком. И, как следствие, точка зрения не может быть определена. Таким образом, я думаю, что это аналогичный вопрос, который был задан в нашем дополнении CDI здесь https://github.com/vaadin/cdi/issues/226 В качестве обходного пути я бы рекомендовал вместо этого использовать шину событий.

...