このマニュアルは、Java Platform, Enterprise Edition (Java EE)を使用してアプリケーションの設計、開発、構成、および管理を行い、エンタープライズ内で複数のネーミングおよびディレクトリ・サービスに対し、統一されたインタフェースを提供するためにJNDI APIを使用する、アプリケーション開発者に向けて書かれています。読者には、JNDIおよびJavaプログラミング言語に関する知識があることが前提となっています。
次の各項では、このマニュアルの内容と構成について説明します。
概要とロードマップは、このガイドの構成を説明します。
WebLogic JNDIの理解,では、WebLogic ServerにおけるJava Naming and Directory Interface (JNDI)実装の概要を示します。
WebLogic JNDIでは、WebLogic JNDIによるプログラミングについて説明します。
JNDIの詳細は、次のドキュメントを参照してください。
Fusion Middlewareエラー・メッセージ・リファレンスには、JNDIサブシステム・メッセージを含むWebLogic Serverエラー・メッセージの一覧があります。
Oracle WebLogic Serverクラスタの管理のクラスタでの通信では、クラスタ全体のJNDIツリーの情報を提供します。
Oracle WebLogic Server管理コンソール・オンライン・ヘルプの各項では、JNDIバインド・ノード、ルート・コンテンツ・ノードまたはコンテキスト・ノードのセキュリティ・ロールおよびポリシーを追加または変更する方法について説明しています。
『WebLogic Server Multitenantの使用』の「JNDIの構成とプログラミング」。
このマニュアルに加えて、Avitek Medical Recordsアプリケーション(MedRec)サンプルのコンテキスト内で、ソフトウェア開発者向けのサンプル(JNDIサンプル・コードを含む)が用意されています。
MedRecはWebLogic Serverに付属したエンドツーエンドのサンプルJava EEアプリケーションであり、一元的で独立した医療記録管理システムをシミュレートします。MedRecアプリケーションには、患者、医師、および管理者に対して、様々なクライアントを使用して患者のデータを管理するフレームワークが用意されています。
MedRecでは、WebLogic ServerとJava EEの機能の実例を挙げ、推奨されるベスト・プラクティスについて重点的に説明します。MedRecは、WebLogic Serverインストールとともにオプションでインストールできます。MedRecをORACLE_HOME
\user_projects\domains\medrec
ディレクトリから起動できます。この場合、ORACLE_HOME
はOracle WebLogic ServerをインストールしたときにOracle Homeとして指定したディレクトリです。詳細は、Oracle WebLogic Serverの理解のサンプル・アプリケーションとコード例を参照してください。
以下の節では、WebLogic ServerのJava Naming and Directory Interface (JNDI)実装の概要について説明します。
アプリケーションでは、ネーミング・サービスを使用してネットワーク上のデータ・ソース、EJB、JMS、メール・セッションなどのオブジェクトを検索します。ネーミング・サービスは、オブジェクトに名前を関連付けたり、指定した名前に基づいてオブジェクトを検索したりします。(RMIレジストリは、ネーミング・サービスの1つです。)
JNDIは、LDAP (Lightweight Directory Access Protocol)やDNS (Domain Name System)など、既存の様々なネーミング・サービスに対する共通インタフェースを提供します。これらのネーミング・サービスは、バインディングのセットを管理します。名前はバインディングによってオブジェクトに関連付けられるので、オブジェクトを名前でルックアップできるようになります。したがって、JNDIを使用すると、分散アプリケーションのコンポーネントが互いを検索できます。
http://docs.oracle.com/javase/7/docs/technotes/guides/jndi/reference.html
のJNDI APIは、特定のネーミング・サービスまたはディレクトリ・サービスの実装とは無関係に定義されています。それは、様々な新規または既存のサービスにアクセスする複数の方法の使用をサポートします。このサポートでは、標準サービス・プロバイダ・インタフェース(SPI)規約を使用してJNDIフレームワークに任意のサービス・プロバイダ実装をプラグインできます。
WebLogic ServerのJNDI実装では、以下のようなメソッドが用意されています。
クライアントにWebLogic Serverネーミング・サービスへのアクセスを提供するメソッド
オブジェクトをWebLogicネームスペースで使用可能にするメソッド
オブジェクトをWebLogicネームスペースから取り出すメソッド
各WebLogic Serverクラスタは、レプリケートされたクラスタ全体のJNDIツリーによってサポートされています。このツリーから、レプリケートされたり、固定されたりしているRMIオブジェクトおよびEJBオブジェクトにアクセスできます。クラスタを表すJNDIツリーは、クライアントからは単一のグローバル・ツリーのように見えますが、クラスタ全体のサービスを含むツリーは、実際には、クラスタ内の各WebLogic Serverインスタンス間でレプリケートされたものです。詳細は、「クラスタ環境でのWebLogic JNDIの使い方」を参照してください
他のWebLogicサービスは、WebLogic Server JNDIに統合されたネーミング・サービスを使用できます。たとえば、WebLogic RMIでは、標準RMIメソッドとJNDIメソッドの両方を使用して、リモート・オブジェクトにバインドし、アクセスできます。
JNDIの標準Javaインタフェースに加えて、WebLogic Serverには、標準JNDIインタフェースを使用する独自の実装であるweblogic.jndi.WLInitialContextFactory
もあります。
このクラスを直接インスタンス化する必要はありません。かわりに、標準のjavax.naming.InitialContext
クラスを使用して、適切なハッシュ表プロパティを設定できます(初期コンテキストへのJNDI環境プロパティの設定を参照)。すべての対話は、javax.naming.Context
インタフェースを経由して行われます(JNDI Javadocを参照)。
クライアント接続用にWebLogic JNDI APIを使用する手順については、「WebLogic JNDI」を参照してください
以下の節では、WebLogic JNDIを使用するプログラミングについて説明します。
WebLogic Server JNDIサービス・プロバイダ・インタフェース(SPI)には、リモートJavaクライアントからWebLogic Serverへの接続を可能にするInitialContext
実装が用意されています。クライアントは、特定のWebLogic Serverデプロイメントを識別する標準のJNDI環境プロパティと、WebLogic Serverへのログインに関連する接続プロパティを指定できます。
JavaクライアントがWebLogic Serverと対話するには、リモート・オブジェクトへの参照を取得し、そのオブジェクトで操作を呼び出すことができなければなりません。そのためには、クライアント・アプリケーション・コードで次の手順を実行する必要があります。
InitialContext
にJNDI環境プロパティを設定します。InitialContext
を作成します。以降の節では、特定のWebLogic Serverインスタンスに接続するためのJNDIクライアントの操作について説明します。WebLogic ServerクラスタでのJNDIの使用については、「クラスタ環境でのWebLogic JNDIの使用」を参照してください
JNDIを使用してWebLogic Server環境内のオブジェクトにアクセスする前に、WebLogic ServerのJNDIツリーにそのオブジェクトをロードしておく必要があります。
Javaクライアント・アプリケーションで実行する必要がある最初のタスクは、環境プロパティの作成です。InitialContext
ファクトリは、各種のプロパティを使用して、特定の環境に合ったInitialContext
をカスタマイズします。これらのプロパティは、ハッシュ表、またはWebLogic環境オブジェクトのset()
メソッドを使用して設定します。名前と値の組合せで指定されるこれらのプロパティによって、WLInitialContextFactory
でのコンテキストの作成方法が決まります。
以下のプロパティが、InitialContext
のカスタマイズに使用されます。
Context.PROVIDER_URL
- ネーム・サービスを提供するWebLogic ServerインスタンスのURLを指定します。デフォルトはt3://localhost:7001
です。
Context.SECURITY_PRINCIPAL
- ユーザー(つまり、WebLogic Serverセキュリティ・レルムで定義されているユーザー)の認証用のIDを指定します。スレッドがすでにWebLogic Serverユーザーに関連付けられていないかぎり、プロパティのデフォルト値はguest
になります。詳細は、「WebLogicユーザーとセキュリティ・コンテキストの関連付け」を参照してください
Context.SECURITY_CREDENTIALS
- このContext.SECURITY_CREDENTIALS
プロパティを使用して、Context.SECURITY_PRINCIPAL
プロパティで定義されているユーザーのパスワード、またはweblogic.security.acl.UserInfo
インタフェースを実装するオブジェクトのいずれかを指定します。このプロパティにUserInfo
オブジェクトを渡すと、Context.PROVIDER_URL
プロパティは無視されます。スレッドがすでにユーザーに関連付けられていないかぎり、プロパティのデフォルト値はguest
になります。詳細は、「WebLogicユーザーとセキュリティ・コンテキストの関連付け」を参照してください
クライアントまたはサーバーのどちらでも、同じプロパティを使用できます。サーバー側オブジェクトでプロパティを定義する場合は、ローカル・コンテキストが使用されます。クライアントまたは別のWebLogic Serverインスタンスでプロパティを定義する場合は、Context.PROVIDER_URL
プロパティで指定されたWebLogic Serverインスタンスで実行中のリモート・コンテキストに委託されます。サーバーにバインドされたリモート・オブジェクトにはpeerGone
のサービスが提供されないため、クライアントに障害が発生すると、これらのオブジェクトはアクセス不能になります。
コンテキスト作成後は変更できないプロパティもあります。プロバイダのURL、ユーザーの資格、ファクトリなどのプロパティです。AddToEnvironment
を使用すると、コンテキスト作成後に他のプロパティを変更できます。
例1-1は、Context.INITIAL_CONTEXT_FACTORY
プロパティとContext.PROVIDER_URL
プロパティを使用してコンテキストを取得する方法を示しています。
例1-1 コンテキストの取得
Context ctx = null; Hashtable ht = new Hashtable(); ht.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory"); ht.put(Context.PROVIDER_URL, "t3://localhost:7001"); try { ctx = new InitialContext(ht); // Use the context in your program } catch (NamingException e) { // a failure occurred } finally { try {ctx.close();} catch (Exception e) { // a failure occurred } }
この他にも、オブジェクトをクラスタ全体のJNDIツリーにバインドする方法を指定するためのWebLogic固有のプロパティがあります。バインドは、クラスタ内にある各サーバーのJNDIツリー間でレプリケートされる場合とされない場合があります。これは、これらのプロパティの設定方法によるものです。このようなプロパティは、weblogic.jndi.WLContext
クラス内の定数によって示されます。JNDIに関連するクラスタリングの問題の詳細は、「クラスタ環境でのクライアントからのWebLogic JNDIの使い方」を参照してください
ハッシュ表を使用して、コンテキストを作成できます。ハッシュ表には、「初期コンテキストへのJNDI環境プロパティの設定」で説明したプロパティを指定しておきます
まず、ハッシュ表をInitialContext
のコンストラクタに渡します。java.naming.factory.initial
プロパティを使用して、InitialContext
の作成方法を指定します。WebLogic JNDIを使用するには、常にjava.naming.factory.initial
プロパティをweblogic.jndi.WLInitialContextFactory
に設定する必要があります。この設定値は、 コンテキストを実際に作成するファクトリを示します。
weblogic.jndi.environment
によって実装されるWebLogic Environmentオブジェクトを使用して、コンテキストを作成することもできます。EnvironmentオブジェクトはWebLogic固有のものですが、以下のような利点があります。
一連のデフォルト値が用意されているので、記述するコードが少なくて済みます。
コンパイル時のタイプ保証を提供する便利なset()
メソッドが用意されています。タイプ保証のset()
メソッドを使用すると、コードの記述とデバッグの両方にかかる時間を短縮できます。
WebLogic環境オブジェクトには、次のデフォルト値が用意されています。
InitialContext
ファクトリを指定しない場合は、デフォルト値としてWLInitialContextFactory
が使用されます。
Context.SECURITY_PRINCIPAL
プロパティおよびContext.CREDENTIALS
プロパティでユーザーおよびパスワードを指定しない場合は、スレッドがすでにユーザーに関連付けられていないかぎり、ユーザーとパスワードのデフォルト値として、guest
が使用されます。
Context.PROVIDER_URL
プロパティを指定しない場合は、デフォルト値としてt3://localhost:7001
が使用されます。
これらのデフォルト値を使用してInitialContext
を作成する場合のコードは、次のようになります。
Environment env = new Environment(); Context ctx = env.getInitialContext();
たとえば、クライアントのクラスタ・アクセスのために、1つのWebLogic Serverだけにドメイン・ネーム・サービス(DNS)名を設定する場合のコードは、以下のようになります。
Environment env = new Environment(); env.setProviderURL("t3://myweblogiccluster.com:7001"); Context ctx = env.getInitialContext();
注意:
新しいJNDI Environmentオブジェクトを作成するたびに、新しいセキュリティ・スコープが作成されます。このセキュリティ・スコープは、context.close()
メソッドで終了します。environment.getInitialContext()
メソッドは、IIOPプロトコルでは正しく動作しません。
例1-2は、JNDI環境オブジェクトを使用してセキュリティ・コンテキストを作成する方法を示しています。
例1-2 JND環境オブジェクトを使用するセキュリティ・コンテキストの作成
weblogic.jndi.Environment environment = new weblogic.jndi.Environment(); environment.setInitialContextFactory( weblogic.jndi.Environment.DEFAULT_INITIAL_CONTEXT_FACTORY); environment.setProviderURL("t3://bross:4441"); environment.setSecurityPrincipal("guest"); environment.setSecurityCrendentials("guest"); InitialContext ctx = environment.getInitialContext();
Enterprise JavaBeans (EJB)オブジェクトやRemote Method Invocation (RMI)オブジェクトのような、WebLogic ServerのJava仮想マシン(JVM)でインスタンス化されるオブジェクトからコンテキストを作成することが必要になる場合もあります。サーバー側オブジェクトを使用する場合は、Context.PROVIDER_URL
プロパティを指定する必要はありません。特定のユーザーとして署名し、ログオンする場合にのみ、ユーザー名とパスワードが必要になります。
サーバー側オブジェクト内からコンテキストを作成するには、まず次のように、新しいInitialContext
を作成する必要があります。
Context ctx = new InitialContext();
ファクトリやプロバイダのURLを指定する必要はありません。デフォルトで、コンテキストはContextとして作成され、ローカルのネーミング・サービスに接続されます。
ユーザー名とパスワードでJNDIコンテキストを作成する場合、ユーザーをスレッドに関連付けます。コンテキストが作成されると、ユーザーはスレッドに関連付けられているコンテキスト・スタックにプッシュされます。スレッドで新しいコンテキストを開始する場合は、最初のコンテキストを閉じて、最初のユーザーとスレッドとの関連付けを解除しておく必要があります。このようにしない場合、新しいコンテキストが作成されるたびにユーザーがスタックにプッシュされます。このため、リソースが効率的に使用されず、ctx.lookup()
呼出しによって誤ったユーザーが返される場合があります。次の手順で、このシナリオについて説明します。
user2
用にctx2
という2番目のコンテキストを(ユーザー名と資格を使用して)作成します。この時点で、スレッドには複数のユーザーが関連付けられます。User2
はスタックの一番上に存在し、user1
はその下に存在します。このため、user2
が現在のユーザーとなります。
ctx1.lookup("abc")
呼出しを行った場合、user2
がスタックの一番上に存在するため、user1
ではなくuser2
がIDとして使用されます。目的の結果を得る、つまり、ctx1.lookup("abc")
呼出しがuser1
として実行されるようにするには、ctx2.close()
呼出しを行う必要があります。ctx2.close()
呼出しにより、スレッドに関連付けられているスタックからuser2
が削除され、ctx1.lookup("abc")
呼出しでuser1
が使用されます。
注意:
weblogic.jndi.enableDefaultUser
フラグが有効化されている場合、close()
呼出しを行っても現在のユーザーがスタックから削除されず、JNDIコンテキストの問題が発生する恐れのある状況が2つあります。JNDIコンテキストの問題の回避方法については、「JNDIコンテキストの問題の回避方法」を参照してください
close()
呼出しを発行すると、通常は「JNDIコンテキストとスレッド」の説明のように動作しますただし、weblogic.jndi.enableDefaultUser
フラグが有効化されていると、予期される動作に対して次の例外が発生します。
IIOPを使用する場合、スタックにコンテキストが1つあり、そのコンテキストがclose()
によって削除される場合に、予期された動作に対する例外が発生します。スタックから削除された最後のコンテキストのIDによって、ユーザーの現在のIDが決まります。次の手順で、このシナリオについて説明します。
ctx1.close()
呼出しを行います。ctx1.lookup()
呼出しを行います。 現在のユーザーはこの時点でuser1です。user2
用にctx2
というコンテキストを(ユーザー名と資格を使用して)作成します。コンテキストの作成処理で、user2
がスレッドに関連付けられてスタックに格納されます。つまり、現在のIDはuser2
に設定されます。 ctx2.close()
呼出しを行います。 ctx2.lookup()
呼出しを行います。 現在のユーザーはこの時点でuser2です。コンテキストでlookup()
メソッドを使用して、名前付きオブジェクトを取得します。lookup()
メソッドに渡される引数は、目的のオブジェクト名を含む文字列です。例1-3は、ServiceBean
という名前のEJBを取り出す方法を示しています。
例1-3 名前付きオブジェクトのルックアップ
try { ServiceBean bean = (ServiceBean)ctx.lookup("ejb.serviceBean"); }catch (NameNotFoundException e) { // binding does not exist }catch (NamingException e) { // a failure occurred }
EJBクライアント・アプリケーションは、EJBホームからEJBリモート・オブジェクトへのオブジェクト参照を取得します。RMIクライアント・アプリケーションは、最初の名前付きオブジェクトからその他のRMIオブジェクトへのオブジェクト参照を取得します。最初の名前付きリモート・オブジェクトはどちらも、ファクトリとしてWebLogic Serverに認識されます。ファクトリとは、WebLogicネームスペース内にある別のオブジェクトへの参照を返すことができるオブジェクトのことです。
クライアント・アプリケーションは、ファクトリでメソッドを呼び出し、特定のクラスのリモート・オブジェクトへの参照を取得します。その後、リモート・オブジェクトでメソッドを呼び出し、必要な引数を渡します。
例1-4は、リモート・オブジェクトを取得した後に、そのオブジェクトでメソッドを呼び出すコードを示しています。
例1-4 名前付きオブジェクトを使用したオブジェクト参照の取得
ServiceBean bean = ServiceBean.Home.create("ejb.ServiceBean") Servicebean.additem(66);
コンテキストの操作が終了したら、クライアントはコンテキストを閉じてリソースを解放し、メモリー・リークを回避してください。この処理はfinally{}
ブロックで行い、close()
メソッドはtry{}
ブロックの中に入れることをお薦めします。エラーが原因で一度もインスタンス化されなかったコンテキストを閉じようとすると、Javaクライアント・アプリケーションでは例外が送出されます。
例1-5では、クライアントでコンテキストが閉じられ、リソースが解放されます。
例1-5 コンテキストのクローズ
try { ctx.close(); } catch () { //a failure occurred }
WebLogic JNDIの目的は、Java EEサービス、特にEJB、RMI、およびJava Messaging Service (JMS)の各サービスに対してネーミング・サービスを提供することです。そのため、クラスタ環境でオブジェクトをJNDIツリーにバインドすることによる影響を十分理解しておく必要があります。
以降の節では、クラスタ環境でのWebLogic JNDIの実装方法について説明し、独自のオブジェクト(カスタム・オブジェクト)をJNDIクライアントで使用できるようにするための方法を紹介します。
WebLogic RMIを使用すると、あるJVMのクライアントが別のJVMのクライアントからEJBサービスやJMSサービスにアクセスできるようになります。RMIスタブは、RMIオブジェクトに対するクライアントからの呼出しを受信し、マーシャリングします。クライアントでJava EEサービスを利用できるようにするために、WebLogicは、特定のサービスのRMIスタブを、特定の名前でJNDIツリーにバインドします。RMIオブジェクトの他のインスタンスがクラスタ内の他のサーバーにデプロイされると、RMIスタブはその場所で更新されます。クラスタ内のサーバーに障害が発生すると、他のサーバーのJNDIツリー内のRMIスタブが更新されてサーバーの障害を反映します。
クライアントがクラスタに接続する場合、実際には、クラスタ内にあるWebLogic Serverインスタンスの1つに接続されます。そのWebLogic ServerインスタンスのJNDIツリーには、そのサーバーによって提供されるサービスだけでなく、クラスタ内の他のサーバーによって提供されるすべてのサービスのRMIスタブが含まれているため、クライアントには、クラスタがクラスタ全体のサービスをすべて提供する1つのWebLogic Serverインスタンスのように表示されます。クラスタに新しいWebLogic Serverインスタンスが加わった場合、すでにクラスタ内に存在する各WebLogic Serverインスタンスは、それぞれの独自のサービスに関する情報を新しいWebLogic Serverインスタンスに渡して共有する必要があります。クラスタ内の他のすべてのサーバーから収集された情報を使用して、新しいサーバーはクラスタ全体のJNDIツリーの独自のコピーを作成します。
以下に示すように、RMIスタブは、クラスタ環境でのWebLogic JNDIの実装方法に大きな影響を与えます。
RMIスタブは比較的小さいものです。このため、WebLogic JNDIではサーバー間通信のオーバーヘッドが少ない状態で、クラスタ内のすべてのWebLogic Serverインスタンスにスタブをレプリケートできます。
RMIスタブは、クラスタ全体をレプリケートするメカニズムとして機能します。RMIオブジェクトのインスタンスは1つのWebLogic Serverインスタンスにデプロイされますが、スタブはクラスタ全体にレプリケートされます。
カスタム・オブジェクト(非RMIオブジェクト)をWebLogic Serverのクラスタ内のJNDIツリーにバインドすると、オブジェクトはクラスタ内の全サーバーにレプリケートされます。ただし、ホスト・サーバーがダウンした場合は、カスタム・オブジェクトはクラスタのJNDIツリーから削除されます。カスタム・オブジェクトは、再度バインドされないかぎり、レプリケートされません。カスタム・オブジェクトに加えられた変更を伝播するには、その都度カスタム・オブジェクトをアンバインドし、リバインドする必要があります。そのため、WebLogic JNDIは、分散オブジェクトのキャッシュとして使用することはできません。WebLogic Serverでサード・パーティ・ソリューションを使用すると、分散型のキャッシュを用意できます。
カスタム・オブジェクトにアクセスする必要があるのは、1つのWebLogic ServerインスタンスにデプロイされているEJBのみであると仮定します。この場合、明らかに、カスタム・オブジェクトをクラスタ内のすべてのWebLogic Serverインスタンスにレプリケートする必要はありません。実際には、サーバー間の不要な通信によるパフォーマンスの低下を回避するために、カスタム・オブジェクトがレプリケートされないようにする必要があります。クラスタ内のWebLogic Serverインスタンス間でレプリケートされないバインドを作成するには、カスタム・オブジェクトをネームスペースにバインドするコンテキストの作成時に、REPLICATE_BINDINGS
プロパティを指定します。例1-6は、REPLICATE_BINDINGS
プロパティの使い方を示しています。
例1-6 REPLICATE_BINDINGSプロパティの使い方
Hashtable ht = new Hashtable(); //turn off binding replication ht.put(WLContext.REPLICATE_BINDINGS, "false"); try { Context ctx = new InitialContext(ht); //bind the object ctx.bind("my_object", MyObect); } catch (NamingException ne) { //failure occured }
この方法でカスタム・オブジェクトを使用する必要がある場合は、WebLogic ServerインスタンスのInitialContext
を明示的に取得する必要があります。クラスタ内の他のWebLogic Serverインスタンスに接続した場合は、バインドはJNDIツリーに表示されません。
クラスタ内のどのWebLogic Serverインスタンスからもカスタム・オブジェクトにアクセスできるようにするには、JNDIバインドをレプリケートせず、カスタム・オブジェクトをクラスタ内の各WebLogic Serverインスタンスにデプロイします。
WebLogic JNDIを使用してバインドをレプリケートすると、バインドされているオブジェクトは、ホストになっているWebLogic Serverインスタンスによって所有されているように処理されます。ホストWebLogic Serverインスタンスに障害が発生すると、カスタム・オブジェクトがクラスタのすべてのWebLogic ServerインスタンスのすべてのJNDIツリーから削除されます。この動作によって、カスタム・オブジェクトの可用性が低下するおそれがあります。
Webアプリケーションには、複数のオブジェクトによって使用されるデータを一定期間キャッシュし、データ計算や別のサービスへの接続に関連するオーバーヘッドを回避するという一般的なタスクがあります。
単一のWebLogic Serverインスタンスで正常に動作するカスタム・データ・キャッシュ・オブジェクトをすでに設計しており、WebLogic Serverクラスタ内でこのオブジェクトを使用するとします。WebLogic ServerインスタンスのいずれかのJNDIツリーのデータ・キャッシュ・オブジェクトをバインドする場合、JNDIは、デフォルトでオブジェクトをクラスタの他のWebLogic Serverインスタンスにそれぞれコピーします。このオブジェクトはRMIオブジェクトではないので、JNDIツリーにバインドされ、他のWebLogic Serverインスタンスにコピーされているものはオブジェクト自身であり、いずれかのWebLogic Serverインスタンスをホストにするオブジェクトの単一のインスタンスを参照するスタブではない点に注意してください。WebLogic Serverがサーバー間でオブジェクトをコピーしても、カスタム・オブジェクトを分散キャッシュとして使用できるわけではありません。カスタム・オブジェクトは、バインドされているWebLogic Serverインスタンスに障害が発生するとクラスタから削除されます。カスタム・オブジェクトへの変更は、オブジェクトをアンバインドしてJNDIツリーにリバインドしないかぎり、クラスタ内に伝播されません。
パフォーマンスと可用性の考慮から、クラスタ内のすべてのWebLogic Serverインスタンスで高可用性が求められる場合は、WebLogic JNDIのバインドのレプリケーションを使用して大きなカスタム・オブジェクトをコピーすることはお薦めできません。そのかわりに、カスタム・オブジェクトの別々のインスタンスを、クラスタ内の各WebLogic Serverインスタンスにデプロイする方法があります。各WebLogic ServerインスタンスのJNDIツリーにオブジェクトをバインドするときは、「カスタム・オブジェクトをWebLogic Serverクラスタで使用できるようにする方法」で説明するように、バインドのレプリケーションを無効にしておく必要があります。この設計パターンでは、各WebLogic Serverインスタンスはカスタム・オブジェクトのコピーを保持しますが、サーバー間で大量のデータがコピーされることはありません。
どの手法を使用する場合でも、オブジェクトの各インスタンスは、クラスタ内の他のデータ・キャッシュ・オブジェクトとは無関係に自分のキャッシュを更新する必要があるときに備えて、独自のロジックを保持する必要があります。たとえば、あるWebLogic Serverインスタンス上のデータ・キャッシュにクライアントがアクセスするとします。そのキャッシュ・オブジェクトがアクセスされるのはその時が初めてなので、オブジェクトは情報を計算または取得し、将来のリクエストに備えて情報のコピーを保存します。次に、別のクライアントがクラスタに接続し、最初のクライアントと同じタスクを実行するとします。ただし、今回は、クラスタ内の別のWebLogic Serverインスタンスに接続します。この特定のデータ・キャッシュ・オブジェクトにとってそれが最初に受け付けるアクセスである場合は、クラスタ内の他のデータ・キャッシュ・オブジェクトがすでに情報をキャッシュしているかどうかに関係なく、アクセスされたオブジェクトは情報を計算する必要があります。もちろん、データ・キャッシュ・オブジェクトのこのインスタンスは、将来のリクエストに対しては保存してある情報を参照できます。
サービスをクラスタ内で一度だけ提供することが望ましい場合もあります。これを実現するには、1つのマシンだけにサービスをデプロイします。RMIオブジェクトの場合は、WebLogic JNDIのデフォルト動作を使用して、バインド(RMIスタブ)をレプリケートすることによって、クラスタ内のすべてのWebLogic Serverインスタンスからオブジェクトの単一のインスタンスにアクセスできるようになります。このようなサービスは、固定サービスと呼ばれます。非RMIオブジェクトの場合は、オブジェクトをネームスペースにバインドするときに、必ずREPLICATE_BINDINGS
プロパティを使用してください。この場合、オブジェクトにアクセスするには、ホストになっているWebLogic Serverインスタンスに明示的に接続する必要があります。かわりに、RMIオブジェクトを作成し、ホストになっている同じWebLogic Serverインスタンスにデプロイすることもできます。このRMIオブジェクトは、非RMIオブジェクトのプロキシとして機能します。WebLogic JNDIのデフォルト動作を使用してプロキシのスタブをレプリケートすれば、クラスタ内の任意のWebLogic Serverインスタンスに接続したクライアントは、RMIプロキシを経由して非RMIオブジェクトにアクセスできます。
高可用性が求められるサービスの場合、RMIオブジェクトの別サーバーへの自動的な移行を構成することができます。自動移行の詳細は、Oracle WebLogic Serverクラスタの管理のサーバー全体の移行を参照してください。
オブジェクトのJNDIバインドをクラスタの単一のWebLogic ServerインスタンスのJNDIツリーに表示したり、クラスタのすべてのWebLogic Serverインスタンスにレプリケートできます。目的のオブジェクトがただ1つのWebLogic Serverインスタンスのみにバインドされている場合は、「WebLogic JNDIを使用したJavaクライアントから単一サーバーへの接続」
で説明されているように、InitialContext
の作成時に、Context.PROVIDER_URLプロパティをホストになっているWebLogic ServerインスタンスのURLに設定することで、ホストになっているWebLogic Serverに明示的に接続する必要があります
ただしほとんどの場合、目的のオブジェクトはクラスタリングされたサービスか、または固定サービスです。結果として、クラスタ内の各WebLogic ServerインスタンスのJNDIツリーには、サービスのスタブが表示されます。この場合、クライアントは、ネーミング・サービスを提供する特定のWebLogic Serverインスタンスの名前を指定する必要はありません。実際、WebLogicクラスタにネーミング・サービスを提供するようリクエストするのが、クライアントにとって最善の方法です。その場合、WebLogic Serverのコンテキスト・ファクトリによって、クライアントに対して最も適切であると思われるWebLogic Serverインスタンスがクラスタの中から選択されます。
現在、ネーミング・サービス・プロバイダは、ClusterAddress
属性で定義できるクラスタのDNS名を使用してWebLogicの中から選択されます。この属性は、クラスタに接続するためにクライアントで使用されるアドレスを定義します。このアドレスは、複数のIPアドレスに対応するDNSホスト名か、単一アドレスのホスト名またはIPアドレスで構成されるカンマ区切りのリストのいずれかになります。ネットワーク・チャネルが構成されている場合は、クラスタ・アドレスをチャネルごとに設定できます。Oracle WebLogic Serverクラスタの管理のクラスタでの通信を参照してください。
一般に、クラスタリングされたサービスのクライアントに対して返されるコンテキストは、フェイルオーバー・スタブとして実装されており、選択されたWebLogic Serverインスタンスとの間で通信障害などの障害が発生した場合は、ネーミング・サービス・プロバイダを透過的に変更できます。
例1-7は、クラスタのネーミング・サービスをクライアントが使用する方法を示しています。
例1-7 WebLogicクラスタでのネーミング・サービスの使い方
Hashtable ht = new Hashtable(); ht.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory"); ht.put(Context.PROVIDER_URL, "t3://acmeCluster:7001"); try { Context ctx = new InitialContext(ht); // Do the client's work } catch (NamingException ne) { // A failure occurred } finally { try {ctx.close();} catch (Exception e) { // a failure occurred } }
プロバイダのURLの一部として指定されているhostnameは、クラスタのDNS名であり、config.xml
ファイルのCluster
スタンザ内のClusterAddress
で定義できます。ClusterAddress
は、このクラスタ内のネーミング・サービスを提供するホストのリストにマップします。詳細は、Oracle WebLogic Serverクラスタの管理のクラスタ構成の理解を参照してください。
例1-7では、acmeCluster
というクラスタ名を使用して、クラスタ内の任意のWebLogic Serverインスタンスに接続しています。結果として得られるコンテキストは、クラスタ内の任意のWebLogic Serverに透過的にフェイルオーバーできるようにレプリケートされます。
WebLogic Serverクラスタとの最初の接続ポイントを指定するもう1つの方法は、カンマで区切ったDNSサーバー名またはIPアドレスのリストを入力することです。
次の例では、同じポートを使用するWebLogic Serverインスタンスのリストが指定されています。
ht.put(Context.PROVIDER_URL,"t3://acme1,acme2,acme3:7001");
すべてのWebLogic Serverインスタンスは、URLの末尾に指定されているポートをリスニングします。
次の例では、異なるポートを使用するWebLogic Serverインスタンスのリストが指定されています。
ht.put(Context.PROVIDER_URL,"t3://node1:7001,node2:7002,node3:7003");
複数のサーバーにマップするDNS名を使用する場合、WebLogic ServerはDNSに依存してロード・バランシングを行います。
WebLogic ServerノードのDNS名をカンマで区切ったリストを使用する場合は、フェイルオーバーがラウンドロビン方式で実行されます。この方式では、リスト内のランダムに選択されたサーバーにリクエストを送り、そのサーバーが応答に失敗すると、その後はリスト内の次のサーバーにリクエストを送ります。サーバー・インスタンスが応答に失敗するたびに次のサーバーで続行します。
クライアントがコンテキストを受け取った後は、失敗がないかぎり、それ以上のロード・バランシングは生じません。失敗があった場合、WebLogic Serverインスタンスはクラスタ内の別のノードへフェイルオーバーを行います。
リモート・クライアントは、最初に使用可能なサーバーからコンテキストを取得します。クラスタ内のサーバーのローカル・クライアントは、リモート・サーバーでJNDI操作を行うことはありません。
スタブをルックアップすると、そのスタブの最初の呼出しは通常、コンテキストの取得元のサーバーに送られます。スタブがクラスタ化可能な場合、その後の呼出しは、ユーザー定義のロード・バランシング・ポリシーに基づいてロード・バランシングされます。
JNDIとクラスタの詳細は、Oracle WebLogic Serverクラスタの管理の概要を参照してください。
Java EEコンポーネントからグローバル環境を直接使用することは可能ですが、コンポーネント環境を使用することをお薦めします。Java EEアプリケーション内の各Java EEコンポーネントには、コンポーネントのデプロイメント記述子に含まれる情報に基づいて設定される独自のコンポーネント環境がありました。
Java EEコンポーネントは以下のコードを使用して独自のコンポーネントをルックアップできます。
Context ctx = new InitailContext(); Context comp_env = (Context)ctx.lookup("java:comp/env");
Java EEコンポーネント内での操作であるため、接続情報を定義するためのハッシュ表または環境オブジェクトを設定する必要はありません。
このコンテキストはグローバル環境と同じ方法で使用します。ただし、使用する名前は、コンポーネントのデプロイメント記述子に定義された名前です。たとえば、デプロイメント記述子に次のようなejb-ref
があるとします。
<ejb-ref> ... <ejb-ref-name>ejb1</ejb-ref-name> <ejb-ref-type>Session</ejb-ref-type> <home>ejb1.EJB1Home</home> <remote>ejb1.EJB1</remote> ... </ejb-ref>
<ejb-ref-name>
で定義された名前をルックアップします。この場合はejb1
です。
グローバル環境ではなくコンポーネント環境を使用してJNDI名を設定すると、JNDI名によって参照される名前がデプロイメント時に解決されるという利点があります。つまり、コードを書き換えなくても、名前の衝突を解決できるということです。
外部JNDIは、リモートのJNDIツリーに直接接続しないでも、そのリモート・ツリーにあるオブジェクトへアクセスできるようにするAPIです。
外部JNDIを使用すると、WebLogic ServerやJavaプログラム内のJNDIツリーなど、別のサーバーまたはプロバイダ上のJNDIツリーへのリンクを作成できます。外部JNDIを構成後は、WebLogic Serverインスタンス内にバインドされたオブジェクトを使用するのと同じくらい容易に、別の場所にあるオブジェクトを使用できます。
外部JNDIを構成するには、使用するオブジェクトがあるリモートJNDIプロバイダのアドレスでForeignJNDIProvider
を作成し、それらのオブジェクトにアクセスするためのユーザー名とパスワードを作成します。オプションで、特定のサーバー、クラスタ、または両方の外部JNDI参照を指定できます。(ターゲットが選択されない場合、外部JNDI参照が全体のドメインにデプロイされます)。その後は、ローカルJNDIツリー内の名前と、リモート・ツリー内のオブジェクトの関係を設定する、ForeignJNDILinks
およびForeignJNDIObjects
を作成できます。
外部JNDIの構成方法の詳細は、Oracle WebLogic Server管理コンソール・オンライン・ヘルプの外部JNDIプロバイダの作成を参照してください。