我在访问PushContext
实例时遇到了一些问题。
我想将消息发送到与托管bean分开运行的线程中。通过@Injected @Push
注入,我不能。有谁知道我怎么能这样做?
答案 0 :(得分:1)
在线程中访问OmniFaces PushContext实例
PushContext
只能注入驻留在WAR中的容器管理工件(例如@Named
,@WebServlet
,@WebFilter
,@WebListener
等) ,而不是其他地方(即绝对不在@Stateless
,@Stateful
,@Singleton
等。)
我想在与托管bean分开运行的线程中发送消息
只有当线程由容器管理时才会起作用,例如由EJB @Asynchronous
启动的线程。如果线程不受管理(即使用Thread
手动创建),它将无法工作。这在Is it safe to start a new thread in a JSF managed bean?
正确使用EJB的@Asynchronous
时,只需按照<o:socket>
文档中的示例操作即可。您可以在EJB design hints部分找到它们。
documentation的以下摘录显示了如何通过@Asynchronous
EJB方法推送应用程序范围的套接字,而后者又被某个后台作业调用(例如{{ 1}})。
如果您想从EAR / EJB端触发推送到应用程序范围的推送套接字,那么您可以使用CDI事件。首先创建一个表示push事件的自定义bean类,类似于下面的PushEvent,将你想要的任何内容作为推送消息传递。
@Schedule
然后使用
public final class PushEvent { private final String message; public PushEvent(String message) { this.message = message; } public String getMessage() { return message; } }
来发起CDI事件。BeanManager.fireEvent(Object, java.lang.annotation.Annotation...)
最后,只需@Observes它在WAR中的某个请求或应用程序范围的CDI托管bean中,并委托给PushContext,如下所示。
@Inject private BeanManager beanManager; public void onSomeEntityChange(Entity entity) { beanManager.fireEvent(new PushEvent(entity.getSomeProperty())); }
documentation的以下摘录显示了如何通过@Inject @Push
private PushContext someChannel;
public void onPushEvent(@Observes PushEvent event) {
someChannel.send(event.getMessage());
}
EJB方法推送到会话或视图范围的套接字由某些JSF动作调用。
如果EAR / EJB端的触发器是在WAR端启动的异步服务方法,那么您可以使用WAR端的回调。让业务服务方法将回调实例作为参数,例如
@Asynchronous
功能界面。java.util.function.Consumer
并在WAR中调用异步服务方法,如下所示。
@Asynchronous public void someAsyncServiceMethod(Entity entity, Consumer<Object> callback) { // ... (some long process) callback.accept(entity.getSomeProperty()); }