今週もまた管理に関する機能です。管理や保守に関する機能はまだまだ当分続きますので,おつきあいください。

MXBeanが便利であることは何度も言及してきました。もちろん,筆者もよく使用しています。しかし,不満な点もあります。MXBeanを自分で作ることができないという点です。

もちろん,MBeanであればいくらでも自作できます。Jakarta Commons Modelerなどを使えば,簡単にMBeanを作成することが可能です。詳しくは「Model MBean - Commons Modelerコンポーネントを使用して」をご覧ください。

ただ,やっぱりMXBeanを作りたいのです。Java SE 6ではようやくMXBeanが自作できるようになりました。さっそくこの機能を紹介していきましょう。

MXBeanの定義

一般的に,MBeanを示すインタフェース名は名前の最後にMBeanが付いていなければなりません。これは命名規約によるものです。

MXBeanでも同様にMXBeanをインタフェース名の最後に付加します。これで,このインタフェースがMXBeanであることを指定できます。

ところが,これ以外にもMXBeanであることを示す方法があります。アノテーションを使用する方法です。アノテーションを使えば,インタフェース名の最後がMXBeanでなくてもMXBeanとして扱うことが可能です。

例えば,以下の定義はすべてMXBeanとして扱うことができます。

public interface FooMXBean {...}
	
@MXBean	
public interface Foo {...}
 
@MXBean(true)
public interface Foo {...}

逆に以下のインタフェースはMXBeanとしては扱えません。

public interface Foo {...}
	
@MXBean(false)	
public interface Foo {...}
 
@MXBean(false)
public interface FooMXBean {...}

最後の例は,インタフェース名にMXBeanと付いていますが,それでもMXBeanとして扱うことはできません。

MXBeanを示すインタフェースができたら,あとはStandard MBeanと同様にMXBeanを実装します。

MXBeanの実装

MXBeanを扱うために簡単なサンプルを作ってみました。テキスト・フィールドとボタンが二つあるアプリケーションです。

テキスト・フィールドには数字が表示されており,これがカウンタを表しています。Incrementボタンを押すと,カウンタが増加します。10までカウントが進むとIncrementボタンを押せないようにしました。

Resetボタンを押すと,カウンタがリセットされ,押せなかったIncrementボタンが再び押せるようになります。

Counter
図1 Counter

このサンプルを,MXBeanを使用してカウンタの値を取得できるようにし,またリセットできるようにしてみます。

サンプルのダウンロードはこちらから:Counter.javaCounterWatcher.javaCounterWatcherImpl.java

Counterクラスがもともとのアプリケーションです。MXBeanの定義はCounterWatcherインタフェースで行います。それをインプリメントしているのがCounterWatcherImplクラスです。

カウンタの値を取得できるように,CounterクラスにはgetCountメソッドを定義しました。また,リセットにはResetボタンを押されたときにコールされるresetCounterメソッドを使用します。

準備はこれでおしまい。実際にMXBeanを作っていきましょう。

MXBeanの定義はCounterWatcherインタフェースで行います。

import javax.management.MXBean;
 
@MXBean
public interface CounterWatcher {
    public int getCount();
    public void reset();
}

getCountメソッドが現在のカウンタの値を取得するメソッド,resetメソッドがカウンタをリセットするメソッドです。MXBeanであることは@MXBeanアノテーションで指定しています。

CounterWatcherインタフェースをインプリメントしているのがCounterWatcherImplクラスです。

public class CounterWatcherImpl implements CounterWatcher {
    private static final String NAME = "net.javainthebox.counter:type=Counter";
 
    private Counter counter;
 
    public CounterWatcherImpl(Counter counter) {
        this.counter = counter;
    }

NAME定数は,MBeanServerに登録するときのMXBeanの名前に使用します。そして,コンストラクタでターゲットとなるCounterオブジェクトを設定しています。

getCountメソッドもresetメソッドもCounterクラスに処理を委譲しています。

    public int getCount() {
        return counter.getCount();
    }
 
    public void reset() {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                counter.resetCounter();
            }
        }); 
    }

resetメソッドでSwingUtilities#invokeLaterメソッドを使用しているのは,Counter#resetメソッドの中で描画処理を行っているからです。Swingはシングルスレッドで設計されており,他のスレッドから描画処理を行うことができません。他のスレッドから描画処理を行うには,ここで記述したようにSwingUtilitiesクラスを使用します。

最後にmainメソッドです。

    public static void main(String[] args) {
        Counter counter = new Counter();
        CounterWatcher watcher = new CounterWatcherImpl(counter);
         
        try {
            MBeanServer server = ManagementFactory.getPlatformMBeanServer();
            ObjectName name = new ObjectName(NAME);
            server.registerMBean(watcher, name);
        } catch (MalformedObjectNameException ex) {
            ex.printStackTrace();
        } catch (InstanceAlreadyExistsException ex) {
            ex.printStackTrace();
        } catch (MBeanRegistrationException ex) {
            ex.printStackTrace();
        } catch (NotCompliantMBeanException ex) {
            ex.printStackTrace();
        }
    }

ターゲットになるCounterオブジェクトを生成し,次にCounterWatcherImplオブジェクトを生成します。

次に行うのがMXBeanの登録です。MXBeanの登録はMBeanServerオブジェクトに対して行います。MBeanServerオブジェクトは,ManagementFactory#getPlatformMBeanServerメソッドで取得します。このメソッドで得られるMBeanServerオブジェクトは,他の標準で提供されるMXBeanがすでに登録されているMBeanServerオブジェクトになります。

MBeanServerオブジェクトにMXBeanを登録するやり方は,MBeanを登録するのと全く同じです。ObjectNameクラスでMXBeanの名前を指定し,MBeanServer#registerMBeanメソッドで登録します。

jconsoleで確認する

ソースができたら,コンパイルして実行してみましょう。起動したら,jconsoleでCounterWatcherImplにアタッチし,[MBean]タグを見てください。ちゃんとCounterがあることを確認できるはずです。

jconsoleで確認
図2 jconsoleで確認

属性のCountを見てみましょう。ちゃんとCounterで表示されている値と同じものが表示されています。

カウンタを参照
図3 カウンタを参照

resetを実行すると,Counterの値がリセットされます。これもやってみてください。

MXBeanは,アノテーションを使うことで簡単に定義できます。また,MXBeanの実装はStandard MBeanとほとんど同じです。ぜひ,自分なりのMXBeanを作ってみてくださいね。

著者紹介 櫻庭祐一

横河電機 ネットワーク開発センタ所属。Java in the Box 主筆

今月の櫻庭

秋も深まりつつある今日この頃。櫻庭の住んでいる東京でもそろそろ紅葉の時期になってきました。

カエデ,ナナカマド,ツタ,サクラなど,それぞれの色で秋の景色を彩っています。櫻庭が好きなのはニシキギ。名前のとおり錦のように赤い葉っぱが特徴です。

家のそばを通っているイチョウ並木もだんだんと黄色くなり始めてきました。日当たりのいい場所ほど,黄葉がはやくはじまるようです。イチョウが黄色くなる頃といえば,ギンナン。おいしいですよね。

と,今月も最後は食べ物の話題になってしまうのでした。