hnakamur’s blog

ものすごい勢いで忘れる私のために未整理でもいいからとりあえずメモ

2011-06-28

SAStrutsでCSVダウンロードのサンプル

hnakamur/sastruts-csvdownload-ex1 at master - GitHub

クエリ結果の件数が多いときに備えて、結果をリストに持つのではなくorg.seasar.extension.jdbc.Select#iterateで1件ずつコールバックして出力するようにしています。

SAStrutsでJSONをレスポンスに書き出すサンプル

SAStrutsでJSONをレスポンスに書き出すサンプルを作ってみました。JSONIC - simple json encoder/decoder for javaを利用しています。

アクションからの呼び出し例
    @Execute(validator = false)
    public String hello() {
        Map<String, Object> json = new HashMap<String, Object>();
        json.put("author", "Goldratt & Fox");
        json.put("title", "The Race");
        JSONResponseUtil.writeJSON(json);
        return null;
    }


ユーティリティの実装
package net.naruh.sastruts.util;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;

import javax.servlet.http.HttpServletResponse;

import net.arnx.jsonic.JSON;

import org.seasar.framework.exception.IORuntimeException;
import org.seasar.struts.util.RequestUtil;
import org.seasar.struts.util.ResponseUtil;

/**
 * JSONをレスポンスに書き出すためのユーティリティクラスです。
 * @author hnakamur
 */
public final class JSONResponseUtil {
    /** JSONのエンコーディング */
    public static final String JSON_ENCODING = "UTF-8";

    /** JSONのコンテントタイプ */
    public static final String JSON_CONTENT_TYPE = "application/json";

    /**
     * JSONをレスポンスに書き出します。
     * @param source 書き出すオブジェクト
     * @param prettyPrint 出力を整形するか
     */
    public static void writeJSON(Object source) {
        writeJSON(source, false, JSON_CONTENT_TYPE, null);
    }

    /**
     * JSONをレスポンスに書き出します。
     * @param source 書き出すオブジェクト
     * @param prettyPrint 出力を整形するか
     */
    public static void writeJSON(Object source, boolean prettyPrint) {
        writeJSON(source, prettyPrint, JSON_CONTENT_TYPE, null);
    }

    /**
     * JSONをレスポンスに書き出します。
     * @param source 書き出すオブジェクト
     * @param prettyPrint 出力を整形するか
     * @param contentType コンテントタイプ
     */
    public static void writeJSON(Object source, boolean prettyPrint, String contentType) {
        writeJSON(source, prettyPrint, contentType, null);
    }

    /**
     * JSONをレスポンスに書き出します。
     * @param source
     *            書き出すオブジェクト
     * @param prettyPrint
     *            出力を整形するか
     * @param contentType
     *            コンテントタイプ。 デフォルトはapplication/context。
     * @param encoding
     *            エンコーディング。 指定しなかった場合は、リクエストのcharsetEncodingが設定される。
     *            リクエストのcharsetEncodingも指定がない場合は、UTF-8。
     */
    public static void writeJSON(Object source, boolean prettyPrint, String contentType, String encoding) {
        if (contentType == null) {
            contentType = JSON_CONTENT_TYPE;
        }
        if (encoding == null) {
            encoding = RequestUtil.getRequest().getCharacterEncoding();
            if (encoding == null) {
                encoding = JSON_ENCODING;
            }
        }
        HttpServletResponse response = ResponseUtil.getResponse();
        response.setContentType(contentType + "; charset=" + encoding);
        try {
            Writer out = new OutputStreamWriter(response
                    .getOutputStream(), encoding);
            try {
                JSON.encode(source, out, prettyPrint);
            } finally {
                out.close();
            }
        } catch (IOException e) {
            throw new IORuntimeException(e);
        }
    }
}

2011-06-25

Eclipse IndigoでjarのUTF-8のソースコード文字化け対策パッチ適用

