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経由で自動的に設定されるようです、いいですね!