Scala で JAX-RS(JSR-311) - Jersey の場合

以前 id:fits:20080522:1235531047 では Groovy で Jersey を使ってみたが、今回は Scala で試してみた。

使用した環境は以下の通り。

  • Scala 2.7.7
  • Jersey 1.1.4
  • JRuby 1.4.0(動作確認で使用)

Scala でサンプル作成

ScalaJAX-RS する場合の注意点は以下。

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"}]}