12 検索サービス
検索サービスを使用すると、JMXテクノロジのクライアントは、検索サービスに登録されているコネクタ・サーバーを検索し、接続することができます。
JMX仕様では、次の各項で説明する既存の検索テクノロジを使用した、検索サービスの3つのバインディングを定義しています:
- 初期設定では、3つのタイプのすべての検索サービスに適用される設定情報を提供します。
- Service Location Protocol (SLP)検索サービスでは、SLP検索の例を示します。
- Java Naming and Directory Interface (JNDI)/LDAP検索サービスでは、JNDI/LDAP検索の例を示します。
初期設定
RMIコネクタを使用した標準および動的MBeanへのアクセスで示したように、リモート・メソッド呼出し(RMI)コネクタを使用している場合、検索するコネクタ・サーバー・スタブの登録に外部ディレクトリを使用できます。RMIコネクタに関連した検索サービスの例の中で、次のケースを示します。
-
次の外部ディレクトリのいずれかを使用したRMIコネクタ
-
RMIレジストリ。デフォルトのJava Remote Method Protocol (JRMP)トランスポートを実装するRMIコネクタ向け
-
Lightweight Directory Access Protocol (LDAP)。JRMPトランスポート向け
-
-
外部ディレクトリを使用しないRMIコネクタ
RMIコネクタ・スタブを外部ディレクトリに登録する場合は、いくつか初期設定が必要です。RMIレジストリまたはLDAPサーバーを設定する必要があります。外部ディレクトリを使用しない場合、RMIコネクタ・スタブはJMXサービスURLにエンコードされます。
次のセクションでは、RMIコネクタを使用する検索サービスの例に使用できる外部ディレクトリについて説明します。これらの外部ディレクトリは、この章の以降のセクションで示す検索サービスの3つの例を実行する場合に参照されます。
外部RMIレジストリ
JRMPトランスポートを実装するコネクタで使用するために、外部RMIレジストリにRMIコネクタ・サーバー・スタブを登録するには、次の手順を実行します。
-
ローカル・ホストのポート9999でRMIレジストリを起動します。
JMXコネクタで説明されているように、RMIレジストリはJRMPトランスポートを実装するRMIコネクタ用のRMIコネクタ・スタブを格納するために使用されます。
$ rmiregistry 9999 &
-
コマンドを入力する場合、RMIレジストリのアドレスに環境変数を作成すると便利です。
例を実行するときに入力するコマンドを短くするために、RMIレジストリのサービスURLを環境変数
jndirmi
として設定します。次の例では、サービスURLはJNDI形式で指定されています。JNDI形式の詳細は、javax.management.remote.rmi
パッケージのAPIドキュメントを参照してください。ローカル・マシン以外のマシンで外部ディレクトリを実行する場合は、ローカル・ホストの代わりに、そのマシンのホスト名を指定する必要があります。$ jndirmi="rmi://localhost:9999"
外部LDAPレジストリ
JRMPトランスポートを実装するコネクタで使用するために、外部LDAPレジストリにRMIコネクタ・サーバー・スタブを登録するには:
-
LDAPサーバーを起動します。
使用するLDAPサーバーは選択できますが、LDAPディレクトリでJavaオブジェクトを表すためのスキーマがサーバーに認識されている必要があります。詳細は、関連するRequest For Comments (RFC)ドキュメントを参照してください。
-
ドメイン・コンポーネントのサフィックスを作成します。
次の例では、次のドメイン・コンポーネントのサフィックスの作成が必要になります。
dc=Test
サーバーの構成方法と、このサフィックスの作成方法の詳細は、使用しているLDAPサーバーに付属のドキュメントを参照してください。
-
便宜上、環境変数に次のLDAPパラメータを設定します。
これらの変数は、外部LDAPサーバーにRMIコネクタ・スタブを登録する検索サービスの例で、ServerクラスとClientクラスを起動するときに、入力するコマンドを短縮するために使用します。
-
LDAPサーバーを実行するマシンの名前(
ldap_host
)$ ldaphost=ldap_host
-
LDAPサーバーが実行されているポート(
ldap_port
)$ ldapport=ldap_port
-
LDAPコマンド名属性。次の例では「Directory Manager」
$ principal=”cn=Directory Manager”
-
LDAPサーバーで要求されるパスワードLDAPサーバーのパスワードを指定します。
$ credentials=your_ldap_password
-
LDAPサーバーのアドレス。この例では、LDAPサーバーのサービスURLはJNDI形式で指定され、変数jndildapで識別されます。
$ jndildap="ldap://$ldaphost:$ldapport"
-
これで、各種の検索サービスの例を実行する準備ができました。
Service Location Protocol (SLP)検索サービス
JMXテクノロジの仕様では、SLP検索サービスにRMIコネクタを登録する方法が指定されています。
この例は、JMX Remote APIコネクタ・クライアントで、SLP検索サービスに登録されたコネクタ・サーバーを検索し、接続する方法を示します。この例では、次の操作を実行します。
-
エージェント側:
-
MBeanサーバーを作成
-
SLP検索サービスのポインタを取得
-
コネクタ・サーバーを作成
-
SLP検索サービスにコネクタ・アドレスを登録
-
-
クライアント側:
-
SLP検索サービスのポインタを取得
-
SLP検索サービスに登録されたすべてのコネクタ・サーバーを検索
-
JMX Remote APIコネクタを作成
-
MBeanサーバーのMBeanに関する情報を取得
-
この例は、ユーザーがSLPテクノロジに習熟していることを前提に記載されています。この例に示すコードは、RFC 2614 (http://www.ietf.org/rfc/rfc2614.txtを参照)で定義されているOracleのSLPの実装に準拠しています。RFC 2614の第5項に準拠したSLPのバージョンを取得する必要があります。OpenSLP Java実装は、http://www.openslp.org/からダウンロードできます。
SLP検索例題クラスの分析
-
「Service Location Protocol (SLP)検索サービス」の項に含まれているソース・コードをコピーし、対応するファイルを
work_dir/jmx_examples/Lookup/slp
ディレクトリに作成します。このディレクトリ内のファイルには、次の情報が含まれます。README
Server.java
Client.java
-
*.java
ファイルをIDEまたはテキスト・エディタで開きます。
次のセクションでは、各クラスを分析し、例題で説明した操作をどのように実行するかについて説明します。
SLP検索の例題のServer.java
SLP検索サービスのServer.java
クラスは、その大きさにより、次の一連のコード(抜粋)で分析されます。
この例で使用されるSLPコードの詳細は、RFC 2614とSLPのAPIドキュメントを参照してください。
コード例12-1 SLP検索サービスの例クラスServer.java (抜粋1)
public class Server {
public final static int JMX_DEFAULT_LEASE = 300;
public final static String JMX_SCOPE = "DEFAULT";
private final MBeanServer mbs;
public Server() {
mbs = MBeanServerFactory.createMBeanServer();
}
[...]
コード例12-1では、デフォルトのSLPリースJMX_DEFAULT_LEASE
を、URLの登録期間に対応するデフォルト・リース300秒に設定し、MBeanサーバーmbs
の初期作成を示しています。
例には示されていないコードでは、次にSLPアドバタイザslpAdvertiser
とSLPサービスURL url
を定義します。slpAdvertiser
は、SLP検索サービスにサービスURLを登録する場合に使用します。SCOPE
とagentName
は、SLPに検索属性として登録されます。
コード例12-2 SLP検索サービスの例クラスServer.java (抜粋2)
[...]
public static void register(JMXServiceURL jmxUrl, String name)
throws ServiceLocationException {
ServiceURL serviceURL =
new ServiceURL(jmxUrl.toString(),
JMX_DEFAULT_LEASE);
debug("ServiceType is: " + serviceURL.getServiceType());
Vector attributes = new Vector();
Vector attrValues = new Vector();
attrValues.add(JMX_SCOPE);
ServiceLocationAttribute attr1 =
new ServiceLocationAttribute("SCOPE", attrValues);
attributes.add(attr1);
attrValues.removeAllElements();
attrValues.add(name);
ServiceLocationAttribute attr2 =
new ServiceLocationAttribute("AgentName", attrValues);
attributes.add(attr2);
final Advertiser slpAdvertiser =
ServiceLocationManager.getAdvertiser(Locale.US);
slpAdvertiser.register(serviceURL, attributes);
}
[...]
コード例12-2に、JMXコネクタ・サーバーのURLのSLP検索サービスへの登録を示します。
JMXサービスURL、jmxUrl
は、コネクタ・サーバーのアドレスであり、コネクタ・サーバーの起動時にJMXConnectorServer
のgetAddress()
メソッドを呼び出して取得します。
このとき、スコープやコネクタ・サーバー・アドレスが登録される際のエージェント名(name
)などのSLP検索の属性は、SLPクラスServiceLocationAttribute
により指定されます。AgentName
属性は必須ですが、ProtocolType
、AgentHost
、およびProperty
などのほかのオプション属性もSLP検索サービスに登録できます。
最後に、JMXコネクタ・サーバー・アドレスはAdvertiser
インタフェースのregister()
メソッドの呼出しによりSLPサービスに登録され、パラメータとしてserviceURL
とattributes
が渡されます。
コード例12-3 SLP検索サービスの例クラスServer.java (抜粋3)
[...]
public JMXConnectorServer rmi(String url) throws
IOException,
JMException,
NamingException,
ClassNotFoundException,
ServiceLocationException {
JMXServiceURL jurl = new JMXServiceURL(url);
final HashMap env = new HashMap();
// Environment map attributes
[...]
JMXConnectorServer rmis =
JMXConnectorServerFactory.newJMXConnectorServer(jurl, env, mbs);
final String agentName = System.getProperty("agent.name",
"DefaultAgent");
start(rmis, agentName);
return rmis;
}
[...]
コード例12-3に、RMIコネクタ・サーバーの作成を示します。JMXサービスURL jurl
は、コマンド行でServer
を起動するためのコマンドに含まれる文字列url
から構築されます。RMIコネクタ・サーバー、rmis
は、環境マップ
とアドレスjurl
で定義されるシステム・プロパティから作成されます。
次にコネクタ・サーバーが起動し、RMIコネクタ・サーバー・アドレスがagentName
の名前でSLP検索サービスに登録されます。
コード例12-4 SLP検索サービスの例クラスServer.java (抜粋4)
[...]
public void start(JMXConnectorServer server, String agentName)
throws IOException, ServiceLocationException {
server.start();
final JMXServiceURL address = server.getAddress();
register(address,agentName);
}
[...]
コード例12-4に、コネクタ・サーバーserver
の起動と、指定されたアドレスaddress
を使用したserver
のSLP検索サービスへの登録を示します。
SLP検索の例題のClient.java
SLP検索サービスのClient.java
クラスは、その大きさにより、次の一連のコード(抜粋)で分析されます。
コード例12-5 SLP検索サービスの例クラスClient.java (抜粋1)
public class Client {
public final static String JMX_SCOPE = "DEFAULT";
public static Locator getLocator() throws ServiceLocationException {
final Locator slpLocator =
ServiceLocationManager.getLocator(Locale.US);
return slpLocator;
}
public static List lookup(Locator slpLocator, String name)
throws IOException, ServiceLocationException {
final ArrayList list = new ArrayList();
Vector scopes = new Vector();
scopes.add(JMX_SCOPE);
String query =
"(&(AgentName=" + ((name!=null)?name:"*") + "))";
ServiceLocationEnumeration result =
slpLocator.findServices(new ServiceType("service:jmx"),
scopes, query);
while(result.hasMoreElements()) {
final ServiceURL surl = (ServiceURL) result.next();
JMXServiceURL jmxUrl = new JMXServiceURL(surl.toString());
try {
JMXConnector client =
JMXConnectorFactory.newJMXConnector(jmxUrl,null);
if (client != null) list.add(client);
} catch (IOException x ) {
[...]
}
}
}
return list;
}
コード例12-5では、SLPクラスServiceLocationManager
のgetLocator
メソッドを呼び出して、SLPサービスLocator
を取得します。次にClient
は、特定のエージェント名または特定のパターンに一致するエージェント名でSLPサービスに登録された、すべてのコネクタ・サーバーを取得します。Client
の起動時にエージェント名が指定されていない場合、すべてのエージェント名が考慮されます。
JMXテクノロジ・サービスURL、jmxUrl
は、SLPで取得されたエージェントごとに生成されます。各エージェントのSLPサービスURL、surl
はパラメータとしてJMXServiceURL
インスタンスに渡されます。URL ,jmxUrl
,は、JMXConnectorFactory
のnewJMXConnector()
メソッドに渡され、SLPサービスに登録される各エージェントに新しいコネクタ・クライアントclient
が作成されます。
取得されたコネクタ・クライアントは、配列リストlist
に保存されます。
コード例12-6 SLP検索サービスの例クラスClient.java (抜粋2)
public static void listMBeans(MBeanServerConnection server)
throws IOException {
final Set names = server.queryNames(null,null);
for (final Iterator i=names.iterator(); i.hasNext(); ) {
ObjectName name = (ObjectName)i.next();
System.out.println("Got MBean: "+name);
try {
MBeanInfo info =
server.getMBeanInfo((ObjectName)name);
MBeanAttributeInfo[] attrs = info.getAttributes();
if (attrs == null) continue;
for (int j=0; j<attrs.length; j++) {
try {
Object o =
server.getAttribute(name,attrs[j].getName());
System.out.println("\t\t" + attrs[j].getName() +
" = "+o);
} catch (Exception x) {
System.err.println("JmxClient failed to get " +
attrs[j].getName() + x);
x.printStackTrace(System.err);
}
}
}
コード例12-6では、SLPサービスに保存されたコネクタ・サーバー・アドレスを使って作成されたすべてのコネクタ・クライアントに、MBeanServerConnection
の参照が取得されています。すべてのMBeanとその属性のリストが取得されます。
コード例12-7 SLP検索サービスの例クラスClient.java (抜粋3)
public static void main(String[] args) {
try {
final String agentName = System.getProperty("agent.name");
final Locator slpLocator = getLocator();
List l = lookup(slpLocator,agentName);
int j = 1;
for (Iterator i=l.iterator();i.hasNext();j++) {
JMXConnector c1 = (JMXConnector) i.next();
if (c1 != null) {
try {
c1.connect(env);
} catch (IOException x) {
System.err.println ("Connection failed: " + x);
x.printStackTrace(System.err);
continue;
}
MBeanServerConnection conn =
c1.getMBeanServerConnection();
try {
listMBeans(conn);
} catch (IOException x) {
x.printStackTrace(System.err);
}
try {
c1.close();
} catch (IOException x) {
x.printStackTrace(System.err);
}
}
}
} catch (Exception x) {
x.printStackTrace(System.err);
}
}
コード例12-7では、agent.name
プロパティはSystem
クラスのgetProperty()
メソッドを呼び出して取得され、SLP検索サービスはLocator
のgetLocator()
メソッドを呼び出して検索されます。
agentName
の名前を持つすべてのエージェントが検索され、検出されたエージェントへの接続が設定されます。エージェントが指定されていない場合、すべてのエージェントが検索されます。Server
で作成されたMBeanサーバーへの接続が設定され、接続が切断される前に、接続内のすべてのMBeanがリストされます。
SLP検索サービスの例題の実行
この例では、SLP検索サービスを使用して、RMIのデフォルトのトランスポートであるJRMPを使用するRMIコネクタ・サーバーを検索する方法を示します。初期設定で説明したように、RMIコネクタ・スタブの登録には別の外部ディレクトリが使用されています。
トランスポートと外部ディレクトリの組合せは次のとおりです。
-
次のものを使用した、JRMPトランスポート上のRMIコネクタ
-
外部ディレクトリなし
-
RMIレジストリ
-
LDAPレジストリ
-
初期設定で実行した操作以外に、SLPを使用する例題を実行する前にこの例に固有の追加操作を実行する必要があります。この作業後、SLPをJMXテクノロジでサポートされる2つのコネクタとともに使用してコネクタの検索を開始できます。
ノート:
例題を実行する場合、作成されたエージェントの種類と、エージェントの作成に使用されたトランスポートを追跡するために、対応するセクションの文字列に等しい文字サフィックスがエージェント名に含まれています。たとえば、サーバーの起動のサブステップa 外部ディレクトリを使用しないJRMP上のRMIコネクタのエージェントは、example-server-a
と呼ばれます。
例題を実行するには、次に説明する一連のステップを実行します。
SLP検索サービスの例題の設定
次のステップは、この例題で実行できる様々なトランスポートのすべてで要求されます。
-
クラスのコンパイルおよび実行が容易になるように、追加で環境変数を定義します。初期設定で設定された共通の環境変数の他に、SLPサービスのパスを追加する必要があります。
使用しているプラットフォームに合せてSLPLIB
を設定します。 -
classp
環境変数を定義し、エクスポートします。この例では、SLPのJavaアーカイブ(JAR)ファイルを含むクラス・パスが必要です:$ classp=$SLPLIB/slp.jar
-
次のコマンドを入力して、例題の
Client
およびServer
クラスをコンパイルします。$ javac -d . -classpath $classp Server.java Client.java
-
使用しているSLPの実装に従ってSLPデーモンを起動します。
サーバーの起動
Server
の起動に使用するコマンドは、使用している外部ディレクトリによって異なります。Client
を起動する前に、Server
の次のインスタンスの1つ以上を起動します。Server
のインスタンスを、各種のトランスポートおよび外部レジストリを使用して、起動できます。
-
外部ディレクトリを使用しないJRMP上のRMIコネクタ: 次のコマンドを入力して
Server
を起動します。$ java -classpath .:$classp -Ddebug=true \ -Dagent.name=example-server-a \ -Durl ="service:jmx:rmi://" \ slp.Server &
コマンドの説明は次のとおりです。
debug
の値はtrueに設定され、Server
の実行時の画面出力をより詳細なものにします。- エージェントの名前は
example-server-a
です。 - サービスURLにより、RMIのデフォルト・トランスポートJRMP上で動作するRMIコネクタの選択が指定されます。
Server
が起動すると、RMIコネクタの作成、およびそのURLのSLPサービスへの登録を確認するメッセージが表示されます。 -
RMIレジストリを外部ディレクトリとして使用するJRMP上のRMIコネクタ: 次のコマンドを入力して
Server
を起動します。$ java -classpath .:$classp -Ddebug=true \ -Dagent.name=example-server-b \ -Durl="service:jmx:rmi:///jndi/${jndirmi}/server" \ slp.Server &
コマンドの説明は次のとおりです。
- 作成されるエージェントの名前は
example-server-b
です。 - サービスURLは、JRMP上のRMIとして選択されるコネクタを指定し、RMIコネクタ・スタブserverが保存される外部ディレクトリは、初期設定でjndirmiと特定したRMIレジストリです。
Server
が起動すると、RMIコネクタの作成、およびそのURLのSLPサービスへの登録を確認するメッセージが表示されます。 - 作成されるエージェントの名前は
-
LDAPを外部ディレクトリとして使用するJRMP上のRMIコネクタ: 次のコマンドを入力して
Server
を起動します。$ java -classpath .:$classp -Ddebug=true \ -Dagent.name=example-server-c \ -Durl="service:jmx:rmi:///jndi/${jndildap}/cn=x,dc=Test" \ -Djava.naming.security.principal="$principal" \ -Djava.naming.security.credentials="$credentials" \ slp.Server &
コマンドの説明は次のとおりです。
- 作成されるエージェントの名前は
example-server-c
です。 - サービスURLは、JRMP上のRMIとして選択されるコネクタを指定し、RMIコネクタ・スタブが保存される外部ディレクトリは、初期設定で
jndildap
と特定したLDAPサーバーです。 - スタブはLDAPサーバーの
Test
ドメイン・コンポーネントに登録されます。 - LDAPサーバーにアクセスするため、共通名の属性
principal
とパスワードcredentials
が与えられます。
Server
が起動すると、RMIコネクタの作成、およびそのURLがエージェント名example-server-c
でSLPサービスに登録されることの確認が表示されます。 - 作成されるエージェントの名前は
クライアントの起動
選択したトランスポートおよび外部ディレクトリを使用してServer
を起動した後、Client
を起動します。
$ java -classpath .:$classp -Ddebug=true \
-Djava.naming.security.principal="$principal" \
-Djava.naming.security.credentials="$credentials" \
slp.Client
Server
で作成され検索サービスに登録されたエージェントの検出を確認する出力が表示されます。また、エージェントに設定された接続の接続名と、接続の確認が表示されます。
特定のエージェントを検索するには、次のコマンドを入力します。
$ java -classpath .:$classp -Ddebug=true \
-Djava.naming.security.principal="$principal" \
-Djava.naming.security.credentials="$credentials" \
-Dagent.name="agentName" \
slp.Client
上に示したこのコマンドで、agentNameは検索するエージェントの名前です。*
を使用してエージェント名を部分的に指定することもできます。たとえば、文字xで始まるすべてのエージェント名を検索する場合は、x*
と指定します。
Java Naming and Directory Interface (JNDI)/LDAP検索サービス
JMXテクノロジでは、LDAPレジストリをバックエンドとして使用して、JNDI検索サービスにRMIコネクタを登録できます。この例では、次の操作を実行します。
-
エージェント側:
-
MBeanサーバーを作成
-
コネクタ・サーバーを作成
-
LDAPサーバーにコネクタ・アドレスを登録
-
-
クライアント側:
-
JNDI/LDAP検索サービスのポインタを取得
-
JNDI/LDAP検索サービスに登録されたすべてのコネクタ・サーバーを検索
-
JMX Remote APIコネクタを作成
-
MBeanサーバーのMBeanに関する情報を取得
-
例題クラスの分析
-
「Java Naming and Directory Interface (JNDI)/LDAP検索サービス」の項に含まれているソース・コードをコピーし、対応するファイルを
work_dir/jmx_examples/Lookup/ldap
ディレクトリに作成します。このディレクトリ内のファイルには、次の情報が含まれます。README
Server.java
Client.java
jmx-schema.txt
60jmx-schema.ldif
*.java
ファイルをIDEまたはテキスト・エディタで開きます。
次のセクションでは、JNDI/LDAP検索サービスの例題で使用される各クラスを分析し、各クラスが上記で説明した操作をどのように実行するかについて説明します。
JNDI/LDAP検索サービスの例題のServer.java
JNDI/LDAP検索サービスのServer.java
クラスは、その大きさにより、次の一連のコード(抜粋)で分析されます。
コード例12-12 JNDI/LDAP検索サービスの例Server.java (抜粋1)
[...]
public class Server {
public final static int JMX_DEFAULT_LEASE = 60;
private static boolean debug = false;
private final MBeanServer mbs;
public Server() {
mbs = MBeanServerFactory.createMBeanServer();
}
public static DirContext getRootContext() throws NamingException {
final Hashtable env = new Hashtable();
final String factory =
System.getProperty(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
final String ldapServerUrl =
System.getProperty(Context.PROVIDER_URL);
final String ldapUser =
System.getProperty(Context.SECURITY_PRINCIPAL,
"cn=Directory Manager");
final String ldapPasswd =
System.getProperty(Context.SECURITY_CREDENTIALS);
debug(Context.PROVIDER_URL + "=" + ldapServerUrl);
debug(Context.SECURITY_PRINCIPAL + "=" + ldapUser);
if (debug) {
System.out.print(Context.SECURITY_CREDENTIALS + "=");
final int len = (ldapPasswd==null)?0:ldapPasswd.length();
for (int i=0;i<len;i++) System.out.print("*");
System.out.println();
}
env.put(Context.INITIAL_CONTEXT_FACTORY,factory);
env.put(Context.SECURITY_PRINCIPAL, ldapUser);
if (ldapServerUrl != null)
env.put(Context.PROVIDER_URL, ldapServerUrl);
if (ldapPasswd != null)
env.put(Context.SECURITY_CREDENTIALS, ldapPasswd);
InitialContext root = new InitialLdapContext(env,null);
return (DirContext)(root.lookup(""));
}
[...]
コード例12-12では、MBeanサーバーmbs
の初期作成を示し、コネクタ・サーバーのアドレスが登録されるLDAPディレクトリ・ツリーのルート・コンテキストのポインタを取得します。プロバイダURL、LDAPユーザー名、セキュリティ資格などの関連するLDAPアクセス変数はすべてここに指定され、環境マップenv
に渡されます。環境マップenv
は、この後、InitialLdapContext
の呼出しにパラメータとして渡され、これによって初期LDAPコンテキストが取得されます。
コード例12-13 JNDI/LDAP検索サービスの例題クラスServer.java (抜粋2)
[...]
public static void register(DirContext root,
JMXServiceURL jmxUrl,
String name)
throws NamingException, IOException {
final String mydn = System.getProperty("dn","cn="+name);
debug("dn: " + mydn );
Object o = null;
try {
o = root.lookup(mydn);
} catch (NameNotFoundException n) {
Attributes attrs = new BasicAttributes();
Attribute objclass = new BasicAttribute("objectClass");
objclass.add("top");
objclass.add("javaContainer");
objclass.add("jmxConnector");
attrs.put(objclass);
attrs.put("jmxAgentName", name);
o = root.createSubcontext(mydn,attrs);
}
if (o == null) throw new NameNotFoundException();
final Attributes attrs = root.getAttributes(mydn);
final Attribute oc = attrs.get("objectClass");
if (!oc.contains("jmxConnector")) {
final String msg = "The supplied node [" + mydn +
"] does not contain the jmxConnector objectclass";
throw new NamingException(msg);
}
final Attributes newattrs = new BasicAttributes();
newattrs.put("jmxAgentName",name);
newattrs.put("jmxServiceURL",jmxUrl.toString());
newattrs.put("jmxAgentHost",InetAddress.getLocalHost().getHostName());
newattrs.put("jmxProtocolType",jmxUrl.getProtocol());
newattrs.put("jmxExpirationDate",
getExpirationDate(JMX_DEFAULT_LEASE));
root.modifyAttributes(mydn,DirContext.REPLACE_ATTRIBUTE,newattrs);
}
[...]
コード例12-13に、JMXコネクタ・サーバーのサービスURLのLDAPディレクトリへの登録を示します。URLが登録されるDNは、コマンド行でdn
システム・プロパティ(-Ddn=mydn
)を使用して渡すことができます。説明は、サーバーの起動に使用されるコマンドを参照してください。dn
システム・プロパティが指定されない場合、DN: cn=name
を使用できます。ここで、name
はagentName
です。ただし、これは必須ではありません。URLが登録される場所は問題ではありません。クライアント・コードで直接そのDNが使用されることはないためです。そのかわり、LDAP検索を実行して、補助的なjmxConnector ObjectClass
を含むノードが検索されます。重要なのは、各URLが個々のLDAPノードに登録されるという点です。これらのノードの命名方式は、LDAP管理者、この場合は各ユーザーに委ねられます。この例では、ノードcn=name
の作成が可能なルート・コンテキストを作成することでLDAPサーバーを構成し、このroot
コンテキストをContext.PROVIDER_URL
プロパティを通じてLDAPの初期コンテキストに渡しているものと仮定しています。コード例12-12 JNDI/LDAP検索サービスの例題のServer.java (抜粋1)を参照してください。
コード例12-13のコードでは、サーバーURLを登録するノードが存在するかどうかをチェックしています。存在しない場合は作成を試してください。親ノードが存在しない場合は失敗します。jmxConnector ObjectClass
は簡単な補助クラスであり、新しいコンテキストを作成する必要がある場合は、構造化クラスとしてjavaContainer ObjectClass
を使用します。これは完全なオプションです。jmxConnector
補助クラスを追加できる構造化クラスは何でもかまいません。コードは次にサーバーを登録するノードに、jmxConnector
補助クラスがすでに使用されているかどうかをチェックします。使用されていない場合は、例外がスローされます。
この時点で、URLを登録するノードが存在し、適切なjmxConnector
補助クラスが指定されていることが確実になります。必要なのは、LDAP検索のためのJMX Remote APIで定義された属性の値を置き換えることのみです。jmx-schema.txtを参照してください。
-
jmxServiceUrl
: サーバーの起動後にserver.getAddress()により取得されたString
形式のサーバーURLが含まれる -
jmxAgentName
: JMXエージェント名が含まれる -
jmxProtocolType
:jmxUrl.getProtocolType()
で返されるJMXプロトコル型が含まれる -
jmxAgentHost
: エージェント・ホストの名前が含まれる -
jmxExpirationDate
: URLの有効期日が含まれる
例12-14 JNDI/LDAP検索サービスの例題クラスServer.java (抜粋3)
[...]
public JMXConnectorServer rmi(String url)
throws IOException, JMException,
NamingException, ClassNotFoundException {
JMXServiceURL jurl = new JMXServiceURL(url);
final HashMap env = new HashMap();
// Prepare the environment Map
[...]
JMXConnectorServer rmis =
JMXConnectorServerFactory.newJMXConnectorServer(jurl, env, mbs)
final String agentName = System.getProperty("agent.name",
"DefaultAgent");
start(rmis,env,agentName);
return rmis;
}
[...]
コード例12-14では、JMXサービスURL jurl
と適切なLDAPプロパティが環境マップenv
に渡され、rmis
という新しいRMIコネクタ・サーバーが作成されています。コネクタ・サーバーrmis
が、JMXConnectorServer.start()
の呼出しにより起動し、LDAPサーバーに登録されます。
例12-15 JNDI/LDAP検索サービスの例題クラスServer.java (抜粋4)
[...]
public void start(JMXConnectorServer server, Map env, String agentName)
throws IOException, NamingException {server.start()
final DirContext root=getRootContext();
final JMXServiceURL address = server.getAddress();register(root,address,agentName)
}
[...]
コード例12-15では、JMXコネクタ・サーバーserverを作成し、LDAPサーバーのルート・ディレクトリrootへのポインタを取得し、addressという名前のサーバーのURLを作成します。ルート・ディレクトリ、URL、およびエージェント名は、パラメータとしてregister()
に渡され、LDAPサーバーに登録されます。
JNDI/LDAP検索サービスの例題のClient.java
JNDI/LDAP検索サービスの例題クラスClient.java
を次のコード例に示します。
コード例12-16 JNDI/LDAP検索サービスの例題クラスClient.java
[...]
public class Client {
private static boolean debug = false;
public static void listAttributes(DirContext root, String dn)
throws NamingException {
final Attributes attrs = root.getAttributes(dn);
System.out.println("dn: " + dn);
System.out.println("attributes: " + attrs);
}
public static DirContext getRootContext() throws NamingException {
final Hashtable env = new Hashtable();
// Prepare environment map
[...]
InitialContext root = new InitialLdapContext(env,null);
return (DirContext)(root.lookup(""));
}
// Confirm URL has not expired
[...]
public static List lookup(DirContext root, String protocolType,
String name)
throws IOException, NamingException {
final ArrayList list = new ArrayList();
String queryProtocol =
(protocolType==null)?"":"(jmxProtocolType="+protocolType+")";
String query =
"(&" + "(objectClass=jmxConnector) " +
"(jmxServiceURL=*) " +
queryProtocol +
"(jmxAgentName=" + ((name!=null)?name:"*") + "))";
SearchControls ctrls = new SearchControls();
ctrls.setSearchScope(SearchControls.SUBTREE_SCOPE);
final NamingEnumeration results = root.search("", query, ctrls);
while (results.hasMore()) {
final SearchResult r = (SearchResult) results.nextElement();
debug("Found node: " + r.getName());
final Attributes attrs = r.getAttributes();
final Attribute attr = attrs.get("jmxServiceURL");
if (attr == null) continue;
final Attribute exp = attrs.get("jmxExpirationDate");
if ((exp != null) && hasExpired((String)exp.get())) {
System.out.print(r.getName() + ": ");
System.out.println("URL expired since: " + exp.get());
continue;}
final String urlStr = (String)attr.get();
if (urlStr.length() == 0) continue;
debug("Found URL: "+ urlStr);
final JMXServiceURL url = new JMXServiceURL(urlStr);
final JMXConnector conn =
JMXConnectorFactory.newJMXConnector(url,null);
list.add(conn);
if (debug) listAttributes(root,r.getName());
}
return list;
}
}
このコード例では、Client
はまずLDAPディレクトリDirContext
のポインタroot
を返し、次にこのディレクトリでjmxConnector
型のオブジェクト・クラスを検索します。jmxConnector
オブジェクト・クラスのサービスURLと有効期日属性、attr
とexp
が取得され、exp
のチェックによりURLが有効期限内であることが確認され、JMXConnectorFactory
の呼出しにより新しいコネクタconn
が作成されます。コネクタconn
がコネクタのリストに追加され、MBeanサーバー内のServer
で作成されたMBeanへのアクセスに使用されます。
JNDI/LDAP検索サービスの例題の実行
この例では、JNDI/LDAP検索サービスを使用して、デフォルトのJRMPトランスポートおよびIIOPトランスポートを実装するRMIコネクタ・サーバーを検索する方法を示します。その他、初期設定で説明したように、RMIコネクタ・スタブの登録には別の外部ディレクトリが使用されています。
ここに示すトランスポートと外部ディレクトリの組合せは次のとおりです。
-
次のものを使用した、JRMPトランスポート上のRMIコネクタ
-
外部ディレクトリなし
-
RMIレジストリ
-
LDAPレジストリ
-
JNDI/LDAP検索サービスを使用する例題を実行する前に、初期設定の項の操作と、この例に固有の操作を完了する必要があります。JNDI/LDAPネットワーク・テクノロジを、JMXテクノロジでサポートされる2つのコネクタとともに使用してコネクタの検索を開始できます
ノート:
例題を実行する場合、作成されたエージェントの種類と、エージェントの作成に使用されたトランスポートを追跡するために、対応するセクションの文字列に等しい文字サフィックスがエージェント名に含まれています。たとえば、サーバーの起動の外部ディレクトリを使用しないJRMP上のRMIコネクタのエージェントは、example-server-a
という名前です。
例題を実行するには、次に説明する一連のステップを実行します。
JNDI/LDAP検索サービスの例題の設定
次のステップは、この例題で実行できる各種のコネクタ/トランスポートのすべての組合せで要求されます。
ノート:
使用しているLDAPサーバーのタイプに応じて次のステップを完了します。
-
初期設定で起動したLDAPサーバーを停止します。
-
JMXテクノロジのスキーマを、使用しているLDAPサーバーのschemaディレクトリにコピーします。
-
LDAPサーバーを再起動します
- ServerがそのサービスURLを登録するルートを定義します。初期設定で作成したドメイン・コンポーネント・サフィックス
dc=Test
へのパスをServerに指定する必要があります。$ provider="ldap://$ldaphost:$ldapport/dc=Test"
-
次のコマンドを入力して、例題の
Client
およびServer
クラスをコンパイルします。$ javac -d . -classpath $classp Server.java Client.java
サーバーの起動
Server
の起動に使用するコマンドは、使用している外部ディレクトリによって異なります。Client
を起動する前に、各種のトランスポートおよび外部レジストリを使用して、Server
の次のインスタンスの1つまたは複数を起動できます。
ここに示すトランスポートと外部ディレクトリの組合せは次のとおりです。
-
外部ディレクトリを使用しないJRMP上のRMIコネクタ: 次のコマンドを入力して
Server
を起動します。$ java -classpath . -Ddebug=true \ -Dagent.name=example-server-a \ -Durl="service:jmx:rmi://" \ -Djava.naming.provider.url="$provider" \ -Djava.naming.security.principal="$principal" \ -Djava.naming.security.credentials="$credentials" \ jndi.Server &
コマンドの説明は次のとおりです。
-
debug
,はtrueに設定され、Server
の実行時の画面出力をより詳細なものにします。 -
作成されるエージェントの名前は
example-server-a
です。 -
エージェントが登録されるドメイン・コンポーネントのサフィックスを示すURL、
provider
が与えられます。 -
LDAPサーバーにアクセスするため、共通名の属性
principal
とパスワードcredentials
が与えられます。 -
サービスURLにより、RMIのデフォルトのJRMPトランスポート上で動作するRMIコネクタの選択が指定されます
Server
が起動すると、RMIコネクタの作成、およびそのURLのJNDI/LDAP検索サービスへの登録を確認するメッセージが表示されます。 -
-
RMIレジストリを外部ディレクトリとして使用するJRMP上のRMIコネクタ: 次のコマンドを入力して
Server
を起動します。$ java -classpath . -Ddebug=true \ -Dagent.name=example-server-b \ -Durl="service:jmx:rmi:///jndi/${jndirmi}/server" \ -Djava.naming.provider.url="$provider" \ -Djava.naming.security.principal="$principal" \ -Djava.naming.security.credentials="$credentials" \ jndi.Server &
コマンドの説明は次のとおりです。
-
作成されるエージェントの名前は
example-server-b
です。 -
エージェントが登録されるドメイン・コンポーネントのサフィックスを示すURL、
provider
が与えられます。 -
LDAPサーバーにアクセスするため、共通名の属性
principal
とパスワードcredentials
が与えられます。 -
サービスURLは、JRMP上のRMIとして選択されるコネクタを指定し、RMIコネクタ・スタブserverが保存される外部ディレクトリは、初期設定で
jndirmi
と特定したRMIレジストリです。
Server
が起動すると、RMIコネクタの作成、およびそのURLのJNDI/LDAP検索サービスへの登録を確認するメッセージが表示されます。 -
-
LDAPを外部ディレクトリとして使用するJRMP上のRMIコネクタ: 次のコマンドを入力して
Server
を起動します。$ java -classpath . -Ddebug=true \ -Dagent.name=example-server-c \ -Durl="service:jmx:rmi:///jndi/${jndildap}/cn=x,dc=Test" \ -Djava.naming.provider.url="$provider" \ -Djava.naming.security.principal="$principal" \ -Djava.naming.security.credentials="$credentials" \ jndi.Server &
コマンドの説明は次のとおりです。
-
作成されるエージェントの名前は
example-server-c
です。 -
エージェントが登録されるドメイン・コンポーネントのサフィックスを示すURL、
provider
が与えられます。 -
LDAPサーバーにアクセスするため、共通名の属性
principal
とパスワードcredentials
が与えられます。 -
サービスURLは、RMI over JRMPとして選択されるコネクタを指定し、RMIコネクタ・スタブserverが保存される外部ディレクトリは、初期設定で
jndildap
と特定したRMIレジストリです。
Server
が起動すると、RMIコネクタの作成、およびそのURLがエージェント名example-server-c
でJNDI/LDAP検索サービスに登録されることの確認が表示されます。 -
クライアントの起動
選択したトランスポートおよび外部ディレクトリを使用してServerを起動した後、次のコマンドを入力してClientを起動します。
$ java -classpath . -Ddebug=true \
-Djava.naming.provider.url="$provider" \
-Djava.naming.security.principal="$principal" \
-Djava.naming.security.credentials="$credentials" \
jndi.Client
Server
で作成され検索サービスに登録されたエージェントの検出を確認する出力が表示されます。また、エージェントに設定された接続の接続名と、接続の確認が表示されます。
特定のエージェントを検索するには、次のコマンドを入力します。
$ java -classpath . -Ddebug=true \
-Djava.naming.provider.url="$provider" \
-Djava.naming.security.principal="$principal" \
-Djava.naming.security.credentials="$credentials" \
-Dagent.name=agentName \
jndi.Client
前述のコマンドで、agentName
は検索するエージェントの名前です。また、*;を使用してエージェント名を部分的に指定することもできます。たとえば、文字xで始まるすべてのエージェント名を検索する場合は、 x*
と指定します。