Play framework 2.0でJSONPを使う

2012.04.03

JSONPとは?

JSONPとは、HTMLのscriptタグを使用してクロスドメインなデータを取得する仕組みです。
JSONでデータをやりとりする場合、通常は同一以外と通信することはできません。
しかし、HTMLのscriptタグのsrcに別ドメインのURLを指定して通信できる点を利用し、別ドメインのサーバからデータを取得することが可能になります。

JSONPではレスポンスの内容がjavascript関数呼び出しの形式となります。
そのため、src属性に指定するURLにその関数の名前をクエリ文字列として加えます。

<script type='text/javascript' 
     src='http://anotherDomain.com/getData?callback=foo'>

そしてレスポンスとして、下記のようなJSON形式のデータを引数とする関数の呼び出し文が返されます。

foo({"name":"syuta","age":30})

JSONPでレスポンスを受け取る

Playframework 2.0では最初からJSONをサポートしていますが、JSONPについては独自で実装する必要がありました。
しかし、現時点のHEADではJSONPのためのヘルパクラスが実装されているようなので、その紹介をします。

今回使用した動作環境は以下のとおりです。
現状リリースされているPlayframewor2.0ではJSONPのサポートが実装されていないため、HEADを取得してビルドします

  • OS : MacOS X 10.7.3
  • Playframework : HEAD
  • Java : 1.6.0_26

注意:
この記事ではgithubから取得したHEAD版を使用して試しています。
正式リリース前の状況のため思わぬ不具合が生じるかもしれませんので、ご了承ください。

ソースのHEADを取得してセットアップ

まだgithubからソースを取得していない人は、play2.0のソースを取得してビルドしましょう。

$ git clone https://github.com/playframework/Play20.git
$ cd Play20/framework
$ ./build
> complile
> build-repository
> publish-local

すでにソースを取得している人は、最新の状態に更新してビルドします。

$ git pull
$ cd Play20/framework
$ ./cleanEverything
$ ./build
> compile
> build-repository
> publish-local

これで準備ができました。

プロジェクト作成

Scalaベースのプロジェクトを作成し、sbtコンソールを起動します。

% play new jsonp
% cd jsonp
% play

ソースをEclipseで編集したいなら、eclipsifyを実行してeclipseプロジェクト化してインポートしてソースの修正をしましょう。

>[jsonp] $ eclipsify

サンプルコードを記述

今回はlocalhost:9000にアクセスしたらJSONPで通信を行い、結果をログに表示するだけの簡単なサンプルを作成します。
まずはデフォルトのコントローラを修正します。

package controllers

import play.api._
import play.api.mvc._

import play.api.libs.json._
import play.api.libs.json.Json._
import play.api.libs.Jsonp

object Application extends Controller {
  
  def index = Action {
    Ok(views.html.index("Your new application is ready."))
  }

  def jsonpService(callback:String) = Action {
	val json = JsObject(List("foo" -> JsString("bar")))
	Ok(Jsonp(callback, json))
  }
  
}

jsonpServiceメソッドでは、callbackパラメータを受け取ります。
そしてJSONデータを生成し、 JSONPクラスでラップして返します。
このメソッドをroutesファイルで指定しましょう。

GET  /jsonp-service                 controllers.Application.jsonpService(callback: String)

コントローラができたら、index.scala.htmlを修正します。
アクセス時にjQueryを使用してJSONP通信をするようにしてみましょう。 

@(message: String)

@main("JSONP in Play 2.0") {    
	<script type="text/javascript">
	  $(function() {
	    $.ajax({
	      url: "http://localhost:9000/jsonp-service",
	      dataType: "jsonp",
	      success:function(json){
	        console.dir(json);
	      },
	      error:function(){
	        alert('error');
	      }  
	    });
	  });
	</script>
    Hello!
}

これでアクセスすると、取得したJSONPデータがログに表示されます。
今回は同一ドメイン上で動作確認しましたが、別ドメインでも問題なく動作します。

まとめ

今回はPlayframework 2.0でのJSONP通信方法についてご紹介しました。
この機能はリリースされているバージョン(2.0)には入っていませんが、次のバージョンでは使用できるようになると思います。