I have a jsf view which shows some data from a managed-bean (viewscope) in a table, that is retrieved remotely.
Currently the data is updated via polling from the client-view using primefaces poll component.
This is not sufficient enough, since to much traffic is sent to client and now that primefaces supports server-push I only want to reload the data and push it to the client-view if data has been changed.
This should be realized via polling from the web-tier to application tier calling a method like hasChanged(...)
. If data is changed the web-tier pushes a notification to client to reload data.
Current client poll
client >> web-tier >> app-tier
client asks web-tier via ajax for data which again asks app-tier for data and updates view
Wished web-tier poll and push
client << web-tier >> app-tier
web-tier polls app-tier if data has changed and reloads on behalf and informs (pushes) client to update view
Approaches:
What is the best approach to realize the polling at the managed-bean in the web-tier?
- TimerTask in the managed-bean
Spawning threads in a JSF managed bean for scheduled tasks using a timer - Additional EJB with Schedule annotation
- Additional EJB with TimerService
- other?
Edit:
Architecture: (3-tier)
- Server1: database
- Server2: app-tier (EAR with Remote EJB + Hibernate)
- Server3: web-tier (WAR with JSF 2.0 + Primefaces 3.4)
- Client: Browser
Based on my experience, I can recommend two routes, Spring Integration and CDI Events. I'd recommend the Spring route, but based on your current stack, I think CDI events have you covered. They cleanly help you achieve the Observer/Observable pattern and you can pull of a clean separation of tiers too. I must warn you though, this approach is effective only for a small-medium use case. Consider the following:
Design and implement an
Event
class that encapsulates all the information that is required to be delivered to consumers. Let's call it aFundsTransfer
event Your event implementation should contain enough information to enable listeners filter only for events of interest. A simple POJOImplement a business object at the business layer, call it
Notifier
. The function of polling should be delegated to this object. It will be in charge of creating and publishing objects of typeevent
in response to changes on the server side. Depending on your requirements, this object could be a singleton to handle allEvent
types or you could have a group ofNotifier
types polling for different events.In the code above, I've used a
Timer
EJB as my Observer. See this for an introduction to EJB timers. Again, theObserver
object will live in the app tierThe client tier will each have access to an listener object that will be notified when an event of interest occurs (that is has been published by a
Notifier
type). Then the listener can issue apush
based on this event. Your listener object could be a POJO with@Named
CDI annotation. In your listener object, simply implement a method with an@Observes
annotation, with a parameter of the type of event the listener is interested in:The above filtering is still quite crude compared to the message filtering options that CDI provides. As you can see from the tutorial I referenced earlier, you could create CDI qualifiers that can give you finer grained filtering on messages. Like I stated earlier, this is a bit heavy for large scale deployment, in which case I'd advise the spring integration route, if you're up to take the dependency on.
In summary, the model of the system will be: