Scala で JAX-RS(JSR-311) - Jersey の場合
以前 id:fits:20080522:1235531047 では Groovy で Jersey を使ってみたが、今回は Scala で試してみた。
使用した環境は以下の通り。
Scala でサンプル作成
json_jersey.scala
import scala.reflect.BeanProperty import scala.collection.mutable.ListBuffer import javax.ws.rs.{GET, POST, Path, PathParam, Consumes, Produces} import javax.xml.bind.annotation.XmlRootElement import com.sun.jersey.api.core.ClassNamesResourceConfig import com.sun.jersey.api.container.httpserver.HttpServerFactory import com.sun.jersey.api.container.ContainerFactory import com.sun.jersey.spi.resource.Singleton //JAXB @XmlRootElement class Customer(@BeanProperty var id: String, @BeanProperty var name: String) { //JAXB にはデフォルトコンストラクタが必須 def this() = this("", "") } //リソースクラス //シングルトンにするために @Singleton を設定 @Path("customers") @Singleton class CustomerResource { val customerList = new ListBuffer[Customer] //Customer の新規追加 @POST @Path("add") @Consumes(Array("application/json")) def addCustomer(customer: Customer): Unit = { customerList += customer } //指定インデックスの Customer 取得 @GET @Path("{index}") @Produces(Array("application/json")) def getCustomer(@PathParam("index") index: Int): Customer = { customerList(index) } //全 Customer の取得 @GET @Produces(Array("application/json")) def getCustomers(): Array[Customer] = { customerList.toArray } } object JerseyJsonTest extends Application { //動作確認用のサーバー定義(上記リソースクラスを localhost:8082 で公開) val server = HttpServerFactory.create("http://localhost:8082/", new ClassNamesResourceConfig(classOf[CustomerResource])) server.start() println("server started") //停止させるには Ctrl + C }
ビルドと実行
CLASSPATH に Jersey の lib ディレクトリ内の JAR ファイルを設定し、ビルドと実行を行う。
>scalac json_jersey.scala >scala JerseyJsonTest 2009/11/15 19:08:53 com.sun.jersey.server.impl.application.WebApplicationImpl initiate 情報: Initiating Jersey application, version 'Jersey: 1.1.4 11/10/2009 05:36 PM' server started
動作確認
動作確認は Ruby スクリプトで実施してみた。(Ruby にした理由は特に無いが、JSON データを POST するのが楽そうだったんで)
まず、http://localhost:8082/customers/add に Customer の JSON データを POST する処理を実装。POST の際に content-type で application/json を指定する。
add_customer.rb(Customer 追加)
require 'net/http' if ARGV.length < 2 puts ">ruby #{__FILE__} [id] [name]" exit end Net::HTTP.version_1_2 Net::HTTP.start('localhost', 8082) do |http| id= ARGV[0] name = ARGV[1] json = "{\"id\": \"#{id}\",\"name\":\"#{name}\"}" puts json res = http.post('/customers/add', json, { 'content-type' => 'application/json' }) p res end
実行結果1(Customer 追加)
>jruby add_cusotmer 1 TestData1 {"id": "1","name":"TestData1"} #<Net::HTTPNoContent 204 No Content readbody=true> >jruby add_cusotmer 2 TestData2 ・・・ >jruby add_cusotmer 3 TestData3 ・・・
次に、http://localhost:8082/customers から全 Customer の内容を取得する処理を実装。
get_list.rb(全 Customer 取得)
require 'net/http' Net::HTTP.version_1_2 Net::HTTP.start('localhost', 8082) do |http| res = http.get('/customers') p res puts res.body end
実行結果2(全 Customer 取得)
>jruby get_list.rb #<Net::HTTPOK 200 OK readbody=true> {"customer":[{"id":"1","name":"TestData1"},{"id":"2","name":"TestData2"},{"id":"3","name":"TestData3"}]}