Deletions are marked like this. | Additions are marked like this. |
Line 18: | Line 18: |
そしてむしろ、これらのスコープされたオブジェクトを使う場合にはオブジェクトそのものの注入は避けるべきである。 なぜなら、注入先のオブジェクトがリクエストやセッションを越えて生き残る場合には、誤ってそのスコープ外でスコープされたオブジェクトを使ってしまうというバグになりかねないからである。 したがって、これらのスコープされたオブジェクト使う場合は、必ずプロバイダあるいはサービスロケータから取得するのがベストと思われる。 |
|
Line 19: | Line 24: |
以下では、Guice 2.0, Wicket 1.4.3, Jetty 7.0.1を利用している。 特にJettyはバージョンによって仕様がよく変更されているので注意・ Guiceは極力XMLを排除するように設計されている。[[guice/Manual/Integration/WebandServlets|ウェブとサーブレット]]でのGuiceFilterの利用例でもこれが貫かれている。 それでも他のサーブレットコンテナでは最低限のweb.xml記述が必要と思われるが、 Jettyでは完全にweb.xmlを排除することができる。 ほとんどのセットアップはInjectorの作成時に行えばよい。 仮にInjectorが得られたものとして、以下のコードでJettyを起動する。 以下のコードは、ほぼどんな場合でも同じになると思われる。 {{{ Server server = new Server(); Connector connector = new SocketConnector(); connector.setPort(8080); server.addConnector(connector); ServletContextHandler context = new ServletContextHandler(server, "/", ServletContextHandler.SESSIONS); context.addFilter(GuiceFilter.class, "/*", 0); context.addEventListener(new GuiceServletContextListener() { @Override protected Injector getInjector() { return injector; } }); context.addServlet(DefaultServlet.class, "/"); server.start(); server.join(); }}} 次に、Injectorの生成について見てみるが、その前にWicketFilterのサブクラスを作成し、 @Singletonを指定しておく。 {{{ import org.apache.wicket.protocol.http.*; import com.google.inject.*; @Singleton public class MyWicketFilter extends WicketFilter { } }}} |
GuiceFilterの利用
サーブレットフィルタとしてGuiceFilterを用いると、@SessionScopedや@RequestScopedのアノテーションが有効になる。 それらのスコープの制御は、Guiceがサーブレットからのリクエストをフックして行うからである。
Wicketでこの機能を利用するには、基本的には「サーブレット」に記述した通りのことを行えばよい。 ただし、これをやっても「インジェクションの方法」で取り上げた問題が解決するわけではない。 相変わらず以下の問題があるのでまとめておく。
- コンストラクタ注入されるオブジェクト以外はコンストラクタ中で使用することはできないが、一般にWicketのページクラスにはそのような特別なパラメータを指定できる余地がない。
- フィールド注入したとしても、Wicketのページは直列化されるため、それらのオブジェクトはSerizlizableでなければならず、大きいと直列化領域を圧迫する。なおかつ、直列化復帰後に(DB接続等の)機能を復旧できなければならない。
したがって、少なくともWicketのページ及びその中のコンポーネント等では、DIではなくサービスロケータを使用するのがベストであると結論づけた。
その上で、@SessionScoped/@RequestScopedの恩恵にあずかることはできる。 サービスロケータからこれらのオブジェクトを取得すると、それぞれセッションで一意なオブジェクト、リクエストで一意なオブジェクトを取得することができるのである。
そしてむしろ、これらのスコープされたオブジェクトを使う場合にはオブジェクトそのものの注入は避けるべきである。 なぜなら、注入先のオブジェクトがリクエストやセッションを越えて生き残る場合には、誤ってそのスコープ外でスコープされたオブジェクトを使ってしまうというバグになりかねないからである。
したがって、これらのスコープされたオブジェクト使う場合は、必ずプロバイダあるいはサービスロケータから取得するのがベストと思われる。
Guice, Wicket, Jettyを使う例
以下では、Guice 2.0, Wicket 1.4.3, Jetty 7.0.1を利用している。 特にJettyはバージョンによって仕様がよく変更されているので注意・
Guiceは極力XMLを排除するように設計されている。ウェブとサーブレットでのGuiceFilterの利用例でもこれが貫かれている。 それでも他のサーブレットコンテナでは最低限のweb.xml記述が必要と思われるが、 Jettyでは完全にweb.xmlを排除することができる。
ほとんどのセットアップはInjectorの作成時に行えばよい。 仮にInjectorが得られたものとして、以下のコードでJettyを起動する。 以下のコードは、ほぼどんな場合でも同じになると思われる。 {{{
- Server server = new Server();
Connector connector = new SocketConnector(); connector.setPort(8080); server.addConnector(connector); ServletContextHandler context =
new ServletContextHandler(server, "/", ServletContextHandler.SESSIONS);
context.addFilter(GuiceFilter.class, "/*", 0); context.addEventListener(new GuiceServletContextListener() {
- @Override protected Injector getInjector() { return injector; }
context.addServlet(DefaultServlet.class, "/"); server.start(); server.join();
}}} 次に、Injectorの生成について見てみるが、その前にWicketFilterのサブクラスを作成し、 @Singletonを指定しておく。
import org.apache.wicket.protocol.http.*; import com.google.inject.*; @Singleton public class MyWicketFilter extends WicketFilter { }