Apache CXF を使用して Web サービス・メッセージのロギングを実行する

Apache CXF を使用して Web サービス・メッセージのロギングを実行する方法を学ぶ

アプリケーションの監視やデバッグのツールとしてロギングを使用することができます。この記事では Apache CXF を使用して Web サービス・メッセージのロギングを実行する方法について学びます。この記事で説明するのは、メッセージ・ロギングを実装するさまざまな方法、インターセプターやフィーチャーなど、CXF の重要機能を使用してメッセージ・ロギングを実行する方法、Spring ベースの Bean 構成を使用してメッセージ・ロギングを実行する方法についても説明します。

Rajeev Hathi, Java Architect, Writer

 Rajeev HathiRajeev Hathi は J2EE プラットフォームに関するソフトウェア・コンサルタントです。彼はアーキテクチャーの設計、J2EE ベースのアプリケーションの設計や開発に専門的な関心を持っており、Java 技術と J2EE 技術 (コア Java、Web、EJB、アーキテクト) で SUN 認定を取得しています。また、IBM の developerWorks ポータルに何本かの技術記事を寄稿しているとともに、『Apache CXF Web Service Development』の共著者でもあります。彼の趣味は音楽鑑賞とスポーツ観戦です。彼の公式な Web サイトは技術ブログのサイト、http://www.rajeevhathi.comです。



2011年 10月 07日

概要

Apache CXF は Web サービスの開発、ビルド、デプロイに使用される Web サービス・フレームワークです。CXF は多くの機能をサポートしており、開発者はそれらの機能を使用して Web サービス・ベースのアプリケーションの開発やデプロイを行うことができます。そうした機能の 1 つがロギングです。ここで言うロギングは、実質的には Web サービス・メッセージのロギングを意味します。CXF は標準的な Java ロギング API を使用してメッセージのロギングを行います。この方法により、受信メッセージと送信メッセージの両方のログを取ることができます。メッセージのロギングはクライアント・サイドでもサーバー・サイドでも行うことができます。ロギングによって、サーバーとの間で送受信される実際の SOAP ペイロードを見ることができるため、ロギングは重要であり、デバッグ・ツールとしても役に立ちます。CXF でロギングを実装する場合、インターセプターとフィーチャーという概念を使用します。この記事では、それらの概念を使用して単純に Web サービス・メッセージのロギングを実行する方法について説明します。また、Spring ベースの Bean 構成を使用してメッセージ・ロギングを構成する方法についても説明します。

ここでは、JAX-WS フロントエンド、つまり CXF の API を使用する単純な Web サービスを作成します。Web サービスとしては、オンラインの LMS (Learning Management System: 学習管理システム) を考えてみましょう。LMS の機能には通常、ユーザー管理、コース作成、ディスカッション・フォーラム、成績表管理、コンテンツ管理などが含まれます。この記事では、「コース作成」を例として取り上げ、CourseBuilder という単純な Web サービス・クラスを作成します。またこの記事では、単純な Web サービスを作成して JAX-WS エンドポイントとして公開する方法を間接的に示します。ただし基本的な目標は、ロギング・メカニズムを示すことです。この記事ではサーバー・サイドのロギングのみに焦点を絞ります。サーバー・サイドのロギングを理解できると、クライアント・サイドのロギングを容易にエミュレートすることができます。

この Web サービス・クラスは以下のようなものです。

リスト 1. CourseBuilderImpl Web サービス・クラス
@WebService
public class CourseBuilderImpl implements CourseBuilder {

    public String createCourse(Course course) {
        System.out.println("Course code is " + course.getCode());
        System.out.println("Course title is " + course.getTitle());
		
		return "Course created successfully";
    }
}

上記の Web サービス・クラス CourseBuilderImpl は非常に単純です。createCourse メソッドは Course という Bean を引数に取り、コースが適切に作成されたことを示すステータス・ストリングを返します。今度はサービス・メッセージのログをコンソールに表示します。サービス・メッセージは実質的に SOAP ペイロード、つまりメソッド・パラメーターと戻り型という形式による実際のデータを意味しています。ロギング機能を有効にすることで、このペイロードをコンソールに表示することができます。

