2008年12月24日水曜日

ZK: MVC ラベルの日付を和暦で表示する

DateUserを参考に日付を和暦(元号)で表示する。(Java6)

public class DateUserWAREKI implements TypeConverter {

@Override
public Object coerceToBean(Object arg0, Component arg1) {
// TODO Auto-generated method stub
return null;
}

@Override
public Object coerceToUi(Object arg0, Component arg1) {
if (arg0 == null) {
return null;
}
Locale locale = Locale("ja","JP","JP");
SimpleDateFormat sdf = new SimpleDateFormat("GGGGyy年M月d日", locale);
Date date = (Date) arg0;
return sdf.format(date);
}
}



<listcell label="@{employee.hireDate, converter='org.zkforge.converters.DateUserWAREKI'}"/>

ZK: MVC ラベルの日付をyyyy/MM/dd形式で表示する

http://www.pichelhofer.at/ZKDemoで紹介されているTypeConverterを利用し日付をロケールに合わせて表示する。

http://www.pichelhofer.at/ZKDemo/src/DateUser.java.html


<listcell label="@{employee.hireDate, converter='org.zkforge.converters.DateUser'}"/>

ZK: MVC 変数selectedにアクセスする

ビューの変数selectedにコントローラからアクセスする。


public void onClick$selectedBtn(Event e) throws Exception{
Employee selected =(Employee)win.getVariable("selected", true);
if (selected != null){
alert(selected.firstName);
}
}

ZK: MVC リストボックスをクリアする

データバインドされているリストボックスをクリアするにはbeanにnullを代入し、
データバインダを使用してデータロードする。


public void onClick$clearBtn(Event e) throws Exception{
empData = null;
empListbox.unsetVariable("selected", true);
binder = (AnnotateDataBinder)page.getVariable("binder");
binder.loadAll();
}

ZK: MVC 選択を解除する

unsetVariableメソッドを使いlistboxからselected変数を取り除いた後、
データバインダを使用してデータをロードし直すことでリストボックスの選択を解除し、
明細をクリアできる。
   
public void onClick$clearSelBtn(Event e) throws Exception{
empListbox.unsetVariable("selected", true);
binder = (AnnotateDataBinder)page.getVariable("binder");
binder.loadAll();
}

2008年12月10日水曜日

ZK: MVC

GenericFowardComposerを拡張したコントローラ・クラスを作成しwindowのapply属性の値に設定すると、イベント・リスナーが自動的に登録されると同時にzulコンポーネントとコントローラのフィールドが自動的に紐つけられる。このためコントローラのコードが非常にすっきり記述できるようになった。

ボタンをクリックすると2個のintboxの値を足し算しlabelへ表示するサンプル
ビュー

<window id="win" title="MVCサンプル" border="normal" width="300px" apply="Controler1">
<hbox>
<intbox id="arg1"/> + <intbox id="arg2"/> <button label=" = " id="addBtn" /> <label id = "ans"/>
</hbox>
</window>


コントローラ

public class Controler1 extends GenericForwardComposer {
private Intbox arg1; //ビューの<intbox id="arg1"/>コンポーネントと自動的に紐付けされる
private Intbox arg2; //ビューの<intbox id="arg2"/>コンポーネントと自動的に紐付けされる
private Label ans; //ビューの<label id="and"/>コンポーネントと自動的に紐付けされる

// addBtnボタンの onClickイベント・リスナー
public void onClick$addBtn(Event e) throws Exception{
ans.setValue(String.valueOf(arg1.getValue() + arg2.getValue()));
}
}

コントローラでビューのzulコンポーネントと同じ型でidと同じ名称のフィールドを宣言するとzulコンポーネントと自動的に紐つけされる。
onイベント名$コンポーネント名の形でイベント・リスナーを書いておけば自動的に登録され対応するビューのコンポーネントのイベントが処理できる


データバインド
S2JDBCを使いFirebirdに付属のemployeeテーブルをリストと明細で表示するサンプル。

データバインダを利用するにはビューを<?init class="org.zkoss.zkplus.AnnotateDataBinderInit" ?>で初期化する。
バリアブル・リゾルバにorg.zkoss.zkplus.seasar.DelegatingVariableResolverを使用しSeasar変数jdbcManagerを利用できるようにする。

ビュー

