I'm trying to come up with a way to create a notification system in my JSF application that mimics a push notification setup. Currently, I have a table set up in Oracle that contains notifications. When a user logs into the system, as part of the authentication process, I hit that table to see if there's any messages for that user, and I show them in a modal dialog upon login.
I would like to update this to also show any notifications that occur during the user's session. They might start a process that takes a while, and go about their business. When that process finishes, I'd like to be able to show a notification right away as opposed to them seeing the notification at next login. I could set up an ajax poller to check that table every minute or so, but that seems overkill. One of my team mates had an interesting idea, but we're not sure how to pull it off, so I'm looking for some input.
His idea was to have a Boolean stored in session. The Boolean would say whether or not there were new notifications added. Any process that adds new notifications would put a message on a JMS topic which would set that Boolean to true. There would be an ajax poller to check that Boolean every minute or so. If the Boolean gets set to "true", we'd make a database call at that time, check & display notifications, and set the Boolean to "false" again.
This means we're not hitting the database every minute unnecessarily, and checking a Boolean in the session costs nothing. If you haven't guessed it yet, the problem comes in when you try to figure out how to get an MDB to update a session variable. Is there some sort of stateful EJB I can set up that can be read by the user's session, as well as updated by a MDB? Or does anyone have an idea for a better implementation that would work?
Here's what I'm working with:
In the company I work for, it's tough to get them to sign off on open source solutions, so this needs to be something in-house. Any ideas are appreciated!
Using MDB to update HTTP session doesn't sound feasible to me anyway.
Using ajax polling may work but too often will impact performance/ user experience.
The first thing that come to my mind is EJB timer, which conceptually should work similarly to ajax polling every x minutes. Given this timer update the logged in user's flag about the messages, when the user does some transaction, if this flag is true (has message) then display the dialog.
The question now becomes does every transaction/page load need to check to this flag? Or don't use the dialog but have a message page with something like "Messages (x)" where x is the new/unread messages. This way won't interrupt user behavior. If he doesn't check it ... so be it show it for next logon.
hmm. Unless I'm misunderstanding you (which is entirely possible), it seems that using the EJB timer has the same problem as what I had originally proposed. I can set up an EJB timer, but how do I update something using an EJB timer that the user can see from their HTTP session? And the EJB timer is still hitting the database regularly to see if there's new messages.
I'm wondering if I might be able to use an application scoped bean to store the variable saying that there's new messages? I don't have a lot of experience with using application scope, but it's something to look at.
I just learned about a feature built into PrimeFaces called PrimeFaces Push. It sounds like it may do what I'm trying to accomplish, so I'll also be looking into that.
Very difficult to judge without knowing the database schema but I would stay clear of polling as the performance overhead just doesn't make sense.
Hitting that notification table with every login also seems a costly action to take, what happens when multiple users log in simultaneously or several notifications are generated at once? This of course depends on the total number of users your system has.
For a high user volume system, I would implement a notification table for each user which can be checked as and when needed (e.g. when a process has finished).
For a low user volume system I would suggest keeping the current notification table but do as your colleague suggested and set a notification flag for each user (held within their data, not the notification table). When a notification is issued to a user then their flag is also set (this also has the advantage of saving a check on the notification table when the user logs in and no notifications have previously been issued).
Other than that I guess you are looking at observer pattern and/or some type of publish-subscribe pattern.
I've not had any experience with PrimeFaces Push but seems likely that it would be another solution to your problem.