インターセプターを使用したロギング

CXF のインターセプターは SOAP メッセージをインターセプトするコンポーネントです。CXF のインターセプターは受信メッセージも送信メッセージもインターセプトすることができます。従って、これらのインターセプターをクライアント・アプリケーションで構成することも、サーバー・サイドで構成することも、あるいはその両方で構成することもできます。CXF にはインターセプターがいくつも組み込まれています。メッセージのロギングを実行するインターセプターとしては、LoggingInInterceptorLoggingOutInterceptor があります。これらのインターセプターを使用してサーバー・サイドでロギングを実行します。以下のコードはその方法を示しています。

リスト 2. サーバー・コード
public final class Server {

    public static void main(String args[]) throws Exception {
		CourseBuilderImpl implementor = new CourseBuilderImpl();
		JaxWsServerFactoryBean svrFactory = new JaxWsServerFactoryBean();
		svrFactory.setAddress("http://localhost:9000/CourseBuilder");
		svrFactory.setServiceBean(implementor);
svrFactory.getInInterceptors().add(new LoggingInInterceptor());
		svrFactory.getOutInterceptors().add(new LoggingOutInterceptor());
		svrFactory.create();
    }
}

上記のコードは JaxWsServerFactoryBean サーバー・ファクトリー・クラスを使用して CourseBuilder サービスを JAX-WS エンドポイントとして公開します。ご覧のとおり、このコードは実装クラスとエンドポイントのアドレスを設定しています。create メソッドは、組み込みのスタンドアロン Jetty サーバーを起動します。このコードの重要な部分は太字で強調してあります。強調した部分では、2 つのインターセプター、つまり LoggingInInterceptorLoggingOutInterceptor を使用しています。これらがファクトリー・クラスに追加された後、create メソッドが呼び出されます。この強調されたコードにより、受信メッセージと送信メッセージの両方に対してサーバー・サイドのロギング機能が有効になります。クライアント・アプリケーションを実行すると、サーバー・コンソールには以下の出力がログとして表示されます。

図 1. サーバー・コンソール
サーバー・コンソール

上記のサーバー・コンソール出力は、受信した SOAP ペイロードと送信した SOAP ペイロードを示しています。また、ログの内容に関する最大サイズをコンストラクターの中で指定して制御することもできます。サイズはバイト数を表しており、例えば new LoggingInInterceptor(1024) のように指定します。これを見るとわかるように、ロギング・インターセプターを利用すると、サービス・メッセージのロギングが非常に容易になります。また、アノテーションを利用してロギングを実装することもできます。以下のコードはアノテーションとインターセプターを利用してロギングを実装しています。

リスト 3. インターセプター・アノテーションを使用したロギング
@WebService
@InInterceptors(interceptors = "org.apache.cxf.interceptor.LoggingInInterceptor")
@OutInterceptors(interceptors = "org.apache.cxf.interceptor.LoggingOutInterceptor")
public class CourseBuilderImpl implements CourseBuilder {
...

@InInterceptors@OutInterceptors というアノテーションを使用すると、それぞれ受信インターセプターと送信インターセプターを定義することができます。アノテーションの宣言は、サービス・クラスまたは SEI (Service Endpoint Interface) の中で行います。これらのアノテーションが SEI の中にあると、クライアント・アプリケーションとサーバー・アプリケーションの両方でロギング機能が有効になります。上記のコードでは CourseBuilderImpl サービス実装クラスでアノテーションが宣言されているため、サーバー・サイドのみでメッセージ・ロギングが実行されます。

フィーチャーを使用したロギング

CXF のフィーチャーの機能はデコレーターとよく似ています。CXF のフィーチャーは、クライアント、サーバー、バスのコンポーネントに適用されます。フィーチャーは基本的に、クライアント、サーバー、またはバスの機能を拡張します。CXF にはフィーチャーの実装がいくつか組み込まれており、その 1 つが LoggingFeature クラスです。LoggingFeature クラスは SOAP メッセージのロギングを実行します。ここでは、先ほど示したサーバー・コードを再度取り上げます。今度はインターセプターの代わりに LoggingFeature クラスを使用します。

リスト 4. ロギング・フィーチャー
public final class Server {