Eclipse Indigoをプロジェクトで参照しているjarのソースファイルがUTF-8だと、プロジェクトのエンコーディング設定(ResourceのText file encoding)がUTF-8になっていても文字化けしてしまいます。Heliosでは大丈夫でした。

ググってみると先人が対応してくれてました。感謝しつつ適用。
Release Details: WTP 3.3.0(Indigo)用 Feature Patch (Feature Patch) - Tools for PDT (PHP Development Tools) - SourceForge.JP

eclipseのエディタでの空白とタブの表示設定

[Windows]/[Preferences]メニュー
左のツリー[General]/[Editors]/[Text Editors]
右の[Show whitespace characters]のチェックをオン
[whitespace characters]のリンクをクリック
SpacesはTrailingのみチェック、Tabはすべてチェック
これでインデントにタブが入っていたり、行末に余分な空白が入っていたら気付きます。

と、この設定にしていたらJavaのエディタで行選択してTABキーを押してインデントしたときに
空白ではなくTABでインデントすることに気付きました。
[General]/[Editors]/[Text Editors]の[Insert spaces for tabs]はチェックをオンにしていますがそうなります。
Javaのフォーマッタの設定を変えることで解決しました。

[Java]/[Code Style]/[Formatter]で[Edit]ボタンを押して[Indentation]タブの[Tab policy]を[Spaces only]にして[Profile name]に何か名前を付けて[OK]を押します。

jsonic 1.2.5をMavenローカルレポジトリにインストール

1.2.0ならseasarのMaven2.0レポジトリにありますが、
http://maven.seasar.org/maven2/net/arnx/jsonic/jsonic/1.2.0/
1.2.5はないのでローカルにインストール。

mvn install:install-file ^
-Dfile=jsonic-1.2.5.jar ^
-Dsources=jsonic-1.2.5-sources.jar ^
-DgroupId=net.arnx.jsonic ^
-DartifactId=jsonic ^
-Dversion=1.2.5 ^
-Dpackaging=jar ^
-Dclassifier=sources ^
-DgeneratePom=true ^
-DcreateChecksum=true
(^はバッチファイルで継続行にするための記号です)

参考:http://maven.apache.org/plugins/maven-install-plugin/usage.html

2011-06-19

Windows 7でgdippを試す

gdipp - Customizable Windows text renderers - Google Project Hosting
窓の杜 - 【REVIEW】インストールするだけであらゆるソフトのテキストを美しく滑らかに描画「gdipp」

eclipseでVLゴシックフォントを使うようにしたら日本語がガタガタだったのでgdippを試してみました。安定版のgdipp_x64_0.7.6.msiをダウロードしてインストールするだけ。起動済みのアプリケーションは一度終了して上げなおします。
美しい表示になり大満足です。

eclipseでVLゴシックフォントを使う

スペースでインデントしていると等幅フォントのほうがみやすい、大文字のアイIと小文字のエルlや大文字のオーOと数字のゼロ0の見た目がはっきり違うほうがうれしいということで、VLゴシックフォントを使うことにしました。

eclipseの設定は以下のとおりです。
[Windows]/[Preferences]メニュー
→左のツリーで[General]/[Appearance]/[Colors and Fonts]
→右のツリーで[Basic]/[Text Font]を選んで[Edit...]ボタン
→フォントを選択して[OK]ボタン

Windows 7でフォント追加・削除

ググってみたところいくつか方法はあるようですが、使いやすそうなのをメモ。

Windows 7でフォント追加
エクスプローラでフォントファイルを選んでポップアップメニューの[インストール]。
ポップアップメニューに[プレビュー]もあり、これがデフォルトメニューなのでダブルクリックでプレビューして[インストール]ボタンでもよいです。

Windows 7でフォント削除
コントロールパネルの[デスクトップのカスタマイズ]→[フォントのプレビュー、削除、表示または非表示]で対象のフォントを選び、ツールバーまたはポップアップメニューの[削除]ボタン。

