struts-config.xml で定義した内容を動的に変更したくなって、ActionConfig を改造する方法を考えていたんだけど、大元の ModuleConfigFactory を切り替えて、独自の ModuleConfig を生成する Factory クラスを用意すれば良いことが分かった。なるほどー、よくできてるなー。
web.xml で configFactory パラメータに、独自の ModuleConfigFactory のクラスを指定してあげればOK。
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<init-param>
<param-name>configFactory</param-name>
<param-value>com.deftrash.OriginalModuleConfigFactory</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>2</param-value>
</init-param>
<init-param>
<param-name>detail</param-name>
<param-value>2</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
いろいろ調べてようやく分かったんだけど、よくよく考えてみると SAStruts の仕組みを見れば一発で分かったんだよなあ。ううう。
そして、もともとはフォワード先のパスを変えたいだけだったので、それなら Filter で ActionConfig を見てごにょごにょやった方がシンプルだったかも。この方法は、少し大げさな感じもする。こういう手段があるのが分かっただけで、前進ですが。
ActionServlet クラスのソースを見ると、他にも細かな制御ができるようになっているのが分かる。このあたりを押さえておくと、プロジェクトに応じて Struts をより柔軟にコントロールできる。知らないって、スゴイ損ですねえ。ふぅ。
Posted by dT by 23:35 | Comments (0) | TrackBacks (0)
半角カナでの登録を拒否するために、自動で全角カナに変換したいときってあるじゃないですか。アプリケーション側で、AOPやFilterといった仕組みで変換してあげる方がスマートだと思ってるんだけど、DB側でやらないといけないケースもあるでしょう。
ということで、こんな関数を用意してみました。
CREATE OR REPLACE FUNCTION h2z_kana(text)
RETURNS text AS
$BODY$
DECLARE
zenkaku alias FOR $1;
result text;
i int;
zt varchar[] = ARRAY['ガ', 'ギ', 'グ', 'ゲ', 'ゴ', 'ザ', 'ジ', 'ズ', 'ゼ', 'ゾ', 'ダ', 'ヂ', 'ヅ', 'デ', 'ド', 'バ', 'ビ', 'ブ', 'ベ', 'ボ', 'パ', 'ピ', 'プ', 'ペ', 'ポ', 'ヴ'];
ht varchar[] = ARRAY['ガ', 'ギ', 'グ', 'ゲ', 'ゴ', 'ザ', 'ジ', 'ズ', 'ゼ', 'ゾ', 'ダ', 'ヂ', 'ヅ', 'デ', 'ド', 'バ', 'ビ', 'ブ', 'ベ', 'ボ', 'パ', 'ピ', 'プ', 'ペ', 'ポ', 'ヴ'];
BEGIN
result = zenkaku;
-- 2バイトで変換
FOR i IN 1..26 LOOP
result = replace(result, ht[i], zt[i]);
END LOOP;
-- 1バイトで変換
result = translate(result,
' アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲンァィゥェォッャュョワイエカケー、。・」「゙,<.>/?_}]*:+;{[~@|\\`^=-)(&%$#"!',
' アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲンァィゥェォッャュョヮヰヱヵヶー、。・」「゛,<.>/?_}]*:+;{[ ̄@|¥`^=-)(&%$#”!'
);
RETURN result;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
ガやザのような濁音のものは、半角カナになるとカと濁点の合計2バイトになる。まずはじめに変換テーブルを用いてそれらを置換してから、残る半角カナを一括して置換してます。記号の置換処理のところは、不要なら除けばOK。でも、大体のケースであっても困らないと思いますけど。
あとは、この関数を使って UPDATE するトリガーを、INSERT と UPDATE 時に発動するように定義してあげれば、冒頭の件は対応できると思います。
DBから値を引っ張ってきて、そのままメール送信するようなケースで、半角カナが含まれてたらイヤンなときにも活用できるかな。そのケースでは、機種依存文字全般の対応もあるので、送信プログラム側でもろもろを処理した方が、スッキリするかしら?
ま、ひとつの参考までに。
Posted by dT by 22:49 | Comments (0) | TrackBacks (0)
csvデータをpostgresqlにインポートしようとしたら、エラーが。
ERROR: invalid byte sequence for encoding "SJIS": 0x00
NULL文字が含まれているのが、納得いかないようす。NULL文字は目で見えない制御文字なので、どうやって削除したもんかなーと思ったら、trコマンドで簡単に除去できました。
$ cat src.csv | tr -d "\000" > dest.csv
これでインポートはバッチリでした。
Posted by dT by 12:56 | Comments (0) | TrackBacks (0)
1対N(OneToMany)の関係にある2つのエンティティについて、N個の文字列を集約する必要があって、方法を考えてみた。
次のような部署マスタと社員マスタを例にとって、説明します。

これに対して、次のような表を出すという要件。
| 部署 | 所属社員 |
|---|---|
| 営業1課 | 佐藤 山下 高山 |
| 営業2課 | 大野 池本 野崎 |
「2つのエンティティを JOIN すれば良いじゃん」という声もあるけど、単純に結合しちゃうと、結果セットから取り出すとき、もしくは表示時点でプログラムでごにょごにょやらないと、うまくいかない。所属社員の一覧を、改行区切りの文字列として、ひとつの変数に格納できれば、らくちん。要するに、DBから値を取得する時点で、表示するときの形まで持っていきたいという話。
ここの方法については賛否両論あるかもしれないけど、SQLはプログラムが最もシンプルで済むような結果が得られるように書くべきだと思ってます。
話が逸れたけど、じゃあ、それをどうやってやるか、という話ですよ。
Posted by dT by 23:30 | Comments (0) | TrackBacks (0)
FreeBSD のサーバに、Java5 と Tomcat5.5 を乗っけて起動したら、OOME で落ちてしまった。ログを見ると、かつて見たことのない内容が。
Exception in thread "CompilerThread0" java.lang.OutOfMemoryError: requested 1168080 bytes for Chunk::new. Out of swap space?
スワップ領域って何のことだろうか。JVMのなかの話だと思うのだけど。
メモリ関連ということで、-Xmx や -Xss などのパラメータをいじるものの状況は改善せず。んで、ひとつひとつ除いていったら分かりました。
CATALINA_OPTS="-server"
というように、サーバクラスを指定していたのだけど、これが原因だった。FreeBSD全部がそうなのか分からないけど、今回のケースではクライアントVMでしか起動できないという罠。うー、しびれるなあ。
サーバクラスマシンの検出にあるとおり、Java5からはサーバ環境に応じて自動でVMを切り替えてくれるということで、下手に指定なんてしなくても良かったんですね。(まあ、FreeBSDのJVMでも互換性があるのかは分かりませんが…)
Linux の方が上だとか言うつもりは毛頭ないけど、個人的には FreeBSD より Linux の方が良いなあ。習慣もあるんだろうけども、エンタープライズ用途だと何かと情報が得やすい Linux や Solaris でないと、ちょっとひるんでしまいますねえ。
Posted by dT by 14:05 | Comments (0) | TrackBacks (1)