在cdi会话上下文之间进行通信 - 使用数据库,是否可以调用适当的cdi上下文?

在cdi会话上下文之间进行通信 - 使用数据库,是否可以调用适当的cdi上下文?

问题描述:

我无法在同一个java-ee容器中使用sessioncoped bean和ejb有状态bean在用户会话之间进行通信。通过反复试验,我决定使用数据库在用户会话之间传递消息。但是现在我遇到了问题,如何通知用户会话数据库已更改
我是否可以在每个用户的会话上下文中启动后台轮询线程来轮询数据库以进行更改?如果这可行,那么避免阻塞的最佳方法是什么,但要确保轮询bean在自己用户的会话上下文中唤醒?

I'm having trouble getting sessionscoped beans and ejb stateful beans to communicate between user sessions, within the same java-ee container. Through trial and error I have settled on using a database to pass messages between the user sessions. But now I have a problem, how do I notify a user's session that the DB has changed Can I start a background polling thread in each user's session context to poll the database for changes? If this would work, what is the best method to avoid blocking, but to make sure the polling bean "wakes up" in their own user's session context?

我正在使用Glassfish 3.1.2,用户会话是CDI会话编程bean,有一些有状态的EJB用于JPA数据库访问。我正在使用CDI事件总线在用户会话中传递bean周围的消息。

I'm using Glassfish 3.1.2, and user sessions are CDI sessionscoped beans, with some stateful EJBs for JPA database access. I'm using the CDI event-bus to pass messages around the beans in the user's session.

我试图使用Singletons在用户会话之间进行通信。但这不起作用,因为一旦源自用户1的消息传递给用户2的bean,并且那些bean触发CDI事件,CDI事件由用户1的会话上下文处理。这是有道理的,因为消息在用户1的会话中创建。

I have tried to use Singletons to communicate between user sessions. But that doesn't work because once the message originating from user 1 is passed to user 2's beans, and those beans fire off a CDI event, the CDI event is handled by the session context of user 1. Which makes sense, since the message was created while in User 1's session.

任何帮助将不胜感激!!

Any help would be appreciated!!

我想我必须回答我自己的问题 -

I guess I have to answer my own question --


  1. 上下文不会传播到新线程或异步调用。这是CDI 1.0规范的未定义行为,因此不需要容器来跟踪创建线程的上下文。如果您创建一个线程,然后在线程唤醒后触发CDI事件,则该CDI事件将没有活动上下文,并将抛出以下错误: org.jboss.weld.context.ContextNotActiveException: WELD-001303范围类型javax.enterprise.context.RequestScoped 没有活动的上下文或者特定于您的线程尝试激活的范围的内容。 查看此Glassfish票证,这不是一个错误,它只是未定义的行为。

  1. Contexts are not propagated to new threads or asynchronous calls. This is an undefined behavior of the CDI 1.0 spec, and so containers are not required to keep track of which context created a thread. If you create a thread and then fire off a CDI event once the thread wakes up, that CDI event will have no active context, and will throw the following error: org.jboss.weld.context.ContextNotActiveException: WELD-001303 No active contexts for scope type javax.enterprise.context.RequestScoped or something specific to the scope your thread was trying to activate. See this Glassfish ticket, which really isn't a bug, it's just undefined behavior.

因此,当设置任何后台轮询线程以检查用户数据是否有任何更改时,当线程检测到更改时,它无法通过CDI事件与用户的会话上下文进行通信。那个时候线程没有上下文。对于少数人来说,这似乎是一个悬而未决的问题:在jboss论坛上 缝论坛

Therefore, when any background polling thread is set up to check if there are any changes to a user's data, when the thread detects the change it has no way to communicate (via CDI events) with the user's session context. The thread has no context at that moment. This seems to be an unanswered question for a few people: on the jboss forum and the seam forum.

希望我的解决方案有所帮助。在CDI 1.1定义了一种将会话上下文传播到线程的方法之前,您必须让用户轮询他们自己的数据,当他们获得新数据时,他们可以在自己的会话上下文中对其进行操作。我设置了自己的系统来使用数据库为每个用户存储一个事件队列,当他们轮询时,他们只是遍历排队的消息并将其解雇,就好像它们是在自己的会话环境中发送的CDI消息一样。

Hopefully my solution will help. Until CDI 1.1 defines a way to propagate session context to threads, you have to make the user poll for their own data, and when they get their new data, they can act on it within their own session context. I set up my own system to use the database to store an event queue for each user, and when they poll, they just iterate through their queued messages and fire them off as if they were CDI messages sent in their own session context.

如果我错了,焊接CDI专家可以纠正我,我将不胜感激!

If a weld CDI expert could correct me if I'm wrong, I would appreciate it!