今週も引き続きJAX-WSの機能について紹介していきます。今週はJAX-RPC 1.0にはなかったWebサービスの非同期実行を取りあげます。

Webサービスの非同期実行

今まで紹介してきたJAX-WSを用いたWebサービスの実行はすべて同期処理で行ってきました。つまり、Webサービスからのレスポンスが戻ってくるまで、クライアントはブロックされたままになっています。

レスポンスがすぐに帰ってくるようなサービスであれば問題ありません。しかし、処理に時間がかかるWebサービスの場合、ブロックされたままの状態が長く続いてしまいます。ユーザにとってみれば、アプリケーションの反応がないわけですから、何らかの異常が発生してしまったと考えてしまうのもしかたありません。

そこで、あらかじめ処理に時間がかかると分かっているのであれば、非同期にWebサービスを実行することが有効です。

もちろん、JAX-WSにはこの非同期実行を行うためのメソッドがあらかじめ用意してあります。

前回前々回とプロキシを使用せずにWebサービスを実行する方法を紹介しました。そこで使用したのがjavax.xml.ws.Dispatchインタフェースです。今まで紹介した方法は、Dispatchインタフェースのinvokeメソッドを使用して、Webサービスを実行する方法でした。

非同期に実行する場合、DispatchインタフェースのinvokeAsyncメソッドを使用します。

せっかくですから今までのHello, World!サービスではなく、時間のかかるサービスを用意しましょう。今回使用するのはフィボナッチ数を求めるWebサービスです。

フィボナッチ数とは F(0) = 0, F(1) = 1, F(n) = F(n-1) + F(n-2) を満たす数のことです。小さいものから順番に並べると、0, 1, 1, 2, 3, 5, 8, 13, 21,..... と続いていきます。

実をいうとフィボナッチ数は一般項を表す式があることが知られています。しかし、それを使ってしまうと、すぐに処理が終わってしまいます。そこで、あえて上記の漸化式を再帰を用いて処理をしてみました。したがって、数が大きくなればなるほど、処理に多大な時間がかかるようになります。また、あまり大きな数を指定してしまうと、StackOverflowError例外が発生してしまいます。

本来は、このような再帰を使うことは避けた方がいいのですが、サンプルということでご容赦ください。

サンプルのソース Fibonacci.java
FibonacciServiceLauncher.java
Fibonacci.zip

フィボナッチ数を計算しているのはFibonacciクラスのcalcメソッドです。

    @WebMethod
    public long getFibonacci(int index) {
        return calc(index);
    }
 
    // フィボナッチ数の計算
    private long calc(int index) {
        if (index == 0) {
            return 0L;
        } else if (index == 1) {
            return 1L;
        }
        
        return calc(index - 1) + calc(index - 2);
    }
}

赤字の部分で再帰計算を行っています。1つ前のフィボナッチ数と2つ前のフィボナッチ数を求め、足しあわせて返しています。

Webサービスとして公開するのはgetFibonacciメソッドです。getFibonacciメソッドは単にcalcメソッドに処理を委譲しているだけです。

このサービスを公開しているのがFibonacciServiceLauncherクラスです。行っていることはHello, World!の場合と同じくjavax.xml.ws.Endpointクラスのpublishメソッドをコールしているだけです。ここでは、http://localhost:8080/fibonacciでサービスを公開しています。

このサービスを非同期で実行していきます。

非同期に処理を行う場合、別のスレッドで処理が行われます。そのため、サービスの結果の受け取りも同期処理とは異なります。Dispatchインタフェースで提供しているのは、ポーリングを使用する方法と、コールバックハンドラを使用する方法です。それぞれの方法を使ってクライアントを作っていきましょう。