native2ascii不要のプロパティエディタ

ホームページ:プロパティエディタ
eclipse更新サイト:http://propedit.sourceforge.jp/eclipse/updates/

Sysdeo TomcatプラグインよりWTPのほうがよいです

hnakamur’s blog: m2eclipseとTomcatプラグインの連携設定ではSysdeo Tomcatプラグインを使った方法を書きましたが、WTP (Web Toolkit Platform)のほうが簡単ということがわかりました。

eclipseのJavaEE版ならWTPが含まれています。

使い方
あらかじめTomcatをインストールしておきます。

Tomcatサーバの登録
Eclipseの[Servers]ビューで右クリックしてポップアップメニューを開き[New]/[Server]メニューを選ぶ。
ツリーでTomcatのバージョンを選んでTomcatのインストールディレクトリを選択(ここの手順はうろ覚え)

ウェブアプリの登録
Eclipseの[Servers]ビューのサーバーの行を右クリックしてポップアップメニューを開き[Add and Remove...]メニューを選ぶ。
ウェブアプリのプロジェクトを選んで追加する。

あとはstartで起動すればよいだけです。試してみた感じではTomcatのインストールディレクトリ内の設定ファイルが書き換えられたりはしないようです。

追記
WTPだからというのは無関係でSAStrutsのDoltengで作成したプロジェクトではsrc/main/webapp/WEB-INF/のlib/にライブラリが置いてあり、classes/以下にコンパイルしたクラスを置くように設定されているというのが本質でした。

試しにpom.xmlの依存関係を変更してmvn war:inplaceを実行すればsrc/main/webapp/WEB-INF/lib/以下が更新されました。なので、これも含めてSubversionなどソース管理システムに登録してしまうのが簡単そうです。

Windows 7でスタートアップやSendToフォルダをエクスプローラで開く

Windows 7でスタートアップやSendToフォルダをエクスプローラで開くには以下の手順が使えます。
スタートアップ:Windows+Rを押して「shell:startup」と入力。
SendTo:Windows+Rを押して「shell:sendto」と入力。

2011-06-11

Spring 3のHello WorldアプリにMyBatisを組み込み

組み込んだ結果はこちら。hnakamur/spring3-example1 at fa38bdcaeb7502d4f105746cc1d0bc6875a7d021 - GitHub

参考:This blog is all about me doing nothing serious :): Using MyBatis 3 with Spring 3 Using Mapper XML Files

上記のサイトではorg.mybatis.spring.SqlSessionTemplateのコンストラクタが引数なしでセッターでインジェクションしていますが、Spring - mybatis - An introduction to MyBatis integration with Spring - SQL Mapping Framework for Java - Google Project Hostingのバージョン1.0.1ではコンストラクタに引数が必要になっていたので変更してあります。

GitHubのソースに含まれない設定内容は以下の通りです。ここではDBはPostgreSQLを使用しています。

$TOMCAT_HOME/conf/server.xmlの<GlobalNamingResources>に以下のようにデータソース定義を追加します。
<Resource name="jdbc/postgresql" auth="Container"
              type="javax.sql.DataSource"
              driverClassName="org.postgresql.Driver"
              url="jdbc:postgresql://127.0.0.1:5432/springdb1"
              username="spring"
              password="spring"
              maxActive="20" maxIdle="10" maxWait="-1" />

$TOMCAT_HOME/lib/にPostgreSQLのJDBCドライバを入れます。ダウンロードはこちら。PostgreSQL JDBC Driver

[Window]/[Preferences]→[Tomcat]→[コンテキスト宣言モード]を「コンテキスト・ファイル」にしていると、コンテキストファイルに<ResourceLink>タグの記述が必要です。プロジェクトのプロパティの[Tomcat]の[その他の情報]に以下の内容を設定しておきます。
<ResourceLink name="jdbc/postgresql" global="jdbc/postgresql" type="javax.sql.DataSource"/>
なお、この設定は上記のGitHubのソースの.tomcatpluginに含まれています。

