9. JMXアプリケーションの開発

WebOTXの運用管理エージェントにアクセスするためのJMXアプリケーションの作成方法について説明します。
JMXアプリケーションを作成するには次のAPIを利用します。

9.1. JMXアプリケーション動作環境について

WebOTXの運用管理エージェントにアクセスするためのJMXアプリケーションを動作させるための環境設定について説明します。

9.1.1. ビルド環境

9.1.2. 実行環境

9.2. JMX Remote APIの設定について

WebOTX AS V8.1を利用してJMX Remote APIを利用したクライアントを作成する場合、次のimport文を含める必要があります。
なお、classpassには${INSTALL_ROOT}/lib/javaee.jarファイルと${INSTALL_ROOT}/lib/wosv-rt.jarファイルを追加する必要があります。
コーディング例
import java.util.*;
import java.security.*;
import java.io.*;
import javax.net.ssl.*;
                  
//
// JMX API 1.2
//
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanNotificationInfo;
import javax.management.MBeanInfo;
                  
import javax.management.Attribute;
import javax.management.MBeanServerConnection;
import javax.management.MBeanServerInvocationHandler;
import javax.management.ObjectName;
import javax.management.AttributeList;
                  
//
// JMX Remote API 1.0
//
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
                  
//
// WebOTX API  8.1
// ${INSTALL_ROOT}/lib/wosv-rt.jar
//
import com.nec.webotx.enterprise.admin.jmx.remote.client.*;
import com.nec.webotx.enterprise.admin.jmx.remote.plainclient.*;

9.3. JMXConnectorの生成

運用管理エージェントに接続するためにJMXConnectorオブジェクトを作成します。
JMXConnectorオブジェクトを作成するには、WebOTXが提供するJMXRemoteClientクラスを利用する方法と、標準のJMX Remote API利用してプロファイル情報を個別に設定する方法があります。

9.3.1. JMXRemoteClientクラスを利用する方法

コーディング例
// URLの生成
// プロトコル RMI
// ホスト名 localhost
// 管理ポート番号 6212
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://host:6212/management/rmi-jmx-connector");

// JMXRemoteClientの生成
final JMXRemoteClient jmxcl = new JMXRemoteClient();
jmxcl.config(System.getProperty("javax.net.ssl.trustStore"), "changeit", false);

// JMXConnectorの生成
final JMXConnector jmxc = jmxcl.connect(url.toString(), username, password);
URLの生成
利用するプロトコル名、アクセスする運用管理エージェントのホスト名、ポート番号からJMXServiceURLオブジェクトを生成します。WebOTXのデフォルトで作成されるdomain1に接続するためには上記コードのように"rmi"プロトコルは6212ポートを利用します。
JMXRemoteClientの生成
JMXRemoteClientクラスを作成し、証明書ファイル(システムプロパティ「javax.net.ssl.trustStore」から取得)と証明書ファイルのパスワード(“changeit”)を指定します。
JMXConnectorの生成
urlとユーザ名、パスワードを指定して運用管理エージェントに接続し、JMXConnectorオブジェクトを取得します。
urlはJMXServiceURLクラスから作成できますが、直接生成することもできます。直接生成する場合は次のフォーマットでurlを作成してください。

service:jmx:[protocol]://[host]:[port][url-path]

運用管理エージェントへの接続パラメータ一覧
パラメータ 説明
protocol
運用管理エージェントと通信するためのプロトコル名を指定します。
jmxmp :JMXMPプロトコル
rmi :RMIプロトコル
RMIプロトコル使用時、WebOTXでは、JNDIを経由し、接続を行います。 この場合、下記のようにurlを作成してください service:jmx:rmi:///jndi/rmi://[host]:[port][url-path]
host 運用管理エージェントのホスト名
port protocolで指定したプロトコルのポート番号
JMXMPプロトコルの場合 :6712 RMIプロトコルの場合 :6212
省略時は6212(管理ドメインのデフォルトポート番号)が指定されます。
url-path RFC 2609の仕様に従ったurlパス名。
例として上記のコーディング例に従ったurl記述は
service:jmx:rmi:///jndi/rmi://localhost:6212/management/rmi-jmx-connector
となります。
ユーザ名、パスワードは接続するドメインでotxadminグループに属しているユーザである必要があります。

9.3.2. 標準のJMX Remote APIを利用する方法

コーディング例
// プロファイル情報格納領域の生成
HashMap env = new HashMap();

