12 検索サービス

検索サービスを使用すると、JMXテクノロジのクライアントは、検索サービスに登録されているコネクタ・サーバーを検索し、接続することができます。

JMX仕様では、次の各項で説明する既存の検索テクノロジを使用した、検索サービスの3つのバインディングを定義しています:

初期設定

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コネクタ・サーバー・スタブを登録するには、次の手順を実行します。

  1. ローカル・ホストのポート9999でRMIレジストリを起動します。

    JMXコネクタで説明されているように、RMIレジストリはJRMPトランスポートを実装するRMIコネクタ用のRMIコネクタ・スタブを格納するために使用されます。

    $ rmiregistry 9999 &
  2. コマンドを入力する場合、RMIレジストリのアドレスに環境変数を作成すると便利です。

    例を実行するときに入力するコマンドを短くするために、RMIレジストリのサービスURLを環境変数jndirmiとして設定します。次の例では、サービスURLはJNDI形式で指定されています。JNDI形式の詳細は、javax.management.remote.rmiパッケージのAPIドキュメントを参照してください。ローカル・マシン以外のマシンで外部ディレクトリを実行する場合は、ローカル・ホストの代わりに、そのマシンのホスト名を指定する必要があります。

    $ jndirmi="rmi://localhost:9999"

外部LDAPレジストリ

JRMPトランスポートを実装するコネクタで使用するために、外部LDAPレジストリにRMIコネクタ・サーバー・スタブを登録するには:

  1. LDAPサーバーを起動します。

    使用するLDAPサーバーは選択できますが、LDAPディレクトリでJavaオブジェクトを表すためのスキーマがサーバーに認識されている必要があります。詳細は、関連するRequest For Comments (RFC)ドキュメントを参照してください。

    http://www.ietf.org/rfc/rfc2713.txt

  2. ドメイン・コンポーネントのサフィックスを作成します。

    次の例では、次のドメイン・コンポーネントのサフィックスの作成が必要になります。

    dc=Test

    サーバーの構成方法と、このサフィックスの作成方法の詳細は、使用しているLDAPサーバーに付属のドキュメントを参照してください。

  3. 便宜上、環境変数に次の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検索例題クラスの分析

  1. 「Service Location Protocol (SLP)検索サービス」の項に含まれているソース・コードをコピーし、対応するファイルをwork_dir/jmx_examples/Lookup/slpディレクトリに作成します。このディレクトリ内のファイルには、次の情報が含まれます。

    • README
    • Server.java
    • Client.java
  2. *.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を登録する場合に使用します。SCOPEagentNameは、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は、コネクタ・サーバーのアドレスであり、コネクタ・サーバーの起動時にJMXConnectorServergetAddress()メソッドを呼び出して取得します。

このとき、スコープやコネクタ・サーバー・アドレスが登録される際のエージェント名(name)などのSLP検索の属性は、SLPクラスServiceLocationAttributeにより指定されます。AgentName属性は必須ですが、ProtocolTypeAgentHost、およびPropertyなどのほかのオプション属性もSLP検索サービスに登録できます。

最後に、JMXコネクタ・サーバー・アドレスはAdvertiserインタフェースのregister()メソッドの呼出しによりSLPサービスに登録され、パラメータとしてserviceURLattributesが渡されます。

コード例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クラスServiceLocationManagergetLocatorメソッドを呼び出して、SLPサービスLocatorを取得します。次にClientは、特定のエージェント名または特定のパターンに一致するエージェント名でSLPサービスに登録された、すべてのコネクタ・サーバーを取得します。Clientの起動時にエージェント名が指定されていない場合、すべてのエージェント名が考慮されます。

JMXテクノロジ・サービスURL、jmxUrlは、SLPで取得されたエージェントごとに生成されます。各エージェントのSLPサービスURL、surlはパラメータとしてJMXServiceURLインスタンスに渡されます。URL ,jmxUrl,は、JMXConnectorFactorynewJMXConnector()メソッドに渡され、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検索サービスはLocatorgetLocator()メソッドを呼び出して検索されます。

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検索サービスの例題の設定

次のステップは、この例題で実行できる様々なトランスポートのすべてで要求されます。

  1. クラスのコンパイルおよび実行が容易になるように、追加で環境変数を定義します。初期設定で設定された共通の環境変数の他に、SLPサービスのパスを追加する必要があります。

    使用しているプラットフォームに合せてSLPLIBを設定します。
  2. classp環境変数を定義し、エクスポートします。この例では、SLPのJavaアーカイブ(JAR)ファイルを含むクラス・パスが必要です:

    $ classp=$SLPLIB/slp.jar
  3. 次のコマンドを入力して、例題のClientおよびServerクラスをコンパイルします。

    $ javac -d . -classpath $classp Server.java Client.java
  4. 使用している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に関する情報を取得

例題クラスの分析

  1. 「Java Naming and Directory Interface (JNDI)/LDAP検索サービス」の項に含まれているソース・コードをコピーし、対応するファイルをwork_dir/jmx_examples/Lookup/ldapディレクトリに作成します。このディレクトリ内のファイルには、次の情報が含まれます。

    • README
    • Server.java
    • Client.java
    • jmx-schema.txt
    • 60jmx-schema.ldif
  2. *.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を使用できます。ここで、nameagentNameです。ただし、これは必須ではありません。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と有効期日属性、attrexpが取得され、expのチェックによりURLが有効期限内であることが確認され、JMXConnectorFactoryの呼出しにより新しいコネクタconnが作成されます。コネクタconnがコネクタのリストに追加され、MBeanサーバー内のServerで作成されたMBeanへのアクセスに使用されます。

jmx-schema.txt

jmx-schema.txtファイルは、JMX Remote API用のLDAPスキーマ・ファイルです。

60jmx-schema.ldif

60jmx-schema.ldifファイルは、JMXテクノロジのLDAPスキーマ・ファイルjmx-schema.txtに対応するldifファイルです。

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サーバーのタイプに応じて次のステップを完了します。

  1. 初期設定で起動したLDAPサーバーを停止します。

  2. JMXテクノロジのスキーマを、使用しているLDAPサーバーのschemaディレクトリにコピーします。

  3. LDAPサーバーを再起動します

  4. ServerがそのサービスURLを登録するルートを定義します。初期設定で作成したドメイン・コンポーネント・サフィックスdc=TestへのパスをServerに指定する必要があります。
    $ provider="ldap://$ldaphost:$ldapport/dc=Test"
  5. 次のコマンドを入力して、例題の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*と指定します。