あと、SpringやMyBatisの設定をsrc/main/webapp/WEB-INF以下に置かず、src/main/resources以下においてclasspath:~やclasspath*:~で参照する方法もあるらしい。Problems with classpath between Eclipse, Tomcat and JUnit in Spring 3 app - Stack Overflowとか。ただ、classpath内に置く利点が私にはまだ不明なので、とりあえずWEB-INF以下に置く方式のままにしておきます。レファレンスではそうなっていますし。
13. Object Relational Mapping (ORM) Data Access
3. The IoC container
17. Integrating with other web frameworks

Spring application context loading tricks « Gridshoreによるとclasspath*:とワイルドカードではまることもあるらしいので注意。

Windows 7でPostgreSQL 9.0.xのpsqlの文字化けはcygwinで対処

Windows 7でPostgreSQL 9.0.xのpsqlの文字化けはcygwinのbashを使うことで対処します。さらに、メッセージの文字化け防止のために、接続後以下のコマンドを実行します。
\encoding sjis
現在の設定は引数なしで\encodingを実行します。
\encoding

参考:Windowsでpsqlに接続した場合|きよのブログ

cmd.exeだとコードページが932(SJIS)のままだと、psqlのパスワードプロンプトやテーブル一覧表示コマンド\dtの結果が文字化けします。
一方、以下のコマンドでコードページを65001(UTF-8)にしてpsqlを起動すると
chcp 65001
psqlのパスワードプロンプトやテーブル一覧表示コマンド\dtの結果は文字化けしなくなるのですが、SQL実行時に表示されるメッセージ(例:「psql:create_tables.sql:5: NOTICE: CREATE TABLE / PRIMARY KEYはテーブル"admin"に暗黙的なインデックス"adminpk"を作成します」)が文字化けします。フォントをデフォルトの[ラスター フォント]ではなく[Consolas]や[Lucida Console]にしてみましたが英語部分は化けなくなりましたが日本語部分が表示されません。

というわけで冒頭に書いた方法がよさそうです。

m2eclipseとTomcatプラグインの連携設定

2011-06-19追記:その後hnakamur’s blog: Sysdeo TomcatプラグインよりWTPのほうがよいですということがわかりました。


プロジェクトのプロパティの[Tomcat]→[全般]タブ→[Webアプリケーション・ルートとするサブディレクトリー]をどう設定するかについてのメモです。

Super Agile StrutsとかMaven2 + Eclipse + Tomcatプラグイン の組み合わせ - Enjoy*Studyではsrc/main/webappにしています。ですが、Maven2でリソースファイルのプロパティ置換をしていたりすると困る気がします。

そこでmavenをフルビルドすることで作成されるwar生成用の一時フォルダを設定するようにしてみました。具体的には以下のようにします。
  • プロジェクトのプロパティの[Builders]では[Maven Project Builder]の行が存在しチェックがついた状態にしておく(m2eclipseでプロジェクトを作ればそうなっています)。
  • プロジェクトのプロパティの[Maven]/[Lifecycle Mapping]→[Goals to invoke after project clean]を「clean package」にする。
  • プロジェクトのプロパティの[Tomcat]→[全般]タブ→[Webアプリケーション・ルートとするサブディレクトリー]は「target/<warファイルのベース名>」とする。warファイルのベース名は、pom.xmlでbuildタグのfinalNameタグを指定する場合はその値になり、finalNameを指定しない場合は${artifactId}-${version}になります。

この設定により、[Project]/[clean]メニューを実行すると「mvn clean package」が実行されて、targetフォルダ以下が作り直されます。ただ、エクスプローラでtargetフォルダを開いていたりするとcleanでフォルダが消せずうまくいかないので注意。