<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit"?>
<?variable-resolver class="org.zkoss.zkplus.seasar.DelegatingVariableResolver"?>
<window id="win" title="Employee" border="normal" width="300px" apply="MyControler">
<listbox id="empListbox" width="200px" rows="10" multiple="true" height="100%"
checkmark="true" model="@{controler.empData}" selectedItem="@{selected}">
<!--
controlerはMyControlerのdoAfterComposeメソッドでWindow変数に追加されている。
aWindow.setVariable("controler", this, true); //aWindowはdoAfterComposeの引数
empDataはcontrolerで定義されているList<Employee>型のプロパティ
-->
<listhead>
<listheader label="姓" />
<listheader label="名" />
</listhead>
<listitem self="@{each=employee}">
<listcell label="@{employee.lastName}"/>
<listcell label="@{employee.firstName}"/>
</listitem>
</listbox>
<vbox>
<hbox>姓: <label value="@{selected.lastName}"/></hbox>
<hbox>名:<label value="@{selected.firstName}"/></hbox>
<hbox>内線番号: <label value="@{selected.phoneExt}"/></hbox>
<hbox>入社日:<label value="@{selected.hireDate}"/></hbox>
</vbox>
</window>


コントローラ

public class MyControler extends GenericForwardComposer {
private List<Employee> empData;
private JdbcManager jdbcManager; //super.doAfterComposeのコール後Seasar変数と自動で紐付けされる

@Override
public void doAfterCompose(Component aWindow) throws Exception {
super.doAfterCompose(aWindow);

// 自分自身をwindowの変数に追加するとビューからアクセス可能なオブジェクトになる。
aWindow.setVariable("controler", this, true);
empData = jdbcManager.from(Employee.class).getResultList();
}

//zulのListboxのmodelプロパティには controler.empData を設定する
public List<Employee> getEmpData() {
return empData;
}
}

2008年12月5日金曜日

ZK: forEach属性のeach変数の値へコンポーネント生成後にアクセス

コンポーネントのeach属性はforEach属性で配列を使用してコンポーネントを表示するときに使われる一時変数なので、あとからonXXXイベント等でこの値にアクセスしたい場合はコンポーネントを表示すると同時にcustom-attributesを使用しeachの値を保存して置く。

<window width="100%">
<zscript>
// コンポーネントのforEach属性を利用して生成するボタンの国名ラベルの配列
String[] countries = {"China", "France", "Germany", "United Kindom", "United States", "Japan"};
</zscript>
<hbox>
<button label="${each}" forEach="${countries}">
<!-- eachの値をcustom-attributesのcountryに保存する -->
<custom-attributes country="${each}"/>
<attribute name="onClick">
{
//countryにアクセスする。
alert(componentScope.get("country"));
}
</attribute>
</button>
</hbox>
</window>

2008年12月4日木曜日

ZK: Listitemのフォントサイズを変更する


<style>
div.cell-inner{
font-size:xx-small;
//font-size:xx-large;
}
</style>

ZK: 小文字の入力時に自動で大文字に変換するtextbox

小文字の入力が入力と同時に大文字に変換される。

<textbox style="text-transform:uppercase" id="idx" />

2008年12月3日水曜日

ZK: Textboxのテキストを選択状態にする


<window title="Button window" border="normal">
<vbox>
<button label="Left" width="125px">
<attribute name="onClick">
Messagebox.show("Textboxのテキストを選択状態にします");
txt.focus();
txt.setSelectionRange(0, txt.getText().length());
</attribute>
</button>
<textbox id="txt" value="123456"/>
</vbox>
</window>

ZK: Window幅のリサイズに自動で追随するリストボックス

listboxのfixedLayoutプロパティをtrueにするとwindowのリサイズに合わせ列幅を自動調整する。


<window title="Window幅のリサイズに自動で追随するリストボックス"
width="300px" height="100px" id="win" sizable="true" mode="modal">
<button label="FILL" onClick="fillList()"/>
<zscript>
public void fillList(){
Listitem item = new Listitem();
new Listcell("Cell Data 1").setParent(item);
new Listcell("Cell Data 2").setParent(item);
new Listcell("Cell Data 3").setParent(item);

item.setParent(lbx);
}
</zscript>
<listbox width="100%" id="lbx" fixedLayout="true">
<listhead sizable="true">
<listheader label="Column 1" />
<listheader label="Column 2" />
<listheader label="Column 3" />
</listhead>
</listbox>
</window>

