2010年9月12日日曜日

ちょっとは暑さがマシになった夜のJava系小ネタ

Log4j、ログのローテートに失敗。原因はlog()メソッド?

プログラマとして社会に踏み出して5年目となる今年、ようやくLog4jを使用するシステムに巡り会えた(※1)。つっても、我々にはLoggerやAppender設計・製造する権限はなく、元請けが昨年製造・全社標準として採択されたjarを使わされるだけの立場なのだが。

言われた通りに組み込んで使用していると、不具合発生。ログファイルは1日ごとにローテーションする設定なのだが、日付が変わってもローテーションされず。さらに、出力済みのログファイルの中身を確認したところ、ある時刻までのログが全く出力されていない(その時刻以降は問題無く全て出力されているが)。

で、調べてみたら、以下の記事発見。java-jaの方でしょうかね。前述の通り日付ローテーションと言うことで、まさにこのAppender使っていた。原因はこいつか?別のAppenderに変更して試したところ…状況変わらず、暗礁空域へ…いや、待て。よくよく考えたら、標準ログ以外のログも出力する要件があり、いくつかのLoggerを自作していたのだが、自作の方はDailyだろうが何だろうが、ローテートに失敗したことは一度も無かった。ということで、不具合の原因はコンポーネント側にあると考えるのが順当だ。ということで、提供元に調査依頼を出した。

完全に我が社の責任範囲外の事象だが、そのコンポーネントのソースコードがjarと一緒に提供されていたので、ちょっと覗いてみた。…空のcatchブロックだらけじゃねぇか。例外殺しやがって、こりゃ発見遅れるわけだ、ったく…
正常にローテートされている自作Loggerと異なる部分を探してみる。すると、ログ出力するのに使用しているメソッドに違いが見られた。自作の方はinfo()とかdebug()とかログレベルの名称を冠したものを使用しているのだが、提供されたものはlog()メソッドを使用している。この違いが原因なのか?log()メソッドの部分をinfo()とかに替えて試してみたかったが、何かのクラスが足りなくてコンパイルできず、試行は断念…

Tomcat5.5にて、<jsp:useBean>タグでJasperException発生の原因

…Tomcatは5.0だったかもしれん…

過去最悪の仕事環境でのお話。JSP+サーブレットというアーキテクチャのシステム(Struts等のフレームワークは未使用)で、本番環境でのサーブレットコンテナは商用のあまり聞いた事のないやつ。そのサーブレットコンテナは、無償開発版といったものが無いので、皆サーバー環境でデバッグしていたのだが、リンク先記事にある通りコードがグダグダ。ステップ実行とかできないのは厳しすぎるので、ローカルにTomcat環境作ることにした。Javaのバージョンは我が社の案件にしては珍しく5.0だったので、Tomcatは5.5をチョイス。

環境構築して実行してみると…当節見出しの通りの不具合が発生。しかし、全ての<jsp:useBean>の箇所で発生するのではなく、決まったBeanでのみ発生している模様。これらBeanの共通点を探してみると…引数なしコンストラクタが定義されていないことが判明。

次に、JSPから変換されたJavaコードを確認してみた。<jsp:useBean>の箇所は、以下のロジックに変換されていた。
  1. 引数なしコンストラクタでBeanをインスタンス化
  2. setter・getterにて値の遣り取り
つまり、1.で未定義のコンストラクタが使用されて例外が飛んだっぽい。

JavaBeansの必要要件である「publicで引数なしのコンストラクタを実装」を行っていなかったために起こった悲劇であった。
コードレビューってやっぱ必要だよね。

正規表現メモ

範囲指定子の「-」。これ、括弧内([])の先頭か末尾に定義した場合、リテラルとして扱われる…ということを先月知りました。はぁ~…(自分に溜息)


※1
ちなみにJava5.0に巡り会うのには4年かかった。
人月計算とExcelとスーツの世界」はホント石橋を叩きすぎだ(それとも我が社の案件が極端なのか?)。

