AjaxSliderを作ってみたけど……

WicketとjQueryの連携にwiQueryを使ってスライダーを使いたい。

AjaxSliderクラスを継承。スライダーのつまみを掴んだ瞬間、startイベントでサーバサイドにイベントを通知して、アトはslideイベントにバインドして、つまみを掴んでいる間は、jQueryで処理というクラスを作ってみた。

使用したバージョンはwiQuery1.5.0 wicketは1.5.2

ちなみに、wiQueryではsetter系メソッドでいろいろと処理が動いているので
getter系メソッドでオーバーライドとかしないようにしている。

public class HogeSlider extends AjaxSlider {

  public HogeSlider(String id, Number min, Number max) {
    super(id, min, max);
  }

  @Override
  protected void onInitialize() {
    super.onInitialize();

    // スライド中のイベント
    setSlideEvent(new JsScopeUiEvent() {

      @Override
      protected void execute(JsScopeContext scopeContext) {
        // あとからsetAjaxStartEvent()を登録すると無効になる。
        scopeContext.append("console.log('slide now');");
      }
    });

    // スライド開始時にAjax通信する
    setAjaxStartEvent(new ISliderAjaxEvent() {

      @Override
      public void onEvent(AjaxRequestTarget target, AjaxSlider slider, int value, int[] values) {
        System.out.println("ajax start event!!");
      }
    });
  }
}

が、イベントが思うように動作しない。

しょっちゅうサーバサイドと通信が走るし、console.logには何も出力されなくなりsetSlideEvent()の処理が動かない。ようするに使えない。

setAjaxStartEvent()をコメントアウトすると、正常に’slide now’という文字が出力される。
悪さをしているのはsetAjaxStartEvent()で間違いない。

AjaxSliderクラスを確認する。

  public void setAjaxStartEvent(ISliderAjaxEvent ajaxStartEvent)
  {
    this.ajaxEvents.put(SliderAjaxEvent.ajaxStartEvent, ajaxStartEvent);
    setSlideEvent(new SliderAjaxJsScopeUiEvent(this, SliderAjaxEvent.ajaxStartEvent));
  }

はい、ビンゴ!

slideイベントに登録されてる。本来ならstartイベントであるはずだ。

ついでに、AjaxSliderクラスの親クラスであるSliderクラスのsetSlideEvent()も調査。

  public Slider setSlideEvent(JsScopeUiEvent slide)
  {
    this.options.put("slide", slide);
    return this;
  }

this.options.put()しているのはただのMapなのでイベントは上書きされて、最初にsetSlideEvent()で登録したイベントは無効になる。これで現象は全部つかめた。

イベントの上書きは、とりあえず妥協してもいいだろう。しかし、バインドするイベントは間違えては困る。スコープの関係でAjaxSliderクラスそのものを修正しなければならない。

  public void setAjaxStartEvent(ISliderAjaxEvent ajaxStartEvent)
  {
    this.ajaxEvents.put(SliderAjaxEvent.ajaxStartEvent, ajaxStartEvent);
    //setSlideEvent(new SliderAjaxJsScopeUiEvent(this, SliderAjaxEvent.ajaxStartEvent));
    setStartEvent(new SliderAjaxJsScopeUiEvent(this, SliderAjaxEvent.ajaxStartEvent));
  }

として再コンパイルすれば期待通りの動作となる。

ITコミュニティ夏祭り

カルカルのスライドをアップしました。

前半のまじめな部分って2,3枚ぐらいで十分だったような気がするし
継承の話以外は全部省略してよかった気がする。

ちょっとづつ暴走……みたいにやってみたい。
LTヘタだなぁと思い反省。

関連リンク
http://el.jibun.atmarkit.co.jp/topics/2011/08/it-474f.html
http://tcc.nifty.com/cs/catalog/tcc_schedule/catalog_110816203681_1.htm
http://www.ustream.tv/recorded/17324450
http://www.ustream.tv/recorded/17326509
http://togetter.com/li/189266

コラムニストとして情報発信をするということ

OSC京都2011 もうひとつのセミナー(?) LT大会の資料&UST

USTは13分ちょっとすぎたあたり

jQueryプラグインの「使い方」ではなく「作り方」

OSC京都の セミナー資料とデモとUST

デモ IEでは動きません(TT)
プラグイン
UST