// SSLSocketFactoryの生成
tring truststore = System.getPropery("javax.net.ssl.trustStore");
char truststorepass[] = "changeit".toCharArray();
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream(truststore), truststorepass);
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(ks);
SSLContext ctx = SSLContext.getInstance("TLSv1");
ctx.init(null, tmf.getTrustManagers(), null);
SSLSocketFactory ssf = ctx.getSocketFactory();

// プロバイダ関数の登録
Security.addProvider( new com.nec.webotx.enterprise.admin.jmx.remote.plainclient.ClientProvider());

// プロファイル情報の設定
env.put("jmx.remote.profiles","TLS SASL/PLAIN");
env.put("jmx.remote.tls.socket.factory", ssf);
env.put("jmx.remote.tls.enabled.protocols", "TLSv1");
env.put("jmx.remote.tls.enabled.cipher.suites","SSL_RSA_WITH_NULL_MD5");

// コールバック関数の登録
env.put("jmx.remote.sasl.callback.handler"
        , new com.nec.webotx.enterprise.admin.jmx.remote.client.UserPasswordCallbackHandler(user, password));

// URLの生成
// プロトコル RMI
// ホスト名 localhost
// 管理ポート番号 6212
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://host:6212/management/rmi-jmx-connector");

// JMXConnectorの生成
final JMXConnector jmxc = JMXConnectorFactory.connect(url, env);
SSLSocketFactoryの生成
証明書ファイル(システムプロパティ「javax.net.ssl.trustStore」から取得)と証明書ファイルのパスワード(“changeit”)から認証情報を取得して、サーバ/クライアント間のSSL通信で利用するSSLSocketFactoryオブジェクトを作成します。証明書ファイルには、サーバ側の${INSTANCE_ROOT}/config/keystore.jksファイルに格納されている情報の認証情報が格納されている必要があります。作成したオブジェクトは、後でプロファイル情報として設定します。
プロバイダ関数の設定
WebOTX AS V8.1で使用するJMXMPプロトコルでは、SASL/PLAINを利用しています。SASL/PLAINのクライアント側の処理を提供するプロバイダ関数を設定します。この例で使用するプロバイダ関数は、${INSTALL_ROOT}/lib/wosv-rt.jarで提供されます。
プロファイル情報の設定
WebOTX AS V8.1で使用するJMXMPプロトコルを利用するための各プロファイル情報を設定します。これらの情報はサーバ/クライアントで一致させる必要があります。
コールバック関数の登録
SASL/PLAINで利用するcallback関数を設定します。この例で使用するコールバック関数は${INSTALL_ROOT}/lib/wosv-rt.jarで提供されます。このコールバック関数の引数には、接続するドメインでotxadminグループに所属するユーザ名とパスワード情報を設定します。
URLの生成
利用するプロトコル名、アクセスする運用管理エージェントのホスト名、ポート番号を指定してJMXServiceURLオブジェクトを生成します。
WebOTXのデフォルトで作成されるdomain1に接続するためには上記コードのようにプロトコルは"rmi"ポートは6212を指定します。
JMXConnectorの生成
URLとプロファイル情報(env)を指定してJMXConnectorオブジェクトを生成します。

9.4. MBeanServerConnectionの取得

運用管理エージェントのMBeanを取得するためにMBeanServerConnectionを取得します。
コーディング例
	MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
	
MBeanServerConnectionインタフェース
JMXではローカルでMBeanにアクセスするためにMBeanServerインタフェースを利用しますが、リモートではMBeanServerConnectionインタフェースを利用します。

9.5. MBeanのObjectNameの取得

運用管理エージェントのMBeanServerConnectionを利用してMBeanのObjectNameを取得します。
コーディング例
// オブジェクト名の検索
ObjectName objname = new ObjectName("*:*");
et objnames = mbsc.queryNames(objname,null);

for (final Iterator i=objnames.iterator();i.hasNext(); ) {
    bjectName name = (ObjectName)i.next();
    System.out.println("MBean: " + name);
}
オブジェクト名の検索について
JMXにおいてMBeanにはMBeanを一意に識別するオブジェクト名が割り当てられています。MBeanServerConnectionインタフェースでMBeanにアクセスするためのメソッドの引数には必ずオブジェクト名を指定します。そこでMBeanServerConnectionのインタフェースではMBeanの検索するためのメソッド(queryNames,queryMBeans)を提供しています。
queryNames,queryMBeansメソッドも引数は同じです。返却値が引数で指定した条件にマッチするObjectNameクラスのsetかMBeanクラスのsetかの違いがあるだけです。
   queryNames,queryMBeansメソッドの第一引数はObjectNameです。このObjectNameでは以下のワイルドカードを使用することが可能です。指定したObjectNameにマッチするMBeanを検索することになります。
