初めてのJava EE 6 (Servlet + CDI(WebBeans))
前回では、Servlet + EJB 3.1という組み合わせのサンプルを試しに作ってみました。今回はServlet + CDIです。
CDIは、http://d.hatena.ne.jp/Hirohiro/20091228/1262006216:title=というマニアックなエントリで既に登場していますが、知らない人は全く知らないと思いますので、簡単にですが紹介します。
CDIとは、Contexts and Dependency Injectionの略でmikiさんのBlogで詳しく書かれていますが、WebBeansと以前は呼ばれていた仕様です。そのCDIの参照実装がWeldというプロダクトで、今回、Java EE 6のお勉強に使っているGlassFishにもバンドルされてます。WeldはJBoss.orgで開発されていますので、もちろんJBossASにもバンドルされます。
さて、CDIは何をしてくれるかというと、ざっくりいうとプレゼンテーション層の技術とビジネスロジック層の技術をつなぐものであり、Java EE全体で統一的なDIコンテナを提供してくれるものです。CDIの元ネタになっているJBoss Seamだと、主にJSFとEJB3をつなぐものとして開発されてましたが、CDIはJSF以外からも使えるようになってます。標準でServletととも連携が可能です。Weld固有の実装ですが、Wicket連携もできるようです。GWT連携も考えているとか。
ということで、今回はServletからCDIを使ってビジネスロジックのオブジェクトをインジェクションして呼び出します。
前回作成したEJBバージョンを修正してCDI利用バージョンに変えたいと思います。EJBバージョンでは、ビジネスロジックであるHelloServiceクラス(EJB)を@EJBでインジェクションしていました。これをCDIを利用してインジェクションするようにします。
変更するものは以下の通りです。
package org.example; import javax.inject.Named; @Named public class HelloService { public void sayHello() { System.out.println("Hello!"); } }
@WebServlet(name = "HelloWorld", urlPatterns = { "/HelloWorld" }) public class HelloWorld extends HttpServlet { private static final long serialVersionUID = 1L; @Inject HelloService helloService;
Javaコードの修正は以上です。あとは、CDIを組み込むためにbeans.xmlというXMLファイルをWEB-INF/libに配置します。なお、今回はインターセプタなどは使わないので、beans.xmlは空でOKです。
これでGlassFishにデプロイし、前回と同様にブラウザからアクセスすると、EJB版と同じように正常に動作します。
EJBと同じように動作するとなると、CDIの利点は何でしょうか?一つは、EJBコンテナがいらないということ。EJB3.1になり、WARだけでもEJBが使えるようになりましたが、EJBコンテナを積んでいないTomcatやJettyでは動きません。CDIなら、EJBコンテナが無い環境でもDIやインターセプタが標準技術として使えます。これは一つの利点だと思います。
他にもCDI固有の機能がありますが、それは追々紹介して行きたいと思います。