ログ日記

作業ログと日記とメモ

LiftでビューのHTMLを動的に更新するためのメモ

http://www.slideshare.net/fungoing/webscalaliftui-first
ここの20ページ目に

※Viewの更新は再コンパイル不要
LiftはViewからロジックが完全に切り離されて いるので、Viewの更新はサーバを起動したま ま行うことができます。 UIは文言やレイアウトなど細かい調整が入るこ とが多いのでこれは大きなメリットです。

Viewの配置作業もBoot.scalaが変わる時以外 は起動したまま作業ができます。

http://www.slideshare.net/fungoing/webscalaliftui-first

こう書いてあるが、これって開発時だけ?完成したあとにちょっとした文章編集だとやっぱりwarからアップし直し?と思ったので試した。



まずはLiftのRun Mode。

Development

  • Snippet errors are shown in the browser
  • Comments are retained in XHTML (comments are stripped out in other run modes)
  • Non-minified version of JavaScript libraries (e.g., JQuery) are served

Production deployments
Production, Staging and Pilot are all considered to be production-level deployments, and as such have similar differences:

  • Templates are cached in memory
http://www.assembla.com/wiki/show/liftweb/Run_Modes

productionモードだとHTMLをキャッシュするらしい。
まずはその動作を試す。
GlassFishの場合は「設定」→「server-config(利用している設定)」→「JVM 設定」の「JVM オプション」タブの項目に -Drun.mode=production を追加して再起動する。
モードの確認は Props.mode.toString を表示すれば簡単。
Productionを確認してからglassfish/domains/domain1/applications/myapp 以下のHTMLファイルを編集してブラウザをリロード。キャッシュされているので予想通り更新されない。


キャッシュ設定の流れ、というかBootの流れは
http://d.hatena.ne.jp/katzchang/20110607/p1
ここが詳しい。

  private def postBoot {
    try {
      ResourceBundle getBundle (LiftRules.liftCoreResourceName)

      if (Props.productionMode && LiftRules.templateCache.isEmpty) {
        // Since we're in productin mode and user did not explicitely set any template caching, we're setting it
        LiftRules.templateCache = Full(InMemoryCache(500))
      }
    } catch {
      case _ => logger.error("LiftWeb core resource bundle for locale " + Locale.getDefault() + ", was not found ! ")
    } finally {
      LiftRules.bootFinished()
    }
  }
http://d.hatena.ne.jp/katzchang/20110607/p1

こういうことらしい。
さっそくソースを探索。
InMemoryCacheはTemplateCache.scalaにあった。同じソースにNoCacheというオブジェクトを発見。


ということは…

    LiftRules.templateCache = Full(NoCache)

Boot.scala にこれを書くとキャッシュを無効にできる。
試しにHTMLファイルを編集してブラウザをリロードすると…更新された!
Boxとか知らないレベルだったのでソース探索に時間がかかったがscalaに慣れてる人なら一瞬で出来たかもしれないくらいの分かりやすさ。


あとはアップロードの仕組みだね。
未だに分からないんだけど、Javaでの開発ってFTPしか使えないデザイナーは直接的な更新は何も出来ない?
少しの文面変更でHTMLを渡してもらってこっちで更新っていうのはやってられないのでまずはシンボリックリンクを試す。
GlassFishの設定で

  <sun-web-app>
    <property name="allowLinking" value="true"/>
  </sun-web-app>
http://wikis.sun.com/display/GlassFish/FaqActivateSymbolicLinksJa

これを書くとシンボリックリンクが有効になるらしい。
これで動作中のアプリケーションのディレクトリから適当なユーザーのホームディレクトリの中にシンボリックリンクを張る。

ln -s /home/ftpuser/lifthtml /opt/glassfish3/glassfish/domains/domain1/applications/liftdemo/static

例えばこんな感じ。
これで、サーバー再読込の必要なしに任意ユーザーのディレクトリのファイルを更新することでHTMLの変更が可能になった。



アプリを再デプロイしたらリンクが消えると思ってたんだけど消えなかった。
それどころか、なんか色々維持したまま再デプロイできる? http://weblogs.java.net/blog/swchan2/archive/2011/03/09/keepstate-keepsessions-keep-state-save-sessions-enabled-glassfish-31
これならPHPのように本番環境を度々更新する方針でも大丈夫なんじゃないか?という気がしてきた。


※ 8/16 追記
再デプロイじゃなくて配備解除してもリンクが残ってる! 他のファイルは綺麗に消えているのにシンボリックリンクだけ残ってる。これって正式な動作なんだろうか?個人的にはこの動きはありがたいが、今のバージョンで偶然そうなってるだけだと困るな…。


※ 8/17 追記
アプリのディレクトリに .glassfishStaleFiles というファイルができていて、ここにシンボリックリンクのファイルが書かれている。検索してもヒット数ゼロという状態なのでまたあとで。