‘*’ :空の1つを含むどんな文字シーケンスとも一致します。
‘?’ :1つのどんな単一文字とも一致します。
以下に例を示します。
次のObjectNameでMBeansがMBeanServerに登録されると仮定します。
   デフォルトドメイン名は”DefaultDomain”とします。
MyDomain:description=Printer,type=laser
MyDomain:description=Disk,capacity=2
DefaultDomain:description=Disk,capacity=1
DefaultDomain:description=Printer,type=ink

DefaultDomain:description=Printer,type=laser,date=1993

Socrates:description=Printer,type=laser,date=1993
queryNames,queryMBeansメソッドの第二引数はQueryExpです。QueryExpはユーザ定義の属性値を基にMBeanのフィルタリング条件を指定します。なおQueryExpをnullに指定するとフィルタリングは行いません。
QueryExpは属性値のconstraints(数値については“equals”や”less-than”、文字列については”matches”のようなもの)から構成されています。このconstraintsは”and”や”or”のようなオペレーションも含みます。
例えば次のようなExpressionが定義できます。
“Retrieve the MBeans for which the attribute age is at least 20 and the attribute name starts with G and ends with ling”
  (属性”age”の値が少なくとも20であり、属性”name”の値がGから始まりlingで終わるMBeanを検索する)
上記のコーディング例ではオブジェクト名に”*:*”を指定しているのでドメインに登録されている全てのMBeanのオブジェクト名を取得できます。
 

9.6. MBeanInfoの取得

MBeanの情報を取得するにはMBeanInfoを取得する必要があります。MBeanInfoを取得することによりそのMBeanがサポートする属性やオペレーションやNotificationの情報を取得することができます。
コーディング例
MBeanInfo info = mbsc.getMBeanInfo((ObjectName)name);
MBeanAttributeInfo[] attrs = info.getAttributes();
if (attrs != null){
  for (int j=0; j<attrs.length; j++) {
    System.out.println("attribute : " + attrs[j].getName());
  }
}

MBeanOperationInfo[] ops = info.getOperations();
if (ops != null){
  for (int j=0; j< ops.length; j++) {
    System.out.println("operation : " + ops[j].getName());
  }
}

MBeanNotificationInfo[] nts = info.getNotifications();
if (nts != null){
  for (int j=0; j< nts.length; j++) {
    System.out.println("nts : " + nts[j].getName());
  }
}
MBeanInfo
MBeanInfoにはそのMBeanに関する以下の情報を取得することが出来ます。

9.7. 属性の取得

MBeanの属性値を取得します。
コーディング例
// 属性の取得
Object attrValue = mbsc.getAttribute(name,attrs[j].getName());
System.out.println(attrs[j].getName() + " = " + attrValue);
属性の取得
属性を取得するにはMBeanServerConnectionの次のメソッドを呼び出します。

9.8. 属性の設定

MBeanの属性値を設定します。
コーディング例
// 属性の設定
Attribute attr = new Attribute("description","sample test");
mbsc.setAttribute(,name,attr);
属性の設定
属性を設定するにはMBeanServerConnectionの次のメソッドを呼び出します。

9.9. オペレーションの呼び出し

MBeanのオペレーションを呼び出します。
コーディング例
// オペレーションの呼び出し
Object retValue = mbsc.invoke(name, "start",null,null);
オペレーションの呼び出し
オペレーションを呼び出すにはMBeanServerConnectionのinvokeメソッドを呼び出します。
 

9.10. Notificationの受信

MBeanのNotificationを受信します。
コーディング例
SampleListener listener = new SampleListener();
mbsc.addNotificationListener(name, listener, null, null);
Notificationリスナクラスの作成
Notification受信をするためのNotificationリスナを作成します。javax.management.NotificationListenerインタフェースをimplementsしたリスナクラスを作成します。
   Notificationイベントが発生した場合、handleNotificationオペレーションがコールバックされるのでhandleNotificationオペレーションを実装します。
Notificationリスナの登録
Notificationを受信するにはNotificationリスナを登録する必要があります。MBeanServerConnectionのaddNotificationListenerメソッドを呼び出し、Notificationリスナを登録します。
   登録が完了すると指定したMBeanで発生したNotificationイベントを受信することができます。