2007年12月24日月曜日

ZK: データバインディング

selectRainfallAvgメソッドを実行し作成したListをZKのListboxコンポーネントにデータバインドします。
まず<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ?>でデータバインダーを初期化します。
Seasarコンポーネントを生成後selectRainfallAvgメソッドを実行しrainfallAvgを作成します。
model="@{rainfallAvg}"でZKのListboxとJavaのListを関連付けるとロード時にデータバインダーによってJavaのListからZKのListModelに変換されます。
selectedItem="@{selected}"は選択された行に対応したビーンに関連付けられた変数selectedを準備します。選択された行を明細表示するのに変数selectedのプロパティが利用出来ます。
self="@{each=rainfall}"はListの各行に対応したビーンをrainfallと言う名前で関連付けます。

<?xml version="1.0" encoding="UTF-8"?>
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ?>
<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/zul.xsd ">
<window title="東京 年間降雨量デモ" width="500px" border="normal">
<zscript>
import org.seasar.framework.container.SingletonS2Container;
rainStatsService = SingletonS2Container.getComponent("rainStatsService");
rainfallAvg = rainStatsService.selectRainfallAvg();
</zscript>
<listbox model="@{rainfallAvg}" id="rainfallListbox" rows="5" selectedItem="@{selected}">
<listhead>
<listheader label="年度"/>
<listheader label="平均降雨量(mm)"/>
</listhead>
<listitem self="@{each=rainfall}">
<listcell label="@{rainfall.year}"/>
<listcell label="@{rainfall.average}"/>
</listitem>
</listbox>
<vbox>
<hbox>年度: <label value="@{selected.year}"/></hbox>
<hbox>平均降雨量:<label value="@{selected.average}"/></hbox>
</vbox>
</window>
</zk>


次のメソッドを実行するとデータベースからリロードすることができます。

void refreshRainfallListbox(){
List list = rainfallListbox.getModel();
list.clear();
list.addAll(rainStatsService.selectRainfallAvg());
}

2007年12月23日日曜日

Seasar: S2JDBC 外出しSQL

