Hatena::Grouparaistudy

czk-htnの日記

2010-01-02

[] Wicket-1.4.2 + Flexigrid-1.0b3 + JSONIC-1.0.4 06:45

処理の流れ

  1. Wicketでページ出力。ページ内にFlexigridのJavaScriptを埋め込む
  2. 画面が表示されるとFlexigridからAJAXサーバJSONが要求される(GETメソッドで)
  3. サーバ側は(Wicketでなく)JSONIC付属の net.arnx.jsonic.web.WebServiceServlet で受け付ける
  4. Serviceクラスを作成しfindメソッドを実装
  5. Flexigridが要求するJSONデータになるように返却オブジェクトを作成
  6. WebServiceServlet がオブジェクトJSON化しレスポンスを送る

勘違いしていたこと

テーブルのソート・ページング・クエリ処理はサーバサイドである、ということ。


Flexigrid がクライアントサイドで ソート・ページング・クエリ をしていない。処理ごとにサーバに要求がだされ、実際のソートやページング処理は Serviceクラス で行ってJSONで返さなければならない。ソートキーや現在のページ番号はfindメソッドのパラメータとして(WebServiceServletによって)セットされるので

public Map<String, Object> find(Map<String,Object> params) {
  Map<String, Object> data = new HashMap<String, Object>();
  IDataService service = new AddressDataService();
  List<IAddress> all = service.findAll();

  List<IAddress> list = service.find(criteria)
  (ソート、クエリ、ページングのために行数制限などの処理...)

  data.put("total", all.size());
  data.put("page", (params.containsKey("page") ? params.get("page") : "1"));
  return data;
}

AddressDataServiceはCSVファイルを読み込んでListを返していたけど、さすがにソートクエリを実装するのはつらいのでデータベース使うか。HSQLでも組み込もう。

トラックバック - http://araistudy.g.hatena.ne.jp/czk-htn/20100102

2009-06-20

[] OSXNetBeans 6.5.1 で NoClassDefFoundError (解決) 06:45

この間OSX LeopardJavaアップデートしてから、NetBeans 6.5.1でJavaソースの新規作成ができなくなった。エラーの内容は

java.lang.NoClassDefFoundError: javax/script/ScriptEngineFactory

no title にも同じ問題を報告している人がいた。

ひとまずJava 1.5は使えなさそうなので、NetBeansを1.6で動かす。

  1. "NetBeans 6.5.1.app"を右クリックして[パッケージの内容を表示]する。
  2. Contents/Resources/NetBeans/etc/netbeans.conf をエディタで開く
  3. 以下のように修正して保存し、NetBeansを起動する

# Default location of JDK, can be overridden by using --jdkhome <dir>:
#netbeans_jdkhome=/System/Library/Frameworks/JavaVM.framework/Versions/1.5/Home
netbeans_jdkhome=/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home
トラックバック - http://araistudy.g.hatena.ne.jp/czk-htn/20090620

2009-06-12

[] NetBeans 6.5.1 で デスクトップアプリケーションを作る 06:45

プロジェクト作成

  1. [ファイル]-[新規プロジェクト]
  2. [Java]-[Java デスクトップアプリケーション]-[次へ]
  3. プロジェクト名は ThreadApp にして[完了]

デザイン

  1. デザイン画面が開くのでパレットからボタンを1つ配置する
  2. デフォルトでついた jButton1 のプロパティを変更する
    1. text を "Start" に変更
  3. 同様に 2つ目のボタンを "Stop" として作成する

まずは実行

  1. F6キーを押すかメニューアイコンの「緑色の右向き矢印」をクリックする
  2. ボタンが2つ並んだウィンドウが表示される(ボタンをクリックしても反応はない)
  3. [File]-[Exit]をクリックすると終了する

クリック時に実行されるメソッドを記述する

ソース画面を開きThreadView.java に下記のコードを記述。

