読者です 読者をやめる 読者になる 読者になる

nekop's blog

OpenShift / JBoss / WildFly / Infinispanの中の人 http://twitter.com/nekop

MDBとJCAのおはなし

jboss

JBoss Advent Calendar 2011の13日目のエントリです。

MDBはメッセージドリブンビーンの略であり、メッセージを処理するEJBコンポーネントです。MDBはJMSのメッセージを処理するコンポーネント、という古い認識の人もたまに居るのですが、MDBはかなり前からJMSに限定しない技術となっています。

最初にMDBが策定されたのはJ2EE 1.3に含まれていたEJB 2.0仕様で、この時点ではMDBはJMSのメッセージを処理するもの、と規程されていました。J2EE 1.4の時代となり、EJB2.1の策定に伴いMDBの動作の仕様の中心はJCA仕様(Java EE Connector Architecture)に移り、メッセージはJMSのものに限定せず、ありとあらゆるメッセージ受信処理ができるよう一段階上の抽象化がなされました。

JCAJava EEと外部システムをつなぐインテグレーションのためのテクノロジです。MDBはこのうちMessage inflowという部分がメインで、JBoss ASではJMS、MailQuartzなどのMDBをサポートしていました。また、ファイルを入力メッセージとするJCA Message inflowのサンプルも提供しています。

現在のJBoss AS 7ではビルトインではJMSのみのサポートとなっていますが、他のものも追って提供されていくことと思います。Mail用のものなどはJBoss AS 7に含まれるJCA実装であるIronJacamarのリポジトリ上には既に存在しています。

また、僕もだいぶ前ですがJBoss AS 7上で動作するTwitter向けのJCA 1.6 Message inflowリソースアダプタを書いてみました。TwitterのクエリAPIを利用し、マッチするツイートをMDBに渡します。以下の例では"jboss"を含むツイートを起動中ずっと標準出力にべろべろと吐き出します。

import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;

import org.jboss.ejb3.annotation.ResourceAdapter;
import jp.programmers.resource.adapter.twitter.inflow.TweetListener;
import twitter4j.Tweet;

@MessageDriven(activationConfig={
   @ActivationConfigProperty(propertyName="query", propertyValue="jboss")
})
@ResourceAdapter("twitter-ra")
public class TwitterMDB implements TweetListener {
    public void onTweet(Tweet t) {
        System.out.println(t);
    }
}

JCAWikipediaのJava EE Connector Architectureのページに簡潔にまとまっていますが、他にもConnection managementやTransaction managementなど多くの機能を提供します。例えばJDBCは通常データベースとのベーシックな接続機能やJDBC独自(データベース独自)のトランザクションシステムを提供しますが、JDBC向けJCAアダプタでは接続プールやJTAトランザクションとの連携というような機能をJDBCに付加します。JDBC向けJCAアダプタ、というのはつまるところJBoss ASのJDBCデータソースを提供している部分です。これはJMSでも同じで、JMS用JCAリソースアダプタは同じくJMSにコネクションプールを提供し、JCAトランザクションをJMSトランザクションにブリッジする機能を付与します。JCAはあまりJava EEのアプリケーション開発者から直接見えない部分ですが、アプリケーションサーバの基礎とも言える非常に重要な機能を提供しているのです。

MDBのプログラミングモデルはシンプルで扱いやすく、例えばモダンなところだとScalaなどで採用されているActorモデルなどにも似ています。リソースアダプタ実装がメッセージを振り分け、MDBで個々のメッセージを処理します。スレッドの割り当てなどはコンテナ側で設定できる、という仕組みです。