CDI と JPA がすでに統合されている Tomcat のバージョン ( TomEE ) を試すことをお勧めします。OpenJPA に付属していますが、Hibernate を使用できます。次に、次のようなクラスでキャッシュを行います。
@Singleton
@Startup
public class CachingBean {
@Resource
private BeanManager beanManager;
@Schedule(minute = "*/10", hour = "*")
private void run() {
// cache things
}
}
このコンポーネントは、アプリの起動時に自動的に起動し、上記のメソッドを 10 分ごとに実行します。詳細については、スケジュールのドキュメントを参照してください。
アップデート
あなたのために例をハックしました。優れた CDI/EJB の組み合わせを使用して、CDI イベントをスケジュールします。
事実上、これはミックスBeanManager.fireEvent(Object,Annotations...)
に追加するメソッドの単純なラッパーです。ScheduleExpression
@Singleton
@Lock(LockType.READ)
public class Scheduler {
@Resource
private TimerService timerService;
@Resource
private BeanManager beanManager;
public void scheduleEvent(ScheduleExpression schedule, Object event, Annotation... qualifiers) {
timerService.createCalendarTimer(schedule, new TimerConfig(new EventConfig(event, qualifiers), false));
}
@Timeout
private void timeout(Timer timer) {
final EventConfig config = (EventConfig) timer.getInfo();
beanManager.fireEvent(config.getEvent(), config.getQualifiers());
}
// Doesn't actually need to be serializable, just has to implement it
private final class EventConfig implements Serializable {
private final Object event;
private final Annotation[] qualifiers;
private EventConfig(Object event, Annotation[] qualifiers) {
this.event = event;
this.qualifiers = qualifiers;
}
public Object getEvent() {
return event;
}
public Annotation[] getQualifiers() {
return qualifiers;
}
}
}
それを使用するにはScheduler
、EJB としてインジェクトし、スケジュールを設定します。
public class SomeBean {
@EJB
private Scheduler scheduler;
public void doit() throws Exception {
// every five minutes
final ScheduleExpression schedule = new ScheduleExpression()
.hour("*")
.minute("*")
.second("*/5");
scheduler.scheduleEvent(schedule, new TestEvent("five"));
}
/**
* Event will fire every five minutes
*/
public void observe(@Observes TestEvent event) {
// process the event
}
}
完全なソース コードと動作例は、こちら.
あなたは知らなければならない
10 人のオブザーバーがあり、それぞれの実行に 7 分かかる場合、1 つのイベントの合計実行時間は 70 分です。そのイベントが 70 分よりも頻繁に発生するようにスケジュールしても、まったく役に立ちません。
あなたがした場合はどうなりますか?ポリシー@Singleton
@Lock
による
@Lock(WRITE)
がデフォルトです。このモードでは、timeout
メソッドは基本的に、前の呼び出しが完了するまでロックされます。70分ごとに1つしか処理できない場合でも、5分ごとに起動すると、最終的にプールされたすべてのタイマースレッドがシングルトンで待機することになります。
@Lock(READ)
メソッドの並列実行を可能にしtimeout
ます。しばらくの間、イベントが並行して発生します。ただし、実際にはそれぞれ 70 分かかるため、上記と同様に、1 時間ほどでタイマー プールのスレッドが不足します。
洗練された解決策は、使用してから、メソッドの@Lock(WRITE)
ように短いタイムアウトを指定することです。次の 5 分間の呼び出しがトリガーされると、あきらめる前にシングルトンへのアクセスを取得するまで 1 分まで待機します。これにより、タイマー プールがバックアップされたジョブでいっぱいになるのを防ぐことができます。「オーバーフロー」は単純に破棄されます。@AccessTimeout(value = 1, unit = TimeUnit.MINUTES)
timeout