プライマリ・コンテンツに移動
Oracle® Fusion Middleware Oracle WebLogic Server JMXによるカスタム管理ユーティリティの開発
12c (12.2.1.3.0)
E90335-01
目次へ移動
目次

前
次

7 通知とモニターMBeanの使い方

この章では、JMXを使用してMBeanをモニターする方法について説明します。JMXにはMBeanをモニターする2つの方法があります。特定のイベント(属性値の変更など)が発生したときに通知を送信する方法、または、モニターMBeanという特別なタイプのMBeanが別のMBeanをポーリングして、属性値について記述した通知を定期的に送信する方法です。これらの通知をリスニングしたり、適切に応答したりするリスナーというJavaクラスを作成します。たとえば、アプリケーションのデプロイ、アンデプロイ、再デプロイ時に通知を受信するリスナーを管理ユーティリティに組み込むことができます。すべてのWebLogic Server 構成MBeanと一部のランタイムMBeanは、属性値が変わると通知を送信します。

この章の内容は以下のとおりです。

ベスト・プラクティス:直接的なリスニングとモニター

モニターするMBeanが通知を送信する場合は、MBeanにおける変更をリスニングするリスナー・オブジェクトを作成するか、MBeanを定期的にポーリングして、属性値が特定の方法で変更された場合にのみ通知を送信するモニターMBeanを作成するかを選択することができます。どちらの方法を選ぶかは、主に通知を受信する状況の複雑さによって決まります。

