アプリケーションスコープのマネージドBeanを、Webアプリの起動時に強制的にインスタンス化/初期化する方法を見つけられないようです。アプリケーションスコープのBeanは、Webアプリの起動時ではなく、Beanに初めてアクセスしたときに遅延インスタンス化されるようです。私のWebアプリの場合、これは最初のユーザーが初めてWebアプリでページを開いたときに発生します。
これを避けたいのは、アプリケーションスコープのBeanの初期化中に、多くの時間のかかるデータベース操作が発生するためです。永続的なストレージから大量のデータを取得して、ListItem要素などの形式でユーザーに頻繁に表示されるデータの一部をキャッシュする必要があります。最初のユーザーが接続するときにすべてのことを実行したくないため、長い遅延を引き起こします。
私が最初に考えたのは、古いスタイルのServletContextListener contextInitialized()メソッドを使用し、そこからELResolverを使用して手動で管理対象Beanのインスタンスを要求することでした(したがって、初期化を強制します)。残念ながら、ELResolverはFacesContextを必要とし、FacesContextはリクエストの存続期間中にのみ存在するため、ELResolverを使用してこの段階で初期化をトリガーすることはできません。
誰かがこれを達成する別の方法を知っていますか?
MyFaces 1.2をJSF実装として使用していますが、現時点では2.xにアップグレードできません。
私の最初の考えは、古いスタイルのServletContextListener contextInitialized()メソッドを使用し、そこからELResolverを使用してマネージドBeanのインスタンスを手動で要求することでした(したがって、初期化を強制します)。 ELResolverにはFacesContextが必要であり、FacesContextはリクエストの存続期間中にのみ存在するため、残念ながら、この段階ではELResolverを使用して初期化をトリガーすることはできません。
that複雑にする必要はありません。 Beanをインスタンス化し、same管理Bean名をキーとしてアプリケーションスコープに配置するだけです。 JSFは、スコープにすでに存在している場合、Beanを再利用します。 JSFがサーブレットAPIの上にある場合、ServletContext
はアプリケーションスコープを表します(HttpSession
はセッションスコープを表し、HttpServletRequest
はリクエストスコープを表し、それぞれsetAttribute()
およびgetAttribute()
メソッド)。
これで十分です
public void contextInitialized(ServletContextEvent event) {
event.getServletContext().setAttribute("bean", new Bean());
}
ここで、"bean"
は、<managed-bean-name>
のアプリケーションスコープBeanのfaces-config.xml
と同じである必要があります。
参考までに、JSF 2.xでは、eager=true
Beanの@ManagedBean
に@ApplicationScoped
を追加するだけで済みます。
@ManagedBean(eager=true)
@ApplicationScoped
public class Bean {
// ...
}
その後、アプリケーションの起動時に自動インスタンス化されます。
または、CDI @Named
でバッキングBeanを管理している場合は、 OmniFaces@Eager
を取得します。
@Named
@Eager
@ApplicationScoped
public class Bean {
// ...
}
Romain Manni-Bucauさんは、CDI 1.1を使用するこの素晴らしいソリューションを blog に投稿しました。
トリックは、組み込みのライフサイクルスコープの初期化をBeanに観察させることです。つまり、この場合はApplicationScoped
です。これは、シャットダウンのクリーンアップにも使用できます。したがって、例は次のようになります。
@ApplicationScoped
public class ApplicationScopedStartupInitializedBean {
public void init( @Observes @Initialized( ApplicationScoped.class ) Object init ) {
// perform some initialization logic
}
public void destroy( @Observes @Destroyed( ApplicationScoped.class ) Object init ) {
// perform some shutdown logic
}
}
私の知る限り、アプリケーションの起動時にマネージドBeanを強制的にインスタンス化することはできません。
マネージドBeanをインスタンス化する代わりに、それ自体ですべてのデータベース操作を実行するServletContextListenerを使用できますか?
別の解決策は、アプリケーションの起動時にBeanを手動でインスタンス化し、そのBeanをServletContextの属性として設定することです。
ここにコードサンプルがあります:
public class MyServletListener extends ServletContextListener {
public void contextInitialized(ServletContextEvent sce) {
ServletContext ctx = sce.getServletContext();
MyManagedBean myBean = new MyManagedBean();
ctx.setAttribute("myManagedBean", myManagedBean);
}
}
私の意見では、これはクリーンなコードからはほど遠いですが、それはトリックを行うようです。