    public static void main(String args[]) throws Exception {
		CourseBuilderImpl implementor = new CourseBuilderImpl();
		JaxWsServerFactoryBean svrFactory = new JaxWsServerFactoryBean();
		svrFactory.setAddress("http://localhost:9000/CourseBuilder");
		svrFactory.setServiceBean(implementor);
svrFactory.getFeatures().add(new LoggingFeature());
		svrFactory.create();
    }
}

CXF バスとは何か

CXF バスはグローバル・レベルまたはアプリケーション・レベルのコンポーネントと考えることができます。CXF バスはフレームワークのコア・コンポーネント、つまりインフラストラクチャー・コンポーネント (拡張機能とも呼ばれます) を管理し、またインターセプターのプロバイダーとしても動作します。バス・レベルでロギングを実装すると、そのロギング・フィーチャーはサーバー・ランタイムまたはクライアント・ランタイムで構成されたサービス・エンドポイントのすべてに共通のものになります。

強調されたコードがすべてを語っています。このコードは受信メッセージと送信メッセージの両方、つまりサーバーが受信したメッセージとサーバーが返した応答をログとして記録します。そして LoggingFeature クラスはロギング・インターセプターを使用します。ただしインターセプターを直接使用した方が、より詳細な制御が可能です。例えば受信メッセージのみをログに記録し、送信メッセージを記録したくない場合には、LoggingInInterceptor インターセプター・クラスのみを使用すればよく、LoggingFeature クラスを使用する必要はありません。ロギング・インターセプターの場合とまったく同じように、LoggingFeature クラスを使用すると、ロギングの内容のサイズをバイト数で制限することができます。制限サイズを指定するためには、コンストラクターの中で以下のようにします。

リスト 5. サイズ制限を付けたロギング・フィーチャー
public final class Server {

    public static void main(String args[]) throws Exception {
		JaxWsServerFactoryBean svrFactory = new JaxWsServerFactoryBean();
		...
// This will only log upto 1K or 1024 characters
		svrFactory.getFeatures().add(new LoggingFeature(1024)); 
		...
	}
}

また LoggingFeature クラスを使用すると、ロギング対象のメッセージの出力先を設定することができます。構成により、メッセージ・ロギングの出力先を stdout (コンソール)、stderr (エラー・コンソール)、またはファイルに設定することができます。出力先は受信メッセージに対しても送信メッセージに対しても設定することができます。以下のコードは LoggingFeature クラスで出力先を使用する場合を示しています。

リスト 6. 出力先を指定したロギング・フィーチャー
public final class Server {

    public static void main(String args[]) throws Exception {
		JaxWsServerFactoryBean svrFactory = new JaxWsServerFactoryBean();
		...
svrFactory.getFeatures().add(
			new LoggingFeature("<stdout>", "file://home/myLog.txt")); 
		...
	}
}

先ほどとは別の、上記の LoggingFeature コンストラクターは、2 つのストリング・パラメーターを引数に取ります。これらのパラメーターはそれぞれ、受信メッセージと送信メッセージのログの出力先を示します。上記のコードから、受信メッセージのログはコンソールに出力され、送信メッセージのログはファイルに出力されます。

フィーチャーにもアノテーションを使用することができます。@Features アノテーションを使用すると、フィーチャーを指定することができます。以下のコードは @Features アノテーションの使い方を示しています。

リスト 7. アノテーションを使用したロギング・フィーチャー
@WebService
@Features(features = "org.apache.cxf.feature.LoggingFeature")
public class CourseBuilderImpl implements CourseBuilder {
...

上記のコードでは、@Features アノテーションを使用して LoggingFeature クラスを指定し、サーバー・サイドでロギングを実行しています。

インターセプター・アノテーションやフィーチャー・アノテーションを使いたくない場合には、単純に @Logging アノテーションを使用してメッセージ・ロギングを実行することができます。以下のコードを使用すると、ロギングをさらに簡単に実行できるようになります。

リスト 8. @Logging アノテーション
@WebService
@Logging
public class CourseBuilderImpl implements CourseBuilder {
...

Spring ベースの Bean 構成を使用したロギング

CXF では、Spring ベースの Bean 構成ファイルを使用して Web サービスを公開することもできます。Spring 構成ファイルを使用することによる当然のメリットとして、サービス Bean にフィーチャーとインターセプターを動的に追加することができ、コードを再コンパイルする必要がありません。私が以前に寄稿した、Apache CXF と Spring を使用した Web サービスの開発に関する記事を読むことをお勧めします。その記事では、Spring 構成ファイルを使用して Web サービスを作成し、最終的にその Web サービスを公開する手順を説明しています。

以下のコードは CourseBuilderImpl Bean を JAX-WS エンドポイントとして定義する構成ファイルを示しています。

リスト 9. CourseBuilderImpl サービス Bean を JAX-WS エンドポイントとして定義する
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:jaxws="http://cxf.apache.org/jaxws"
	xsi:schemaLocation="
http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