要件が単純な場合は、MBeanからリスナーに通知が送信され、変更が直ちに通知されるので、リスナーを直接MBeanに登録する方法が適しています。ただし、リスナーとオプショナルなフィルタ(javax.management.NotificationListenerおよびNotificationFilter)を実装するベース・クラスには、値をしきい値や他の値と比較する機能がほとんどありません(Java SE 8 API仕様javax.managementパッケージ(http://docs.oracle.com/javase/8/docs/api/javax/management/package-summary.html)を参照してください。)

通知の要件が複雑な場合や、MBean属性値の1つの変更に直接関連付けられない一連の変更をモニターする場合は、モニターMBeanを使用します。(Java SE 8 API仕様javax.management.monitorパッケージ(http://docs.oracle.com/javase/8/docs/api/javax/management/monitor/package-summary.html)を参照してください。)モニターMBeanには、データを比較して、特定の状況でのみ通知を送信するツールが豊富に用意されています。ただし、モニターは観察対象MBeanで属性値の変更を定期的にポーリングし、変更の通知は指定したポーリング間隔でのみ受けられます。

ベスト・プラクティス: WebLogic Serverイベントのリスニング

WebLogic Server JMXエージェントとWebLogic Server MBeanは、様々なタイプのイベントに応じて様々な型の通知オブジェクトを送信します。ほとんどのイベント・タイプは複数のMBeanをトリガーして、イベント・プロセスの様々な時点で通知を送信します。表7-1では、一般的なイベント・タイプについて説明し、通知をリスニングするためにJMXモニター・アプリケーションが登録すべき推奨MBeanを示しています。

注意:

各JMX通知オブジェクトには、ドット区切りの文字列を格納するTypeという属性があります。このType属性の説明と通知のオブジェクト型を混同しないようにしてください。

Type属性によって、通知の分類やフィルタ処理を行うことができます。たとえば、カスタムMBeanが通知を送信する場合、JMXの規約では、通知オブジェクトのType属性を、mycompany.myapp.valueIncreasedという企業名で始まる文字列に設定するように薦めています。

すべてのJMX通知オブジェクトはjavax.management.Notificationオブジェクト型を拡張します。JMXとWebLogic Serverではjavax.management.AttributeChangeNotificationなどの追加の通知オブジェクト型を定義しています。追加のオブジェクト型には、様々なタイプのイベントに適した特殊な情報が含まれています。(Java SE 8 API仕様に記載されたjavax.management.NotificationNotificationサブクラス・リスト(http://docs.oracle.com/javase/8/docs/api/javax/management/Notification.html)を参照してください。)Oracle WebLogic Server Java APIリファレンスweblogic.management.logging.WebLogicLogNotificationも参照してください。)

表7-1 イベント通知オブジェクト

イベント リスニングの推奨事項

WebLogic Serverインスタンスが起動する、停止する

サーバーの起動または停止時に通知を受信するには、リスナーをドメイン・ランタイムMBeanサーバー内の各サーバーのServerLifeCycleRuntimeMBeanに登録して、AttributeChangeNotificationFilterを構成します。

ドメイン内の各サーバーには独自のServerLifeCycleRuntimeMBeanがあり、そのサーバーがアクティブでない場合でも、ドメイン・ランタイムMBeanサーバーから利用できます。サーバー・インスタンスを起動すると、そのサーバーのServerLifeCycleRuntimeMBeanState属性の値を更新して、AttributeChangeNotificationを送信します。

このようなリスナーとフィルタの例については、「WebLogic Server MBeanからの通知のリスニング:主な手順」を参照してください。

注意: この推奨事項では、管理対象サーバーを起動する前にドメインの管理サーバーを起動することを前提としています。管理サーバーよりも前に管理対象サーバーを起動すると、管理対象サーバーのServerLifeCycleRuntimeMBeanの状態がRUNNINGに変わるときにドメインのランタイムMBeanサーバー(管理サーバー上でのみ動作する)が初期化されません。管理サーバーが最初に起動することを保証できない場合は、JMXタイマー・サービスを使用し、ドメイン・ランタイムMBeanサーバーに対して、オブジェクト名にType=ServerRuntimeキー・プロパティが含まれるMBeanがあるかどうかを定期的に問い合せます。この問合せに一致するMBeanは、各サーバー・インスタンスが起動プロセス中に作成したServerRuntimeMBeanです。新しく作成されたServerRuntimeMBeanが問合せで見つかった場合、新しいサーバー・インスタンスが起動されたことになります。MBeanServerConnection queryNamesを参照してください。(http://docs.oracle.com/javase/8/docs/api/javax/management/MBeanServerConnection.html#queryNames%28javax.management.ObjectName,%20javax.management.QueryExp%29を参照。

WebLogic Serverリソースが作成される、破棄される

サーバーやJDBCデータ・ソースなどのリソースを作成するときに、WebLogic Serverはリソースの構成MBeanをMBeanサーバーに登録します。リソースを削除するときに、構成MBeanの登録を解除します。

Mbeanの登録と登録解除をリスニングするには、javax.management.MBeanServerDelegateにリスナーを登録します。MBeanが登録または登録解除されるとjavax.management.MBeanServerNotification

型の通知を送信します。

編集MBeanサーバー内のMBeanServerDelegateにリスナーを登録した場合は、保留中のMBean階層が変更されたときに通知を受信します。

ランタイムMBeanサーバーまたはドメイン・ランタイムMBeanサーバーでリスナーを登録した場合は、保留中の変更がドメインで正常にアクティブ化されたときにのみ通知を受信します。構成データのモニターにのみ関心があり、ランタイム統計のモニターには関心がない場合は、リスナーをランタイムMBeanサーバーにのみ登録します。「ベスト・プラクティス: MBeanサーバーの選択」を参照してください。

「例:構成MBeanの登録のリスニング」を参照してください。

WebLogic Serverリソースの構成が変更される

すべての構成MBeanは、属性値が変わるときにAttributeChangeNotification型の通知を送信します。

この通知を受信するには、ドメイン・ランタイムMBeanサーバーまたはランタイムMBeanサーバー内のMBeanにリスナーを登録します(「ベスト・プラクティス: MBeanサーバーの選択」を参照)。

編集MBeanサーバー内のMBeanに登録した場合は、保留中のMBean階層が変更されたときに通知を受信します。

ランタイムMBeanサーバーまたはドメイン・ランタイムMBeanサーバーでリスナーを登録した場合は、保留中の変更がドメインで正常にアクティブ化されたときにのみ通知を受信します。構成データのモニターにのみ関心があり、ランタイム統計のモニターには関心がない場合は、リスナーをランタイムMBeanサーバーにのみ登録します。「ベスト・プラクティス: MBeanサーバーの選択」を参照してください。

WebLogic Serverリソースの実行時状態が変わる

一部のランタイムMBeanは、属性値が変わるとAttributeChangeNotification型の通知を送信します。この通知を受信するには、ドメイン・ランタイムMBeanサーバー内のMBeanにリスナーを登録します。

実行時MBeanが通知を送信しない場合は、実行時MBeanをポーリングするモニターMBeanを作成できます。「モニターMBeanを使用した変更の観察: 主な手順」を参照してください。

WebLogic Serverリソースがログ・メッセージを送信する

WebLogic Serverリソースがログ・メッセージを送信するとき、サーバーのweblogic.management.runtime.LogBroadcasterRuntimeMBeanweblogic.management.logging.WebLogicLogNotification型の通知を送信します。これは、標準のjavax.management.Notificationクラスとしてキャストできます。

ログ・メッセージの通知をリスニングするには、LogBroadcasterRuntimeMBeanにリスナーを登録します。標準のJMX通知をリスニングできます。または、ログ・メッセージの詳細情報を取得する場合は、詳細情報の取得に使用できるメソッドを備えたWebLogicLogNotificationをリスニングできます。WebLogicLogNotificationをリスニングするには、このWebLogic Serverクラスをリスナー・クラスにインポートする必要があります。

WebLogic Serverリソースが生成するエラー・メッセージのリストについては、エラー・メッセージを参照してください。

Oracle WebLogic Server Java APIリファレンスWebLogicLogNotificationに関する項を参照してください。

ベスト・プラクティス: WebLogic Serverランタイム統計のリスニングまたはモニター

WebLogic Server MBeanは、サービスやリソースの実行時状態に関する詳細な統計を提供します。表7-2の統計は、WebLogic Serverのパフォーマンスの概要を提供するものです。これらの統計の変化をリスニングするには、リスナーを作成して、属性が含まれるMBeanにリスナーを直接登録します。または、モニターMBeanを構成して、重要だと判断した統計のみを定期的にポーリングして報告させることもできます。(通知リスナーとフィルタの登録およびモニターとリスナーの登録を参照してください。)

表7-2 一般的にモニターされるWebLogic Serverランタイム統計

追跡する統計 リスニングまたはモニターするMBean属性

サーバーの現在の状態

MBeanのタイプ: ServerLifeCycleRuntimeMBean

属性名: State

サーバーのリスニング・ポートのアクティビティ

MBeanのタイプ: ServerRuntimeMBean

属性名: OpenSocketsCurrentCount

MBeanのタイプ: ServerMBean

属性名: AcceptBacklog

この2つの属性を一緒に使用して、サーバーのリスニング・ポートにおける現在のアクティビティと、ポート上でバックログできるリクエストの総数を比較します。

メモリーとスレッドの使用状況

MBeanのタイプ: ThreadPoolRuntimeMBean

属性名: ExecuteThreadIdleCount

メモリー領域を占有しているがデータの処理には使用されていない、サーバーの実行キューのスレッド数を示します。

メモリーとスレッドの使用状況

MBeanのタイプ: ThreadPoolRuntimeMBean

属性名: PendingUserRequestCount

サーバーの実行キューで待機するユーザー・リクエスト数を示します。

メモリーとスレッドの使用状況

MBeanのタイプ: JVMRuntimeMBean

属性名: HeapSizeCurrent

サーバーのJVMヒープで現在使用可能なメモリー量(バイト単位)を示します。

データベース接続

MBeanのタイプ: JDBCDataSourceRuntimeMBean

属性名: ActiveConnectionsCurrentCount

JDBC接続プールでの現在アクティブな接続数を示します。

データベース接続

MBeanのタイプ: JDBCDataSourceRuntimeMBean

属性名: ActiveConnectionsHighCount

JDBC接続プールのアクティブな接続の最大数。この数は、接続プールがインスタンス化されるたびにゼロから開始します。

データベース接続

MBeanのタイプ: JDBCDataSourceRuntimeMBean

属性名: LeakedConnectionCount

リークされた接続の総数を示します。リークされた接続はチェックアウト済みの接続ですが、close()呼出しを通じて接続プールに返されません。リークされた接続はその後の接続リクエストの遂行に使用できないので、その総数をモニターすることは重要です。

データベース接続

MBeanのタイプ: JDBCDataSourceRuntimeMBean

属性名: ConnectionDelayTime

接続プールに接続する平均時間を示します。

データベース接続

MBeanのタイプ: JDBCDataSourceRuntimeMBean

属性名: FailuresToReconnectCount

接続プールがデータ・ストアへの再接続に失敗した場合を示します。アプリケーションでは、この属性がインクリメントしたり、しきい値に達したりすると、許容できる中断時間のレベルに応じてリスナーに通知できます。

WebLogic Server MBeanからの通知のリスニング:主な手順

MBeanが送信する通知を直接リスニングするには、次の手順に従います。

  1. アプリケーションにリスナー・クラスを作成します。「通知リスナーの作成」を参照してください。
  2. 通知を受信するMBeanにリスナーとフィルタ(オプション)を登録する追加のクラスを作成します。「通知フィルタの構成」および「通知リスナーとフィルタの登録」を参照してください。
  3. リスナーおよび登録クラスをパッケージ化してデプロイします。「WebLogic Serverにリスナーのパッケージ化およびデプロイ化」を参照してください

通知リスナーの作成

通知リスナーを作成するには、次の手順に従います。

  1. javax.management.NotificationListenerを実装するクラスを作成します。

    Java SE 8 API仕様NotificationListener (http://docs.oracle.com/javase/8/docs/api/javax/management/NotificationListener.html)を参照してください。

  2. クラス内にNotificationListener.handleNotification(Notification notification, java.lang.Object handback)メソッドを追加します。

    注意:

    通知ブロードキャスタをブロックしないように、このメソッドの実装はできるだけ早く復帰する必要があります。

  3. (オプション)ほとんどの場合、MBeanが通知オブジェクトを送信したという単純な事実以上のことを知る必要があります。たとえば、通知オブジェクトのType属性の値を知ることができます。この値は、通知の送信を引き起こしたイベントのタイプを分類するのに使用します。

    通知オブジェクトから情報を取得するには、handleNotificationメソッドの内部で、そのオブジェクトのメソッドを呼び出します。すべての通知型はjavax.management.Notificationを拡張しているので、Notificationの以下のメソッドはすべての通知で使用できます。

    • getMessage()

    • getSequenceNumber()

    • getTimeStamp()

    • getType()

    • getUserData()

    Java SE 8 API仕様Notification (http://docs.oracle.com/javase/8/docs/api/javax/management/Notification.html)を参照してください。

    ほとんどの通知型は、その通知に固有のデータを取得するための追加のメソッドを提供しています。たとえば、javax.management.AttributeChangeNotificationには、値がどのように変化したかを判断するのに使用できるgetNewValue()getOldValue()があります。

例7-1 通知リスナー

import javax.management.Notification;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.AttributeChangeNotification;

public class MyListener implements NotificationListener {

    public  void handleNotification(Notification notification, Object obj) {

        if(notification instanceof AttributeChangeNotification) {
            AttributeChangeNotification attributeChange =
                     (AttributeChangeNotification) notification;
            System.out.println("This notification is an
                      AttributeChangeNotification");
            System.out.println("Observed Attribute: " +
                                       attributeChange.getAttributeName() );
            System.out.println("Old Value: " + attributeChange.getOldValue() );
            System.out.println("New Value: " + attributeChange.getNewValue() );
        }
    }
}

例7-1は、AttributeChangeNotificationのメソッドを使用して、値が変化した属性の名前と古い値および新しい値を取得する簡単なリスナーです。

リモートJVMからのリスニング

JMX 1.2では、リスニングするMBeanとは別のJVMで動作するリスナーのプログラミングに関する特別な要件はありません。

(javax.management.MBeanServerConnectionを使用して)リモートJMXエージェントへの接続を確立すると、JMXによってJVM間のデータの共有が処理されます。リモートJVMから接続を確立する手順については、「通知リスナーとフィルタの登録」,を参照してください。

ベスト・プラクティス:通知リスナーの作成

NotificationListenerクラスを作成するときに、以下の推奨事項を考慮してください。

  • 通知フィルタを使用しない限り、リスナーはそのリスナーが登録されているMBeanからの(すべての通知型の)すべての通知を受信します。

    MBeanから送信されるすべての通知に1つのリスナーを使用するのではなく、フィルタとリスナーを組み合せて使用するのが最適です。複数のリスナーを使用するとJVMの初期化に時間がかかりますが、そのかわりにコードの保守が容易になります。

  • WebLogic Server環境にモニターする必要のあるMBeanタイプの複数のインスタンスがある場合は、1つの通知リスナーを作成して、モニターするMBeanインスタンスと同じ数だけ登録クラスを作成できます。

    たとえば、WebLogic Serverドメインに3つのJDBCデータ・ソースがある場合は、AttributeChangeNotificationをリスニングする1つのリスナー・クラスを作成できます。次に、3つの登録クラスを作成します。各登録クラスは、リスナーをJDBCDataSourceRuntimeMBeanの特定のインスタンスに登録します。

  • handleNotificationメソッド・シグネチャにはhandbackオブジェクトの引数が含まれていますが、リスナーではhandbackオブジェクトからデータを取得したり、handbackオブジェクトを操作したりする必要はありません。それは、リスナーがMBeanエミッタに関する情報を関連付けるのを助ける不透明なオブジェクトです。

  • 通知ブロードキャスタをブロックしないように、handleNotificationメソッドの実装はできるだけ早く復帰する必要があります。

  • 特殊な通知型のメソッドを呼び出す場合は、そのメソッド呼出しをif文でラップして、リスナーがすべての型の通知オブジェクトのメソッドを呼び出さないようにします。

通知フィルタの構成

JDK 1.5では、指定する条件に一致した通知を転送するように構成できる、簡単なフィルタ・クラスが2つ用意されています。JDKのフィルタ・クラスを構成するには、次の手順に従います。

  1. リスナーをMBeanに登録するクラスで、javax.management.NotificationFilterSupportまたはAttributeChangeNotificationFilterのインスタンスを作成します。
  2. フィルタ・クラスのメソッドを呼び出して、フィルタ条件を指定します。

    Java SE 8 API仕様NotificationFilterSupport (http://docs.oracle.com/javase/8/docs/api/javax/management/NotificationFilterSupport.html)またはAttributeChangeNotificationFilter (http://docs.oracle.com/javase/8/docs/api/javax/management/AttributeChangeNotificationFilter.html)を参照してください。

たとえば、以下のコード行では、Stateという属性で変更があった場合にのみ属性変更通知を転送するAttributeChangeNotificationFilterを構成します。

AttributeChangeNotificationFilter filter = 
   new AttributeChangeNotificationFilter();
filter.enableAttribute("State"); 

カスタム・フィルタの作成

JDKのフィルタ・クラスでは単純過ぎて要件に合わない場合は、より高度なカスタム・フィルタ・クラスを作成できます。(Java SE 8 API仕様NotificationFilter (http://docs.oracle.com/javase/8/docs/api/javax/management/NotificationFilter.html)を参照してください。)ただし、カスタム・フィルタを使用すると、リスナーおよびフィルタのパッケージ化とデプロイメントが複雑になるため、できる限りJDKのフィルタ・クラスを使用することをお薦めします。「WebLogic Serverにリスナーのパッケージ化およびデプロイ化」を参照してください

通知リスナーとフィルタの登録

通知リスナー・クラスを実装したら、MBeanインスタンスにリスナーを登録する(また、必要に応じてフィルタを構成して登録する)追加のクラスを作成します。

通知リスナーとフィルタをMBeanに登録するには、次の手順に従います。

  1. ランタイムMBeanサーバーまたはドメイン・ランタイムMBeanサーバーへの接続を初期化します。
  2. WebLogic Server MBeanに登録するには、MBean階層を移動して、リスニングするMBeanのオブジェクト名を取得します。「MBeanサーバーへのリモート接続の作成」を参照してください。

    カスタムMBeanに登録するには、そのMBeanのJMXオブジェクト名を含むObjectNameを作成します。Java SE 8 API仕様javax.management.ObjectName (http://docs.oracle.com/javase/8/docs/api/javax/management/ObjectName.html)を参照してください。

  3. 作成したリスナー・クラスをインスタンス化します。
  4. (オプション) JDKのフィルタ・クラスのいずれかをインスタンス化して構成します。または、カスタム・クラスをインスタンス化します。
  5. MBeanのオブジェクト名、リスナー・クラス、およびフィルタ・クラスをMBeanServerConnection.addNotificationListener (ObjectName name, ObjectName listener, NotificationFilter filter,Object handback)メソッドに渡して、リスナーとフィルタを登録します。

例7-2 ServerLifeCycleRuntimeMBeanへのリスナーの登録

import java.util.Hashtable;
import java.io.IOException;
import java.net.MalformedURLException;

import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.MalformedObjectNameException;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import javax.naming.Context;

import javax.management.AttributeChangeNotificationFilter;

public class RegisterListener {
   private static MBeanServerConnection connection;
   private static JMXConnector connector;
   private static final ObjectName service;
   // Initializing the object name for DomainRuntimeServiceMBean
   // so it can be used throughout the class.
   static {
      try {
         service = new ObjectName(
         "com.bea:Name=DomainRuntimeService,Type=weblogic.management.mbeanserv
          ers.domainruntime.DomainRuntimeServiceMBean");
      }catch (MalformedObjectNameException e) {
         throw new AssertionError(e.getMessage());
      }
   }

   /*
    * Initialize connection to the Domain Runtime MBean Server
    * each server in the domain hosts its own instance.
    */
   public static void initConnection(String hostname, String portString, 
      String username, String password) throws IOException,
      MalformedURLException {
      String protocol = "t3";
      Integer portInteger = Integer.valueOf(portString);
      int port = portInteger.intValue();
      String jndiroot = "/jndi/";
      String mserver = "weblogic.management.mbeanservers.domainruntime";
      JMXServiceURL serviceURL = new JMXServiceURL(protocol, hostname, port,
         jndiroot + mserver);
      Hashtable h = new Hashtable();
      h.put(Context.SECURITY_PRINCIPAL, username);
      h.put(Context.SECURITY_CREDENTIALS, password);
      h.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES,
         "weblogic.management.remote");
      connector = JMXConnectorFactory.connect(serviceURL, h);
      connection = connector.getMBeanServerConnection();
   }

   /*
    * Get an array of ServerLifeCycleRuntimeMBeans
    */
   public static ObjectName[] getServerLCRuntimes() throws Exception {
      ObjectName domainRT = (ObjectName) connection.getAttribute(service,
         "DomainRuntime"); 
      return (ObjectName[]) connection.getAttribute(domainRT,
         "ServerLifecycleRuntimes");
   }

   public static void main(String[] args) throws Exception {
      String hostname = args[0];
      String portString = args[1];
      String username = args[2];
      String password = args[3]; 
      try {
         //Instantiating your listener class.
         MyListener listener = new MyListener();
         AttributeChangeNotificationFilter filter = 
            new AttributeChangeNotificationFilter();
         filter.enableAttribute("State");           

         initConnection(hostname, portString, username, password);
         //Passing the name of the MBeans and your listener class to the
         //addNotificationListener method of MBeanServer.
         ObjectName[] serverLCRT = getServerLCRuntimes();
         int length= (int) serverLCRT.length;
         for (int i=0; i < length; i++) {
            connection.addNotificationListener(serverLCRT[i], listener, 
               filter, null);
            System.out.println("\n[myListener]: Listener registered with"
               +serverLCRT[i]);
         }

      //Keeping the remote client active.
         System.out.println("pausing...........");
         System.in.read();
      } catch(Exception e) {
         System.out.println("Exception: " + e);
      }
   }
}

サンプル・クラスでは、例7-1のリスナーとJDKのAttributeChangeNotificationFilterを、ドメインのServerLifeCycleRuntimeMBeanに登録します。このクラスではhandbackオブジェクトは渡しません。

このサンプルで、weblogicはMBean属性を表示および変更する許可を与えられたユーザーです。MBeanの表示や変更を行う許可については、Oracle WebLogic Serverロールおよびポリシーによるリソースの保護のユーザー、グループおよびセキュリティ・ロールを参照してください。

サンプル・クラスには、RegisterListenerクラスをアクティブに保ち、メイン・プログラムを終了しないコードも含まれています。リスナー・クラスは、クラスの呼出しとアクティブの維持を行う、より大きなアプリケーションのコンテキストで動作するため、このコードは通常は必要ありません。ここでは、簡単にコンパイルしてサンプルの機能を確認できるように含まれています。

WebLogic Serverにリスナーのパッケージ化およびデプロイ化

JMXリスナーは、リモート・アプリケーションとして、WebLogic Server起動クラスとして(サーバーが起動するとすぐにリスナーが使用可能になります)、またはWebLogic Serverにデプロイする他のアプリケーションの内部に、パッケージ化してデプロイできます。

JDKのフィルタを使用する場合は、フィルタ・クラスをパッケージ化する必要はありません。常にJDKから使用できるようになっています。

表7-3では、リスナーとカスタム・フィルタをパッケージ化してデプロイする方法について説明します。

表7-3 リスナーとカスタム・フィルタのパッケージ化とデプロイ

リスナーのデプロイ方法 リスナーに関する手順 カスタム・フィルタに関する手順

リモート・アプリケーションとして

リスナーのクラスをリモート・クライアントのクラスパスで使用可能にします。

フィルタのクラスをリモート・クライアントのクラスパスで使用可能にします。

また、モニターするMBeanをホストしている各サーバー・インスタンスのクラスパスにフィルタ・クラスを追加します。それには、クラスをJARファイルにアーカイブして、そのJARを各サーバーのlibディレクトリにコピーします。Oracle WebLogic Serverドメイン構成の理解のドメイン・ディレクトリの内容を参照してください。

WebLogic Server起動クラスとして

リスナー・クラスをサーバーのクラスパスに追加します。それには、クラスをJARファイルにアーカイブして、そのJARをサーバーのlibディレクトリにコピーします。

フィルタ・クラスをサーバーのクラスパスに追加します。それには、クラスをJARファイルにアーカイブして、そのJARをサーバーのlibディレクトリにコピーします。Oracle WebLogic Serverドメイン構成の理解のドメイン・ディレクトリの内容を参照してください。

WebLogic Serverにデプロイするアプリケーションの一部として

リスナー・クラスをアプリケーションと一緒にパッケージ化します。

リスナー・クラスをアプリケーションと一緒にパッケージ化します。

また、モニターするMBeanをホストしている各サーバー・インスタンスのクラスパスにフィルタ・クラスを追加します。それには、次のいずれかを行います。

例:構成MBeanの登録のリスニング

サーバーやJDBCデータ・ソースなどのWebLogic Serverリソースを作成すると、WebLogic Serverは構成MBeanを作成してドメイン・ランタイムMBeanサーバーに登録します。

これらのイベントをリスニングするには、リスナーをjavax.management.MBeanServerDelegateに登録します。

MBeanが登録または登録解除されるたびに、javax.management.MBeanServerNotification型の通知を送信します。Java SE 8 API仕様MBeanServerDelegate (http://docs.oracle.com/javase/8/docs/api/javax/management/MBeanServerDelegateMBean.html)を参照してください

例7-3のサンプル・リスナーに関する以下の点に注意してください。

  • 登録されたWebLogic Server MBeanのタイプに関する情報を提供するために、リスナーは登録されたMBeanのオブジェクト名を検索します。すべてのWebLogic Server MBeanオブジェクト名には、名前が「Type」で、値がMBeanのタイプを表す、キー・プロパティが含まれています。たとえば、ServerRuntimeMBeanのインスタンスには、オブジェクト名にType=ServerRuntimeキー・プロパティが含まれています。

  • すべてのJMX通知にはType属性が含まれており、その値によって通知の分類とフィルタ処理ができます。MBeanServerNotificationType属性には、2つの文字列「JMX.mbean.registered」または「JMX.mbean.unregistered」のうち1つだけ含まれています。また、JMX通知にはType属性の値を返すgetTypeメソッドも含まれます。

    例7-3のリスナーは、Type属性の値に応じて異なるコード行を呼び出します。

  • JDBCDataSourceRuntimeMBeanが登録されると、リスナーはこのMBeanのオブジェクト名をカスタム・メソッドに渡します。カスタム・メソッドはリスナーを登録し、JDBCDataSourceRuntimeMBean用のフィルタを構成します。このMBeanリスナーは、MBeanのEnabled属性が変更されるとメッセージを送信します。

    カスタム・メソッドの実装クラスは(フィルタ・クラスではなく) 登録クラス内にあるので、メソッドは登録クラスのMBeanサーバーへの接続を再利用できます。再利用によってリソースが有効に活用され、複数のクラスに資格証明とURLを格納する必要がなくなります。

例7-3 例: MBeanの登録および登録解除のリスニング

import javax.management.Notification;
import javax.management.NotificationListener;
import javax.management.MBeanServerNotification;
import javax.management.ObjectName;

public class DelegateListener implements NotificationListener {
   public void handleNotification(Notification notification, Object obj) {
      if (notification instanceof MBeanServerNotification) {
         MBeanServerNotification msnotification = 
         (MBeanServerNotification) notification;

         // Get the value of the MBeanServerNotification
         // Type attribute, which contains either
         // "JMX.mbean.registered" or "JMX.mbean.unregistered"
         String nType = msnotification.getType();

         // Get the object name of the MBean that was registered or
         // unregistered
         ObjectName mbn = msnotification.getMBeanName();

         // Object names for WebLogic Server MBeans always contain
         // a "Type" key property, which indicates the
         // MBean's type (such as ServerRuntime or Log)
         String key = mbn.getKeyProperty("Type");

        if (nType.equals("JMX.mbean.registered")) {
            System.out.println("A " + key + " has been created.");

            System.out.println("Full MBean name: " + mbn);
            System.out.println("Time: " + msnotification.getTimeStamp());
               if (key.equals("JDBCDataSourceRuntime")) {
               // Registers a listener with a ServerRuntimeMBean.
               // By defining the "registerwithServerRuntime" method
               // in the "ListenToDelegate" class, you can reuse the
               // connection that "ListenToDelegate" established;
               // in addition to being an efficient way to use resources,
               // it eliminates the need to store credentials and URLs in
               // multiple classes.
               ListenToDelegate.registerwithJDBCDataSourceRuntime(mbn);
            }
         }
         if (nType.equals("JMX.mbean.unregistered")) {
            System.out.println("An MBean has been unregistered");
            System.out.println("Server name: " +
               mbn.getKeyProperty("Name"));
            System.out.println("Time: " + msnotification.getTimeStamp());
            System.out.println("Full MBean name: "
               + msnotification.getMBeanName());
         }
      }
   }
}

例7-4では、登録クラスのメソッドを示します。以下の点に注意してください。

  • MBeanServerDelegateのJMXオブジェクト名は常に"JMImplementation:type=MBeanServerDelegate"

  • mainメソッドでは、通知のType属性の値が「JMX.mbean.registered」または「JMX.mbean.unregistered」で始まる場合にのみ通知を転送するように、javax.management.NotificationFilterSupportのインスタンスを構成します。

  • registerwithJDBCDataSourceRuntimeメソッドは、指定されたJDBCDataSourceRuntimeMBeanインスタンスに例7-1のリスナーを登録します。このメソッドではjavax.management.AttributeChangeNotificationFilterも構成します。これは、Enabledという属性の変更について説明するAttributeChangeNotificationのみを転送します。

これらのメソッドをコンパイルして実行するには、例7-2の補助的なカスタム・メソッドを使用し、生成されたクラスをリモートJMXクライアントとして実行します。

例7-4 例: MBeanServerDelegateへのリスナーの登録

public static void main(String[] args) throws Exception {
   String hostname = args[0];
   String portString = args[1];
   String username = args[2];
   String password = args[3];
   ObjectName delegate = new ObjectName(
      "JMImplementation:type=MBeanServerDelegate");

   try {
      //Instantiating your listener class.
      StartStopListener slistener = new StartStopListener();
      NotificationFilterSupport filter = new NotificationFilterSupport();
      filter.enableType("JMX.mbean.registered");
      filter.enableType("JMX.mbean.unregistered");

      /* Invoke a custom method that establishes a connection to the
       * Domain Runtime MBean Server and uses an instance of 
       * MBeanServerConnection to represents the connection. The custom
       * method assigns the MBeanServerConnection to a class-wide, static
       * variable named "connection".
       */
      initConnection(hostname, portString, username, password);

      //Passing the name of the MBeans and your listener class to the
      //addNotificationListener method of MBeanServer.
      connection.addNotificationListener(delegate, slistener, filter,
         null);

      System.out.println("\n[myListener]: Listener registered ...");
      //Keeping the remote client active.
      System.out.println("pausing...........");
      System.in.read();
   } catch (Exception e) {
      System.out.println("Exception: " + e);
   }
}

// Called by the listener if it receives notification of a
// JDBCDataSourceRuntimeMBean being registered.
public static void registerwithJDBCDataSourceRuntime(ObjectName mbname) {
   try {
      MyListener mylistener = new MyListener();
      AttributeChangeNotificationFilter filter = 
         new AttributeChangeNotificationFilter();
      filter.enableAttribute("Enabled");

      connection.addNotificationListener(mbname, mylistener, 
         filter, null);
   } catch (Exception e) {
      System.out.println("Exception: " + e);
   }
}

モニターMBeanを使用した変更の観察:主な手順

モニターMBeanを構成して使用するには、次の手順に従います。

  1. モニターの要件に合うモニターMBeanタイプを選択します。「モニターMBeanのタイプと通知の型の選択」を参照してください
  2. モニターMBeanからの通知をリスニングできるリスナー・クラスを作成します。「モニターMBean用の通知リスナーの作成」を参照してください。
  3. モニターMBeanの作成、登録、および構成、リスナー・クラスのモニターMBeanへの登録、モニターMBeanの起動を行うクラスを作成します。「モニターとリスナーの登録」を参照してください。

モニターMBeanのタイプと通知の型の選択

JMXでは、特定のタイプの変更を観察する特別なモニターMBeanを提供しています。

  • StringMonitorMBean - 値がStringの属性を観察します。

    このモニターを使用して、ServerLifeCycleRuntimeMBean Stateなどの属性を定期的に観察します。

    StringMonitorMBeanを実装するJava SE 8 API仕様javax.management.monitor.StringMonitor (http://docs.oracle.com/javase/8/docs/api/javax/management/monitor/StringMonitor.html)を参照してください。

  • GaugeMonitorMBean - 値がNumberの属性を観察します。

    このモニターを使用して、通常の処理の結果として値が変動する属性を観察します。属性の値が特定の範囲外まで変動した場合に通知を送信するように、ゲージ・モニターを構成します。たとえば、ゲージ・モニターを使用してThreadPoolRuntimeMBean StandbyThreadCount属性をモニターし、サーバーの未使用かつ使用可能なスレッドの数が許容範囲内にあることを確認できます。

    GaugeMonitorMBeanを実装するJava SE 8 API仕様javax.management.monitor.GaugeMonitor (http://docs.oracle.com/javase/8/docs/api/javax/management/monitor/GaugeMonitor.html)を参照してください。

  • CounterMonitorMBean - 値がNumberの属性を観察します。

    このモニターを使用して、通常の処理の結果として値が増加する属性を観察します。属性の値が上限しきい値を超えた場合に通知を送信するように、カウンタ・モニターを構成します。しきい値を増やして指定された時点でしきい値をリセットするように、カウンタ・モニターを構成することもできます。

    たとえば、サーバーでのヒット総数を追跡して、100ヒット増えるたびに通知を受けるようにするには、ServerRuntimeMBean SocketsOpenedTotalCount属性を観察するカウンタ・モニターを使用します。

    CounterMonitorMBeanを実装するJava SE 8 API仕様javax.management.monitor.CounterMonitor (http://docs.oracle.com/javase/8/docs/api/javax/management/monitor/CounterMonitor.html)を参照してください。

すべてのモニターMBeanはjavax.management.monitor.MonitorNotification型の通知を送信します。モニターMBeanは通知を生成するときに、特定の値を通知のTypeプロパティに書き込んで、通知を生成したイベントについて記述します。表7-4では、様々なタイプのモニターMBeanがエンコードするTypeプロパティの値について説明します。フィルタまたはリスナーは通知のgetType()メソッドを使用して、Typeプロパティ内のStringを取得します。

表7-4 モニターMBeanとMonitorNotificationのTypeプロパティ

モニターMBeanのタイプ MonitorNotificationのTypeプロパティ内にエンコードされる文字列
CounterMonitor 

jmx.monitor.counter.threshold - カウンタの値がしきい値(比較レベル)に到達したか、またはそれを超えた場合。

GaugeMonitor

jmx.monitor.gauge.high - 観察対象の属性値が増加し、上限しきい値と等しくなるかそれを超えた場合。この属性値が下限しきい値と等しくなるかそれを下回った場合を除き、以後上限しきい値に達しても通知は行われません。

jmx.monitor.gauge.low - 観察対象の属性値が減少し、下限しきい値と等しくなるかそれを下回った場合。この属性値が上限しきい値と等しくなるかそれを超えた場合を除き、以後下限しきい値に達しても通知は行われません。

StringMonitor 

jmx.monitor.string.matches - 観察対象の属性値が比較文字列値と一致した場合。この属性値が比較文字列値と異なる場合を除き、以後この文字列が比較文字列と一致しても通知は行われません。

jmx.monitor.string.differs - この属性値が比較文字列値と異なる場合。この属性値が比較文字列値と一致する場合を除き、以後この文字列が比較文字列と異なっても通知は行われません。

エラーとMonitorNotificationのTypeプロパティ

エラーが発生した場合、すべてのモニターは通知のTypeプロパティに以下のいずれかの値をエンコードします。

  • jmx.monitor.error.mbean - 観察対象MBeanがMBeanサーバーに登録されていないことを示します。通知では、観察対象のオブジェクト名が示されます。

  • jmx.monitor.error.attribute - 観察対象の属性が観察対象オブジェクトに存在しないことを示します。通知では、観察対象のオブジェクト名と属性名が示されます。

  • jmx.monitor.error.type - 観察対象の属性値のオブジェクト・インスタンスがnullか、またはモニターに対応していない型であることを示します。通知では、観察対象のオブジェクト名と属性名が示されます。

  • jmx.monitor.error.runtime - 観察対象の属性値の取得中に(上記以外の理由で)スローされた例外が含まれます。

また、カウンタ・モニターとゲージ・モニターは、以下のような場合にTypeプロパティにjmx.monitor.error.thresholdをエンコードできます。

  • カウンタ・モニターの場合、しきい値、オフセット、または係数の型が観察対象のカウンタ属性と同じでない場合

  • ゲージ・モニターの場合、下限しきい値または上限しきい値が観察対象のゲージ属性と同じでない場合

モニターMBean用の通知リスナーの作成

観察対象の属性が指定した条件に一致する場合、モニターMBeanは通知を送信します。MonitorNotification用のリスナーを作成するための特別な要件はありません。手順は、次の点を除いて通知リスナーの作成で説明した手順と同じです。

  • MonitorNotification型の通知をリスニングします。

  • 必要に応じて、javax.management.monitor.MonitorNotificationクラスをインポートし、そのメソッドを呼び出して、通知を生成したイベントに関する追加情報を取得できます。

例7-5を参照してください。

例7-5 モニター通知用のリスナー

import javax.management.Notification;
import javax.management.NotificationListener;
import javax.management.monitor.MonitorNotification;
public class MonitorListener implements NotificationListener {
   public  void handleNotification(Notification notification, Object obj) {
      if(notification instanceof Notification) {
         Notification notif = (Notification) notification;
         System.out.println("Notification type" + notif.getType() );
         System.out.println("Message: " + notif.getMessage() );
      }
      if (notification instanceof MonitorNotification) {
         MonitorNotification mn = (MonitorNotification) notification;
         System.out.println("Observed Attribute: " +
             mn.getObservedAttribute());
         System.out.println("Trigger: " + mn.getTrigger() );
      }
   }
}

モニターとリスナーの登録

モニターMBeanを使用するには、まず、MBeanサーバー内でモニターMBeanのインスタンスを作成して登録する必要があります。次に、作成したモニターMBeanにリスナーを登録します。この手順のすべてを1つのクラスの中で行うことができます。

モニターMBeanを登録し、リスナーを登録して、モニターMBeanを起動するには、次の手順に従います。

  1. ドメイン・ランタイムMBeanサーバーへの接続を初期化します。
  2. モニターMBeanインスタンスのObjectNameを作成します。

    Java SE 8 API仕様javax.management.ObjectName (http://docs.oracle.com/javase/8/docs/api/javax/management/ObjectName.html)を参照してください。

    オブジェクト名は組織の名前で始めて、モニターMBeanインスタンスの目的を明確に表すキー・プロパティを含めることをお薦めします。

    例: mycompany:Name=SocketMonitor,Type=CounterMonitor

  3. いずれかのモニターMBeanを作成して登録します。

    javax.management.MBeanServerConnection.createMBean(String classname ObjectName name)メソッドを使用します。ここで、

    • classnameは、次のいずれかの値です。

      • javax.management.monitor.CounterMonitor

      • javax.management.monitor.GaugeMonitor

      • javax.management.monitor.StringMonitor

    • nameは、モニターMBeanインスタンス用に作成したオブジェクト名です。

  4. 属性値を設定して、モニターMBeanを構成します。

    設定する属性のガイドラインについては、Java SE 8 API仕様javax.management.monitoringパッケージ(http://docs.oracle.com/javase/8/docs/api/javax/management/monitor/package-summary.html)を参照してください。

  5. モニターMBeanがモニターするMBean(観察対象MBean)を指定するには、モニターMBeanのaddObservedObject(ObjectName objectname)およびaddObservedAttribute(String attributename)操作を呼び出します。
    • objectnameは観察対象MBeanのObjectName

    • attributenameはモニターする観察対象MBeanの属性名

    モニターMBeanの1つのインスタンスで複数のMBeanをモニターできます。モニターするMBeanインスタンスごとにaddObservedObjectおよびaddObservedAttribute操作を呼び出します。

  6. 「モニターMBean用の通知リスナーの作成」で作成したリスナー・オブジェクトをインスタンス化します。
  7. 必要に応じて、フィルタをインスタンス化して構成します。
  8. リスナーとフィルタ(オプション)をモニターMBeanに登録します。リスナーを観察対象MBeanには登録しないでください。

    モニターMBeanのaddNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback)メソッドを呼び出します。

  9. モニターMBeanのstart()操作を呼び出して、モニターを起動します。

例: CounterMonitorMBeanとそのリスナーの登録

例7-6では、CounterMonitorMBeanを作成および構成して、ドメインの各ServerRuntimeMBeanインスタンスのSocketsOpenedTotalCount属性を観察するクラスのmain()メソッドを示します。(Oracle WebLogic Server MBeanリファレンスSocketsOpenedTotalCountを参照してください。)

このサンプル・コードでは、ServerRuntimeMBeanの複数のインスタンスをモニターできるように、ドメイン・ランタイムMBeanサーバーに接続します。以下の点に注意してください。

  • CounterMonitorMBeanの1つのインスタンスでServerRuntimeMBeanのすべてのインスタンスをモニターします。ドメイン・ランタイムMBeanサーバーは、別のJVMで動作するServerRuntimeMBeanインスタンスへの結合アクセスをCounterMonitorMBeanに与えています。

  • リスナー・クラスのとフィルタ・クラスの1つのインスタンスが、CounterMonitorMBeanからの通知をリスニングしてフィルタ処理します。

このmainメソッドをコンパイルして実行するには、例7-2の補助的なカスタム・メソッドを使用し、生成されたクラスをリモートJMXクライアントとして実行します。

例7-6 例: CounterMonitorMBeanとそのリスナーの登録

public static void main(String[] args) throws Exception {
   String hostname = args[0];
   String portString = args[1];
   String username = args[2];
   String password = args[3];

   try {
      /* Invokes a custom method that establishes a connection to the
       * Domain Runtime MBean Server and uses an instance of
       * MBeanServerConnection to represents the connection. The custom
       * method assigns the MBeanServerConnection to a class-wide, static
       * variable named "connection".
       */
      initConnection(hostname, portString, username, password);
      //Creates and registers the monitor MBean.
      ObjectName monitorON = 
         new ObjectName("mycompany:Name=mySocketMonitor,Type=CounterMonitor");
      String classname = "javax.management.monitor.CounterMonitor";
      System.out.println("===> create mbean "+monitorON);
      connection.createMBean(classname, monitorON);

      //Configure the monitor MBean.
      Number initThreshold = new Long(2);
      Number offset = new Long(1);
      connection.setAttribute(monitorON, 
         new Attribute("InitThreshold", initThreshold));
      connection.setAttribute(monitorON, new Attribute("Offset", offset));
      connection.setAttribute(monitorON, 
         new Attribute("Notify", new Boolean(true)));

      //Gets the object names of the MBeans that you want to monitor.
      ObjectName[] serverRT = getServerRuntimes();
      int length= (int) serverRT.length;
      for (int i=0; i < length; i++) { 
         //Sets each instance of ServerRuntime MBean as a monitored MBean.
         System.out.println("===> add observed mbean "+serverRT[i]);
         connection.invoke(monitorON, "addObservedObject",
            new Object[] { serverRT[i] },
            new String[] { "javax.management.ObjectName" });

         Attribute attr = new Attribute("ObservedAttribute",
            "SocketsOpenedTotalCount");
         connection.setAttribute(monitorON, attr);
      }

      // Instantiates your listener class and configures a filter to
      // forward only counter monitor messages.
      MonitorListener listener = new MonitorListener();
      NotificationFilterSupport filter = new NotificationFilterSupport();
      filter.enableType("jmx.monitor.counter");
      filter.enableType("jmx.monitor.error"); 

      //Uses the MBean server's addNotificationListener method to
      //register the listener and filter with the monitor MBean.
      System.out.println("===> ADD NOTIFICATION LISTENER TO "+monitorON);
      connection.addNotificationListener(monitorON, listener, filter, null);
      System.out.println("\n[myListener]: Listener registered ...");

      //Starts the monitor.
      connection.invoke(monitorON, "start", new Object[] { }, new String[] { });

      //Keeps the remote client active.
      System.out.println("pausing...........");
      System.in.read();
   } catch(Exception e) {
      System.out.println("Exception: " + e);
      e.printStackTrace();
   }
}