Shoeisha Technology Media

CodeZine(コードジン)

特集ページ一覧

AjaxとCometを利用したLiftのアプリケーションを作る

Scala+Liftによる実践Webアプリケーション開発(5)

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2010/03/15 14:00

 前回までで、LiftのViewとModelを利用した簡単なアプリケーションの作成までを解説してきました。本連載は今回で最終回となります。これまでのまとめの意味もこめて、いままで作成してきたTwitterのクローンのようなアプリケーションを改良して、Liftの目玉であるAjaxとCometを利用したアプリケーションの作成方法を解説します。

目次

はじめに

 前回までで、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の内容に修正します。

[リスト1]src/main/webapp/index.html(追記は太字部分)
<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の通りに修正します。

[リスト2]HelloWorld.scala
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/」にアクセスして動作確認してみましょう。次のように表示されるはずです。

図1:生成された、Ajaxによるボタン
図1:生成された、Ajaxによるボタン

 この[押して]ボタンが、greating関数によって作成されたものです。ボタンを押すと、ログインしているユーザー名の挨拶文がボタンの上に表示されるはずです。

図2:Ajaxによる呼び出しの結果
図2:Ajaxによる呼び出しの結果

 サーバ側のログを見てみましょう。ajaxButton関数に渡した関数オブジェクトによって出力されたログが出ていることが確認できます。

[リスト3]Ajax呼び出しの時のサーバー側ログ
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が出力されていることが分かると思います。

[リスト4]SetHtmlオブジェクトによりブラウザに返却された内容
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を利用した処理を作ることができる、ということを理解していただけたと思います。


  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XMLD...

  • WINGSプロジェクト 尾崎 智仁(オザキ トモヒト)

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂...

バックナンバー

連載:Scala+Liftによる実践Webアプリケーション開発
All contents copyright © 2005-2018 Shoeisha Co., Ltd. All rights reserved. ver.1.5