jQueryの空判定

jQueryのソースを眺めていたら、オブジェクトの空判定をするコードを見つけた。

isEmptyObject: function( obj ) {
  for ( var name in obj ) {
    return false;
  }
  return true;
},

普通ならnullチェックをするような処理である。しかし、javascriptにはnull以外にもundefinedという未定義値が存在する。これらを一個づつチェックしていく方法ももちろん正しい。

javascriptのfor/in文は、オブジェクトのプロパティごとにループを回す。プロパティが存在すればループ内部が実行し、falseを返す。オブジェクトが空の場合、プロパティが存在しないのでforループそのものが実行されず trueが返される。

仮にループが実行されたとしても、ループ内処理は、たった一回しか実行されない。この文脈においてfor/in文はif文と同じ役割を果たしているのだ。

査読論文を提出してきた

全125ページ。読めるものな読んでみやがれってんだ(^^)

ダメ出しもあるだろうし発表資料とか作らなくちゃいけないんだけど、一区切りついたような気がする。2年前と比べて何か変わったのだろうか。ちゃんと真摯に向き合えただろうか。ちゃんとレベルアップできたのだろうか。

こういう一区切りついた瞬間は何もかもが真っ白になる。気持ちににムラッ気があるのは悪いクセだ。もうひと踏ん張り、残り一ヶ月がんばる。

自分の知らない言葉は検索できない

デジタルな世界は能動的に動くことを是とする。受身で情報収集していてるのならアナログな世界で情報を得ることと変わらないない。yahooニュースでニュースを知ることと、朝のニュース番組でニュースを知ることにそんなに違いはない。

インターネットで、わからない言葉に出会ったときに瞬時に検索できるって言うよね。だけど、よくよく考えればニュース番組だって丁寧に解説してくれているじゃないか。

本屋さんで何気なくとった本が世界を広げてくれる。そんな感覚をネットの世界に持ち込んだのがtwitterなりMIXIなりの友達がしゃべった言葉だ。

デジタルな検索の世界には偶然の出会い、セレンディピティがない。もちろん、そこに挑戦する動きも当然のごとくある。twitterの中から重要っぽい言葉を重み付けして、自分の発言を係数にしたら、みたいなアルゴリズムを考えるのが次世代検索エンジンなんだろう。

検索のインプットが単なる単語、キーワードでは足りなくなった。人が面白いと思う感覚は千差万別だ。「面白い画像」に対する検索結果がすべての人にとって同じ結果ではなくて、わたしだけの結果であること。自分の発言やネット上での行動から文脈、コンテキストをキーにする。そういう検索方法っていうのが今後生まれてくる。

そんな検索エンジンが実現できたとして……

そこで自分も知らない結果が突きつけられたら?
自分でも気づかなかった新しい「面白い画像」であればいい。例えば、とんでもなく猟奇的な画像を「面白い画像」の検索結果として突きつけられたらどうなるだろう。

技術は使い方である。コンテキスト検索が自分自身の持つ闇の感情やネガティブな思想を呼び起こすプログラムだとしたら、その結果を直視できるだろうか。

ソーシャル・ネットワーク

マーク・ザッカーバーグは「世界で最も若い10人の億万長者」のひとりである。「ソーシャルネットワーク」は彼が大学時代に作ったWebアプリケーション「facebook」とそれにまつわる物語だ。

彼の在籍するハーバード大学限定で始まった「facebook」は瞬く間にキャンパスを席巻。少しづつサービスを拡大し数年で5億人が使うアプリケーションにまで成長した。世界人口が69億人。世界の14人にひとりが使っている計算である。

誰もが使いたがるソフトウェアは金のなる木だ。「facebook」が成長していく過程で買収の話は幾度となくあった。売れるソフトウェアに買収の話はつきものである。いかに高値で大企業に買われるか?大学発のベンチャー企業が考えるゴールのひとつだ。

しかし、自分のチカラでゼロから生み出したソフトウェアはエンジニアにとって宝物である。会社ごと売り払って大金を手にするか、会社を存続させてソフトウェア開発を続けるか。2択を迫られる。10億ドルを突きつけられて平気な人間などいやしない。そういうギリギリの葛藤の世界だ。

