如何在Web层中实现托管bean的轮询最佳方法?
- 在托管bean中使用TimerTask
在JSF托管bean中生成线程以进行定时任务的方法 - 使用Schedule注释的其他EJB
- 使用TimerService的其他EJB
- 其他方法?
编辑:
架构:(3层)
- 服务器1:数据库
- 服务器2:应用层(带有远程EJB + Hibernate的EAR)
- 服务器3:Web层(带有JSF 2.0 + Primefaces 3.4的WAR)
- 客户端:浏览器
如何在Web层中实现托管bean的轮询最佳方法?
编辑:
架构:(3层)
Design and implement an Event
class that encapsulates all the information that is required to be delivered to consumers. Let's call it a FundsTransfer
event Your event implementation should contain enough information to enable listeners filter only for events of interest.
A simple POJO
class FundsTransfer {
BigDecimal transferValue;
Date transferDate;
int transferCurrencyCode;
public FundsTransfer(BigDecimal transferValue, Date date, int currencyCode) {
//set accordingly
}
//setters and getters
}
Implement 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 type event
in response to changes on the server side. Depending on your requirements, this object could be a singleton to handle all Event
types or you could have a group of Notifier
types polling for different events.
//A sample implementation of your Observer object :
@Singleton //Defines a singleton EJB
public class PollerService {
@Inject
Event fundsTranferNotifier;
//this annotation specifies that the polling method should run every second.
@Schedule(second = "*/1", minute = "*", hour = "*", persistent = false)
public void pollIt() {
boolean found = this.pollingMethod(); // pollingMethod() will do the actual polling
if (found) { //based on the outcome of the polling method, fire the notifier method
blowWhistleOnTransfer();
}
}
public void blowWhistleOnTransfer() {
//this is the broadcast event.
fundsTransferNotifier.fire(new FundsTransfer(new BigDecimal("100000", new Date(), 855));
}
}
In the code above, I've used a Timer
EJB as my Observer. See this for an introduction to EJB timers. Again, the Observer
object will live in the app tier
The 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 a push
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:
public void onNewTransfer(@Observes FundsTransfer transfer) {
if (transfer.compareTo(new BigDecimal("150000")) > 0) {
//push to view.
}
}
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.
总的来说,该系统的模型将会是:
One Poller(Notifier) Object (In the app layer)
|
|
|
Multiple Listener Objects (In the web tier)
---------------------------------------------------
| | | | | | | | | | | |
Notifier
对象将位于应用程序层。它应该进行轮询/检查以查找更改。根据其发现,它将在整个JEE上下文中广播消息。Observer
对象将根据Notifier
的广播接收Event
实例/通知。Observer
对象将位于Web层,并根据Event
实例,您可以使用primefaces push来影响客户端的更改。 - kolossusapp-tier
中创建了一个名为Notifier
的单例EJB,它具有定时方法和事件Event<String>
(定期触发事件并打印到控制台)。在我的web-tier
中,我创建了一个有状态的EJB Listener
,其中包含@Observes String str
方法,该方法将字符串打印到控制台。该ListenerEJB
使用@EJB
注入到托管bean中,在我的视图中调用该bean。当然什么也没有发生。这个EJB应该如何被远程单例通知?对于以前的所有远程EJB访问,我都必须使用jndi查找来建立连接,在这种情况下我该怎么办? - djmj