ThreadView.java
    private static Logger logger = Logger.getLogger(ThreadView.class.getName());
    private MessageRunner runner;
    private List<Thread> threadList = new ArrayList<Thread>();
    @Action
    public void jButton1Clicked() {
        for (int i = 1; i <= 5; i++) {
            runner = new MessageRunner();
            Thread thread = new Thread(runner, "Thread " + i);
            runner.setThread(thread);
            thread.start();
            threadList.add(thread);
            try {
                Thread.sleep(2000);
            } catch (InterruptedException ex) {
                logger.log(Level.FINE, null, ex);
            }
        }
    }

    @Action
    public void jButton2Clicked() {
        for (Thread thread : threadList) {
            if (thread != null) {
                thread.interrupt();
                logger.log(Level.INFO, thread.getName() + " is interrupted");
                thread = null;
            }
        }
    }
MessageRunner.java
package threadapp;

import java.util.logging.Logger;

class MessageRunner implements Runnable {
    private static Logger logger = Logger.getLogger(MessageRunner.class.getName());
    private Thread thread;

    public void setThread(Thread thread) {
        this.thread = thread;
    }

    public void run() {
        logger.log(Level.INFO, thread.getName() + " is running.");
        if (thread != null) {
            try {
                thread.sleep(5000);
                thread.run();
            } catch (InterruptedException ex) {
                logger.log(Level.FINE, null, ex);
            }
        }
    }
}

ボタンとアクションメソッドを結びつける

  1. 再度 ThreadView をデザインモードで開く
  2. "Start"ボタンをクリックしプロパティの action で "jButton1Clicked" を選択する
  3. "Stop"ボタンをクリックしプロパティの action で "jButton2Clicked" を選択する

再び実行

  1. F6キーを押す
  2. ウィンドウが表示されるので"Start"をクリックする
  3. NetBeans ウィンドウ下部の"Thread (run)"というコンソールにスレッドが実行されていることをしめすメッセージが表示される
  4. ウィンドウの"Stop"ボタンをクリックするとスレッドが停止され、メッセージが表示される
run:
2009/06/12 23:21:54 threadapp.MessageRunner run
情報: Thread 1 is running.
2009/06/12 23:21:56 threadapp.MessageRunner run
情報: Thread 2 is running.
2009/06/12 23:21:58 threadapp.MessageRunner run
情報: Thread 3 is running.
2009/06/12 23:21:59 threadapp.MessageRunner run
情報: Thread 1 is running.
2009/06/12 23:22:00 threadapp.MessageRunner run
情報: Thread 4 is running.
2009/06/12 23:22:01 threadapp.MessageRunner run
情報: Thread 2 is running.
2009/06/12 23:22:02 threadapp.MessageRunner run
情報: Thread 5 is running.
2009/06/12 23:22:03 threadapp.MessageRunner run
情報: Thread 3 is running.
2009/06/12 23:22:04 threadapp.MessageRunner run
情報: Thread 1 is running.
2009/06/12 23:22:05 threadapp.MessageRunner run
情報: Thread 4 is running.
2009/06/12 23:22:06 threadapp.ThreadView jButton2Clicked
情報: Thread 1 is interrupted
2009/06/12 23:22:06 threadapp.ThreadView jButton2Clicked
情報: Thread 2 is interrupted
2009/06/12 23:22:06 threadapp.ThreadView jButton2Clicked
情報: Thread 3 is interrupted
2009/06/12 23:22:06 threadapp.ThreadView jButton2Clicked
情報: Thread 4 is interrupted
2009/06/12 23:22:06 threadapp.ThreadView jButton2Clicked
情報: Thread 5 is interrupted
トラックバック - http://araistudy.g.hatena.ne.jp/czk-htn/20090612

2009-04-26

[][] Dateを自分好みの書式でラベルにする 06:45

掲示板を作りながらWicketコンポーネントの使い方を学んでいる。