2008年12月2日火曜日

ZK: タイムアウト時間を設定する

WEB-INF/zk.xmlでタイムアウト時間を設定することができる。

<zk>
<desktop-config>
<desktop-timeout>3600</desktop-timeout> <!--秒単位、マイナスはタイムアウト無し。 -->
</desktop-config>
</zk>

ZK: no empty制約付きのテキストボックスをクリアする

no empty制約付きのテキストボックスをクリアするときは
textbox.setRawValue("")を使用すると制約を回避しテキストボックスをクリアできる。


<window title="no empty制約付きのテキストボックスをクリアする"
width="300px" height="200px" border="normal">
<zscript><![CDATA[
public void save(){
alert("テキストボックスの値 "+tb1.value+" を保存しました。");
tb1.setValue(""); //no empty制約にひっかかりクリアできない
//tb1.setRawValue(""); //制約を回避しクリアできる。
}
]]></zscript>
<vbox>
<textbox id="tb1" constraint="no empty" ></textbox>
<button label="保存" onClick="save()" />
</vbox>
</window>


2008年12月1日月曜日

ZK: Windowをスクリーントップを越えて移動させない


<window id="win" border="normal" title="隠れません!!"
mode="overlapped" width="350px" onMove="resetTop()">
<zscript><![CDATA[
void resetTop(){
String top = win.getTop();
if (top != null){
float winTop = Float.parseFloat((top.substring(0,top.lastIndexOf("px"))));
if (winTop < 0.0){
win.setTop(0 + "px");
}
}
}
]]></zscript>

<label value="ウィンドウはスクリーントップを越えて上には移動しません!!"/>
</window>

ZK: 親ウィンドウの中だけ移動するパネル

パネルを親ウィンドウの中だけしか移動できないようにするには親ウィンドウでcontentStyle="position:relative;"を指定する。


<window width="500px" height="200px" title="親ウィンドウ
contentStyle="position:relative;"" border="normal"
contentStyle="position:relative;" >
<panel id="panel" height="100px" width="300px" title="親ウィンドウの中だけ移動するパネル"
maximizable="true" border="normal" collapsible="true" floatable="true" movable="true">
<panelchildren>
最大化しても親ウィンドウの中に収まります。

</panelchildren>
</panel>
</window>


ZK: リストボックスの行の背景色をカスタマイズする


<style>
/* 偶数行の背景色 */
tr.z-list-item, tr.z-row td.z-row-inner, tr.z-row td.z-group-inner,
tr.z-row td.z-group-foot-inner, tr.z-row {
background: #EEEEEE none repeat scroll 0 0;
}

/* 奇数行の背景色 */
tr.odd td.gc, tr.odd, tr.z-listbox-odd, tr.z-grid-odd td.z-row-inner,
tr.z-grid-odd {
background: #FFFFFF none repeat scroll 0 0;
}
/* 選択されていない行の上をマウスが通過する時の背景色 */
tr.overd, td.overd, tr.z-list-item-over {
background: #D3DBFC none repeat scroll 0 0;
}
/* 選択された行の背景色 */
tr.seld, td.seld, tr.z-list-item-seld {
background: #B8BFDC none repeat scroll 0 0;
}
/* 選択された行の上をマウスが通過する時の背景色 */
tr.overseld, td.overseld, tr.z-list-item-over-seld {
background: #D3DBFC none repeat scroll 0 0;
}
</style>

ZK: リクエスト・パラメータを取得する


<window title="リクエスト・パラメータの取得"
width="250px" height="200px" border="normal">
<label value="${param.q}"/>
</window>

ZK: Borderlayout 折り畳みアイコン表示

Boderlayoutの子コンポーネントはcollapsible="true"で折り畳めるようになるが、折り畳みアイコンを表示させるにはtitleを設定しタイトルバーを表示する必要がある。

<borderlayout height="500px">
<north title="「折り畳みアイコン」を表示するには何かタイトルが必要 →"
size="20%" splittable="true" collapsible="true"/>
<east size="20%" splittable="true" collapsible="true"/>
<center border="normal"/>
<west title="→" size="20%" splittable="true" collapsible="true"/>
<south size="30%" border="normal" splittable="true" collapsible="true"/>
</borderlayout>

