从MDB触发CDI事件以更新JSF页面

时间:2013-12-12 01:47:58

标签: jsf jms cdi

是否可以从MDB发起CDI事件?此MDB正在监视JMS队列,然后需要更新JSF页面。

我遇到的问题是JSF bean有一个范围(是会话,但尝试请求),MDB没有范围。 JSF bean包含控制器代码(更新页面)和方法参数上的@Observes注释。由于MDB不在“上下文”中且没有作用域,因此从不在JSF Bean上触发CDI事件。

如何基于JMS(带有MDB)事件更新JSF页面呢?

4 个答案:

答案 0 :(得分:0)

免责声明,我很清楚我在这里声称的是什么,但不是100%。

只有MDB和CDI事件才能做到这一点。通常,CDI事件会重用请求线程,并在调用方法后同步执行事件。这意味着它即使有效也是潜在的瓶颈。第二部分是它将根据产生它的请求找到观察者,而不是找到其他“用户”或其他什么。

您可以通过几种不同的方式和多种技术来解决这个问题,但WebSockets / Atmosphere框架通常是将信息传递到那里的可靠方法。请注意,Primefaces Push存在且基于Atmosphere。

我最近有一个项目(小),我需要一个普通的tomcat,我无法使用WebSockets,因此我使用CDI事件制作了一个解决方案。

它的工作原理如下:

  1. 我没有使用event.fire(new myEvent()),而是采取了更透明的方式,即我希望它能够清楚地表明此活动将会播放到所有会话中。所以我创建了我称之为SessionEventDelegator的东西。它有一个名为putEvent(Object object)的方法(当你需要限定符时也有其他方法)。当您想要将事件发送到所有会话时,您只需注入并“放置”您的活动。也许我应该称之为加载,因为它会在以后被解雇; p

  2. 稍后,JSF PhaseListener调用getEvents()并获取自上次检查以来的所有新事件。时间戳功能已到位,因此您只能获得新事件。

  3. 现在只需遍历找到的事件,然后使用BeanManager.fire将它们删除。

  4. 由于PhaseListener只会在用户发出新请求时触发,我会使用来自primefaces的p:poll,确保每隔三秒钟轮询一次新事件。

  5. 清理算法可确保每个人获得的事件都从SessionEventDelegator中的队列中删除。

  6. 如果你想要代码让我知道。如果听起来不合适,就懒得粘贴它。

答案 1 :(得分:0)

如果CDI事件不起作用(我不相信,因为规范说非上下文对象无法观察事件,没有任何关于触发它们)但最简单的解决方法似乎使用拦截器。 MDB可以有拦截器,只需截取onMessage方法并从拦截器触发事件​​。

答案 2 :(得分:0)

是的,您可以从MDB发起CDI事件。问题是它们只会在应用程序级别上被观察到。如果您正在使用推送技术(例如Websockets),则可以让此ApplicationScoped对象接收事件,然后根据websockets中的会话ID推送到相应的客户端。

答案 3 :(得分:0)

在RichFaces库中,a4j:push组件可以完全满足您的需求。查看RichFaces Push section