| JBoss EJB 3.0と拡張機能
JMXサービスオブジェクト
はじめに
| JMX MBeanサービスはJBossアプリケーションサーバを形成する重要なサービスです。開発者は、MBeanサービス同士の依存関係を指定し、サーバ起動時に正しい順番でサービスが起動するように指定できます。また、これはサーバの内部サービスを実装するのに特に最適です。JBossの内部サービスの多くはMBeanとして実装されています。サービス同士は内部JMXバス（つまりJBoss JMXマイクロカーネル）を通してお互いに通信します。MBeanは、JBossの内部サービスを管理するJBoss管理者のための統一された管理インタフェースも提供します。 管理オブジェクトのプールから提供されるEJBサービスと異なり、JMX MBeanはサーバのJVMでシングルトンオブジェクトとして提供されます。サービスオブジェクトはステートフルで、アプリケーション全体で有効です。 MBeanサービスはとても有用ですが、開発は簡単ではありません。通常のJMXサーバ環境では、たくさんのフレームワーククラスを拡張し、リフレクションのようなAPIを使用しなければなりません。一方、JBoss EJB 3.0サーバでは簡単なアノテーションを使って、POJOをMBeanサービスにすることができます。このトレイルでは、EJB 3.0スタイルのMBeanサービスの開発について学びます。このトレイルで学ぶアノテーションはJBoss固有です。正式なEJB 3.0仕様の範囲には含まれていません。
サンプルアプリケーション
| このトレイルでは、投資計算を行うMBeanサービスを作成します。サービスの管理的な側面を紹介するために、計算プログラムでは成長率は固定にしています。成長率は、管理者がJMX管理サーバを通して変更します。 クライアントアプリケーションは、JMX APIを使ってコンテナからMBeanのシングルトンオブジェクトの参照を取得し、計算サービスを利用します。下のボタンをクリックして、別ウィンドウで計算プログラムを起動してみてください。JSPページがセッションBeanにアクセスし、投資計算を行います。 計算プログラムの成長率を変更するには（つまり、サービスを管理するには）、JMX管理コンソールを使用します。通常、JMXコンソールはアクセス制限されているため、運用中のサーバでこの機能をお見せするのは困難です。そこで、フラッシュムービーを使って、管理コンソールで計算プログラムを管理し、成長率（利率）を変更するところをご覧いただきます。下のボタンをクリックしてムービーをご覧ください。 ご自分のサーバにTrailBlazerアプリケーションをデプロイし、JMXコンソールにアクセスできる場合は、http://localhost:8080/jmx-console/ページの下のほうにcalculator MBeanが見えるはずです。ページの最下部までスクロールしてください。また、`calculate()`メソッドに適切な引数を指定することによって、JMXコンソールから直接投資計算を行うこともできます。
MBean管理インタフェース
| MBean管理インタフェースは、MBeanサービスの外向きのインタフェースです。MBeanサービスのクライアントやJMX管理コンソールからアクセス可能な属性やメソッドを公開します。EJB 3.0プログラミングモデルにおいては、MBean管理インタフェースはセッションBeanインタフェースと同じように、単なるJavaインタフェースです。以下のコードの抜粋では、`Calculator` インタフェースで、`Growthrate`属性と`calculate()`メソッドを定義しています。
    public interface Calculator {

      // Attribute
      public void setGrowthrate (double g);
      public double getGrowthrate ();

      // The management method
      public double calculate (int start, int end, double saving);

      // Life cycle method
      public void create () throws Exception;
      public void destroy () throws Exception;
    }
