0

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?

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.

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!!

Christopher Poile
  • 985
  • 1
  • 11
  • 17

2 Answers2

4

I guess I have to answer my own question --

  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.

  2. 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.

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.

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

Christopher Poile
  • 985
  • 1
  • 11
  • 17
0

I don't think the CDI event bus can be used to communicate between user sessions.

Wouldn't it be better to solve this problem with a JMS message broker? Your application will scale so much better! Run it as a separate instance or embed it in your application server. You could for example use an ActiveMQ broker.

Post a notification message on a JMS topic, and make user sessions subscribe to it. I haven't yet used the Seam 3 JMS module, but it looks like it is able to bridge the gap between JMS and CDI. Using Seam JMS you could receive JMS messages in each user session. The example in the documentation explains how for each user you register a JMS listener in the @PostConstruct of a @SessionScoped bean.

jonne
  • 305
  • 3
  • 5
  • Nope, it won't work -- I tried it. When a JMS message is received there is no context for the receiving bean -- it cannot send a sessionscoped contextual event to existing session because the message receiving bean (the listener method or the MDB) is out of scope. You will get the WELD-001303 exception I noted above. – Christopher Poile Mar 30 '12 at 17:17