![]() |
体重計やレントゲンに相当するStabdard MBean |
---|
![]() |
血液検査に相当するDynamic MBean |
さて,今週から実際にMBeanを作っていきましょう。
MBeanの種類には大別すると,Standard MBeanとDyanamic MBeanがあります(先月の記事を参考にしてください)。
Standard MBeanは,管理情報の取得や操作のためのインタフェースとクラスを作成する必要があります。仕組みは簡単なのですが,管理情報を追加したい時はインタフェースとクラスを書き換える必要があります。
これに対して,Dynamic MBeanは管理情報の取得・操作を行うクラスを動的に生成します。このため,管理情報を追加したいときでも,設定を変更するだけで済みます。
たとえてみると,Standard MBeanは体重計やレントゲン,Dynamic MBeanは血液検査に相当します。
体重計は体重を測るという用途に特化されています。体重計で体脂肪を測れるようにするには,体重計自体の変更を行わなければなりません(普通は,体脂肪測定機能が付いた新しい体重計を買いますね)。
血液検査にはコレステロールなど様々な測定項目があり,そこから検査の時に何を測定するかを指定します。すでに,それぞれの測定項目に対応する検査機器は用意されているので,それらの中から使うものを選ぶという感じでしょうか。
さて,今週は体重計のほう,つまりStandard MBeanを作成していきます。
Standard MBeanの作成
Standard MBeanは前述したようにインタフェースとクラスから構成されます。
まずはMBeanのインタフェースを作成しましょう。Standard MBeanを表すインタフェースには,名前の最後にMBeanを付けるという命名規則があります。
今回はDispatcher1クラスに対応するMBeanなので,DispatcherInfoMBeanという名前にしてみました。
public interface DispatcherInfoMBean { public int getPageCount(); public void resetPageCount(); }
DispatcherInfoMBeanインタフェースで定義しているのは,ページ・カウントを取得するためのgetPageCountメソッドと,ページ・カウントをリセットするためのresetPageCountメソッドです。
このメソッド,どこかで見たことのあるような感じがしませんか。そうです,先週説明したDispatcher1クラスに変更した部分に対応しています(先週の記事)。
このインタフェースを実装するクラスを作りましょう。クラス名はMBeanのインタフェース名からMBeanを取りのぞいたものにします。
public class DispatcherInfo implements DispatcherInfoMBean{ private Dispatcher1 dispatcher; public DispatcherInfo(Dispatcher1 dispatcher) { this.dispatcher = dispatcher; } public int getPageCount() { return dispatcher.getPageCount(); } public void resetPageCount() { dispatcher.resetPageCount(); } } |
DispatcherInfoクラスは「フィールドにDispatcher1オブジェクトを保持し,それぞれのメソッドはDispatcher1オブジェクトをコールする」というだけの簡単なクラスです。
MBeanServerの作成とMBeanの登録
MBeanを定義できたので,MBeanを生成し,MBeanServerに登録する処理を記述しましょう。
MBeanの本体であるDispatcherInfoクラスはDispatcher1クラスに対応するので,Dispatcher1オブジェクトが生成されるときにDispatcherInfoオブジェクトを生成することにします。
Dispatcher1オブジェクトの生成はN1クラスで行っています。該当個所を以下に示します。
void runServer() throws Exception { Dispatcher d = new Dispatcher1(); d.register(ssc, SelectionKey.OP_ACCEPT, new AcceptHandler(ssc, d, sslContext)); d.run(); } |
このrunServerメソッドにMBeanの生成,およびMBeanServerへの登録処理を加えました(赤字が変更箇所)。なお,例外処理は省略しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
private static final String DISPATCHER_NAME = "sample:name=dispatcher"; void runServer() throws Exception { Dispatcher1 d = new Dispatcher1(); // MBeanを作成 DispatcherInfo info = new DispatcherInfo(d); ObjectName name = new ObjectName(DISPATCHER_NAME); // MBeanServerがすでに生成されていれば,それを使用する // なければ新しく生成 MBeanServer server; List servers = MBeanServerFactory.findMBeanServer(null); if (servers.size() > 0) { server = (MBeanServer)servers.get(0); } else { server = MBeanServerFactory.createMBeanServer(); } // MBeanを登録 server.registerMBean(info, name); d.register(ssc, SelectionKey.OP_ACCEPT, new AcceptHandler(ssc, d, sslContext)); d.run(); } |
8~9行目がMBeanの生成を行っている部分です。
MBeanの生成は普通のオブジェクト生成と変わりありません。異なるのはMBeanには名前があるということです。MBeanの名前を表すにはjavax.management.ObjectNameクラスを使用します。
MBeanの名前で必須なのはドメインです。ドメインは,パッケージに相当するMBeanの名前空間を示しており,実際にパッケージ名を使うことも多くあります。ここでは,サンプルなのでsampleというドメインを使用しました。
名前は[ドメイン名:属性名=属性値]と記述します。属性にはnameなどがありますが,MBeanによって記述できる属性は異なります。属性が複数ある場合は,カンマで区切って指定するようにします。
ここではnameを"dispatcher"としました。
次はMBeanServerオブジェクトの生成です。13行目から20行目が対応する部分です。
一つのシステムの中に複数のMBeanServerオブジェクトを生成することは可能です。しかし,ここではすでにMBeanServerオブジェクトが存在していればそれを使用し,なければ生成するようにしました。
すでにMBeanServerオブジェクトが存在するかどうかを調べるにはjavax.management.MBeanServerFactoryクラスのfindMBeanServerメソッドを使用します。引数がnullの場合はすべてのMBeanServerオブジェクトを返します。
findMBeanServerメソッドの戻り値はListオブジェクトなので,空でなければ先頭にあるMBeanServerオブジェクトを利用します。
もし,MBeanServerオブジェクトがなければ,MBeanServerFactoryクラスのcreateMBeanServerメソッドを使用して,MBeanServerオブジェクトを生成します。
最後にMBeanServerオブジェクトにMBeanを登録します(23行目)。registerMBeanメソッドは第1引数がMBeanオブジェクト,第2引数がObjectNameオブジェクト(つまりMBeanの名前)です。
このサンプルでは,外部の管理ツールからアクセスするためのConnectorもしくはProtocol Adapterに関しては何も設定していません。
J2SE 5.0では,起動時オプションでMXBeanを参照できるように指定すると,Connectorが自動的に生成されます。自動的に生成されたConnectorを使用することで,コードに記述しなくても外部の管理ツールからMXBeanにアクセスできます。
著者紹介 櫻庭祐一 横河電機の研究部門に勤務。同氏のJavaプログラマ向け情報ページ「Java in the Box」はあまりに有名 |