この映画の面白いところは、主人公の行動原理がハッカー的な思考にもとづいていることにある。ビジネスマンであるよりもプログラマーであることに価値観を置く。さきほどの買収話もそのハッカー的思考にもとづいて判断をくだす。その考え方は共感を覚える。

いままでにいろんなビジネス書を読んできてしっくりとこない理由がわかった気がした。。ビジネスマン的思考はわたしのモノの考え方にそぐわない。自分の考え方はプログラマーのそれであり、エンジニア的思考のそれであり、ハッカー文化のそれである。立ち居地がそこにあること確認することができた。

「シンプルにやれ」

エンジニアはもっと自由であっていいんだと思う。

GlassFishV2.1のクラスタでおこる、ふたつのバグと回避策

GlassFishのバグを見つけたので詳細報告。OSS版でも同じ現象が起こるかもしれない。

現象詳細
GlassFish V2.1系でインメモリーレプレケーションでクラスタを構築、ロードバランサープラグインを使いApacheなどのWebServerからロードバランシングを行う。このとき、セッション内容とスティッキー性が失われる場合がある。

■セッションの消失
   新しいSessionIDが発行され、それまでのセッション内容が保持できない
   F5キーを押下し続けて連続でリロードを行った場合に再現される
■ スティッキー性の消失
  同一クライアント、同一セッションでアクセス中に接続されているインスタンスが固定されない

上記、現象が併発した場合、同一SessionIDにもかかわらずインスタンスごとに違う内容のセッションを保持しているケースも確認された。

原因
■ セッションの消失

複数のクライアントから同時に同じSessionIDへアクセスした場合に、SessionIDが変わることがある。F5押下(KeyPress-Keep)による連続リロードや複数のAjaxによる同一SessionIDへアクセスした場合などに発生する。

Cookie情報であるJSESSIONIDVERSIONがセッション情報のキャッシュを管理している。通常、同一セッションへのアクセスごとに連続した値(プラス1づつカウントアップ)を返すが、同時に同じセッションIDへアクセスした場合に、不正な値を返す場合がある。

JSESSIONIDVERSIONが不正な値を返した場合に、それまでのSessionIDが無効と判断され新しいSessionIDが発行される。

■ スティッキー性の消失

Cookie情報のうちJROUTEの値が稼動しているインスタンスの識別子となる。アクセスしているインスタンスが停止した場合、稼動中のインスタンスに対応する識別子に変更される。

JROUTEを書き換えるのはロードバランサプラグインが行うが、設定ファイルであるloadbalancer.xmlがCookie情報の書き換え禁止するオプションで出力されている。アクセス中のインスタンスが停止した場合、JROUTEが設定されずスティッキー性が失われる。

回避策

■セッションの消失への対応
relaxCacheVersionSemanticsを設定する。ただし、9.1U2P05以降でのみ有効

配備するsun-web.xmlに非公開パラメータである以下を記述
  <session-config>
    <session-manager persistence-type=”replicated”>
      <manager-properties>
        <property name=”relaxCacheVersionSemantics” value=”true”/>
      </manager-properties>
この設定によりJSESSIONIDVERSIONが正しい値を返すようになる。

実は、このrelaxCacheVersionSemanticsは非公開パラメータ。マニュアルに載せて欲しいとは言っておいたがどうなるのだろう。

■ スティッキー性の消失への対応

一時的な回避策としてloadbalancer.xmlに以下を記述する(falseからtrueに変更)。
または、設定を削除する。

 <property name=”rewrite-cookies” value=”true”/>

この設定によりアプリケーションサーバでCookie情報(JROUTE)の書き込みを許可する。ただし、現在、Oracleが対応しているバグ修正では、GlassFishでJROUTEへの書き込みを行うため、修正版のリリース後は、上記設定は不要になるはず。

V3での対応は不明だがお願いはしておいた。たぶん、ちゃんと対応してくれるはず。
オマケ GlassFishのコードを簡単にカスタマイズする

GlassFishで使用されている同名クラスを作成して、jarにまとめる。

GlassFishの管理GUIからConfiguration->server-config->JVM Settings->Path Settingsへと進む。Classpath Prefixにjarファイルを設定後、GlassFishを再起動

オリジナルのコードが既存のJavaクラスに上書きして使用される。

大学院ではロボットを研究しているんだ

中間発表のスライドをUPしたよ。

ついでにテーマ発表のスライド。
半年前から進展しているんだろうか……