2010年9月7日火曜日

暴風前夜のeclipse

「.metadata」は定期的にバックアップしとけ

eclipseを長く使っていると、ある日突然、起動できない、ビルドできない等のトラブルが時々発生する。原因の殆どは、ワークスペースフォルダ直下でeclipseを設定情報を管理している「.metadata」の破損。トラブった際は.metadata内のあのファイルをああしろこうしろと言った情報がWebに溢れているが、定期的に丸ごとバックアップしておいてズドンと上書くのが一番手っ取り早いです(当然、バックアップ取得以降の変更内容は失われますが)。

SVN管理化のJavaソースファイル名称変更後に発生した、同期化エラートラブルの記録

一般的なトラブルかどうか分からんが、一応記録しておく。

SVN管理化のJavaクラスの名称を、リファクタリング機能にて変更した。Javaの場合、クラス名=ファイル名という決まりなので、必然的にファイル名も変更することになる。これにより、変更前のJavaファイルは「削除」、変更後は「新規」扱いとなり、それぞれコミットした。すると、それ以後、ファイル名変更をコミットしたメンバー(厳密にはworkspace?)以外の開発環境において、同期化エラーが発生するようになってしまった。

上記のトラブルは度々発生した。何が原因なのか結局わからなかったが、トラブル発生直前の操作内容を見聞すると、以下の共通点が浮かび上がってきた。
  1. クラス名を変更した。
  2. 変更するのにeclipseのリファクタリング機能を用いた。
  3. 新規ファイル(クラス名変更後のJavaファイル)は、「バージョン管理に追加」せずに、いきなりコミットした。
これらを踏まえて、クラス名変更時の手順を以下のようにしたら、トラブルは発生しなくなった。
  1. クラス名を変更する際は、リファクタリング機能は使わない。
    つまり、新名称のJavaファイルは新規作成、旧名称のは普通に削除。
  2. 新名称Javaファイルは、まず「バージョン管理に追加」し、それからコミットする。
上記解決方法は別の人が調べて持ってきてくれたのだが、1・2どちらか片方だけではダメだったのだろうか。まあ「ダメだった」って言ってたからダメなのだろうが…一度自分で試そうとしたが、これ以上トラブル発生して作業が停滞するのもしんどかったので(てかプチ炎上中だったし)、実行に映さず。

ちなみに、そのリポジトリのルートディレクトリに対するアクセス権限が与えられていなかったのだが、関係あるのかな?

別リポジトリ管理化のリソースをコピペしてくる際の注意事項

ユーティリティ群など汎用的な部品は、別プロジェクトで作成したものをコピーしてくるという事はよくやると思うが(※1)、その際は「.svn」はコピーしないこと。どのリポジトリに接続するかという情報はこの中で管理しているので、「.svn」ごとコピーしてしまうと、同期化時に別のリポジトリに対する接続ダイアログが何度も表示されたり、「遮断」的なエラーが発生したりする。

ちなみに、TortoiseSVNのエクスポート機能を利用すれば簡単に削除できる。

※1
てかjar化しろって話か。

2010年9月5日日曜日

昨日よりはマシな夜のOracle

長さ0の文字列('')はNULLとして扱われる

「フィールドの値がスペースのみのデータを抽出」という仕様を実現するのに「TRIM( [フィールド名] ) = ''」と組んだが、期待した結果とならず。TRIM( [フィールド名] )をSELECTして戻り値を見てみると、値がスペースのみの場合は何とNULLが返ってきている。あれっ!?空文字とNULLは別物の筈だが…何とも不可解であるが、ゴーイングマイウェイなOracleならあり得るかと、素直に抽出条件を「TRIM( [フィールド名] ) IS NULL」と修正した。