ZK + Seasar:JFreeChartで使った降雨量の年間平均をS2JDBCの外出しSQLで求めてみました。

  • 年と平均降雨量を格納するDTOを作成します。

    package zkseasar.dto;

    public class RainfallAvgDto {
    public Integer year;
    public Double average;
    }

  • RainStatsServiceに年間平均降雨量を取り出すメソッドを追加します。
    DTOのプロパティ名とSQLのカラム名を統一するだけでSQLを実行した結果がDTOへ自動的にマッピングされるようです。

    ...
    public List selectRainfallAvg(){
    return jdbcManager.selectBySql(RainfallAvgDto.class,
    " select year, avg(rainfall) as average" +
    " from rain_stats " +
    " group by year " +
    " order by year ")
    .getResultList();
    }
    ...


  • S2TestCaseを継承したクラスを作り動作確認します。
    EclipseのメニューからRun>Debug As>JUnit Testで実行できます。

    public class RainStatsServiceTest extends S2TestCase {
    private JdbcManager jdbcManager;

    protected void setUp() throws Exception {
    include("app.dicon");
    }

    public void testSelectRainfallAvg() throws Exception {
    RainStatsService rainStatsService =
    SingletonS2Container.getComponent("rainStatsService");

    List results =
    rainStatsService.selectRainfallAvg();
    for (RainfallAvgDto dto : results) {
    System.out.println(dto.year + ":"+ dto.average);
    }
    }
    }
  • 2007年12月19日水曜日

    ZK: ウィンドウをブラウザの中央に表示

    windowをブラウザの中央に表示したい時はvboxの中にwindowを配置する。

    <zk>
    <vbox height="100%" width="100%" pack="center" align="center">
    <window title="Login" border="normal"
    style="text-align: center;left-margin: 30%;right-margin: 30%; width:30%;">
    Login Window
    </window>
    </vbox>
    </zk>

    2007年12月2日日曜日

    ZK: iText

    Report with ZK : Using JasperReports As an Exampleを参考に動的にPDFファイルを作成するサンプルを作ってみました。
    PDF作成にはiTextライブラリを使います。まずこちらのサイトからjarファイルをダウンロードします。日本語を使うためにこちらのサイトからiTextAsian.jarをダウンロードします。
    次にダウンロードしたjarファイルをWEB-INF/libへインポートして準備完了です。

    <?xml version="1.0" encoding="UTF-8"?>
    <?page style="height:100%" ?>
    <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 ">
    <window width="100%" height="100%">
    <borderlayout height="100%">
    <north maxsize="24" size="24" border="0">
    <hbox>
    名前:<textbox id="name"/>
    <button label="PDF出力" onClick="doReport()"/>
    </hbox>
    </north>
    <center border="none" flex="true">
    <iframe id="report" />
    </center>
    </borderlayout>
    <zscript><![CDATA[
    import java.io.*;
    import com.lowagie.text.*;
    import com.lowagie.text.pdf.*;
    import org.zkoss.util.media.AMedia;
    import java.awt.Color;

    void doReport() {
    try {
    //iTextでは出力するPDF全体はDocumentクラスで表現される
    Document doc = new Document();
    //ゴシック体の日本語ベースフォント作成
    BaseFont bf_goth = BaseFont.createFont(
    "HeiseiKakuGo-W5", //ゴシック体
    "UniJIS-UCS2-H", //横書日本語Unicodeエンコーディング
    BaseFont.NOT_EMBEDDED);
    //明朝体の日本語ベースフォント作成
    BaseFont bf_min = BaseFont.createFont(
    "HeiseiMin-W3", //明朝体
    "UniJIS-UCS2-H", //横書日本語Unicodeエンコーディング
    BaseFont.NOT_EMBEDDED);

    //日本語フォント作成
    Font font_goth = new Font(bf_goth);
    Font font_min15 = new Font(bf_min, 15); //明朝体 15pt
    Font font_goth8red = new Font(bf_goth, 8); //ゴシック体8pt
    font_goth8red.setColor(new Color(255,0,0)); //文字色を赤に設定

    //出力用のStreamをインスタンス化し
    ByteArrayOutputStream byteout = new ByteArrayOutputStream();
    //PDFの出力先へ割り当てる。
    PdfWriter.getInstance(doc, byteout);

    doc.open();
    //本文を追加
    doc.add(new Paragraph(name.value + "さん、 " + "こんにちは!!" , font_goth));
    doc.add(new Paragraph(name.value + "さん、 " + "こんにちは!!" , font_min15));
    doc.add(new Paragraph(name.value + "さん、 " + "こんにちは!!" , font_goth8red));
    doc.close();

    //PDF出力から入力ストリームを作成し
    final InputStream mediais = new ByteArrayInputStream(byteout.toByteArray());
    //入力ストリームをiframeのコンテンツへ媒介するAMediaオブジェクトを生成
    final AMedia amedia =
    new AMedia("FirstReport.pdf", "pdf", "application/pdf", mediais);

    //iframeにコンテンツをセット
    report.setContent(amedia);
    }catch (IOException e) {
    e.printStackTrace();
    }catch (DocumentException e) {
    e.printStackTrace();
    }
    }
    ]]></zscript>
    </window>
    </zk>

    2007年11月19日月曜日

    ZK + Seasar: JFreeChart(2)

    チャートモデルにSimpleCategoryModelを使用するグラフを表示します。次のグラフのモデルにSimpleCatagoryModelが使えます。

    • 棒グラフ
    • 折れ線グラフ
    • エリアグラフ
    • 積み上げ棒グラフ
    • 積み上げエリアグラフ
    • ウォータフォールグラフ

    データは降雨量ですので意味不明なグラフもありますがご愛嬌ということで(^^

    <?xml version="1.0" encoding="UTF-8"?>
    <?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 ">
    <window title="東京 年間降雨量デモ" width="500px" border="normal">
    <vbox>
    <chart id="myChart" title="月別降雨量 (mm)" width="500" height="250" type="bar" threeD="false" fgAlpha="128"/>
    <radiogroup>
    <radio label="棒グラフ" id="bar" onCheck="myChart.type=self.id" checked="true"/>
    <radio label="折れ線グラフ" id="line" onCheck="myChart.type=self.id" />
    <radio label="エリアグラフ" id="area" onCheck="myChart.type=self.id" />
    <radio label="積み上げ棒グラフ" id="stacked_bar" onCheck="myChart.type=self.id" />
    <radio label="積み上げエリアグラフ" id="stacked_area" onCheck="myChart.type=self.id" />
    <radio label="ウォータフォール" id="waterfall" onCheck="myChart.type=self.id" />
    </radiogroup>
    <checkbox label="3D チャート" checked="false" onCheck="myChart.setThreeD(self.isChecked())"/>
    </vbox>
    <zscript>
    model = new SimpleCategoryModel();
    model.clear();
    // 年を指定して降雨量をセット
    void processYear(String year) {
    rainStats = rainStatsService.selectAll(year);
    for(data: rainStats){
    model.setValue(year, data.month, data.rainfall);
    }
    }
    processYear("2003");
    processYear("2004");
    processYear("2005");
    myChart.setModel(model);
    </zscript>
    </window>
    </zk>



    2007年11月12日月曜日

    ZK + Seasar + Ruby: JFreeChart

    JFreeChartアプリをRubyで書き直してみました。
    rainStatsServiceコンポーネントはSingletonS2Container.getComponent(Object componentKey)を用い取得することにしました。Seasarの機能リファレンスによるとcomponentKeyにはコンポーネントのクラスまたはコンポーネント名を指定できるそうです。
    コンポーネント名を自動登録するようにapp.diconへ追加設定します。

    ...
    <component
    class="org.seasar.framework.container.autoregister.FileSystemComponentAutoRegister">
    <property name="autoNaming">
    <component class="org.seasar.framework.container.autoregister.DefaultAutoNaming">
    <initMethod name="setCustomizedName">
    <arg>"zkseasar.service.EmpService"</arg>
    <arg>"empService"</arg>
    </initMethod>
    </component>
    </property>
    <initMethod name="addClassPattern">
    <arg>"zkseasar.service"</arg>
    <arg>".*Service"</arg>
    </initMethod>
    </component>
    ...

    上記の設定でzkseaser/service/EmpServiceがempServiceというコンポーネント名で登録されるように、zkseaser/service/下の正規表現.*Serviceで表されるファイル名の先頭が大文字から小文字に変換された形で自動的にコンポーネント登録されます。
    コンポーネントが自動登録されたか確認してみます。web.xmlでs2servletのdebugパラメータをtrueにしてTomcatを再起動します。

    ...
    <servlet>
    <servlet-name>s2servlet</servlet-name>
    <servlet-class>org.seasar.framework.container.servlet.S2ContainerServlet</servlet-class>
    <init-param>
    <param-name>configPath</param-name>
    <param-value>app.dicon</param-value>
    </init-param>
    <init-param>
    <param-name>debug</param-name>
    <param-value>true</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
    </servlet>
    ...


    WEBブラウザで下記のアドレスにアクセスし確認します。

    http://localhost:8080/zkseasar/s2servlet?command=list


    empServiceとrainStatsServiceがコンポーネント登録されていました。

    スクリプトをRubyで書き直します。

    ...
    <window title="東京 年間降雨量デモ (Ruby)" width="500px" border="normal">
    年度:
    <listbox id="yr" rows="1" mold="select" onSelect="ruby:process_year">
    <listitem label="2005" selected="true"/>
    <listitem label="2004"/>
    <listitem label="2003"/>
    </listbox>
    <vbox>
    <chart id="myChart" title="月別降雨量 (mm)" width="500" height="250" type="pie" threeD="false" fgAlpha="128"/>
    <checkbox label="3D チャート" checked="false" onCheck="myChart.setThreeD(self.isChecked())"/>
    </vbox>
    <zscript language="ruby">
    import 'zkseasar.service.RainStatsService'
    import 'org.zkoss.zul.SimplePieModel'
    import 'org.seasar.framework.container.SingletonS2Container'

    $model = SimplePieModel.new

    #自動登録されたコンポーネント名でコンポーネントを取り出す。
    $rainStatsService = SingletonS2Container.getComponent('rainStatsService')

    def process_year
    year = $yr.selectedItem.label
    $model.clear
    rain_stats = $rainStatsService.selectAll(year)
    rain_stats.each{|data| $model.setValue(data.month, data.rainfall)}

    $myChart.model = $model
    end
    process_year
    </zscript>
    </window>
    ...

    RubyでS2ContainerのコンポーネントにもJFreeChartにもアクセスすることができました。

    2007年11月7日水曜日

    ZK + Seasar: JFreeChart

    今は見当たりませんが、以前ZKサイトのSmalltalksにあったパイチャートデモを参考に東京の月別降雨量をパイチャートで表示するアプリを作ってみました。データベースにはs2jdbcでアクセスします。
  • テーブル作成
    データベースが起動していないときはDatabaseViewでzkseasarプロジェクトをクリックしデータベースを起動します。次にブラウザでlocalhost:8082へアクセスしH2 Consoleを開きデータベースに接続します。SQLステートメントに下記のSQLをコピーし実行するとテーブルが作成されサンプルデータが登録されます。

    create table rain_stats(
    year integer,
    month char(3),
    rainfall decimal(4, 1)
    );

    insert into rain_stats values(2003, '1月', 101.0);
    insert into rain_stats values(2003, '2月', 53.5);
    insert into rain_stats values(2003, '3月', 159.5);
    insert into rain_stats values(2003, '4月', 121.0);
    insert into rain_stats values(2003, '5月', 172.5);
    insert into rain_stats values(2003, '6月', 85.0);
    insert into rain_stats values(2003, '7月', 187.5);
    insert into rain_stats values(2003, '8月', 370.0);
    insert into rain_stats values(2003, '9月', 150.0);
    insert into rain_stats values(2003, '10月', 171.5);
    insert into rain_stats values(2003, '11月', 229.5);
    insert into rain_stats values(2003, '12月', 53.0);
    insert into rain_stats values(2004, '1月', 3.5);
    insert into rain_stats values(2004, '2月', 20.0);
    insert into rain_stats values(2004, '3月', 129.5);
    insert into rain_stats values(2004, '4月', 69.5);
    insert into rain_stats values(2004, '5月', 149.0);
    insert into rain_stats values(2004, '6月', 112.5);
    insert into rain_stats values(2004, '7月', 23.5);
    insert into rain_stats values(2004, '8月', 79.5);
    insert into rain_stats values(2004, '9月', 195.0);
    insert into rain_stats values(2004, '10月', 780.0);
    insert into rain_stats values(2004, '11月', 108.5);
    insert into rain_stats values(2004, '12月', 79.5);
    insert into rain_stats values(2005, '1月', 77.0);
    insert into rain_stats values(2005, '2月', 48.0);
    insert into rain_stats values(2005, '3月', 71.0);
    insert into rain_stats values(2005, '4月', 81.0);
    insert into rain_stats values(2005, '5月', 180.5);
    insert into rain_stats values(2005, '6月', 170.5);
    insert into rain_stats values(2005, '7月', 247.5);
    insert into rain_stats values(2005, '8月', 189.5);
    insert into rain_stats values(2005, '9月', 177.5);
    insert into rain_stats values(2005, '10月', 201.5);
    insert into rain_stats values(2005, '11月', 34.5);
    insert into rain_stats values(2005, '12月', 3.5);


  • エンティティRainStatsを作成する。

    package zkseasar.entity;

    import java.math.BigDecimal;
    import javax.persistence.Entity;
    import javax.persistence.Table;

    @Entity
    @Table(name = "RAIN_STATS")
    public class RainStats {
    public Integer year;

    public String month;

    public BigDecimal rainfall;
    }


  • サービスRainStatsServiceを作成する。

    package zkseasar.service;
    import java.util.List;
    import org.seasar.extension.jdbc.JdbcManager;
    import zkseasar.entity.RainStats;

    public class RainStatsService {
    public JdbcManager jdbcManager;

    public List<RainStats> selectAll(String year) {
    return jdbcManager.from(RainStats.class)
    .where("year = ?", year)
    .getResultList();
    }

    }


  • rainfall.zulを作成する。

    <?xml version="1.0" encoding="UTF-8"?>
    <?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 ">
    <window title="東京 年間降雨量デモ" width="500px" border="normal">
    年度:
    <listbox id="yr" rows="1" mold="select" onSelect="processYear(self.selectedItem.label)">
    <listitem label="2005" selected="true"/>
    <listitem label="2004"/>
    <listitem label="2003"/>
    </listbox>
    <vbox>
    <chart id="mychart" title="月別降雨量 (mm)" width="500" height="250" type="pie" threeD="false" fgAlpha="128"/>
    <checkbox label="3D チャート" checked="false" onCheck="mychart.setThreeD(self.isChecked())"/>
    </vbox>
    <zscript>
    model = new SimplePieModel();

    // 年を指定してパイチャートを表示
    void processYear(String year) {
    model.clear();
    rainStats = rainStatsService.selectAll(year);
    for(data: rainStats){
    model.setValue(data.month, data.rainfall);
    }
    mychart.setModel(model);
    }
    // デフォルトは最新の年
    processYear("2005");
    </zscript>
    </window>
    </zk>


  • localhost:8080/zkseasar/view/rainfall.zulへアクセスする。


    当初パイチャートの日本語が文字化けしていました。OSはFedora Core6です
    http://blog.goo.ne.jp/koregaiya/e/ac4c0c130df9fa8ef0cf7e31be71671aを参考にして文字化けを解消することが出来ました。コマンドだけ書いておきます。

    # cd $JAVA_HOME/jre/lib/fonts
    # mkdir fallback
    # cd fallback
    # ln -s /usr/share/fonts/japanese/TrueType/ipagp.ttf kochi-gothic-subst.ttf
    # ln -s /usr/share/fonts/japanese/TrueType/ipamp.ttf kochi-mincho-subst.ttf

  • 2007年11月5日月曜日

    ZK: Seasar2

    ZKからSeasar2のS2JDBCを利用してデータベースにアクセスするアプリケーションをとりあえず動作させた手順のメモです。

  • Seasarサイトの「セットアップ>Doltengを使う場合」を参考にしてEclipseにSeasarをセットアップする。

  • EclipseでChuraプロジェクトを作成する。
    File>New>Other>Chura>Chura Project
    Nextボタンを押してCreate a Chura Projectダイアログを表示する

    Project name; [zkseasar]
    Root Package Name: [zkseasar]
    Project Type: Super Agile(Teeda + S2Dao)

    Finishボタンを押すとプロジェクトが作成される。
    zkseasarプロジェクトを右クリックしメニューを表示する。
    「Tomcat プロジェクト>コンテキスト定義を更新」をクリックする。


  • ZKライブラリをPROJECTHOME/src/webapp/WEB-INF/libへコピーする。
    プロジェクトツリーでzkseasarをクリック
    src>main>webapp>WEB-INF>libを選択し右クリックしてメニューを表示する。
    ImportをクリックしImport Selectダイアログを表示する。
    General>File Systemを選択しNextボタンをクリックしFile systemダイアログを表示する。
    From directory: の右にある BrowseボタンをクリックしZKを展開してできたディレクトリのdist/libのjarファイルを選択しコピーする。

    今の作業を繰り返しdist/lib/extのjarファイルもコピーする。


  • 同様にs2-tiger/libにあるgeronimo-jpa_3.0_spec-1.0.jarとgeronimo-ejb_3.0_spec-1.0.jarをWEB-INF/libへコピーする。


  • 同様にs2-tiger/src/test/resourcesにあるs2jdbc.diconをsrc/main/resourcesへコピーする。

  • s2jdbc.diconを編集しdialectをh2dialectに変更しChuraプロジェクトのサンプル
    データベースにあわせる。

    <components>
    ...
    <property name="dialect">h2Dialect</property>
    ...


  • geronimo-jpa_3.0_spec-1.0.jarをBuild Pathに追加する。
    プロジェクトツリーでzkseasarをクリック
    Referenced Librariesを右クリックしメニューを表示する。
    Build Path>Configure Build Path...をクリックしJava Build Pathダイアログを表示する。

    LibrariesタグをクリックしAdd External JARS..ボタンをクリックして出てきたダイアログでgeronimo-jpa_3.0_spec-1.0.jarを選択しOKボタンをクリックする。

  • app.diconを編集しs2jdbc.diconを追加する。

    .....
    <include path="s2jdbc.dicon"/>
    </components>


  • convention.diconを編集しorg.seasar.framework.convention.impl.PersistenceConventionImplを登録する。

    ....
    <component class="org.seasar.framework.convention.impl.PersistenceConventionImpl"/>
    </components>


  • WEB-INF/web.xmlへzkdemoの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-mapping>
    <servlet-name>zkLoader</servlet-name>
    <url-pattern>*.zhtml</url-pattern>
    </servlet-mapping>

    <!-- Optional. Uncomment it if you want to use richlets.
    -->
    <servlet-mapping>
    <servlet-name>zkLoader</servlet-name>
    <url-pattern>/zk/*</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>
    ....


    アプリケーション作成


  • エンティティEmp.javaを作成。

    package zkseasar.entity;
    import java.math.BigDecimal;
    import java.util.Date;

    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.Table;

    @Entity
    @Table(name = "EMP")
    public class Emp {
    @Column(name = "ID")
    public Integer id;

    @Column(name = "EMP_NO")
    public Integer empNo;

    @Column(name = "EMP_NAME")
    public String empName;

    @Column(name = "MGR_ID")
    public Integer mgrId;

    @Column(name = "HIREDATE")
    public Date hiredate;

    @Column(name = "SAL")
    public BigDecimal sal;

    @Column(name = "DEPT_ID")
    public Integer deptId;

    @Column(name = "VERSION_NO")
    public Integer versionNo;

    }



  • サービスEmpService.java作成。

    package zkseasar.service;
    import java.util.List;

    import org.seasar.extension.jdbc.JdbcManager;
    import zkseasar.entity.Emp;

    public class EmpService {
    public JdbcManager jdbcManager;

    public List<Emp> selectAll() {
    return jdbcManager.from(Emp.class).getResultList();
    }
    }


  • src/main/webapp/viewにemp.zulを作成。

    <?xml version="1.0" encoding="UTF-8"?>
    <?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;

    public class MyRowRenderer implements RowRenderer {
    public void render(Row row, Object data) {
    new Intbox(((Emp)data).id).setParent(row);
    new Intbox(((Emp)data).empNo).setParent(row);
    new Textbox(((Emp)data).empName).setParent(row);
    // new Intbox(((Emp)data).mgrId).setParent(row);
    new Datebox(((Emp)data).hiredate).setParent(row);
    new Decimalbox(((Emp)data).sal).setParent(row);
    new Intbox(((Emp)data).deptId).setParent(row);
    new Intbox(((Emp)data).versionNo).setParent(row);
    }
    }
    emps = empService.selectAll();
    model = new SimpleListModel(emps.toArray());
    rowRenderer = new MyRowRenderer();
    </zscript>
    <window title="Emplyee list" >
    <grid model="${model}" rowRenderer="${rowRenderer}">
    <columns>
    <column label="id"/>
    <column label="Emp no"/>
    <column label="Emp name"/>
    <column label="Hiredate"/>
    <column label="Sal"/>
    <column label="Dept id"/>
    <column label="Version no"/>
    </columns>
    </grid>
    </window>
    </zk>


  • 完成
    まだDBを起動していないときはDoltengと一緒にインストールしたDatabaseViewから起動する。
    Window>Show View>Other>Dolteng>DatabaseViewをクリックしビューを表示。
    ビューの中のzkseasarをクリックして表示されるjdbc.diconをクリックするとDBが起動する。
    Ellipse>Tomcat>Tomcat起動をクリックしTomcatを起動する。
    Webブラウザでhttp://localhost:8080/zkseasar/view/emp.zulを表示する。


    Seasarコンポーネントの変数もapp.diconからs2jdbc.dicon経由で自動的に設定されるようです、いいですね!
  • 2007年10月26日金曜日

    ZK: zulスキーマを使いzulファイルを生成する

    Eclipe環境がセットアップできたのでzulファイルを作ってみました。
  • Project ExplorerでプロジェクトのWebContentディレクトリを選択しメニューを表示する


  • メニューからNew/Otherを選択しSelect a wizardダイアログを表示しXML/XMLを選択しNextボタンを押す


  • XML Fileダイアログを開きFile nameにhelloworld.zulを入力しNextボタンを押す


  • XML file作成方法選択ダイアログが開くのでCreate XML file form an XML schema file を選択しNextボタンを押す


  • スキーマファイル選択ダイアログの中からhttp//www.zkoss.org/2005/zul/zul.xsdを選択しNextボタンを押す


  • 私の場合、ルートエレメントはwindowにしたい


  • p:プレフィックスが鬱陶しいのでEditボタンを押しprefixを消す


  • helloworld.zulが生成され、コンポーネント名やアトリビュート名の入力補完が可能になりました
  • 2007年10月25日木曜日

    ZK: Eclipseセットアップ

    ZK How-Tosを参考にEclipse3.3.1へZK開発環境をセットアップした時のメモです。

    [OS] Fedora Core 6
    [Java] jdk1.5.0_09
    [Eclipse] wtp-all-in-one-sdk-linux-gtk

    zulファイルをXMLファイルとして扱う



  • EclipseのWindowメニューをクリック

  • Preferencesを選択しPreferencesダイアログを開く

  • ダイアログの左サイドのツリーメニューでGeneral/Content Typesをクリック

  • Content TypesペインでText/XMLを選択しAddボタンを押しNew File Typeダイアログを開く

  • File Typeに*.zulを入力しOKボタンを押す。


    zul.xsdスキーマのセットアップ


    zul.xsdをセットアップすることでコンポーネント名やアトリビュートの入力補完が可能になります。

  • Window/PreferencesメニューをクリックしPreferencesダイアログを開く

  • ダイアログの左サイドのツリーメニューでWeb and XML/XML Catalogをクリックする

  • XML Catalog Entriesの中でUser Specified EntriesをクリックしAddボタンを押す


  • Add XML Catalog Entryダイアログを表示し下図の様に入力しOKボタンを押す


  • User Specified Entriesにhttp://www.zkoss.org/2005/zul/zul.xsdが表示されれば完了
  • 2007年10月12日金曜日

    ZK: Ruby on ZK を試す

    ZK Forumで紹介されていたRuby on ZKを試してみました。
    とりあえずダウンロードしたrozk_r0.2.warを展開してみるとmySql.sqlなるファイルがあり、中身を確認するとテーブル作成ddlだったのでmysqlで実行してtestデータベースにテーブルを作成してみました。

    $ cd ~/tmp
    $ unzip rozk_r.0.2.war
    $ mysql -u myadmin -p test
    Enter password:
    mysql> \. mySql.sql
    ...
    mysql> exit
    Bye

    アプリケーションに必要なテーブルが作成できたと思い、rozk_r0.2.warをTOMCAT_DIR/webappsに配備後tomcatを再起動しました。
    tomcatにより展開されてできたアプリケーションディレクトリのcustomer.zulとinvoice.zulにmysqlユーザとパスワードの記述があるので実状に合わせ変更します。
    WEB-INF/libの中が空っぽなのでZKライブラリをコピーします。
    またWEB-INF/web.xmlが不完全なので動作しているZKアプリのweb.xmlをコピーしました。

    $ diff customer.zul customer.zul~
    8c8
    < dbc=Dbc.new('test','MySql','myadmin','XXXXXX')
    ---
    > dbc=Dbc.new('test','MySql','root','david')

    $ diff invoice.zul invoice.zul~
    9c9
    < dbc=Dbc.new('test','MySql','myadmin','XXXXXX')
    ---
    > dbc=Dbc.new('test','MySql','root','david')

    # cp zk-bin-3.0.0-RC/dist/lib/*jar TOMCAT_DIR/webapps/rozk_r0.2/WEB-INF/lib

    # cp zk-bin-3.0.0-RC/dist/lib/ext/*jar TOMCAT_DIR/webapps/rozk_r0.2/WEB-INF/lib

    # cd TOMCAT_DIR/webapps
    # cp ZKAPP_DIR/WEB-INF/web.xml rozk_r0.2/WEB-INF

    Firefoxでアクセスして見たところエラーです。


    ワークディレクトリの設定がうまくいっていないようなのでrozk_r0.2/rozk/bl_init.rbを編集しアプリケーションのフルパスを記入してアクセスしてみたところ動作させることができました。

    # vi bl_init.rb
    ...
    else # change the working directory to the webapps, if tomcat
    # Dir.chdir('webapps'+work_path) # 'webapps/rozk_sample'
    Dir.chdir('/usr/tomcat/webapps'+work_path) # 'webapps/rozk_sample'
    end
    ...



    どうやら

    customer.zul
    ...
    # 他になんの設定もなしで
    dbc=Dbc.new('test','MySql','myadmin','XXXXXX')
    #データベースに接続し

    # 他になんの設定もなしで
    dao_cus = Dao.new(dbc,'cus','cus as Customer, name as Name, email as eMail','cus')
    # DAOが出来上がり

    # 生成されたDAOから自動的に
    AutoGrid.dao_2_grid(dao_cus,$cus_form)
    # DAO操作用のグリッドが作成されるようです!!



    ということはambitionを試すで作ったpetsテーブルの操作はこれだけでOK?

    pet.zul
    <?page zscript-language="Ruby"?>
    <window >
    <div id='pet_form'/>
    <zscript src='rozk/bl_init.rb'/>
    <zscript>
    dbc=Dbc.new('sampledb','MySql','myadmin','XXXXXX')
    pets = Dao.new(dbc,'pets','id as ID, name as Name, age as Age','pets')
    AutoGrid.dao_2_grid(pets,$pet_form)
    </zscript>
    </window>



    でした、面白いですね。



    こちらも気に掛かりますひがやすをさんのブログ

    ...
    来週出す予定のSeasar2の次のバージョン(2.4.18)で、S2Daoが統合されます。
    ...
    目玉は、ManyToOne、OneToMany、OneToOneの完全サポートでしょうか。
    ...

    List employees =
    jdbcManager.from(Employee.class).join("department").getResultList();



    わくわくしますね。

    2007年10月8日月曜日

    ZK: ブラウザを判別

    WEBサイトにアクセスしてきたブラウザの種類は
    Executions.getCurrent().[isGecko(),isExplore(),isExplore7(),isSafari()]
    を使用して判別し、HTTPリクエストのユーザエージェント情報がそのまま欲しいときは
    HttpServletRequest)Executions.getCurrent().getNativeRequest()).getHeader("User-Agent")
    を使用して取得する。


    <window title="Client User Agent" border="normal" width="360px">
    <zscript>
    import javax.servlet.http.HttpServletRequest;
    void dispClientAgent(){
    String agentInfo = ((HttpServletRequest)Executions.getCurrent().
    getNativeRequest()).getHeader("User-Agent");
    userAgent.value = agentInfo;
    }
    </zscript>
    <vbox>
    <label value="Hello ZK!!" id="userAgent"/>
    <button label="ユーザエージェント情報を表示" onClick="dispClientAgent()"/>
    </vbox>
    <zscript>
    if (Executions.getCurrent().isGecko()){
    userAgent.value = "Firefoxでアクセス";
    }else if (Executions.getCurrent().isExplorer()){
    userAgent.value = "Explorerでアクセス";
    }else if (Executions.getCurrent().isExplorer7()){
    userAgent.value = "Explorer 7でアクセス";
    }else if (Executions.getCurrent().isSafari()){
    userAgent.value = "Safariでアクセス";
    }else {
    userAgent.value = ".....";
    }
    </zscript>
    </window>

    2007年9月30日日曜日

    Ruby: ambition(2)テーブル結合

    Rubyのコレクション系のメソッドがそのまま意味的に等価なSQLを生成し、データベースにアクセスするAmbitionって面白いですね。テーブル結合はどうなるのだろうと思いビートルズのディスコグラフィーを作って試してみました。
    まずはアルバムのデータ作成

    create table albums(
    id integer not null auto_increment,
    name varchar(50),
    year smallint,
    primary key(id)
    );


    insert into albums(name, year)values('Please Please Me', 1963);
    insert into albums(name, year)values('With the Beatles', 1963);
    insert into albums(name, year)values('A Hard Day\'s Night', 1964);
    insert into albums(name, year)values('Beatles for Sale', 1964);
    insert into albums(name, year)values('Help!', 1965);
    insert into albums(name, year)values('Rubber Soul', 1965);
    insert into albums(name, year)values('Revolver', 1966);
    insert into albums(name, year)values('Sgt. Pepper\'s Lonly Hears Club Band', 1967);
    insert into albums(name, year)values('The Beatles', 1968);
    insert into albums(name, year)values('Yellow Submarine', 1969);
    insert into albums(name, year)values('Abbey Road', 1969);
    insert into albums(name, year)values('Let it Be', 1970);


    次は曲のデータ、「ビートルズがやってきた」までです。ぁ〜なつかしいな!!

    create table songs(
    id integer not null auto_increment,
    name varchar(50),
    album_id integer not null,
    primary key(id),
    foreign key(album_id) references albums(id)
    );

    insert into songs(name, album_id)values('I Saw Her Standing There', 1);
    insert into songs(name, album_id)values('Anna (Go to Him)', 1);
    insert into songs(name, album_id)values('Misery', 1);
    insert into songs(name, album_id)values('Boys', 1);
    insert into songs(name, album_id)values('Ask Me Why', 1);
    insert into songs(name, album_id)values('Please Please Me', 1);
    insert into songs(name, album_id)values('Love Me Do', 1);
    insert into songs(name, album_id)values('P.S. I Love Yoe', 1);
    insert into songs(name, album_id)values('Baby It\'s You', 1);
    insert into songs(name, album_id)values('Do You Want to Know a Secret', 1);
    insert into songs(name, album_id)values('A Taste of Honey', 1);
    insert into songs(name, album_id)values('There\'s a Place', 1);
    insert into songs(name, album_id)values('Twist and Shout', 1);

    insert into songs(name, album_id)values('It Won\'t Be Long', 2);
    insert into songs(name, album_id)values('All I\'ve Got To Do', 2);
    insert into songs(name, album_id)values('All My Loving', 2);
    insert into songs(name, album_id)values('Don\'t Bother Me', 2);
    insert into songs(name, album_id)values('Little Child', 2);
    insert into songs(name, album_id)values('Till There Was You', 2);
    insert into songs(name, album_id)values('Please Mister Postman', 2);
    insert into songs(name, album_id)values('Roll Over Beethoven', 2);
    insert into songs(name, album_id)values('Hold Me Tight', 2);
    insert into songs(name, album_id)values('You Really Got A Hold On Me', 2);
    insert into songs(name, album_id)values('I Wanna Be Your Man', 2);
    insert into songs(name, album_id)values('Devil I Her Heart', 2);
    insert into songs(name, album_id)values('Not A Second Time', 2);
    insert into songs(name, album_id)values('Money', 2);

    insert into songs(name, album_id)values('A Hard Day\'s Night', 3);
    insert into songs(name, album_id)values('I Should Have Known Better', 3);
    insert into songs(name, album_id)values('If I Fell', 3);
    insert into songs(name, album_id)values('I\'m Happy Just to Dance With You', 3);
    insert into songs(name, album_id)values('And I Love Her', 3);
    insert into songs(name, album_id)values('Tell Me Why', 3);
    insert into songs(name, album_id)values('Can\'t Buy Me Love', 3);
    insert into songs(name, album_id)values('Any Time At All', 3);
    insert into songs(name, album_id)values('I\'ll Cry Instead', 3);
    insert into songs(name, album_id)values('Things We Said Today', 3);
    insert into songs(name, album_id)values('When I Get Home', 3);
    insert into songs(name, album_id)values('You Can\'t Do That', 3);
    insert into songs(name, album_id)values('I\'ll Be Back', 3);


    スクリプトを作成し実行してみます。

    require 'rubygems'
    require 'active_record'
    require 'ambition'

    ActiveRecord::Base.establish_connection(
    :adapter => 'mysql',
    :database => 'sampledb',
    :host => 'localhost',
    :username => 'myadmin',
    :password => 'xxxxxx'
    )



    # テーブルが複数形なのに対してクラスは単数形
    class Album < ActiveRecord::Base
    end

    class Song < ActiveRecord::Base
    belongs_to :album
    def to_s
    return sprintf("%-30s [%s]", name, album.name)
    end
    end


    puts Song.select{|s| s.album.name =~ 'Please%'}
    #SELECT * FROM songs JOIN album WHERE albums.name LIKE 'Please%'
    # SQL変ですね!!

    Song.select{|s| s.album.name =~ 'Please%'}.each{|s| print s, s.album.year, "\n"}
    #I Saw Her Standing There [Please Please Me]1963
    #Anna (Go to Him) [Please Please Me]1963
    #Misery [Please Please Me]1963
    #Boys [Please Please Me]1963
    #Ask Me Why [Please Please Me]1963
    #Please Please Me [Please Please Me]1963
    #Love Me Do [Please Please Me]1963
    ...


    to_sで出力されたSQLは変ですが、 DBへはきちんとアクセスしているみたいです???

    Ruby: ambitionを試す

    Rubyのブロックで条件指定するとSQLを作成するAmbitionなるものを試してみました。
    とりあえずActiveRecordだけあればよさげですが、今回はRails一式をインストールしてから試してみました。
    使用するデータベースはMySQLです。

    まずはAmbitionのインストール

    $ sudo gem install ambition -y


    次にMySQLにお試しテーブルを作成します。

    $ mysql -u myadmin -p sampledb
    mysql> \. pet.sql
    ...
    mysql>exit;
    Bye

    $ cat pet.sql
    create table pets(
    id integer not null auto_increment,
    name varchar(20),
    age smallint,
    primary key(id)
    );

    insert into pets(name, age)values('Hanako', 13);
    insert into pets(name, age)values('Wan-taro', 15);
    insert into pets(name, age)values('Pochi', 3);
    insert into pets(name, age)values('Shiro', 8);
    insert into pets(name, age)values('Tama', 4);
    insert into pets(name, age)values('Tora', 2);


    さっそくAmbitionを試しましょう

    require 'rubygems'
    require 'active_record'
    require 'ambition'

    ActiveRecord::Base.establish_connection(
    :adapter => 'mysql',
    :database => 'sampledb',
    :host => 'localhost',
    :username => 'myadmin',
    :password => 'xxxxxxx'
    )



    # petテーブルに対応するクラス テーブルが複数形なのに対してクラスは単数形
    class Pet < ActiveRecord::Base
    def to_s
    return "name:#{name} age:#{age} "
    end
    end

    # Rubyの条件でSQLが作成されます
    puts Pet.select{|p| p.name == 'Hanako'}
    #SELECT * FROM pets WHERE pets.`name` = 'Hanako'

    puts Pet.select{|p| p.name =~ '%ako%'}
    #SELECT * FROM pets WHERE pets.`name` LIKE '%ako%'

    # MySQLは正規表現も使えるんですね
    puts Pet.select{|p| p.name =~ /ako/}
    #SELECT * FROM pets WHERE pets.`name` REGEXP 'ako'

    puts Pet.sort_by{|p| [p.age, p.name]}
    #SELECT * FROM pets ORDER BY pets.age, pets.name

    # テーブルにアクセスし年齢でソートして画面に出力
    Pet.sort_by{|p| p.age}.each{|p| puts p}
    #name:Mie age:2
    #name:Pochi age:3
    #name:Tama age:4
    #name:Shiro age:8
    #name:Hanako age:13
    #name:Wan-taro age:15

    # データベースに接続されていなくても構わないようです
    pets = [Pet.new(:name => 'Foo', :age => 2),
        Pet.new(:name =>'Bar', :age => 11)],
    Pet.new(:name => 'Baz', :age => 7))]

    Pet.ambition_source = pets
    # 年齢を降順にソート
    Pet.sort_by{|p| -p.age}.each{|p| puts p}
    #name:Bar age:11
    #name:Baz age:7
    #name:Foo age:2


    # ambition_source を nilに戻すと再びデータベースへアクセスします
    Pet.ambition_source = nil
    Pet.sort_by{|p| p.age}.each{|p| puts p}
    #name:Mie age:2
    #name:Pochi age:3
    #name:Tama age:4
    #name:Shiro age:8
    #name:Hanako age:13
    #name:Wan-taro age:15


    なんかいい感じですね!!JRubyで動作しないのが残念です。

    2007年9月29日土曜日

    ZK: XMLエディタをデフォルトエディタに設定


    Eclipseでzulファイルの編集にXMLエディタをデフォルトエディタとして使用するように設定するには、Eclipseメニューの「ウィンドウ」->「設定」で設定画面を表示する。
    ファイルの関連付け画面を表示し、ファイルタイプの中から*.zulをクリックする。
    関連づけられたエディターの中からXMLエディターを選択し「デフォルト」ボタンをクリックするとXMLエディタがzulファイルのデフォルトエディタに設定される。

    ZK: ボタンのテキストアライン設定

    CSSを使用してボタンのテキストアラインの設定が可能です。

    <window title="ボタンのテキストアライン設定" border="normal" width="500px">
    <vbox>
    <button label="hello" style="width:200px;text-align:left"/>
    <button label="hello" style="width:200px;text-align:right"/>
    <button label="hello" style="width:200px;text-align:center"/>
    </vbox>
    </window>

    2007年9月28日金曜日

    ZK: アプリでボタンのサイズを統一

    CSS使用してアプリケーションの全てのボタンのサイズ同じに設定可能です。

    <window title="アプリのボタンサイズを統一する" border="normal" width="500px">
    <style>
    .fixwidth{
    width:200px;
    }
    </style>
    <vbox>
    <button label="ADD" sclass="fixwidth"/>
    <button label="DELETE" sclass="fixwidth"/>
    </vbox>
    </window>

    2007年9月19日水曜日

    ZK: JNDI接続

    WEBアプリケーションはJDBC接続を通じてリモートのRDBMSにアクセスする。この際クライアントアプリケーションとRDBMSサーバの間にはTCP/IPを介し物理的にJDBC接続が確立されるがデータベースと物理的に接続を確立するには大きなCPUパワーが必要で時間もかかる。このためHTTPリクエストの度にアプリケーションとRDBMSの間で物理的に接続、切断を行うことはパフォーマンスに大きな影響がでる。そこでアプリケーションサーバはシステム起動時にデータベースとの物理的な接続をプールし、データベースとの接続を必要とするアプリケーションはールマネージャを介しデータベースに論理的に接続するようにする。そしてデータベース使い終えたアプリケーションは論理的に接続を切断し、プールマネージャは次のデータベース接続要求を待つことになる。
    --だそうです


    JNDIとはJava Naming and Directory Interfaceの頭文字を取ったもので、Javaから
    * ネーミング・サービス
    * ディレクトリー・サービス
    扱うためのインターフェイスを規定した仕様です。

    *詳しくは「今さら人に聞けないJNDI」


    Fedor Core 6 でハマッタ
    /etc/hostsに 127.0.0.1 localhost エントリが無い!!
    $ cat /etc/hosts
     # Do not remove the following line, or various programs
    # that require network functionality will fail.
    ::1 localhost.localdomain localhost



    JNDI接続ではlocalhostが127.0.0.1に解決できないとデータベース接続できないようだ。
    ブラウザからはlocalhost:8080で アドレス解決できるし、SpringやSeasarでもホスト名にはlocalhostを使用していて問題なかったので気づくのに時間がかかった。



      動作環境確認
    • OS Fedora Core 6

    • Java jdk1.5.0_09

    • /usr/java/jdk1.5.0_09へインストールし、シンボリックリンク/usr/java/jdk作成
      $JAVA_HOME=/usr/java/jdk $CLASSPATH=.:/usr/java/jdk/jre/lib:/usr/java/jdk/lib:/usr/java/jdk/lib/tools.jar
    • MySQL 5.20.27

    • Tomcat apache-tomcat-5.5.20

    • /usr/apache-tomcat-5.5.20へインストールし、シンボリックリンク/usr/tomcat作成
    • Eclipse 3.2(wtp-all-in-one)

    • ZK 2.4

    • ZKライブラリの配置
      アーカイブを展開してできたディレクトリdist/libとdist/lib/ext内の全てのjarファイルをEclipseのライブラリとして取り込む。
    • /usr/tomcat/common/libへ配置したjarファイル

    • MySQL JDBCドライバ mysql-connector-java-5.0.4-bin.jar
      commons-pool-1.3.jar
      commons-collections-3.2.jar
      commons-dbcp-1.2.1.jar


  • Tomcat用JNDIリソース mysql/hellodb を設定する

  •  ($TOMCAT_DIR/conf/context.xml)
    <Context reloadable="true">
    <Resource
    name="mysql/hellodb"
    username="myadmin"
    password="*********"
    url="jdbc:mysql://localhost:3306/hellodb"
    auth="Container"
    defaultAutocommit="false"
    driverClassName="com.mysql.jdbc.Driver"
    type="javax.sql.DataSource"
    maxActive="20"
    maxIdle="30000"
    maxWait="100"
    />

    </Context>

    (Eclipseプロジェクトではcontext.xmlは$PROJECT_HOME/WebContent/META-INF/に配置する)

  • アプリケーションで使用するJNDIリソースmysql/hellodbを定義する

  •  (WEB-INF/web.xml)

    <resource-ref>
    <res-ref-name>mysql/hellodb</res-ref-name>
    <res-type>javax.sql.Datasource</red-type>
    <res-auth>Container</res-auth>
    </resource-ref>



  • Bean作成

  •  (my.Emp.java)

    public class Emp {
    private int empno;
    private String ename;
    private String job;

    public Emp(int empno, String ename, String job){
    this.empno = empno;
    this.ename = ename;
    this.job = job;
    }

    public int getEmpno() {
    return empno;
    }
    public void setEmpno(int empno) {
    this.empno = empno;
    }
    ... 残りのフィールドのgettter、setter メソッド省略
    }


  • アプリケーションからデータソースを参照するクラスを作成

  •  (my.EmpManager.java)

    public class EmpManager {
    public List findAll() throws Exception {
    DataSource ds = (DataSource)new InitialContext()
    .lookup("java:comp/env/mysql/hellodb");

    Connection conn = null;
    Statement stmt = null;
    ResultSet rs = null;

    List results = new LinkedList();
    try {
    conn = ds.getConnection();
    stmt = conn.createStatement();
    rs = stmt.executeQuery("select EMPNO, ENAME, JOB from EMP");
    while (rs.next()) {
    int empno = rs.getInt("EMPNO");
    String ename = rs.getString("ENAME");
    String job = rs.getString("JOB");
    results.add(new Emp(empno, ename, job));
    }
    return results;
    } finally {
    if (rs != null) try{ rs.close(); } catch (SQLException ex){}
    if (stmt != null) try{stmt.close();} catch (SQLException ex){}
    if (conn != null) try(conn.close();} catch (SQLException ex){}
    }
    }
    }


  • ビュー作成

  •  (conn-pool1.zul)

    <window title="Connection Pooling Demo 1" border="normal">
    <zscript>

    import my.EmpManager;
    emps = new EmpManager().findAll();
    </zscript>
    <listbox id="empList" width="800px">
    <listhead>
    <listheader label="Empno" />
    <listheader label="Name" />
    <listheader label="Job"/>

    </listhead>
    <listitem value="${each.empno}" forEach="${emps}">
    <listcell label="${each.empno}" />
    <listcell label="${each.ename}" />
    <listcell label="${each.job}" />
    </listitem>

    </listbox>
    </window>

  • インターフェース Initiatorの実装

  • org.zkoss.ak.ui.util.Initiatorを実装しinitディレクティブを使用することでzulファイルにJavaコードを記述せずにデータロードが可能になる。

    Eclipseメニュー
    +-ファイル
    +-新規
    +-その他
    +-クラス

    パッケージ: my
    名前: AllEmpFinder

    インターフェース
    [追加]

    インターフェースを選択してください: org.zkoss.ak.ui.util.Initiator
    [OK]


  • 作成されたテンプレートを編集


  • public void doInit(Page arg0, Object[] arg1) throws Exception {
    try {
    arg0.setVariable((String)arg1[0], new EmpManager().findAll());
    } catch (Exception ex){
    throw UiException.Aide.wrap(ex);
    }
    }


  • ビュー作成

  • (conn-pool2.zul)

    <window title="Connection Pooling Demo 2" border="normal">
    <?init class="my.AllEmpFinder" arg0="emps"?>
    ... 以降はconn-pool1.zulに同じ

    2007年9月11日火曜日

    ZKアプリから最も簡単にJDBC接続するには


    ZKアプリから最も簡単にJDBC接続するにはJDBCの入門書にあるようにjava.sql.DriverManagerを使用する方法がある。データベースへの接続といったコストのかかる処理は効率的に行われるべきなので、この方法は簡単ではあるが勧められるものではない。
    --そうです。


    MySQLデータベースhellodbにあるnameとemailの二つのカラムを持つテーブルusersへデータ登録するアプリケーションを作成する。

    jdbc-demo.zul

    <window title="JDBC demo" border="normal">
    <zscript>
    import java.sql.*;
    void submit() {
    //ドライバをロードしデータベースに接続する。
    Class.forName("com.mysql.jdbc.Driver");
    Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/hellodb?user=myadmin&amp;password=********");
    PreparedStatement stmt = null;
    try {
    stmt = conn.prepareStatement("INSERT INTO users values(?, ?)");
    //ユーザ入力をステートメントにセットする
    stmt.setString(1, name.value);
    stmt.setString(2, email.value);
    //ステートメントを実行
    stmt.executeUpdate();
    } finally { //クリーンアップ作業
    if (stmt != null) {
    try {
    stmt.close();
    } catch (SQLException ex) {
    // log.error(ex); //log and ignore
    }
    }
    if (conn != null) {
    try {
    conn.close();
    } catch (SQLException ex) {
    // log.error(ex); //log and ignore
    }
    }
    }
    }
    </zscript>
    <vbox>

    <hbox>Name : <textbox id="name"/></hbox>
    <hbox>Email: <textbox id="email"/></hbox>
    <button label="submit" onClick="submit()"/>
    </vbox>

    </window>


    お終い

    2007年8月29日水曜日

    ZK: Fileupload サイズ制限の変更

    ZKではアップロードできるファイルサイズはデフォルトで5120kbに制限されている。WEB-INF/zk.xml(オプション)を作成しsystem-configエレメント内のmax-upload-sizeエレメントでキロバイト単位でアップロード可能なファイルサイズを変更できる。max-upload-sizeが負の場合アップロードするファイルサイズに制限がなくなる。(ZK The Developer's Reference)


    <system-config>
    <max-upload-size>10240</max-upload-size>
    </system-config>

    2007年8月28日火曜日

    ZK: CSSでグリッドヘッダの色を変更





    <window title="Grid Header" border="normal">
    <style>
    div.grid-head th{
    background-color: red;
    }
    </style>
    <grid >
    <columns>
    <column width="150px" label="Author"/>
    <column width="300px" label="Title"/>
    <column width="150px" label="Manufacturer"/>
    <column width="100px" label="ProductGroup"/>
    </columns>
    <rows>
    <row>
    <label value="Sidney Sheldon"/>
    <label value="Master of the Game"/>
    <label value="Warner Books"/>
    <label value="Book"/>
    </row>
    ...
    </rows>
    </grid>
    </window>

    ZK: Fileuploadデモ

    http://commons.apache.orgよりcommons-fileupload-1.2-bin.tar.gz及びcommons-io-1.3.2-bin.tar.gzをダウンロード。ダウンロードしたファイルを展開しcommons-fileupload-1.2.jarとcommons-io-1.3.2.jarをアプリケーション/WEB-INF/libへ配置する。

    EclipseではWEB-INF/libを選択し右クリックしメニューを表示
    Importメニューよりjarファイルをプロジェクトにインポートする。


    <window title="fileupload demo" border="normal">
    <button label="Upload">
    <attribute name="onClick">{
    Object media = Fileupload.get();
    if (media instanceof org.zkoss.image.Image) {
    Image image = new Image();
    image.setContent(media);
    image.setParent(pics);
    } else if (media != null)
    Messagebox.show("Not an image: "+media, "Error",
    Messagebox.OK, Messagebox.ERROR);
    }
    </attribute>
    </button>
    <vbox id="pics"/>
    </window>

    2007年8月23日木曜日

    ZK: マウスオーバーでpopup表示

    「ボタン上にマウスカーソルが来るとバルーンヘルプのように時刻をポップアップ表示させる。」
    マウスオーバーでポップアップ表示させたいpopupコンポーネントのIDをボタンのtooltip属性に設定する。popupコンポーネントのonOpenイベントハンドラはRubyで実装した。

    <window title="ツールチップ表示" border="normal" width="360px">
    <zscript language="ruby">
    def popup_open
    $lbltime.value = Time.now.strftime("%H:%M:%S")
    end
    </zscript>
    <button label="マウスオーバーで時刻をポップアップ表示"
    tooltip="any"/>
    <popup id="any" onOpen="ruby: popup_open">
    <label id="lbltime"/>
    </popup >
    </window>

    ZK:onMouseOver,onMouseOutイベント

    マウスカーソルがボタンの上に来たらボタンの文字を赤くし、カーソルがボタンから外れたらボタンの文字を黒くする。


    <window title="Customizable Tooltips" border="normal" width="360px">
    <script type="text/JavaScript" >
    function red(el){
    el.style.color = "red";
    }
    function black(el){
    el.style.color = "black";
    }
    </script>
    <button label="Info"
    action="onMouseOver:red(this);onMouseOut:black(this)">
    </button>
    </window>

    2007年8月1日水曜日

    ZK: SVGを使う


    ZKでSVGを使用するにはhtmlコンポーネントの中でembedタグ、またはobjectタグを使用する方法またはiframeタグを使う方法がある。

    Scalable Vector Graphics(SVG、スケーラブル ベクター グラフィックスは、XMLによって記述されたベクターグラフィック言語のこと、或いは、SVGで記述された画像フォーマットのこと。W3Cでオープン標準として勧告されている。...だそうです。





    use-svg.zul

    <window title="Test SVG" border="normal" width="500px">
    <html>
    <attribute name="content">
    <![CDATA[
    <embed src="rectangle.svg" width="300" height="100"
    type="image/svg+xml"
    pluginspage="http://www.adobe.com/svg/viewer/install/"> </embed>
    ]]>
    </attribute>
    </html>
    <iframe src="circle1.svg"/>
    </window>


    rectangle.svg

    <?xml version="1.0" standalone="no"?>
    <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
    "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

    <svg width="100%" height="100%" version="1.1"
    xmlns="http://www.w3.org/2000/svg">

    <circle cx="100" cy="50" r="40" stroke="black"
    stroke-width="2" fill="red"/>

    </svg>

    2007年7月31日火曜日

    Tuigwaaコメントプラグインのカスタマイズ

    Tuigwaaのコメントプラグインのタグはinput/textのためコメントの入力欄は1行しかないがtextareaタグを使用し複数行入力可能にする方法を発見した。

    classes/org/seasar/tuigwaa/plugin/database/CommentView.vm
    を編集しコメント入力用のタグをinputからtextareaに変更すればよい。

    ...
    <input type="text" name="postingUser" size="15" maxsize="15"/>
    <!--
    <input type="text" name="comment" size="70" maxsize="70"/>
    -->
    <br/>
    <textarea name="comment" cols=50 rows=3></textarea>
    ...

    2007年7月23日月曜日

    ZK: Rubyでの制約

    ROZK - Ruby on ZK very simple tools for build

    ZKフレームワークでRubyを使用する場合データバインディングなどで制約がある。
    例えばUsing Timebox ComponentのソースのスクリプトでDateオブジェクトを生成しアノテーションでtimeboxの値にセットしているが、RubyスクリプトでTimeオブジェクトを生成したときはアノテーションはnullになってしまう。関数コールのようにruby:プレフィックスをつけネームスペースを変えてみたがエラーとなった。現状ではRubyオブジェクトはアノテーションで使えない事を頭に入れておこう。


    <zscript>
    import java.text.SimpleDateFormat;
    import java.util.Date;

    SimpleDateFormat format = new SimpleDateFormat("HH:mm");
    Date date = format.parse("23:59");
    </zscript>
    <!-- <zscript language="ruby">
    date = Time.mktime(1970, 1, 1, 23, 59)
    # RubyオブジェクトはZUMLアノテーション${date}で参照できない
    </zscript> -->
    <window title="Time Value(Date)" width="300px" border="normal">
    <timebox id="tb0" value="${date}" />

    2007年7月21日土曜日

    ZK: イベントハンドラにruby関数

    ZKフレームワークではスクリプト言語にrubyを使うことができる。ruby関数をZKコンポーネントのイベントハンドラとして呼び出すときはruby関数の名前の前にruby:をつけること。


    <window title="sample" border="normal">
    <zscript language='ruby'>
    def button1_clicked
    $t.value = $self.label
    end
    </zscript>
    <button onClick="ruby: button1_clicked" label="button1"/>
    <label id="t" value="label"/>
    </window>

    2007年7月20日金曜日

    ZK: vflexモールド付きのdivコンポーネント

    Div with vflex
    mold="vflex"を追加しブラウザ画面の空いている高さにあわせていっぱいになるよう高さを自動調整するDivコンポーネント。

    真ん中のウィンドウはブラウザの空いている部分を埋めるように高さを調整して表示される。


    <?page id="mainPage" title="Hello" ?>
    <zk>
    <window border="normal" title="window">
    This is my header window
    </window>
    <window border="normal" title="window">
    <div mold="vflex">
    This is my my content window
    </div>
    </window>
    <window border="normal" title="window">
    This is my footer window
    </window>
    </zk>

    Yui-Ext Grid (Ext JS)をZKフレームワークで利用する。

    Integrating Yui-Ext into ZK Framework
    Yui-Ext Grid (Y-Grid)の特徴

    *マウスが行の上に来ると色が変化
    *複数行選択が可能
    *列でソート機能
    *列の表示、非表示が選択可能
    *列のリサイズ、移動が可能
    *列の固定

    利用法:
    Y-Gridコンポーネントを利用するときはネームスペースで標準の
    コンポーネントと区別すること。

    <window ... y="http://www.zkoss.org/2007/yui">

    後はコンポーネントにプレフィックスy:付けるだけでY-Gridコンポーネントとして使用可能になる

    2007年7月13日金曜日

    tuigwaaアプリ引越

    新しくセットアップしたホストに既存のtuigwaaサイトを再配備する。

    WebUDA Tuigwaaとは
    tuigwaa (とぅいがー) とは、HTML タグを知らない人が、
    専門知識や特別な環境なしにブラウザだけでデータベースと連動する
    Webアプリケーションを作るツールです。新しいジャンルのミドルウェアとして、
    WebUDA(ユーザ主導型Webアプリケーション作成ツール)と名づけました。
    --だそうです
    ホスト環境
    • OS: Redhat EL 4
    • Java: JDK1.5.0.12
    • Tomcat: 5.5.23
    • Tuigwaa: 1.0.4
    ◎ JavaサイトよりJDK5.0 Update12をダウンロードしインストール
    ダウンロードしたファイルに実行属性を付け実行すると使用許諾
    が表示される、最後までスクロールしyesで同意すると
    /usr/java/jdk1.5.0_12にJDK5.0がインストールされる。
    インストールディレクトリにシンボリックリンクjdkを作成しておく。
    環境変数JAVA_HOMEとCLASSPATHを設定しPATHに
    $JAVA_HOME/binを追加する。
    $ chmod +x jdk-1_5_0_12-linux-i586-rmp.bin
    $ su
    # ./jdk-1_5_0_12-linux-i586-rmp.bin
    # cd /usr/java
    # ln -s jdk1.5.0_12 jdk
    $ vi .bash_profile
    JAVA_HOME=/usr/java/jdk
    PATH=$JAVA_HOME/bin:$PATH
    CLASSPATH=.:$JAVA_HOME/jre/lib:/$JAVA_HOME/lib:\
    /$JAVA_HOME/lib/tools.jar
    export JAVA_HOME CLASSPATH PATH
    $ . .bash_profile
    ◎TomcatダウンロードページよりTomcat5.5.23をダウンロードしインストール
    ダウンロードしたファイルを/usrディレクトリへ展開しシンボリックリンクを作成後Tomcatを起動してみる。
    # cd /usr
    # tar xfvz /tmp/apache-tomcat-5.5.23.tar.gz
    # ln -s apache-tomcat-5.5.23 tomcat
    # tomcat/bin/startup.sh
    ◎Tuigwaaのインストール
    tuigwaa-1.0.4.zipをダウンロードし作業ディレクトリで展開する。
    インストール方法はここに詳しく説明されているので参照のこと、コマンド操作のみを記述する。
    $ unzip tuigwaa-1.0.4.zip
    # cp jaas.conf /usr/tomcat/conf
    # cp tuigwaa.xml /usr/tomcat/conf/Catalina/localhost
    # cp tuigwaa.war /usr/tomcat/webapps

    /usr/tomcat/bin/startup.shを編集しCATALINA_OPTSを追加する
    export CATALINA_OPTS=
    "-Djava.security.auth.login.config=/usr/tomcat/conf/jaas.conf"

    Tomcatを再起動しブラウザでhttp://localhost:8080/tuigwaaにアクセスできればインストール成功。


    ◎既存のtuigwaaサイトを新しいホストに配備する
    • 旧ホストのTuigwaa Managerにアクセスしサイト管理・サイト一覧より再配備するサイトを選び一括ダウンロードする。
    • 新ホストのTuigwaa Managerにアクセスしユーザー管理で旧ホストのサイトで作成していたユーザとロールを登録する。
    • Tuigwaa Managerのサイト管理・サイト一覧ページのサイトのアップロードでダウンロードしたtgwarファイルを指定してアップロードする。
    • アップロードするサイトのファイルサイズが2Mを超えている場合はusr/tomcat/webapps/tuigwaa/WEB-INF/struts-config-tgw-manager.xmlを編集し制限を緩和する。具体的にはstruts-config-tgw-manager.xmlの277行目のmaxFileSize="2M"を適切な値に設定すればよい。