关于 jsf:@Asynchronous CDI Events 和 @Named bean 中的 @Observes 方法

@Asynchronous CDI Events and an @Observes method in @Named bean

我有 CDI 事件来通知我的 JSF 应用程序来自 EJB 进程的进度。当一切都同步时,代码可以正常工作。

1
2
3
4
5
6
7
8
9
10
11
12
13
@Stateless
public class MySessionBean implements Serializable {

    @Inject
    @ProcessEvent
    Event<ProcessEvent> processEvent; // Also tried to use BeanManager

    @Asynchronous // This annotation breaks my code
    public void runLongProcess() {
        processEvent.fire(new ProcessEvent());
    }

}

.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Named
@ViewScoped
public class ManagedBean implements Serializable {

    @EJB
    MySessionBean sessionBean;

    public void runProcess () {
        sessionBean.runLongProcess();
    }

    @Asynchronous // This annotation doesn't work
    public void onEvent(@Observes @ProcessEvent ProcessEvent event){
        LOGGER.log(Level.INFO,"Event was received"); // Never called
    }
}

如果我在 runLongProcess() 上使用 @Asychronous 注释,则永远不会调用 JSF @Observer 方法。

我怎样才能实现这个功能?

JSF 2.2
玻璃鱼 3.1
杰伊 7
爪哇 8
Omnifaces 2.3


在那个时刻和那个线程中的任何地方都不一定意味着 HTTP 请求。因此,此时不一定有可用/可识别的 JSF 视图(更不用说 HTTP 请求或会话了)。

它将在应用程序范围的 bean 中工作。

鉴于您使用的是 OmniFaces 2.3,可能值得花点时间查看一下 <o:socket> 来解决您心中的需求。它的文档还准确描述了这种情况以及如何在回调的帮助下正确解决它(并通过 Web 套接字将结果推送到视图)。

1
2
3
4
5
6
7
8
9
@Inject
private SomeService someService;

@Inject @Push
private PushContext someChannel;

public void someAction() {
    someService.someAsyncServiceMethod(entity, message -> someChannel.send(message));
}
1
2
3
4
5
@Asynchronous
public void someAsyncServiceMethod(Entity entity, Consumer<Object> callback) {
    // ... (some long process)
    callback.accept(entity.getSomeProperty());
}