Apache2.2とTomcatを連携させるmod_proxy_ajp

Apache2.2系では、Tomcatと連携するのに、mod_jk を入れずとも mod_proxy_ajp モジュールを使って対応できるようなので、試してみた。

mod_proxy.so と mod_proxy_ajp.so が必要になるので、次のようにコンパイルする。とりあえず、他にも色々と必要だったりしたので、次のようにした。

# tar xvfz httpd-2.2.8.tar.gz
# cd httpd-2.2.8/
# ./configure --prefix=/usr/local/apache \
	--enable-so \
	--enable-shared \
	--enable-rewrite \
	--enable-ssl=shared \
	--with-mpm=worker \
	--enable-deflate \
	--enable-headers \
	--enable-dav=no \
	--enable-proxy-ajp \
	--enable-proxy \
	--enable-mods-shared=all
# make
# make install

Tomcat 側のデフォルトのAJPポートは 8009 なので、変更なければ、httpd.conf に次のように書けば終わり。

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so

<Location /manager/> ProxyPass ajp://xxx.xxx.xxx.xxx:8009/manager/ </Location>

これで、それまで http://xxx.xxx.xxx.xxx:8080/manager とアクセスしていたところ、http://xxx.xxx.xxx.xxx/manager とアクセスできるようになる、と。mod_jk に比べてすんごくラクチン。これは良いかも。

ジェネリクスのインスタンスを生成する方法

java でジェネリクス(総称型)のインスタンスを生成するには、どうするのか悩んでいる土曜日の昼下がり。

例えば、次のようにメソッドの総称型を定義してみる。

public  T add(T date) {
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    calendar.add(Calendar.DATE, 1);
    return (T) calendar.getTime();
}

これだと、引数に java.util.Date を渡した場合は問題ないが、そのサブクラスである java.sql.Date なんかを渡すと、最後の総称型へのキャストで、ClassCastException でコケてしまう。そりゃそうだ。

同じ型のインスタンスを生成できれば、そこに値を詰めて返せるんだけど、総称型はその名のとおりクラス名を特定できないから、さて困った。

T result = new T();

みたいなことができれば良いんだけど、当然できるわけもなく。それじゃあ、と思って次に試したのがコレ。

public  T add(T date) {
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    calendar.add(Calendar.DATE, 1);

T result = date.clone(); result.setTime(calendar.getTimeInMillis());
return result; }

型が分からないなら、もうクローンしちゃえば良いんじゃね、と。これは確かに動くのだけど、いやいやインスタンスを生成するのと、クローンするのでは意味が違う。

public  T add(T date) throws Exception {
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    calendar.add(Calendar.DATE, 1);

T result = date.getClass().newInstance(); result.setTime(calendar.getTimeInMillis());
return result; }

ということで、今のところ、これが一番しっくり来てる。

このケースだと java.util.Date のサブクラス限定だから、このくらいで良いけど、もっと汎用化するなら、newInstance() じゃなくて Constructor とか使って生成していかないといけないんだろうなあ。でも、引数はどこから持ってくるんだ? なんてことを考えると、「やっぱクローンでも良いんじゃね?」とか思える。

どっかに良いお作法が転がってないかなあ…。

plpgsql で SELECT 結果を変数に入れるには

/ db

plpgsql で SELECT 文を発行して、その結果を変数に代入したいときは、SELECT INTO 構文を使用する。

CREATRE OR REPLACE FUNCTION test() RETURNS int AS
'
DECLARE
    ct int;
BEGIN
    SELECT INTO ct count(*) FROM table;
    return ct;
END
'
language 'plpgsql';

このように書くと、count(*) の値が、宣言済み変数 ct に代入できる。

複数の結果をそれぞれ変数に代入したいときは、

DECLARE
    one int;
    two int;
BEGIN
    SELECT INTO one,two count(one),count(two) FROM table;
    RETURN one * two;
END

といった感じで並べればOK。

まあ、取り扱うカラム数が多い場合には、不向き。そういう場合は、RECORD で受け取ったりすると良いのかな。

PostgreSQL で plpgsql がないときは

/ db

さーて、もりもり CREATE FUNCTION でもするかと思ったら、こんなエラー。

ERROR:  language "plpgsql" does not exist

PostgreSQL を標準インストールすると、plpgsql は入らないんだろうか。plpgsql を後から追加するときは、コマンドラインから次のようにするらしい。

$ /usr/local/pgsql-8.3.0/bin/createlang -d database_name plpgsql

これで無事に CREATE FUNCTION できました。わーい。忘れそうなので、メモ。

引数final

Java の言語仕様で、メソッドの引数にも final 修飾子を与えることができる。

public void execute(final List list) {
    //
}

これ、今までずーっと意味を勘違いしてました。「引数 object への変更は認めない」ではなくて、「引数 list への代入は認めない」という意味のようだ。なので、次のリストのようなことになる。

public void execute(final Object object) {
    list.add("aaa"); // これはOK
    list = new ArrayList(); // これはコンパイルエラー
}

つまり、引数 final は、その引数インスタンスそのものに対する意味であって、内部データを保護する意味はないのね。完全に期待していたのと違った意味付けになっていて、ホントに狼狽した。せっかくの修飾子なんだけど、ここに final を付けることの方が、余計に意味が分かりにくくなっている気がする。

ただ、唯一意味があるのは、メソッド内部で匿名クラスを使用するような場合。

public void add(Button button, final Label label) {
    button.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
            label.setText("hoge");
        }
    });
}

このようなケースでは、引数 Label に final 修飾子が付いていないと、逆にコンパイルエラーになってしまう。(メソッド内部で final 宣言した変数に入れ替えても動くので、引数 final が必須ではないけれども)

自分が言語仕様をちゃんと把握してなくてダメだって話なんだけど、またいつか別のプロジェクトではまりそうな気がするので、コーディング規約として禁止したいなあ。アノテーションもそうだけど、余計な意味付けがなされていると、深読みしちゃいますよネ。ね?


最新エントリー
Apache2.2とTomcatを連携させるmod_proxy_ajp
ジェネリクスのインスタンスを生成する方法
plpgsql で SELECT 結果を変数に入れるには
PostgreSQL で plpgsql がないときは
引数final
あわせて読みたいブログパーツ