開いていなくてもTomcatプラグインでTomcatを起動中の場合もうまくいかないときもあるようです。Consoleにエラーは出ないのですが、targetフォルダ内のwarファイル生成用フォルダの中身が不足しているときがありました。

Tomcatを停止してから[Project]/[clean]を実行するほうが無難です。つまりホットデプロイはあきらめるということですが、不安定になるよりはいいと割り切ることにします。

Struts2.2とSpring3.0のHelloWorldアプリを作ってみた

Struts2.2とSpring3.0のHelloWorldアプリを作ってみた。

hnakamur/struts2-example1 at 6153ab91682aaab9e9b30870cd562db36b8267fe - GitHub

hnakamur/spring3-example1 at 7bb45dbf8e4eeea0873d1187c626544d9994c9ec - GitHub

java ee - compare spring mvc 3 and struts 2 - Stack Overflow
java - Struts or Spring MVC or Struts & Spring? - Stack Overflow
を見ると、Spring バージョン2.5で導入されたアノテーションベースのSpring MVCがいいらしい。

@Transactionalアノテーションを使う関係でSpringはどのみち使うし、Struts2は使わずにSpring MVCを使うことにします。依存関係は少ないほうがいいですしね。

2011-06-04

Domaのチュートリアルをやってみた

Doma - チュートリアルをやってみたときのメモです。
Doma - ダウンロードからdoma-tutorial-1.14.0をダウンロードして試しました。

m2eclipseインストール済みのeclipseで「Existing Maven Projects」でpom.xmlをインポートしてプロジェクトを作ると
を使ってpom.xmlをeclipseにインポートするとsrc/main/javaがソースディレクトリに登録されない状態になっていました。

Doma - アプリケーションのビルド方法を見ると、javacのバグ回避のためmaven-compiler-pluginでexcludesでソースを除外し、別途maven-antrun-pluginでコンパイルしているそうで、これが原因のようです。

ぐぐってみるとMaven annotation processing with maven-compiler-plugin - Stack Overflowというページを見つけました。maven-compiler-pluginのバージョン2.3.2とbuild-helper-maven-pluginの組み合わせを使えば別途maven-antrun-pluginでコンパイルせずともいけるようです。試してみるとうまくいきました。

この方法だとpom.xmlをインポートしたときにsrc/main/javaもソースパスに含まれます。

この点は解決したのですが、インポート後に以下のようなプロジェクト情報の修正が必要です。
  1. 一度ビルドしてtarget/apt_generatedディレクトリを作る。
  2. ソースパスにtarget/apt_generatedを追加。
  3. ソースパスのsrc/main/resourcesとsrc/test/resroucesのExcludedが*.*になっているのでExcludedの行で[Remove]を押して*.*を(None)に変更。
なお、[Builders]で[Maven Project Builder]がチェックされていればそちらでaptも実行されるので、[Java Compiler]/[Annotation Processing]や[Java Compiler]/[Annotation Processing]/[Factory Path]の設定は不要です。

pom.xmlのdiffをつけておきます。

diff -ruN doma-tutorial-1.14.0.orig/pom.xml doma-tutorial-1.14.0/pom.xml
--- doma-tutorial-1.14.0.orig/pom.xml 2011-03-30 20:25:22.000000000 +0900
+++ doma-tutorial-1.14.0/pom.xml 2011-06-04 09:30:09.865440100 +0900
@@ -108,14 +108,31 @@
     </plugin>
     <plugin>
      <artifactId>maven-compiler-plugin</artifactId>
+     <version>2.3.2</version>
      <configuration>
       <source>1.6</source>
       <target>1.6</target>
       <encoding>UTF-8</encoding>
