问题
I have CDI Events in place to notify my JSF application of progress from EJB processes. The code works fine when everything is synchronous.
@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());
}
}
.
@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
}
}
If I use an @Asychronous
annotation on runLongProcess()
, the JSF @Observer
method is never called.
How can I achieve this functionality ?
JSF 2.2 Glassfish 3.1 JEE 7 Java 8 Omnifaces 2.3
回答1:
There's not necessarily means of a HTTP request anywhere at that moment and in that thread. Therefore, there's not necessarily a JSF view available/identifiable at that moment (let alone a HTTP request or session).
It'll work in an application scoped bean.
Given that you're using OmniFaces 2.3, it might be worth the effort to take a look at <o:socket> to solve the requirement you had in mind. Its documentation also describes exactly this case and how to solve it properly with help of callbacks (and push the result via a web socket to the view).
@Inject
private SomeService someService;
@Inject @Push
private PushContext someChannel;
public void someAction() {
someService.someAsyncServiceMethod(entity, message -> someChannel.send(message));
}
@Asynchronous
public void someAsyncServiceMethod(Entity entity, Consumer<Object> callback) {
// ... (some long process)
callback.accept(entity.getSomeProperty());
}
来源:https://stackoverflow.com/questions/37117457/asynchronous-cdi-events-and-an-observes-method-in-named-bean