掲示板の書き込み日付(java.util.Date)を任意の書式で表示したい時にどうしたらいいのか?Wicketソースコードを追ってIConverterを実装してあげるのが良さそうだ。

package buzool.bbs;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.util.convert.IConverter;
import org.apache.wicket.util.convert.converters.DateConverter;

import buzool.bbs.data.BBSData;
import buzool.bbs.data.DummyBBSDataService;
import buzool.bbs.data.IBBSDataService;

public class Home extends WebPage {
    public Home() {
        add(homePageLink("goTop"));
        IBBSDataService service = new DummyBBSDataService();
        add(new ListView<BBSData>("bbsListView", service.findAll()) {
            private static final long serialVersionUID = 1L;

            @Override
            protected void populateItem(ListItem<BBSData> item) {
                BBSData data = item.getModelObject();
                item.add(new Label("bbsSeq", new PropertyModel<String>(data, "seq")));
                item.add(new Label("bbsTitle", new PropertyModel<String>(data, "title")));
                //
                //ロケールを基に日付を文字列にフォーマットする
                //自分好みの書式にするにはどうしたらいいんだろう・・・
                //
                //item.add(new Label("bbsModifiedAt", new PropertyModel<Date>(data, "modifiedAt")));
                
                //
                //あらかじめ日付を文字列にフォーマットしてからLabelに設定する
                //コンポーネントがLabelならこれでもいいんだろうけど・・・
                //
                //DateFormat df = new SimpleDateFormat("yyyy/MM/dd HH:mm");
                //Date modifiedAt = data.getModifiedAt();
                //item.add(new Label("bbsModifiedAt", df.format(modifiedAt)));
                
                //Labelを継承してgetConverterをオーバーライド
                //これが正しい作法?
                //毎回インスタンスを作るのは無駄なのでアプリケーションで使いまわすべきか
                item.add(new Label("bbsModifiedAt", new PropertyModel<Date>(data, "modifiedAt")) {
                    @Override
                    public IConverter getConverter(Class<?> type) {
                        final DateFormat df = new SimpleDateFormat("yyyy/MM/dd HH:mm");
                        IConverter converter = new DateConverter() {
                            @Override
                            public DateFormat getDateFormat(Locale locale) {
                                return df;
                            }
                        };
                        return converter;
                    }
                });
            }
        });
    }
}
トラックバック - http://araistudy.g.hatena.ne.jp/czk-htn/20090426

2009-04-11

[][] オープンソース徹底活用WicketによるWebアプリケーション開発 - 14日目(第9章 DIコンテナ06:45

IoCコンテナ/DIコンテナ

これが最終章。ちょうど2週間かかったわけだ。本の題名を「2週間で覚えるApache Wicket」に変えてもいいかもしれない。余計なお世話ですね。

日本ではDIコンテナDependency Injection:依存性注入)と呼ぶ機会が多いけど、海外ではIoCコンテナと呼ぶらしい。IoCはInversion of Contorol(制御の反転)という意味。

一般的にはオブジェクトを使う側(アプリケーション)がオブジェクトを管理する側(コンテナ)からオブジェクトを取得する(プル方式)わけだけど、IoC「制御を反転」することでコンテナからアプリケーションオブジェクトを注入する(プッシュ方式)ことになる。

これによりアプリケーションJavaインターフェース中心のプログラムを行い、インターフェースを実装している具体的なクラスおよび実体の管理はコンテナに任せる(疎結合)ことができる。

代表的なDIコンテナ

こう見るとWicket哲学にあっているのはGuiceみたい。今後Webアプリケーション開発する際に基本Javaのみでシステムを制御したい時の選択肢は「Wicket + Guice + S2JDBC?」S2JDBCってSeasarなしで単体で使える?ORマッパーでXMLレスを謳っているのは他にあったっけ?

参考URL

トラックバック - http://araistudy.g.hatena.ne.jp/czk-htn/20090411