クライアントAPIを使ってRESTサービスにアクセスする

前回はJSR 311: JAX-RSのJBoss Communityによる実装「RESTEasy」を紹介した。このRESTEasyには、サーバ用のAPIだけでなく独自実装としてクライアントアプリケーション側からRESTサービスを利用するためのフレームワークが付属している。

RESTEasyのクライアントフレームワークは、サーバ側と同じアノテーションを用いてサービス利用のためのインタフェースを定義できるのが特徴だ。すなわち@Pathや@GETや@Producesなどのアノテーションを使ってインタフェースを定義し、それを介して実際のRESTサービス呼び出すのが一般的なプログラミングの流れとなる。使用するアノテーションが同じであるため、サーバ側とクライアント側で共通のインタフェースを利用できるという利点もある。

たとえば、前回の例で作成したSimpleMessageクラスのgetMessage()メソッドによるサービスを呼び出すクライアント側のインタフェースはリスト1のように定義できる。

リスト1

package jp.co.mycom.toolde;

import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;

@Path("/message")
public interface SimpleMessageClient {
    @GET
    @Path("/{name}")
    @Produces("text/plain")
    String getMessage(@PathParam("name")String name);
}

このインタフェースは/messageというパスに関連付けられている。getMessage()メソッドはnameというパラメータを受け取り、文字列を返す。この定義はSimpleMessageクラスのgetMessage()メソッドのものとまったく同様である点に注意してほしい。

続いて、このインタフェースを介してRESTサービスを利用するアプリケーション本体のコードについて説明する。ここではリスト2のようなプログラムを用意した。getMessage()を呼び出して、取得したメッセージを表示するだけの簡単な例である。

リスト2

package jp.co.mycom.toolde;

import org.jboss.resteasy.client.ProxyFactory;
import org.jboss.resteasy.plugins.providers.RegisterBuiltin;
import org.jboss.resteasy.spi.ResteasyProviderFactory;

public class SimpleMessageClientTest {
    public static void main(String[] args) {
        // RESTEasyのプロバイダを利用するために1度だけ呼び出す必要がある
        RegisterBuiltin.register(ResteasyProviderFactory.getInstance());

        // RESTサービスのメソッドにアクセス
        SimpleMessageClient client =
                ProxyFactory.create(SimpleMessageClient.class,
                                    "http://localhost:8084/RESTEasySample");
        String message = client.getMessage("Takaaki");

        System.out.println(message);
    }

}

このプログラムをコンパイル/実行するには

  • resteasy-jaxrs-xxx.jar
  • jaxrs-api-xxx.jar
  • slf4j-api-xxx.jar
  • slf-simple-xxx.jar
  • commons-httpclient-xxx.jar
  • commons-logging-xxx.jar
  • commons-codex-xxx.jar

をクラスパスに含めておく必要がある。すべてRESTEasyのバイナリパッケージに付属している。

最初のRegisterBuiltin.register()の呼び出しは、RESTEasyのクライアントフレームワークを利用するために1度だけ必要となる。JVMごとに1度呼び出せば、その後同じJVMのインスタンスで実行されるコードすべてに適用される。

SimpleMessageClientインスタンスの生成は、コンストラクタではなくProxyFactory.create()メソッドの呼び出しによって行う。このメソッドの第1引数に生成したいインスタンスのクラスオブジェクトを渡すことで、第2引数に指定したURLのRESTサービスにアクセス利用するSimpleMessageClientインスタンスが作られる。

あとは生成したインスタンスのgetMessage()メソッドを呼び出せば、この例ならば「http://localhost:8084/RESTEasySample/message/Takaaki」にアクセスした場合の結果を得ることができる。サーバ側のサービスを起動した状態でこのプログラムを実行すれば、コンソールに「Hello Takaaki」と表示されるはずだ。

アノテーションを使わずにRESTサービスを利用する

上の例ではJAX-RSで定義されたのと同じアノテーションを利用して、サービスへアクセスするためのインタフェースを作成した。RESTEasyのクライアントフレームワークには、このようなインタフェースを使わずに手動でRESTサービスにアクセスするための方法も用意されている。それにはClientRequestというクラスを利用する。

次のコードは、アノテーションを用いずにClientRequestクラスを利用してSimpleMessageサービスにアクセスする例である。

リスト3

package jp.co.mycom.toolde;

import org.jboss.resteasy.client.ClientRequest;
import org.jboss.resteasy.client.ClientResponse;
import org.jboss.resteasy.plugins.providers.RegisterBuiltin;
import org.jboss.resteasy.spi.ResteasyProviderFactory;

public class ManualClientRequest {
    public static void main(String[] args) {
        // RESTEasyのプロバイダを利用するために1度だけ呼び出す必要がある
        RegisterBuiltin.register(ResteasyProviderFactory.getInstance());

        // 手動でRESTサービスのメソッドにアクセス
        ClientRequest request =
                new ClientRequest("http://localhost:8084/RESTEasySample/message/Takaaki");

        try {
            // サーバからのレスポンスを取得して表示
            ClientResponse response = request.get(String.class);
            if (response.getStatus() == 200) { // OK!
                String message = response.getEntity();
                System.out.println(message);
            } else {
                System.out.println("Error: " + response.getStatus());
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

ClientRequestはRESTサービスに対してリクエストを送るためのクラスである。手順としてはまずサービスのURLを引数としてClientRequestインスタンスを生成し、必要に応じてheader()やbody()、pathParameter()、options()などのメソッドを用いてサーバに送信するリクエストを作成する。実際のリクエストの発行は、get()やpost()などのHTTPメソッドに対応した各メソッドを用いて行う。この例ではget()メソッドを使っていて、引数には戻り値のクラスのインスタンスを渡す。

レスポンスはClientResponse%lt;T>インスタンスとして返されるので、ここからgetEntity()メソッドを用いて内容を取得すればよい。ステータスはgetStatus()メソッドで調べることができる。この例の場合、正しく接続できていれば「Hello Takaaki」という文字列が帰ってきているはずだ。

自分でREST形式のWebアプリケーションを作成するだけでなく、RESTスタイルで公開されているサービスを利用するケースも多々あるだろう。RESTEasyはそのような場合にも活用することができる。