管理インタフェースはMBeanのライフサイクルメソッドも定義します。以下のメソッドを組み合わせて定義します。 `create()` -- サービスと、依存しているすべてのサービスが生成されたときにサーバから呼ばれます。この時点では、サービス（および依存しているすべてのサービス）はJMXサーバにインストールされていますが、まだ機能しません。 `start()` -- サービスと、依存しているすべてのサービスが起動されたときにサーバから呼ばれます。この時点では、サービス（および依存しているすべてのサービス）は全機能が使用可能です。 `stop()` -- サービスが停止したときにサーバから呼ばれます。この時点では、サービス（およびそのサービスに依存しているすべてのサービス）はもはや機能しません。 `destroy()` -- サービスが破棄され、MBeanサーバから削除されるときにサーバから呼ばれます。
MBeanの実装
| MBean実装クラスはMBean管理インタフェースを実装するだけです。JBossは`@Service`タグでアノテーションされたクラスをJMXサーバに登録します。アノテーションの`objectName`属性で、このMBeanサービスが登録するサービス名を指定します。`@Management`アノテーションで管理インタフェースを指定します。つまり、同じBeanクラスに対して、ローカルインタフェース、リモートインタフェース、管理インタフェースの複数のインタフェースを定義できるのです。JMXコンソールでは、`trail:service=calculator`の名前でこのMBeanを参照できます。
    @Service (objectName="trail:service=calculator")
    @Management(Calculator.class)
    public class CalculatorMBean implements Calculator {

      double growthrate;

      public void setGrowthrate (double growthrate) {
        this.growthrate = growthrate;
      }

      public double getGrowthrate () {
        return growthrate;
      }

      public double calculate (int start, int end, double saving) {
        double tmp =
            Math.pow(1. + growthrate / 12., 12. * (end - start) + 1);
        return saving * 12. * (tmp - 1) / growthrate;
      }

      // Lifecycle methods
      public void create() throws Exception {
        growthrate = 0.08;
        System.out.println("Calculator - Creating");
      }

      public void destroy() {
        System.out.println("Calculator - Destroying");
      }
    }
MBeanサービスのシングルトンオブジェクトが生成されると、JMXサーバから`create()`メソッドが呼ばれ、`Growthrate`属性に初期値が設定されます。
MBeanサービスを使う
| MBeanサービスを利用するには、まずサービス名でサービスのシングルトンオブジェクト（またはプロキシ）を検索します。JBoss JMXではこのような処理を行う以下のような便利なメソッドを用意しています。
    private Calculator cal = null;

    public void jspInit () {
        try {
            MBeanServer server = MBeanServerLocator.locate();

            cal = (Calculator) MBeanProxyExt.create(
                Calculator.class,
                "trail:service=calculator",
                server);
        } catch (Exception e) {
            e.printStackTrace ();
        }
    }
ここで、MBeanサービスと管理メソッドを呼び出すことができます。
    result = nf.format(cal.calculate(start, end, saving));
MBean間の依存関係
| MBeanサービスの重要な機能のひとつは、MBean間の依存関係を指定して、他のサービスが正しく起動されている場合にのみ、あるサービスを起動するようにできることです。`@Depends`アノテーションで、依存しているMBeanを指定します。
    @Service (objectName="trail:service=investmentAdvisor")
    @Depends ("trail:service=calculator")
    public class InvestmentAdvisorMBean implements InvestmentAdvisor {
        // ... ...
    }
あるいは、MBeanが依存するMBeanの一覧を指定することもできます。
    @Service (objectName="trail:service=investmentAdvisor")
    @Depends ({"trail:service=calculator",
               "trail:service=riskAnalysis"})
    public class InvestmentAdvisorMBean implements InvestmentAdvisor {
        // ... ...
    }
MBeanが持つ属性が別のMBeanの場合、その属性のセッターメソッドに`@Depends`アノテーションを使用することで、コンテナは自動的に依存するMBeanオブジェクトに依存性を注入します（セッターの依存性注入）。下の例では、`trail:service=calculator`のMBeanが起動されると、コンテナは適切な引数で`setCalculator()`メソッドを呼びます。`InvestmentAdvisor`のMBeanの`Calculator`属性は、明示的なルックアップを行わなくても自動的に正しい値が設定されます。
    @Service (objectName="trail:service=investmentAdvisor")
    public class InvestmentAdvisorMBean implements InvestmentAdvisor {

        @Depends ("trail:service=calculator")
        public void setCalculator (Calculator calculator) {
          this.calculator = calculator;
        }

        // ... ...
    }
ソースコード参照
| JMXサーバ Calculator.java: MBean管理インタフェース CalculatorMBean.java: MBean実装 JMXクライアント calculator.jsp: 計算プログラムMBeanのクライアント
まとめ
| このトレイルでは、簡単なEJB 3.0スタイルのアノテーションを使ってJMX MBeanサービスを開発する方法を学びました。JBossアプリケーションサーバの内部サービスや他のコンポーネントに対して管理可能なサービスを提供するにはMBeanサービスはとても有効です。次のトレイルでは、もう一つのタイプのサービスであるメッセージ駆動型サービスについて議論します。