後で調べてみたら、やはりOracleの独自仕様らしい。DB界の泰斗であらせられるミックさんの記事で知った。 上記記事によると、これに関してはOracleも反省しているのか知らんが、将来修正されるかもしれないとのこと。マジかよ。そうなったら上記みたいなSQLは修正しなきゃいけないじゃないか…

ANSI SQLの外部結合構文(OUTER JOIN)を使用時のバグが盛りだくさん

バージョン9i,10gにて、SQLの結合構文にANSI SQLのOUTER JOINを使用すると、エラーや結果不正が発生することがあるらしい。まあ、結構有名な話ですが。

ちなみに、具体的なバグの発生条件・内容や修正パッチは、サポート契約しないと入手できない(ケッ!)。
ネットに転がってないか散策していたら、以下のページを発見。何かのグループウェアのページのようだ。
上記ページの「Oracle9i,10gにおける不具合事項」の節に
「問題を修正した9.2.0.8,10.1.0.5,10.2.0.2のPSRが提供されています」
とあるが…本家発の情報じゃないので、何とも言えないな…

余程複雑なSQLでなければ、まあ大丈夫だというような意見をどこかで聞いたが…発生条件が不明である以上、あの忌まわしき(+)を使わざるを得ない。はぁ~…

複合主キーにまつわる幻?

ここで今から述べることは、夢幻の可能性大。

Oracleのバージョンは9i、複合主キーを使用したテーブルに、キーの一部がNULLのレコードを登録できてしまった…気がする。
例えば、複合主キーが3項目からなる場合、以下のようなレコードが登録できてしまった…気がする。
INSERT INTO table VALUES ('pk1', 'pk2', NULL, …)

しかも、複合主キーの一部がNULLのレコードは、幾つでも登録できてしまった…気がする。NULLはどの値とも等しくはならない(例え比較対象がNULLであっても)からだろう。

しかし、ネットで調べてみると、「複合主キーの一部にはNULLをセットできる」なんて誰も言ってない。自宅PCのMySqlで試したら、見事にはじかれたし。Oracleで試せって話だが、重たいし汚れるから自宅PCに入れたくない。

うーむ、俺、疲れてたのかな…

2010年9月4日土曜日

[Trac Lightning]秋とは名ばかりの夜の小ネタ集Ⅱ

VistaでTracLightningをサービスとしてインストールするには

TracLightningをサービスとしてインストールするには、スタートメニューの「サービスのインストール」を実行すればよい…のだが、Vistaだとエラーが発生した。


詳しく調べる気にもならんが、原因は十中八九、一般ユーザーには悪名高いUAC(ユーザーアカウント制御)によるものだろう(※1)。

よって、管理者として実行してみる。「サービスのインストール」で実行されるのは「[TracLightningルート]/bin」フォルダ直下の「install-service.bat」なので、これを右クリック→「管理者として実行」(※2)。続いてUACのダイアログが表示されるので迷わず「続行」…結果はうまくいった模様。

サービスのアンインストールも同様で、「uninstall-service.bat」を管理者として実行すればよい。
ちなみに、上記画像のコマンドからお分かりだと思うが、サービスの実体は「httpd.exe」つまりApacheです。

ビルトインアカウント「admin」を削除すると、プロジェクト追加時の手間が増える

…ここでのお話、ちょっと記憶が曖昧&メモ取り忘れのため、間違っているかもしれません…

僕がTracLightningを使い始めるに当たって、以下の記事を参考にさせていただいた。
この記事のユーザー設定の節にて、
「管理者ユーザーを作成したら、admin/leader/guestアカウントは速やかに削除しましょう」
と述べられていたので、この通りに行った。

そしてある日、「create-project.bat」を実行して新規プロジェクトを作成。設定を行うため、作成した管理者ユーザーでログインを試みる。上記記事でも述べられているが「Trac Lightningのユーザーはプロジェクト共有」なので、問題無くログインできる筈…OK、問題無い。しかし、「管理」メニューが表示されない!。

