在一个线程中触发 CDI-Events

Firing CDI-Events within a thread

在 Vaadin 应用程序中,我计划为方法实现异步结果概览。

结果概览包含 table 可能的结果。这些结果应该在后端方法在线程中 运行 异步时生成。应用程序后端和前端之间的通信计划使用 CDI-Events(结果信息将在 CDI-Event 中)。

我已经实现了触发 CDI-Events,将它们放入结果-table 并在方法完成后显示 table。但是当我在一个线程中执行该方法时(因此显示视图并插入事件而不是等待看到完整的 table),我的 CDI-Events 不会触发(或收到)。

有什么办法可以解决这个问题吗?我阅读了有关接收异步 CDI 事件的信息 (blog entry),但我没有找到任何有关在线程内触发事件的信息...

WildFly 10.0.1.Final、Java 8、Java-EE 7 和 Vaadin 7.6.6.

应该触发 CDI 事件的线程:

public class Executer implements Runnable{ 

  @Override
  public void run(){
    // Here will be the backend-method invocation for firing CDI-Events

    // CDI-Dummy-Event - Does not fire properly. receiveStatusEvent() does not invoke
    BeanManager beanManager = CDI.current().getBeanManager();
    beanManager.fireEvent(new ResultEvent("Result event example"));
  }

}

接收 CDI 事件的 Bean

public class EventReceiver implements LoggingProvider{

  public EventReceiver(){

  }

  public void receiveStatusEvent(@Observes ResultEvent event) {
     this.info("Event received: " + event.toString());
  }

}

在 ManagedExecutorService 的帮助下启动线程

public void executeAsynchBackendMethod(){

  // CDI-Dummy-Event works - receiveStatusEvent() invokes correctly
  BeanManager beanManager = CDI.current().getBeanManager();
  beanManager.fireEvent(new ResultEvent("Result event example"));

  /* The following alternative starts a thread, but the events, which are fired in the run() method, do not take any action in the receiveStatusEvent() method */

  // Getting managedExecuterService 
  this.managedExecuterService = (ManagedExecutorService) new InitialContext().lookup("java:comp/DefaultManagedExecutorService");

  // Getting Instance of executer-Runnable (for injecting the backend-service afterwards)
  Instance<Executer> executerInstance = CDI.current().select(Executer.class);
  Executer executer = executerInstance.get();

  // Start thread
  this.managedExecuterService.submit(executer);
}

在 CDI 1.2 及更低版本中,事件是严格同步的。在 CDI 2.0 中已经有异步事件的实现版本(在 Weld 中),但我想你被 1.2 困住了。

这意味着(正如您阅读的博客 post 所建议的那样),您可以使用声名狼藉的 EJB。

至于为什么 CDI 在这种情况下不起作用 - 我会说这都是线程绑定的。换句话说,在您触发事件的给定线程中,您没有观察者被触发。