アダプタの開発
![]() |
![]() |
![]() |
![]() |
ロギングは、アダプタ コンポーネントに不可欠な機能です。通常、アダプタは複数のアプリケーションの統合に使用され、データの処理時にエンドユーザとは対話しません。フロントエンド コンポーネントとは異なり、アダプタにエラーや警告が発生すると、処理を中断してエンドユーザの応答を待つことができません。
ADK では、ロギング フレームワークを実装することにより、アダプタ アクティビティのログを記録できます。このフレームワークにより、複数の出力先へのインターナショナライズまたはローカライズされたメッセージを記録できます。また、メッセージ、カテゴリ、優先度、フォーマット、および送信先を調整するためのさまざまなコンフィグレーション パラメータを使用できます。
ADK のロギング ツールを使用すると、インターナショナライズされたメッセージを複数の出力先にログとして記録できます。ロギング ツールキットを使用すると、Apache Log4j オープン ソース プロジェクトの機能が強化されます。そのため、この製品には、Apache Software Foundation (http://www.apache.org) によって開発されたソフトウェアが組み込まれています。
ロギング ツールキットは、必要な Log4j クラスをラップし、J2EE 準拠アダプタに機能を追加するためのフレームワークです。このツールキットは、WLI_HOME
/lib
ディレクトリの logtoolkit.jar
ファイル内にあります。logtoolkit.jar ファイルは、DOM、XERCES、および Log4j に依存します。XERCES の依存関係には、WebLogic Server で提供される weblogic.jar
ファイルと xmlx.jar
ファイルが必要です。log4j.jar
は、WL_HOME
/common/lib
にあります。
Log4j パッケージは、オープン ソース イニシアチブによって認可されたオープン ソースの完全ライセンス、Apache 公用ライセンスに従って配布されています。すべてのソース コード、クラス ファイル、およびドキュメントが含まれた最新バージョンの Log4j は、Apache Log4j Web サイト (http://www.apache.org) にあります。
この節では、ロギング コンフィグレーション ファイルへの参照や、このファイルのコードの抜粋を紹介します。ロギング コンフィグレーション ファイルは、BEA_WLS_DBMS_ADK.xml
などのアダプタ論理名で識別される .xml
ファイルです。このファイルには、「ロギングの概念」で説明されている 4 つのロギングの概念に関する基本情報が定義されており、使用するアダプタに合わせて変更できます。
ADK では、WLI_HOME
/adapters/sample/src
に基本的なロギング コンフィグレーション ファイル BEA_WLS_SAMPLE_ADK.xml
が格納されています。このファイルを使用するアダプタに合わせて変更する場合は、GenerateAdapterTemplate
を実行してください。このユーティリティを使用すると、サンプル バージョンのロギング コンフィグレーション ファイルを、開発者の新しいアダプタに関連する情報に基づいてカスタマイズし、そのカスタマイズ バージョンのファイルを新しいアダプタの開発環境で使用できます。GenerateAdapterTemplate
の詳細については、「カスタム開発環境の作成」を参照してください。
ADK のロギング ツールキットを使用する前に、ロギング フレームワークの主要概念を理解する必要があります。ロギングには、次の 4 つの主要コンポーネントがあります。
これらのコンポーネントは連携して機能し、メッセージ タイプと優先度に従ってメッセージを記録し、実行時にはメッセージのフォーマットや出力先を管理できます。
カテゴリは、定義された基準に従ってログ メッセージを識別するロギング フレームワークの中心的な概念です。ADK では、カテゴリは BEA_WLS_SAMPLE_ADK.DesignTime
のように名前で識別されます。
カテゴリは階層で定義されており、どのカテゴリも親カテゴリからプロパティを継承できます。階層は以下のように定義されています。
たとえば、以下の図に示すように、BEA_WLS_SAMPLE_ADK.DesignTime
は BEA_WLS_SAMPLE_ADK
の子孫で、さらに BEA_WLS_SAMPLE_ADK はルート カテゴリの子孫になります。
ROOT CATEGORY
|
|->BEA_WLS_SAMPLE_ADK
|
|->BEA_WLA_SAMPLE.ADK.DesignTime
ルート カテゴリはカテゴリ階層の最上位にあり、削除したり名前で検索できません。
カテゴリを作成する場合は、アダプタのコンポーネントに対応した名前を割り当てます。たとえば、アダプタに設計時ユーザ インタフェース コンポーネントがある場合は、次のようなカテゴリ名にします。BEA_WLS_SAMPLE_ADK.DesignTime
どのメッセージにも、重要度を示す優先度があります。メッセージの優先度は、メッセージの記録に使用される ILogger インタフェース メソッドによって決まります。たとえば、ILogger インスタンスでデバッグ メソッドを呼び出した場合は、デバッグ メッセージが生成されます。
ロギング ツールキットには、メッセージに対する 5 つの優先度があります。これらを重要度の高い順に表 5-1 に示します。
|
|
|
BEA_WLS_SAMPLE_ADK
カテゴリには下記の子要素があるので、優先度は「WARN
」になります。
<priority value='WARN' class='com.bea.logging.LogPriority'/>
優先度に使用されるクラスは、com.bea.logging.LogPriority
である必要があります。
カテゴリには優先度を割り当てることができます。カテゴリに優先度が割り当てられていない場合、そのカテゴリの優先度は、優先度が割り当てられている最も近い祖先から継承されます。つまり、カテゴリに継承される優先度は、そのカテゴリの階層の上位をたどり、最初に見つかった NULL でない優先度になります。
ログ メッセージは、優先度がそのカテゴリの優先度以上の場合に、ログの出力先に送られます。それ以外の場合は、メッセージはログに書き込まれません。優先度が割り当てられていないカテゴリは、階層から優先度が継承されます。最終的にすべてのカテゴリに優先度が継承されるようにするには、ルート カテゴリに必ず優先度を割り当てる必要があります。カテゴリに継承されている優先度が q で、そのカテゴリ内のログ文の優先度が p の場合、p >= q の場合にロギングが有効になります。ただし、このルールでは、優先度の順位が DEBUG
< INFO
< WARN
< ERROR
< AUDIT
であるという前提に基づきます。
ロギング フレームワークでは、アペンダと呼ばれるインタフェースを使用することにより、1 つのアダプタで複数の出力先にログ メッセージを転送できます。Log4j には、以下の出力先に対応するアペンダがあります。
また、ADK のロギング ツールキットには、ご使用の WebLogic Server ログにログ メッセージを送信するために、呼び出せるアペンダも用意されています。
1 つのカテゴリが、複数のアペンダを参照できます。あるカテゴリで有効なロギング要求は、カテゴリ階層の上位にあるすべてのアペンダと、カテゴリ内にあるすべてのアペンダに転送されます。つまり、アペンダはカテゴリ階層から累加的に継承されます。
たとえば、コンソール アペンダがルート カテゴリに追加されると、有効なロギング要求はすべてコンソールに表示されます。さらにファイル アペンダがカテゴリ C に追加されると、カテゴリ C と C の子カテゴリの有効なロギング要求はファイルに出力され、コンソールに表示されます。このようなデフォルトの動作を無効にする (アペンダの累加的な継承を止める) には、累加フラグを false に設定します。
注意 : この場合、さらにコンソール アペンダを直接 C に追加すると、同じメッセージが 2 回 (C およびルートから) コンソールに表示されます。これは、ルート カテゴリでは常にコンソールにログが出力されるためです。
コード リスト 5-1 は、WebLogic Server ログに対するアペンダを示します。
コード リスト 5-1 WebLogic Server ログに対するアペンダを示すサンプル コード
<!--
WeblogicAppender がログ出力を Weblogic ログに送る。WebLogic 外で実行される場合
、アペンダはメッセージを System.out に書き出す。
-->
<appender name="WebLogicAppender"
class="com.bea.logging.WeblogicAppender"/>
</appender>
Log4j では、レイアウトをアペンダに関連付けることでログ メッセージのフォーマットをカスタマイズできます。レイアウトによってログ メッセージのフォーマットが決定され、アペンダはフォーマットされたメッセージを出力先に転送します。ロギング ツールキットでは、通常 PatternLayout を使用してログ メッセージのフォーマットを設定します。PatternLayout は標準 Log4j 配布キットに含まれており、これを使用することで C 言語の printf
関数に似た変換パターンに従って出力フォーマットを指定できます。
たとえば、変換パターンが「%-5p%d{DATE} %c{4} %x - %m%n
」の PatternLayout を呼び出すと、次のようなメッセージが生成されます。
AUDIT 21 May 2001 11:00:57,109 BEA_WLS_SAMPLE_ADK - admin opened connection to EIS
%-5p
は、メッセージの優先度を示す。上記の例では AUDIT
です。%d{DATE}
は、メッセージの日付を示す。上記の例では 21 May 2001 11:00:57,109
です。 %c{4}
は、ログ メッセージのカテゴリを示す。上記の例では BEA_WLS_SAMPLE_ADK
です。コード リスト 5-2 では、サンプル アダプタの新しいカテゴリを宣言し、新しいカテゴリに優先度を関連付け、アペンダを宣言することでログ メッセージの送信先のファイルのタイプを指定しています。
コード リスト 5-2 新しいログ カテゴリを宣言するサンプル XML コード
<!-
重要!!! アダプタのルート カテゴリ。これをユニークにすることで、
他のアダプタによるカテゴリへのロギングを防ぐ。
-->
<category name='BEA_WLS_SAMPLE_ADK' class='com.bea.logging.LogCategory'>
<!-
デフォルト優先度 (レベルで実行時に変更可能)
DEBUG は、アダプタのコード ベースの全メッセージ。
INFO は、情報、警告、エラー、監査ログ。
WARN は、警告、エラー、監査ログ。
ERROR は、エラー、監査ログ。
AUDIT は、監査ログのみ。
-->
<priority value='WARN' class='com.bea.logging.LogPriority'/>
<appender-ref ref='WebLogicAppender'/>
</category>
注意 : クラスを com.bea.logging.LogCategory
として指定する必要があります。
注意 : 以下の手順は、GenerateAdapterTemplate ユーティリティを実行して開発環境の複製が作成されていることを前提としています。このユーティリティの詳細については、「カスタム開発環境の作成」を参照してください。
アダプタに対してロギング フレームワークをセットアップするには
WLI_HOME
/adapters/ADAPTER/src/
フォルダにあります。ファイルの拡張子は .xml
です。たとえば、DBMS サンプル アダプタ コンフィグレーション ファイルは、WLI_HOME
/adapters/dbms/src/BEA_WLS_DBMS_ADK.xml
です。コード リスト 5-3 EventGenerator ログ カテゴリを優先度 DEBUG で追加するサンプル コード
<category name='BEA_WLS_DBMS_ADK.EventGenerator'
class='com.bea.logging.LogCategory'>
<priority value='DEBUG'
class='com.bea.logging.LogPriority'/>
</category>
<appender>
要素内に基本ファイル アペンダを追加する方法を示します。<layout>
要素内の指示により、メッセージ フォーマットを特定します。注意 : WebLogic Integration に用意されているすべてのサンプル アダプタでは、WebLogicAppender
がデフォルトで使用されています。
コード リスト 5-4 ファイル アペンダおよびレイアウト パターンを追加するサンプル コード
<!-- 基本ファイル アペンダ -->
<appender name='FileAppender'
class='org.apache.Log4j.FileAppender'>
<!-- 出力をファイルに送信 -->
<param name='File' value='BEA_WLS_DBMS_ADK.log'/>
<!-- 既存を短縮 -->
<param name="Append" value="true"/>
<!-- 基本 LOG4J パターン レイアウトを使用 -->
<layout class='org.apache.Log4j.PatternLayout'>
<param name='ConversionPattern' value='%-5p %d{DATE} %c{4}
%x - %m%n'/>
</layout>
</appender>
ここで、以下のコンフィグレーション ファイルの設定を確認します。
WLI_HOME
/adapters/
ADAPTER
/src/rar/META-INF/ra.xml
および weblogic-ra.xml
— AbstractManagedConnectionFactory
が、この基本コンフィグレーション ファイルに入力されたロギング情報を使用して、初期化時にログ フレームワークのコンフィグレーションを行います。WLI_HOME
/adapters/
ADAPTER
/src/war/web-inf/web.xml
— RequestHandler
(AbstractDesignTimeRequestHandler
の親) が、この基本コンフィグレーション ファイルに入力されたロギング情報を使用して、初期化時にログ フレームワークのコンフィグレーションを行います。これらのパスの ADAPTER
はアダプタ名を示します。たとえば、DBMS サンプル アダプタの場合、関連するコンフィグレーション ファイルのパス名は以下のようになります。
WLI_HOME
/adapters/dbms/src/rar/META-INF/ra.xml
ロギング フレームワークの基本的概念を踏まえ、さらにロギング ツールキットに用意されている以下の 3 つのメイン クラスを理解する必要があります。
このクラスは、ロギング フレームワークのメイン インタフェースです。メッセージ ロギング用の便利なメソッドが多数あります。
基本ログ コンフィグレーション ファイルでロギングをコンフィグレーションする方法については、「ロギングの設定方法」を参照してください。また、以下のロギング メソッドを実装しても、プログラム的にロギングのコンフィグレーションを行うことができます。
logger.setPriority ("DEBUG")
- 現在の ILogger から出力されるメッセージの最低優先度を変更します。logger.addRuntimeDestination (writer)
- コンテナが PrintWriter
をアダプタに渡すときに使用されるアペンダを追加します。logger.warn ("Some message", true)
- 優先度レベルが WARN
のメッセージをログに記録しますが、ResourceBundle
を使用しません。ブール値は、文字列がメッセージであり、キーではないことを示します。logger.warn ("someKey")
- 優先度レベルが WARN
のメッセージをログに記録します。ResourceBundle
では "someKey"
を使用してルックアップします。logger.info ("someKey", anObjArray)
- 優先度レベルが INFO
のメッセージをログに記録します。ResourceBundle
では someKey
を使用してテンプレートをルックアップし、空白を anObjArray
の要素で埋めます。logger.error (exception)
- 優先度レベルが ERROR
のメッセージを、このメソッドに例外 (Throwable) を渡すことによって、ログに記録します。このメソッドは、getMessage()
を呼び出し、スタック トレースを組み込みます (Throwable を引数として取得するロギング メソッドは、すべてスタック トレースをログに記録します)。 このクラスは、ロギング フレームワークの ILogger インスタンスの識別に必要な情報をカプセル化します。現在、LogContext クラスは、ログ カテゴリ名、および en_US
などのロケールをカプセル化します。このクラスは、ログ マネージャ内の ILogger
インスタンスをユニークに識別するための主キーです。
このクラスのメソッドによって、ロギング フレームワークのコンフィグレーションが可能になり、ILogger
インスタンスにアクセスできます。
使用するアダプタに対応するロギング ツールキットを適切にコンフィグレーションできるように、ADK では、LogManager
の configure()
メソッドを コード リスト 5-5 に示す引数で実装しています。
コード リスト 5-5 ロギング ツールキットのコンフィグレーション用のサンプル コード
public static LogContext
configure(String strLogConfigFile,
String strRootLogContext,
String strMessageBundleBase,
Locale locale,
ClassLoader classLoader)
表 5-2 に、configure()
によって渡される引数を示します。
コンフィグレーションが完了すると、LogContext
オブジェクトを指定することで、アダプタで使用する ILogger
インスタンスを取得できます。
コード リスト 5-6 LogContext オブジェクトを指定するサンプル コード
LogContext logContext = new LogContext("BEA_WLS_SAMPLE_ADK", java.util.Locale.US);
ILogger logger = LogManager.getLogger(logContext); logger.debug("I'm logging now!");
ADK では、ほとんどのログ コンフィグレーションおよび設定が表示されません。com.bea.adapter.spi.AbstractManagedConnectionFactory
クラスは、サービス接続のロギング ツールキットをコンフィグレーションし、AbstractEventGenerator
はイベント接続のロギング ツールキットをコンフィグレーションします。さらに、ADK に用意されているクライアント コネクタ インタフェース (Client Connector Interface : CCI) およびサービス プロバイダ インタフェース (Service Provider Interface : SPI) の基本クラスは、すべて ILogger
とこれに関連付けられた LogContext
へのアクセス機能を備えています。
アダプタには、EIS に対する通信を確立するために使用するソケット レイヤなど、CCI/SPI レイヤをサポートするレイヤも含まれる場合があります。アダプタが適切な ILogger
オブジェクトにアクセスする方法は、2 つあります。
LogContext
オブジェクトを渡すことができます。ただし、この方法はオーバーヘッドが大きくなります。LogContext
を設定できます。ADK の com.bea.adapter.cci.ConnectionFactoryImpl
クラスは、現在実行中のスレッドに対する LogContext
を getConnection()
メソッドに設定します。この getConnection()
メソッドが、クライアント プログラムとアダプタの間の最初の接点になります。したがって、アダプタ内の下位のレイヤは、以下のコードを使用することにより、現在実行中のスレッドの LogContext
に安全にアクセスできます。コード リスト 5-7 現在のスレッドに対する LogContext にアクセスするためのコード
public static LogContext getLogContext(Thread t)
throws IllegalStateException, IllegalArgumentException
また、LogManager
には以下のような便利なメソッドがあります。
public static ILogger getLogger() throws IllegalStateException
このメソッドは、現在実行中のスレッドに対して ILogger
を設定します。 ただし、この方法には注意点が 1 つあります。下位レイヤには、LogContext
または ILogger
をメンバーとして格納しないでください。下位レイヤが、これらを LogManager から動的に取得するようにします。LogContext が現在実行中のスレッドに対して設定される前にこのメソッドが呼び出されると、IllegalStateException
が送出されます。
インターナショナライゼーション (I18N) とローカライゼーション (L10N) は、ADK のロギング フレームワークの中心的な概念です。ILogger
インタフェースで、ロギングに使用するすべてのメソッドは、デバッグ メソッドを除き I18N を提供しています。この実装は Java インターナショナライゼーション標準に従い、ResourceBundle
オブジェクトを使用して、ロケール固有のメッセージまたはテンプレートを格納します。Java 言語の I18N および L10N 標準の使用方法については、Sun Microsystems 社から優れたオンライン チュートリアルが提供されています。
実際に運用されているシステムの多くは、複数のクライアントを同時に処理する必要があります。そのようなシステムの典型的なマルチスレッド実装では、スレッドごとに異なるクライアントを処理します。ロギングは、特に複雑な分散アプリケーションのトレースおよびデバッグに適しています。2 つのクライアント間のロギング出力を区別する一般的な方法は、クライアントごとに個別カテゴリをインスタンス化することです。ただし、この方法には欠点があります。カテゴリが増大し、これらを管理するオーバーヘッドが大きくなる点です。
より負荷の小さい方法は、同じクライアント対話で開始された各ログ要求に、ユニークな識別子でスタンプを設定することです。Neil Harrison 氏が、この方法を『Pattern Languages of Program Design 3』 (R. Martin、D. Riehle、F. Buschmann 編、Addison-Wesley、1997) の「Patterns for Logging Diagnostic Messages」で説明しています。
各要求にユニークな識別子でスタンプを設定するには、ユーザはコンテキスト情報を NDC (Nested Diagnostic Context) にプッシュします。ロギング ツールキットには、NDC メソッドへのアクセスのための独立したインタフェースがあります。このインタフェースは、getNDCInterface()
メソッドを使用して ILogger から取得されます。
NDC 出力は、XML コンフィグレーション ファイル (%x
記号による) でオンになります。ログ要求が行われるたびに、適切なロギング フレームワーク コンポーネントが、現在のスレッドに対する全 NDC スタックをログ出力に組み込みます。ユーザがこの処理に介入する必要はありません。ユーザの作業は、コード内のいくつかの決められた場所で push および pop メソッドを使用して、正しい情報を NDC に入力するだけです。
public void someAdapterMethod(String aClient) {
ILogger logger = getLogger();
INestedDiagnosticContext ndc = logger.getNDCInterface();
// すべてのログ メッセージに対してこのクライアント名をトラッキングします
ndc.push("User name=" + aClient);
// メソッド本体
ndc.pop();
}
![]() ![]() |
![]() |
![]() |