-      <excludes>
-       <exclude>**/*</exclude>
-      </excludes>
-     </configuration>
+      <generatedSourcesDirectory>${project.build.directory}/apt_generated</generatedSourcesDirectory>
+      </configuration>
+    </plugin>
+    <plugin>
+     <groupId>org.codehaus.mojo</groupId>
+     <artifactId>build-helper-maven-plugin</artifactId>
+     <version>1.5</version>
+     <executions>
+      <execution>
+       <phase>generate-sources</phase>
+       <goals>
+        <goal>add-source</goal>
+       </goals>
+       <configuration>
+        <sources>
+         <source>${project.build.directory}/apt_generated</source>
+        </sources>
+       </configuration>
+      </execution>
+     </executions>
     </plugin>
    </plugins>
   </pluginManagement>
@@ -134,6 +151,7 @@
    </plugin>
    <plugin>
     <artifactId>maven-resources-plugin</artifactId>
+    <version>2.5</version>
     <configuration>
      <encoding>UTF-8</encoding>
     </configuration>
@@ -156,29 +174,6 @@
     </executions>
    </plugin>
    <plugin>
-    <artifactId>maven-antrun-plugin</artifactId>
-    <executions>
-     <execution>
-      <id>ant-compile</id>
-      <phase>compile</phase>
-      <configuration>
-       <tasks>
-        <property name="apt_generated" value="target/apt_generated"/>
-        <delete dir="${apt_generated}" failonerror="false"/>
-        <mkdir dir="${apt_generated}"/>
-        <javac fork="yes" compiler="javac1.6" debug="on" encoding="UTF-8"
-         classpathref="maven.compile.classpath" srcdir="src/main/java" destdir="target/classes">
-         <compilerarg line="-s ${apt_generated}" />
-        </javac>
-       </tasks>
-      </configuration>
-      <goals>
-       <goal>run</goal>
-      </goals>
-     </execution>
-    </executions>
-   </plugin>
-   <plugin>
     <groupId>com.google.code.maven-license-plugin</groupId>
     <artifactId>maven-license-plugin</artifactId>
     <version>1.4.0</version>
@@ -220,7 +215,7 @@
   <dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
-   <version>1.2.126</version>
+   <version>1.3.154</version>
    <scope>test</scope>
   </dependency>
  </dependencies>

pom.xmlのインポート時にsrc/main/resourcesとsrc/test/resourcesのExcludedが*.*になってしまう問題については、
[#MNGECLIPSE-864] resources folder are added with "Excluded: **" and this make my tests to fail. - Sonatype JIRAeclipse - m2eclipse resource filtering - Stack Overflowというページを見つけましたが、解決方法は見つけられませんでした。
[Maven]/[Update Project Configuration]を実行するたびに上記の手順を行う必要があります。

h2はh2-2011-05-27.zipで試したところ1.2.126ではJDBCドライバのバージョンが古いと言われたので1.3.154に変えてあります。

それとDoma - クイックスタートに書かれているcreate table文とinsert文は記述が古いらしくdoma-tutorial-1.14.0のソースとはあっていませんでした。動くようにしたものを以下につけます。insert文の値は適当です。
create sequence employee_seq start with 100 increment by 1;
create table employee (
  id integer not null primary key,
  name varchar(255) not null,
  age integer not null,
  salary integer,
  job_type varchar(20),
  hiredate timestamp, 
  department_id integer, 
  version integer not null, 
  insertTimestamp timestamp, 
  updateTimestamp timestamp
);
create table department (
  id integer not null primary key,
  name varchar(255) not null,
  version integer not null
);

insert into department values (1, 'Sales', 1);
insert into department values (2, 'Business', 1);

insert into employee values (nextval('employee_seq'), 'SMITH', 45, 800, 'PRESIDENT', '1980-12-17', 1, 1, current_timestamp, current_timestamp);
insert into employee values (nextval('employee_seq'), 'ALLEN', 43, 700, 'MANAGER', '1981-02-20', 1, 1, current_timestamp, current_timestamp);
insert into employee values (nextval('employee_seq'), 'WARD', 40, 600, 'CLERK', '1981-02-22', 2, 1, current_timestamp, current_timestamp);

ブログ アーカイブ