2008年6月21日土曜日

ZK: Pagingコンポーネントでライブデータ表示

Smalltaksの記事Use Load-On-Demand to Handle Huge Dataを試してみました。
リストボックスに一度に大量なデータを表示するとWEBアプリにもサーバにも大きな負担がかかります。
Pagingコンポーネントを明示的に使いオンデマンドでページ単位にクエリーを実行し、取得したライブデータでリストボックスの表示を効果的に処理する方法が紹介されていました。

<window
title="Listbox with Paging Performance using ZK version: ${desktop.webApp.version}"
border="normal" use="sample.ui.EmployeeUI"
xmlns:zk="http://www.zkoss.org/2005/zul"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.zkoss.org/2005/zul http://www.zkoss.org/2005/zul/zul.xsd">
<zk:toolbarbutton href="/" label="Back" />
<zk:listbox id="listEmployee" width="350px" checkmark="true">
<zk:listhead sizable="true">
<zk:listheader label="ID" sort="auto" />
<zk:listheader label="Full Name" sort="auto" />
<zk:listheader label="User Name" sort="auto" />
</zk:listhead>
</zk:listbox>
<!-- 明示的にpagingコンポーネントを使用する。 -->
<zk:paging id="pageEmployee" pageSize="30" />
</window>

Windowを継承したクラスでインターフェースAfterComposeを実装します。
afterComposeメソッドでは
  • データのトータル行数をセット
  • 最初のページにデータを表示
  • pagingコンポーネントに onPaging イベントリスナを登録
    を行います。

    public class EmployeeUI extends SimpleWindow implements AfterCompose {
    private final String LISTBOX_ID= "listEmployee"; //zulファイルの listbox コンポーネントの id
    private final String PAGING_ID = "pageEmployee"; //zulファイルの paging コンポーネントのid
    private JdbcManager jdbcManager; //Seasar変数

    public EmployeeUI(){
    DelegatingVariableResolver variableResolver = new DelegatingVariableResolver();
    jdbcManager = (JdbcManager)variableResolver.resolveVariable("jdbcManager");
    }

    /**
    * AfterComposeインターフェースのafterComposeメソッドはコンポーネント作成段階で処理される。
    * コンポーネントを作成した直後に初期化できパフォーマンスの改善に役立つ。
    *
    */
    public void afterCompose() {
    Paging page = getPaging(PAGING_ID);

    //データのトータル行数を取得
    page.setTotalSize((int)jdbcManager.from(Employee.class).getCount());

    final int PAGE_SIZE = page.getPageSize();

    // Listboxに最初のページを表示 オフセット--0 行数---PAGE_SIZE
    redraw(0, PAGE_SIZE);

    // onPagingイベントリスナの登録 決まり文句
    page.addEventListener("onPaging", new EventListener() {
    public void onEvent(Event event) {
    PagingEvent pageEvent = (PagingEvent) event;
    int pageNo = pageEvent.getActivePage();
    int offset = pageNo * PAGE_SIZE;

    // クリックされたページ番号でライブデータを取得し再表示
    redraw(offset, PAGE_SIZE);
    }
    });

    }


    /**
    * afterCompose及びonPagingイベントリスナから呼び出されListboxを描画する。
    * コールされる度にクエリを実行しデータベースからライブデータを取得する。
    *
    * @param firstResult オフセット
    * @param maxResults 行数
    */
    private void redraw(int firstResult, int maxResults) {
    Listbox listBox = getListbox(LISTBOX_ID);
    listBox.getItems().clear();

    // データ取得
    List<Employee> emps = jdbcManager.from(Employee.class)
    .orderBy("id") // 問い合わせ結果をページングするにはorder by が必要
    .offset(firstResult)
    .limit(maxResults)
    .getResultList();
    // 表示
    for (Employee employee : emps) {
    Listitem li = new Listitem();
    li.setValue(employee);
    li.appendChild(new Listcell("" + employee.id));
    li.appendChild(new Listcell(employee.fullname));
    li.appendChild(new Listcell(employee.username));
    listBox.appendChild(li);
    }
    }
    }


    大量なデータでも paging コンポーネントを用いライブデータで処理を行うとアプリの動作は非常に軽快ですね。
  • 2008年6月1日日曜日

    ZK: Spreadsheet

    以前から気になっていたZK Spreadsheetをいじってみました。ZK SpreadsheetではあらかじめExcelで作成しておいた表のテンプレートを読み込むことでZKのコンポーネントとして操作可能になるようです。つまり使い慣れたエクセルファイルがそのままZKのコンポーネントになるんですね。
    Integrate ZK Spreadsheet with Springを元ネタにしてZK SpreadsheetとSeasarの統合を試して見ました。
    まずはZssSpring.warをダウンロードし動作確認。

    次にデモと同じ表示をさせるようにテーブルを作成。

    create table FinancialData (
    fyear integer,
    fquarter integer,
    item char(10),

    liquidAssets decimal(10, 0),
    fundInvestment decimal(10, 0),
    fixedAssets decimal(10, 0),
    intangibleAsset decimal(10, 0),
    otherAssets decimal(10, 0),

    currentLiabilities decimal(10, 0),
    longTermLiabilities decimal(10, 0),
    otherLiabilities decimal(10, 0),

    capitalStock decimal(10, 0),
    capitalSurplus decimal(10, 0),
    retainedEarnings decimal(10, 0),
    otherEquity decimal(10, 0),
    treasuryStock decimal(10, 0)

    );


    insert into FinancialData(
    fyear,
    fquarter,
    item,

    liquidAssets,
    fundInvestment,
    fixedAssets,
    intangibleAsset,
    otherAssets,

    currentLiabilities,
    longTermLiabilities,
    otherLiabilities,

    capitalStock,
    capitalSurplus,
    retainedEarnings,
    otherEquity,
    treasuryStock
    )values(
    2007,
    1,
    'Quarter',
    146504221,
    23181709,
    7168392,
    221426,
    2270018,

    102515784,
    3000,
    456175,

    33630080,
    7127901,
    34420905,
    1826731,
    -634810
    );
    ...



    Bean作成
    キャメルケースでテーブルを作るとBeanの作成時にテーブル名と列名を一々指定しなければ
    ならなかった(^^;;

    package churazk.entity;
    import java.math.BigDecimal;
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.Table;

    @Entity
    @Table(name="FINANCIALDATA")
    public class FinancialData {
    @Column(name="fYear")
    public Integer fYear;

    @Column(name="fQuarter")
    public Integer fQuarter;

    @Column(name="item")
    public String item;

    @Column(name="liquidAssets")
    public BigDecimal liquidAssets;

    @Column(name="fundInvestment")
    public BigDecimal fundInvestment;

    @Column(name="fixedAssets")
    public BigDecimal fixedAssets;

    @Column(name="intangibleAsset")
    public BigDecimal intangibleAsset;

    @Column(name="otherAssets")
    public BigDecimal otherAssets;

    @Column(name="currentLiabilities")
    public BigDecimal currentLiabilities;

    @Column(name="longTermLiabilities")
    public BigDecimal longTermLiabilities;

    @Column(name="otherLiabilities")
    public BigDecimal otherLiabilities;

    @Column(name="capitalStock")
    public BigDecimal capitalStock;

    @Column(name="capitalSurplus")
    public BigDecimal capitalSurplus;

    @Column(name="retainedEarnings")
    public BigDecimal retainedEarnings;

    @Column(name="otherEquity")
    public BigDecimal otherEquity;

    @Column(name="treasuryStock")
    public BigDecimal treasuryStock;
    }


    つづいてzulファイルを編集。

    <?xml version="1.0" encoding="UTF-8"?>
    <?variable-resolver class="org.zkoss.zkplus.seasar.DelegatingVariableResolver"?>
    <window>
    Quarter:
    <listbox id="quarter" mold="select" rows="1" onSelect="refreshQuarter()">
    <listitem value="0" label="Select"/>
    <listitem value="1" label="Quarter 1"/>
    <listitem value="2" label="Quarter 2"/>
    <listitem value="3" label="Quarter 3"/>
    <listitem value="4" label="Quarter 4"/>
    </listbox>
    Style:
    <listbox id="style" mold="select" rows="1" onSelect="changeStyle()">
    <listitem label="Style 1" value="/BalanceSheet.xls"/>
    <listitem label="Style 2" value="/NewSheet.xls"/>
    </listbox>
    <zscript>
    import churazk.entity.FinancialData;
    import org.seasar.extension.jdbc.where.SimpleWhere;

    FinancialData reloadQuarter(int quarter){
    FinancialData bean = jdbcManager.from(FinancialData.class)
    .where(new SimpleWhere()
    .eq("fYear", 2007)
    .eq("fQuarter", quarter)
    )
    .getSingleResult();

    return bean;
    }

    void refreshQuarter() {
    Listitem listitem = quarter.getSelectedItem();
    int quarter = Integer.parseInt(listitem.value);
    //Call the method to reload data
    dataBean = reloadQuarter(quarter);
    //Call the method to refresh values of cells
    balance.book.notifyChange(new String[]{"dataBean"});
    }

    void changeStyle() { //Change the URL of spreadsheet
    balance.url = style.getSelectedItem().value;
    }

    dataBean = reloadQuarter(0);
    </zscript>
    <spreadsheet id="balance" url="/BalanceSheet.xls" maxrow="40" maxcolumn="20" height="600px" width="1300px"/>
    </window>


    スプレッドシートデモのWEB-INF/libより次のファイルをプロジェクトWEB-INF/libへインポート

    commons-math-1.2.jar
    jxl.jar
    zss.jar
    zssex.jar
    zssjxl.jar


    プロジェクトのWEBルートにBalanceSheet.xlsとNewSheet.xlsを配置して実行

    ZKコンポーネントとは言えExcelシートにビーンの値が表示され不思議な感じです、でもとても使い勝手がよさそうなコンポーネントです。

    動作環境

  • OS: Ubuntu 8.04
  • JDK: 1.6.0_04
  • Tomcat: apache-tomcat-6.0.16
  • Eclipse: Europa wtp-all-in-one-sdk
  • ZK: zk-3.0.5
  • Seasar: DoltengプラグインよりChuraプロジェクト(Teeda+S2Dao)として
  • S2JDBC関連: sa-struts-tutorial-1.0.2-rc4.zipより

    geronimo-jpa_3.0_spec-1.0.jar
    geronimo-ejb_3.0_spec-1.0.jar
    s2jdbc.dicon

  • web.xml追加

    <!-- ZK -->
    <listener>
    <listener-class>org.zkoss.zk.ui.http.HttpSessionListener</listener-class>
    </listener>
    <servlet>
    <servlet-name>zkLoader</servlet-name>
    <servlet-class>org.zkoss.zk.ui.http.DHtmlLayoutServlet</servlet-class>
    <init-param>
    <param-name>update-uri</param-name>
    <param-value>/zkau</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup><!-- Must -->
    </servlet>
    <servlet-mapping>
    <servlet-name>zkLoader</servlet-name>
    <url-pattern>*.zul</url-pattern>
    </servlet-mapping>

    <servlet>
    <servlet-name>auEngine</servlet-name>
    <servlet-class>org.zkoss.zk.au.http.DHtmlUpdateServlet</servlet-class>
    </servlet>
    <servlet-mapping>
    <servlet-name>auEngine</servlet-name>
    <url-pattern>/zkau/*</url-pattern>
    </servlet-mapping>

    <!-- Miscellaneous -->
    <session-config>
    <session-timeout>120</session-timeout>
    </session-config>
    <!-- ZK -->


  • 2008年3月11日火曜日

    ZK: jdbcManager Seasar変数(3)

    jdbcManagerを使いながらデザインとロジックを分離したいときは
    こんな感じでいけそうです。

    listboxのモデルにEmpWindowのプロパティemps、selectedItemにselectedをセットします。


    ...
    <window id="win" title="Emplyee list" use="zkseasar.view.EmpWindow">
    <listbox id="lb" model="@{win.emps}" selectedItem="@{win.selected}">



    EmpWindow.java

    public class EmpWindow extends Window {
    private JdbcManager jdbcManager;
    private List<Emp> emps;
    private Emp selected;

    public EmpWindow(){
    DelegatingVariableResolver variableResolver = new DelegatingVariableResolver();
    jdbcManager = (JdbcManager)variableResolver.resolveVariable("jdbcManager");

    emps = jdbcManager.from(Emp.class)
    .where("sal between ? and ?", 2000, 3000)
    .orderBy("sal").getResultList();
    }

    public List<Emp> getEmps(){
    return emps;
    }

    public void setSelected(Emp emp){
    selected = emp;
    }

    public Emp getSelected(){
    return selected;
    }


    /*
    * listboxにempを追加する
    * http://sourceforge.net/forum/message.php?msg_id=4752395
    */
    public void addEmp(Emp emp){
    Listbox lb = ((Listbox) getFellow("lb"));
    ((ListModelList) lb.getModel()).add(emp);
    }
    }


    ZKをSeasarと組み合わせるとデータベースアクセスはjdbcManagerの使いかただけ知っていればいいみたいですね。

    ZK: jdbcManager Seasar変数(2)

    可変長引数を持つメソッドはzscriptでは使用できないようです。


    <zscript>
    import zkseasar.entity.Emp;
    emps = jdbcManager.from(Emp.class)
    .where("sal >= ?", 2000)
    .orderBy("sal")
    .getResultList();
    </zscript>

    上記のスクリプトを実行すると次のエラーメッセージを吐いてしまいます。

    致命的: サーブレット zkLoader のServlet.service()が例外を投げました
    org.zkoss.zk.ui.UiException: Sourced file: inline evaluation of: ``import zkseasar.entity.Emp;
    emps = jdbcManager.from(Emp.class) . . . '' :
    Error in method invocation: Method where( java.lang.String, int ) not found in class'org.seasar.extension.jdbc.query.AutoSelectImpl' :

    検索条件を指定するときはSQL文字列ではなくSimpleWhereが使えます。

    <zscript >
    import zkseasar.entity.Emp;
    import org.seasar.extension.jdbc.where.SimpleWhere;
    emps = jdbcManager.from(Emp.class)
    .where(new SimpleWhere()
    .ge("sal", 2000)
    )
    .orderBy("sal")
    .getResultList();
    </zscript>


    Rubyからは可変長引数を持つJavaメソッドでも呼び出せるか試してみました。

    <zscript language="ruby">
    import 'zkseasar.entity.Emp'
    emps = $jdbcManager.from(Java::ZkseasarEntity::Emp:Class).
    where("sal >= ?", 2000).
    orderBy("sal").
    getResultList()

    emps.each{|emp| print emp.deptId, "\t", emp.empName, "\t", emp.sal, "\n"}
    </zscript>

    やはりダメですね。

    致命的: サーブレット zkLoader のServlet.service()が例外を投げました
    :1: no where with arguments matching [class java.lang.String, class java.lang.Long]
    on object JavaUtilities (NameError)
    ...internal jruby stack elided...

    ZK: jdbcManager Seasar変数

    DelegatingVariableResolverでZKから直接jdbcManagerが使えるんですね。

    emp.zul


    <?xml version="1.0" encoding="UTF-8"?>
    <?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ?>
    <?variable-resolver class="org.zkoss.zkplus.seasar.DelegatingVariableResolver"?>
    <zk xmlns="http://www.zkoss.org/2005/zul" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.zkoss.org/2005/zul http://www.zkoss.org/2005/zul/zul.xsd ">
    <zscript >
    import zkseasar.entity.Emp;
    emps = jdbcManager.from(Emp.class)
    .orderBy("sal")
    .getResultList();
    </zscript>
    <window title="Emplyee list" >
    <listbox model="@{emps}">
    <listhead>
    <listheader label="id"/>
    <listheader label="Emp no"/>
    <listheader label="Emp name"/>
    <listheader label="Hiredate"/>
    <listheader label="Sal"/>
    <listheader label="Dept id"/>
    <listheader label="Version no"/>
    </listhead>
    <listitem self="@{each=emp}">
    <listcell label="@{emp.id}"/>
    <listcell label="@{emp.empNo}"/>
    <listcell label="@{emp.empName}"/>
    <listcell label="@{emp.hiredate}"/>
    <listcell label="@{emp.sal}"/>
    <listcell label="@{emp.deptId}"/>
    <listcell label="@{emp.versionNo}"/>
    </listitem>
    </listbox>
    </window>
    </zk>

    これは楽ちん!!



    java.util.Date および java.util.Calendar 型のプロパティには時制を指定する必要があるそうです。
    EmpクラスのhiredateプロパティはDate型なので@Temporalを使い時制にTemporalType.DATEを指定します。

    Emp.java

    public class Emp {
    ..
    @Temporal(TemporalType.DATE)
    @Column(name = "HIREDATE")
    public Date hiredate;
    ..