はじめに
前回までで、LiftのViewとModelを利用した簡単なアプリケーションの作成までを解説してきました。
本連載は今回で最終回となります。これまでのまとめの意味もこめて、いままで作成してきたTwitterのクローンのようなアプリケーションを改良して、Liftの目玉であるAjaxとCometを利用したアプリケーションの作成方法を解説します。
対象読者
- Javaは知っているが、Scalaも学んでみたいと思っている方
- ScalaでのWebアプリケーション開発に興味がある方
必要な環境
最低動作環境
- J2SE 5.0 JDK
推奨環境
- J2SE 6.0 JDK
- Apache Maven 2.10
- Scala 2.7.5
Ajaxを利用した処理
LiftにおけるAjax
LiftでAjaxを利用する方法は、とてもシンプルです。通常、Ajaxを利用したアプリケーションでは、ブラウザ側にJavaScriptを利用してXMLHttpRequestをサーバーに送信する処理を作成したうえで、サーバー側の処理を用意する必要があります。
この場合、ブラウザ側はHTMLとJavaScriptであり、サーバー側とは異なった知識が必要です。
Liftの場合は、JavaScriptライブラリとしてはデファクトスタンダードとなっているJQueryと統合されており、複雑なJavaScriptを実装せずとも、ScalaのプログラムだけでAjaxを利用した処理を行えるようになっています。
これより、どのようにしてLiftでAjaxを利用するのか、例を見ながら解説します。
シンプルなAjax
ここでは、最もシンプルなAjaxの処理を作成してみます。
Liftで生成したアプリケーションのTopページに配置したボタンを押すと、Ajaxでサーバーにリクエストを送信し、「こんにちわ! ○○さん。」のような挨拶文をサーバー側で生成してdivタグに表示させるようにしてみます。
テンプレートの用意
Topページに対応するテンプレートファイルに、Ajaxを利用したボタンを生成するSnippetを呼び出すためのXMLタグを追加します。「src/main/webapp/index.html」を、リスト1の内容に修正します。
<lift:surround with="default" at="content"> <h2>Welcome to your project!</h2> <p><lift:helloWorld.howdy /></p> <!-- Ajaxを利用したボタンを生成するSnippetを呼び出すタグを追加 --> <lift:helloWorld.greating > <div id="greating-div"/> <greating:button /> </lift:helloWorld.greating> </lift:surround>
太字の部分を追加します。
<lift:helloWorld.greating >は、HelloWorld Snippetの呼び出しに対応しており、内包するdivタグに、サーバー側で生成した挨拶文が出力されます。
<greating:button />の部分は、Snippetで生成したボタンに置き換えられます。
Snippetの用意
あらかじめ生成されているHelloWorldクラスを修正します。
「src/main/scala/demo/helloworld/snippet」ディレクトリに、「HelloWorld.scala」という名前のファイルをリスト2の通りに修正します。
package demo.twitterclone.snippet // 必要なimportを追加 import _root_.net.liftweb.http.SHtml._ import _root_.net.liftweb.util.Helpers._ import _root_.net.liftweb.http.js.JE._ import _root_.net.liftweb.http.js.JsCmds._ import _root_.scala.xml.{NodeSeq, Text } import _root_.net.liftweb.util.{Box, Full} import _root_.demo.twitterclone.model._ class HelloWorld { def howdy = <span>Welcome to twitterclone at {new _root_.java.util.Date}</span> // Ajaxを利用したボタンを生成するSnippet関数 def greating(html: NodeSeq) : NodeSeq = { // *1 // bind関数を利用してボタンを生成 bind("greating", html, // ajaxButto関数でサーバーへAjaxでリクエストを // 送信するボタンが生成される "button" -> ajaxButton( Text( "押して"),{ // *2 // 第2引数には、Ajaxで呼び出されたときの // サーバー側の処理を関数オブジェクトで渡す () => { // ログ出力 println("Ajaxで呼び出されました。") // *3 // ログインしているユーザー名を取得 val username = User.currentUser.dmap( "Guest" ){ _.shortName } // *4 // "greating-div"に挨拶文を出力するJavaScriptを生成する SetHtml("greating-div", Text ("こんにちわ! %sさん。".format( username ))) // *5 } }) ) } }
greating関数(*1)が、先ほどindex.htmlに追加したタグから呼び出されるSinppet関数です。前回までで説明した、bind関数で、<greating:button/>タグをボタンに置きかえています。ここまでは、これまで説明してきたbind関数を利用した処理と変わりありません。
*2の部分で、ajaxButton関数を呼び出して<greating:button/>タグの内容を生成しています。ajaxButton関数は、第1引数にボタンに表示する文字列を渡します。
第2引数には、ボタンを押された時のサーバー側の処理を、関数オブジェクトで渡します。ここでは、ログを出力し(*3)、現在ログインしているユーザーの名前を取得し(*3)、「greating-div」に挨拶文を出力(*4)しています。
*4の処理は、サーバー側で実行されているように見えますが、実はSetHtmlオブジェクトによって、レスポンスとしてブラウザにJavaScriptが送信されているのです。
このようなSetHtmlオブジェクトのように、JavaScriptを生成するものは、JsCmdトレイトを継承しており、他にも多数用意されています。
LiftのAjax処理では、Ajaxで呼び出された際の関数オブジェクトの返り値に、SetHtmlオブジェクトなどJavaScriptを表すオブジェクトを返すことで、ブラウザ側でさまざまな処理を行わせることができます。
動作確認
では、「mvn jetty:run」コマンドで開発サーバを起動して、「http://localhost:8080/」にアクセスして動作確認してみましょう。次のように表示されるはずです。
この[押して]ボタンが、greating関数によって作成されたものです。ボタンを押すと、ログインしているユーザー名の挨拶文がボタンの上に表示されるはずです。
サーバ側のログを見てみましょう。ajaxButton関数に渡した関数オブジェクトによって出力されたログが出ていることが確認できます。
INFO - Service request (GET) /classpath/json.js took 2 Milliseconds INFO - Service request (GET) /ajax_request/liftAjax.js took 1 Milliseconds INFO - Service request (GET) /images/ajax-loader.gif took 1 Milliseconds INFO - Service request (GET) /favicon.ico took 1 Milliseconds Ajaxで呼び出されました。 INFO - Service request (POST) /ajax_request/F919374770649GDI/ took 4 Milliseconds INFO - Service request (POST) /ajax_request/F919374770646WNK/ took 1 Milliseconds
SetHtmlオブジェクトを返すことにより、ブラウザにJavaScriptを送り返すことができると説明しました。実際には、どのようなレスポンスが返されているのでしょうか?
リスト4は、FireBugを用いてサーバーより返却されたレスポンスの内容を確認したものです。jQueryを用いたJavaScriptが出力されていることが分かると思います。
try{jQuery('#greating-div').each(function(i) {this.innerHTML = '\u3053\u3093\u306b\u3061\u308f! Guest\u3055\u3093\u3002';});} catch (e) {}
LiftでのAjax処理の特徴としては、Ajaxで呼び出されたサーバー側の処理を、関数オブジェクトして登録しておくだけで、簡単にScalaのコードのみで実装できるという点です。もちろん、任意のJavaScriptを組み込むことも可能です。
この関数オブジェクトを利用したAjax処理は、これまでに説明してきたFunction Mappingという機能で実現されています。Function Mappingは通常のHttpリクエストの他に、AjaxによるXMLHttpRequestに対しても任意の処理を関数オブジェクトとして割り当てることが可能なのです。
このように、LiftではScalaのコードのみでJavaScriptを一切書かずにAjaxを利用した処理を作ることができる、ということを理解していただけたと思います。