	<jaxws:endpoint 
	  id="courseBuilder" 
	  implementor="demo.cxf.logging.CourseBuilderImpl" 
	  address="/CourseBuilder" />
</beans>

<jaxws:endpoint> 要素を使用することで、CourseBuilderImpl サービス Bean を JAX-WS エンドポイントとして定義しています。エンドポイントの URL はWeb コンテンツに対する相対 URL です (これは http トランスポートとして CXFServlet を使用している場合には当然です)。ここで、ロギング・インターセプターを使用するためには、上記のコードを以下のように変更する必要があります。

リスト 10. ロギング・インターセプターを構成する
<beans>
...
        <bean id="logIn" class="org.apache.cxf.interceptor.LoggingInInterceptor"/>
	<bean id="logOut" class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>

	<jaxws:endpoint 
	  id="courseBuilder" 
	  implementor="demo.cxf.logging.CourseBuilderImpl" 
	  address="/CourseBuilder" >
	  
                <jaxws:inInterceptors>
			<ref bean="logIn"/>
		</jaxws:inInterceptors>
		<jaxws:outInterceptors>
			<ref bean="logOut"/>
		</jaxws:outInterceptors>
		
	</jaxws:endpoint>
</beans>

変更された上記のコードには、2 つのインターセプター Bean、つまり LoggingInInterceptorLoggingOutInterceptor が追加されています。これらの Bean の参照が、それぞれ <jaxws-inInterceptors> 要素と <jaxws-outInterceptors> 要素を使用して CourseBuilderImpl サービス Bean に渡されています。こうすることで、必ず受信サービス・メッセージと送信サービス・メッセージの両方のロギングが実行されます。

同様に、Spring を利用してロギング・フィーチャーを構成することもできます。以下のコードはロギング・フィーチャーを示しています。

リスト 11. ロギング・フィーチャーを構成する
<beans>
...
	<jaxws:endpoint 
	  id="courseBuilder" 
	  implementor="demo.cxf.logging.CourseBuilderImpl" 
	  address="/CourseBuilder" >
	  
<jaxws:features>
			<bean class="org.apache.cxf.feature.LoggingFeature"/>
        </jaxws:features>
		
	</jaxws:endpoint>
</beans>

上記のコードを見るとわかるように、<jaxws:features> 要素を使用してロギング・フィーチャーを指定しています。

以上の内容を要約すると、この記事ではインターセプターやフィーチャーなど、CXF のネイティブ機能を利用してサービス・メッセージのロギングを実行する方法を詳しく探りました。アノテーションを使用することで、また Spring ベースの Bean 構成を使用することで、プログラムでメッセージ・ロギングを実行することができます。Apache CXF フレームワークは、Log4j や SLF4J などのロギング・フレームワークと統合することができ、Web サービス・ランタイムのためのさまざまなデバッグ・ツールもサポートしています。CXF を使用したロギングやデバッグについての詳細は、Apache CXF の「Debugging and Logging」を参照してください。

参考文献

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=SOA and web services
ArticleID=762695
ArticleTitle=Apache CXF を使用して Web サービス・メッセージのロギングを実行する
publish-date=10072011