標準のAPIを使ってプログラムを書いておくと色々と都合がいいので、RESTfulなWebサービスを作成しようとするときはJAX-RSを使いたいものです。
JavaEE6には初めから入っているJAX-RSですが、現場ではTomcat5.5(もちろんJava5です)とかが頑張っているのでそのままでは使えません。Apache Tomcat 5.5 と、JAX-RSのリファレンス実装である Jersey 1.4 を使って、単純なRESTサービスを実装する手順を紹介します。
まずはJersey1.4のインストールから。Maven2を使っている場合は、java.netのリポジトリを設定します。
(pom.xml に以下を追加) <repositories> <repository> <id>maven2-repository.dev.java.net</id> <name>Java.net Repository for Maven</name> <url>http://download.java.net/maven/2/</url> <layout>default</layout> </repository> </repositories>
サーバアプリケーション側のライブラリは以下です。
(pom.xml に以下を追加) <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-server</artifactId> <version>1.4</version> </dependency>
jarをそのまま使いたい場合は、 http://jersey.java.net/ のDownloadからライブラリをダウンロードしてクラスパスに含めましょう。
入門にはありがちですが、まずは単純に"Hello World!"という文字列を返すだけのRESTサービスを構築してみます。以下のクラスを作成してください。
jerseytest.resources.HelloworldResource
package jerseytest.resources; import javax.ws.rs.GET; import javax.ws.rs.Path; @Path("/helloworld") public class HelloworldResource { @GET public String getMessage() { return "Hello World!n"; } }
サービスの記述はこれだけです。アノテーションについては後で解説することにしましょう。
次にweb.xmlにサーブレットの設定をします。
<servlet> <servlet-name>JAX-RS Servlet</servlet-name> <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> <init-param> <param-name>com.sun.jersey.config.property.packages</param-name> <param-value>jerseytest.resources</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>JAX-RS Servlet</servlet-name> <url-pattern>/rest/*</url-pattern> </servlet-mapping>
jerseyに含まれているサーブレットクラスを指定して、初期化パラメータとしてサービスを記述したクラスのパッケージ名を与えるだけです。
それではアプリケーションをTomcatに配備して、サービスを参照してみましょう。
$ curl "http://localhost:8080/jerseytest/rest/helloworld" Hello World!
おお!ちゃんど文字列が返ってきましたね!
RESTサービスでは、”サービスはURLで指定されるweb上のリソースである”と考えます。それで先ほどのHelloworldResourceクラスにもResourceと名付けていました。
そのリソースクラスで使用した2つのアノテーションを説明します。
RESTサービスでは、サービスを提供するために必要な引数をURLのクエリパラメータとして受け取ることがあります。クエリパラメータを受け取るリソースクラスを作成してみましょう。
jerseytest.resources.SayHelloResource
package jerseytest.resources; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; @Path("/sayhello") public class SayHelloResource { @GET public String say(@QueryParam("name") String name) { return String.format("Hello %s!%n", name); } }
では実際にサービスを参照してみます。
$ curl "http://localhost:8080/jerseytest/rest/sayhello?name=George" Hello George!
確かにクエリパラメータを受け取ることができていますね。
引数をURLのパスに含めたいこともあるかもしれません。その場合には次のようなコードにします。
jerseytest.resources.SayHelloResource2
package jerseytest.resources; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; @Path("/sayhello2/{name}") public class SayHelloResource2 { @PathParam("name") private String name; @GET public String say() { return String.format("Hello %s!%n", name); } }
今度はプロパティにセットするようにしました。また、@Pathの指定方法にも注目してください。
サービスを参照すると以下のようになります。
$ curl "http://localhost:8080/jerseytest/rest/sayhello2/emily" Hello emily!
新たにパラメータを扱うアノテーションが2つ登場しました。
ここまでで、サービスの記述とURLとのマッピング、そしてパラメータの取り出しなどが簡単にできることがお分かり頂けたと思います。
ただ、これまでのところ単純な文字列を返すサービスを構築しただけで、まったく現実的なサービスを提供できたとは言えません。次回はXMLやJSONを返すサービスを構築する手順を紹介しようと思います。