#Play'R v0.4
今回は、Play Scala 2.5で書かれているコレクション指向(?)のRESTフレームワークPlay'Rを試す。
https://github.com/26lights/PlayR
バージョンはまだ0.4と若いが、解説サイトが用意されている。
http://playr.26lights.com/index.html
使い方はシンプルで好感が持てる。
#例題を試す。
github側にかかれて通りように、sbtベースで動かす(compile/run)。
随時更新のようなので、動かないよ、とか怒られた時は、自ら直す。
サンプルのコードは短く見通しは良い。
##①playr-demo
コードは、
app/controller/PersonController.scala
のみのシンプルな例題。
Play'Rでは、以下のように書かれたPersonsをREST APIを介し公開できる。
case class Person(name: String)
@ImplementedBy(classOf[Persons])
trait PersonList {
val persons: Map[Int, Person]
}
class Persons extends PersonList{
val persons = Map(
1 -> Person("john"),
2 -> Person("jane")
)
}
公開は、PlayのController経由にPlay'RのResource系traitを付したコントローラーで行う。
case class PersonController(personList: PersonList) extends Controller
with Resource[Person]
with ResourceRead
with ResourceList {
def name = "person"
implicit val personFormat = Json.format[Person]
val persons = personList.persons
def fromId(sid: String): Option[Person] = toInt(sid).flatMap(persons.get(_))
def read(person: Person) = Action { Ok(Json.toJson(person)) }
def list() = Action { Ok(Json.toJson(persons.keys)) }
}
class PersonRouter @Inject() (personList: PersonList) extends RestResourceRouter(PersonController(personList)) with ApiInfo {
Logger.debug(s"Router instance created with person list: $personList")
}
解説は以下にある。
http://playr.26lights.com/demo.html
デバックモードで起動(sbt run)している時、コレクションを例えば以下のように更新すると、
class Persons extends PersonList{
val persons = Map(
1 -> Person("john"),
2 -> Person("jane"),
3 -> Person("石川五右衛門")
)
}
更新がPersonRouterに伝えられ、Logger.debugが走る。
curlでアクセスしてみる:
curl -f http://localhost:9000/person
[1,2,3]
curl -f http://localhost:9000/person/3
{"name":"石川五右衛門"}
Personクラスの定義を変更すると、
case class Person(name: String,age:Int)
@ImplementedBy(classOf[Persons])
trait PersonList {
val persons: Map[Int, Person]
}
class Persons extends PersonList{
val persons = Map(
1 -> Person("john",10),
2 -> Person("jane",22),
3 -> Person("石川五右衛門",34)
)
}
即反映される。
curl -f http://localhost:9000/person/3
{"name":"石川五右衛門","age":34}
##②playr-tutorial
こちらは少し複雑になっているので、チュートリアル文書を読みながら試すのが良さそう。
conf/routesは、以下の定義のみ。
# Routes
# This file defines all application routes (Higher priority routes first)
# ~~~~
-> /api controllers.Application
GET /*file controllers.Assets.at(path="/public", file)
sbt runした後、ついつい/apiにアクセスしたくなるが、404となる。
curl -f http://localhost:9000/api
curl: (22) The requested URL returned error: 404 Not Found
Play'Rでは、上のroutesの定義は、
/api以下のアクセスは、controllers.Applicationがコントロールすると読むのが正しい。
app/controller/Application.scalaを見てみる。
class Application @Inject()(val cache: CacheApi, crmApi: CrmApi) extends PlayRRouter with PlayRInfo {
implicit val colorContainer = ColorContainer(cache)
val api = RootApiRouter()
.add(new ColorController)
.add(crmApi)
.add(EnumValuesController(DaysEnum))
.withFilter(LoggingFilter)
val info = Map(
"info" -> ApiInfo,
"jquery.js" -> JQueryApi
)
}
RESTインターフェースを
val api = RootApiRouter().add(new ColorController).add(crmApi)...
といった具合に追加していくものらしい。
いろいろとアクセスを試してみる。以下、わかりやすさからhttpieを用いる
参考 curlを捨ててhttpieを使おう #curlは捨てなくて良いが..
> http GET localhost:9000/api/color
HTTP/1.1 200 OK
Content-Length: 9
Content-Type: application/json
Date: Sat, 30 Apr 2016 03:49:56 GMT
[
1,
2,
3,
4
]
POSTしてみる。
あれ?
ヘッダーのパラメータに入れても :
http -v POST localhost:9000/api/color name:fakePurple rbg:#123456
JSONで送っても :
http -v POST localhost:9000/api/color name=fakePurple rbg=#123456
エラーになる。
DELETEはできた:
このあたりはもう後で見直すこととしよう。。。
この例題では、会社-職種-従業員 <-> Person的な入れ子関係のRESTインターフェースも提供されている:
こちらはweb DB的なものを作る時に参考になりそう。
###jquery.scala.jsも
アクセス方法がわからなかったが、scala.jsも使われている模様。
#感想
今回は、ちら見しただけだが、Scala使いな人が、さくっとPlay scalaでRESTしたい時には良いのかも。
前回見たBaasBoxはPlay2.2でがっつり書かれたRESTなmBaaS。BaasBoxそのものの改造/改良は大変な感じ...、なので、このPlay'Rに、BaasBoxのRESTインターフェースを移してのは学習として良いかも!?