Nanowebを強引に試してみる

codehausホスティングされているNanoContainer関係のコンポーネント?ファミリ?のnanoweb(今はnanowarにマージされてるの?)を試してみた。

pserverが使えない環境からのアクセスなので distサーバからSNAPSHOTを拾ってきて動作させる。サンプルも置かれているが動作しない。どうも、

DefaultPicoContainer   →  DefaultSoftCompositionPicoContainer

とかしないと駄目だった。このへんはまだ揺れてるみたい。でもとりあえず試すだけだし。

20回ぐらい試行錯誤してついにコンテキストの起動に成功。さっそくブラウザでアクセス!おお、出来た!出来たとなったらさっそくソースを追いかけてみる。

まず nanowebでは groovyのクラスがそのままStrutsでいうところのActionに相当しているようだ。ソースの断片を見て見ると

[game.groovy]

play() {
  .
  .
  return "input"
}

などと定義されており、このメソッドひとつひとつがActionを司っている。そういう意味ではStrutsのActionとは違って 1:Nというのか、そんな感じになっているわけか。
クライアントからのリクエストはこんな感じだった。

http://localhost:8080/nanoweb/game/play.groovy

これで "game/play.groovy"を解釈してくれるServletが、最終的にはgame.groovyのplay()をinvokeする、と。なんかちょっとややこしいね。

で、groovyのメソッドのreturn "input" はそのまま Velocityのファイル名に対応しているわけですね。ビューとの値の受け渡しはどうやるんだろう?

[game_input.vm]
       <p>
           ${action.hint}
       </p>
       <form action="play.groovy">
           <input name="guess" type="text" value="${action.guess}"/>
           <input type="submit" value="Guess"/>
       </form>

なるほど。Velocityのコンテキストに"action"がバインドされてるわけか。formのsubmit側は素直にnameに指定している、と。中身まだどうなってるか分からないけども action = game.groovyで定義しているクラスのインスタンス、となっている予感?
groovyは特になにも宣言しなければ

class Game {
    GUESS_NEW_HINT = "Guess a number between 1 and 20"

    NumberToGuess numberToGuess
    int guess = Integer.MIN_VALUE
    hint = GUESS_NEW_HINT

だけで、guessも hintも参照可能だから、ってことですかね。Javaから見たときのgroovyのこういうクラスはsetter/getterが自動的に定義されていたような気がします(ウソかもしれない)。

それだけか、と思ってたんですけど、さすがNanoContainerファミリ。

class Game {
.
    NumberToGuess numberToGuess
.
.
    Game(NumberToGuess n) {
        numberToGuess = n
    }
}

というわけで、このgroovyのクラス、constructor-based injectionなんですよ。で、このインジェクションにnanocontainer,picocontainerが活躍しているというわけですね。
はて、「コンポーネントの登録」はどこでしているのか…と思ったらこれはダサかった。

  
    nanocontainer.groovy
    
  

まあ、要するにS2でいうところの app.diconみたいなことが書いてあるわけですね。ちなみに、このスクリプト部分は外部ファイルに持つこともできるので「ひどすぎ」ということはありません。でもなんかもうちょっとやり方ないのかなあ?? > ifの羅列部分とか

とりあえず動いたので今日はここまで。NanoWebが誇らしげに言うように、本当に設定ファイルはありませんが、上のコンポーネント登録のとこだけが引っかかる。