どうも、自分で追加したユーザーの場合、新規プロジェクトではパーミッション設定が初期化されてしまう模様。ビルトインアカウントの場合はそのような事は無く、新規プロジェクトでも「admin」は名に違わず管理者権限を有しているのだが、上記の例では記事に従って削除してしまっていた。

以上より、管理者不在の状態に…嗚呼、設定ができない…
と、GUIどっぷり野郎の嘆きはここまでにして、この時は確かコマンドプロンプトでTRAC_ADMIN権限を付与して解決したような…
trac-admin [プロジェクトルートのパス] permission add [ユーザー名] TRAC_ADMIN

と言うわけで、adminアカウントを削除してしまうとこのような手間が発生してしまいましたと。
もちろん、セキュリティの観点では削除すべきであることは言うまでもありません。

添付ファイル最大サイズの設定

trac.iniで設定可能。確か再起動しなくても適用された。
[attachment]
max_size = 2000000

Wikiのファイル添付時Internal Error

に何度か遭遇したのだが、どうもファイル名(orフルパス?)にスペースや全角文字が混じっていると発生しうる模様。



※1
ちなみに僕はマルウェアビビりなので、セキュリティを強化してくれるUACに対して嫌悪感は無い。

※2
管理者権限で実行する設定は、ファイルのプロパティの「互換性」タブ下部「特権レベル」セクションで設定できるのだが、バッチファイルの場合はグレーアウトしており設定できない。セキュリティ的な問題を考慮したVistaの仕様か?

2010年9月1日水曜日

[Trac Lightning]秋とは名ばかりの夜の小ネタ集Ⅰ

気がつけば夏は過ぎ去り、気がつけばTracLightningは2.5になっていた。
ファイル添付をドラッグ&ドロップで行えるのはすげー便利だ。

複数ワードで検索時、ワードの区切りは半角スペースで

TracLightningの目玉機能の一つである全文検索機能。検索ワードをスペースで区切って複数入力した場合は、一般的なサーチエンジンと同様にAND検索となる…が、検索ワードの区切りのスペースが全角の場合、どうも区切り文字として認識されず、全角スペースという一つの文字として扱われる模様。

以前、ログファイルの出力レベルに関してヘルプを検索しようと「ログ△レベル」で検索した際、結果は以下の通り空振り。
※△=全角スペース

「ログ レベル」と半角スペースで区切って検索すると、以下の通りヒット。

Googleとかと同じ感覚で検索してはいけないようだ。我々日本人にとっては地味に面倒臭いが仕方が無い。
尚、半角スペースを含むワードで検索したい(いわゆるフレーズ検索ね)場合は、一般的なサーチエンジンなどと同じように引用符(「'」「"」)で囲ってやればよろしい。

ログファイルの出力レベルは必ず設定しましょう

プロジェクトの動作ログは「{プロジェクトルート}/log/trac.log」に出力される訳だが、デフォルト設定のままだとデバッグメッセージも出力される。このまま運用すると、ログファイルサイズはすぐにGBの大台に達する。ログファイルのローテーション設定というのは無いようだし、ここは大人しくログレベルを適切に設定するようにしましょう。

設定方法はヘルプ(TracLogging)に書いてある。trac.iniの[logging]セクションでlog_levelオプションを記述。
[logging]
log_level = WARN

そう言えば、ソース弄ってログファイルローテーションを実現するとか言ってる奴がいたな…

Wikiの見出しに記号が含まれる場合、その見出しのURLに記号は含まれない

Wikiの見出しには以下のようにURLが割り当てられる。あるWikiページにて、別のWikiページの特定見出しへのリンクの記法は
[wiki:Wiki名#見出し リンクテキスト]
という具合。

ところで、見出しに記号が含まれる場合は、URLは以下のように記号を除いたものとなる。記号は半角だろうが全角だろうが除去される。リンク貼る際は要注意。