DATE : 2007/06/14 (Thu)
理不尽な不具合が発生した場合は、一度、コンパイル済み JSP ファイルを消してみるのもいいかもしれません。
稼動しているウェブアプリケーションのバージョンを上げようと、サーバを止めて新しいバージョンのファイル類を配備したところ、トップページで特定のクラスが見つからないという例外が発生してしまいました。
このクラスは、ある JSR 仕様を実装したライブラリに含まれていたもので、新バージョンでは別のベンダーが実装したものに置き換えていました。これだけであれば、あからさまに理不尽なのでコンパイル済み JSP ファイルを消去していたのですが、不具合の原因を究明するのを難しくしていた要因がもう一つありました。旧バージョンで使用していたライブラリに依存するライブラリを新バージョンでも使用していたのです。元々、旧バージョンで使用していたのは、JSR 仕様を実装したライブラリとそれを拡張するためのライブラリとして組でよく紹介されるライブラリでした。ところが、JSR 仕様を実装した方の品質があまり良くないので、それだけ別ベンダーのものに取り替えたのです。
ともに JSR 仕様を実装したライブラリなので、両者のインタフェースは同じです。そのため、開発機上では普通に動作していました。ところが、公開用サーバに移動したところでエラーが発生したので戸惑ってしまったわけです(また、開発機上と公開用サーバではサーブレットコンテナも違っていました)。
実際には、初めに書いたように、コンパイル済み JSP ファイルを消去しただけで正しく動作してくれるようになりました。公開用サーバのサーブレットコンテナは、JSP ファイルに変化があると自動的に再コンパイルするような設定になっていたのですが、どうもうまく変化を検知してくれなかったようです。
というわけで、理不尽な不具合が発生した場合、JSP ファイルが再コンパイルされなかったという状況も考えたほうがよさそうです。
(;^ω^)コンパイル済み JSP ファイルを消去しても不具合が直らなかった場合は、地獄の始まりのようなものですが……。
DATE : 2007/06/11 (Mon)
例外の発生原因をスタックトレースから探りたい場合があります。例えば、データベース関係の例外の発生時などです。データベースへの問い合わせで例外が発生した場合、データベースに渡した SQL がおかしかったのか、それともデータベースそのものに障害が発生しているのか、JDBC などのデータベースにアクセスするライブラリ部分の例外なのかなどを判断する必要があります。ところが、Hibernate や Spring Framework などでは、これらの例外は特定の例外オブジェクト内に格納されています。Hibernate の場合、永続化機構(データベースなど)で例外が発生した場合、全て org.hibernate.HibernateException が投げられ、原因(SQL の異常など)はそれに格納されています。
発生した例外の原因は、java.lang.Throwable#getCause() で取り出せます。しかし、これで取り出せるのは1段階下の原因で、2段階以上下のものを取り出すには繰り返し getCause() を呼び出さなければなりません。このようなコードを書くのは非常に面倒です。
そこで、「Jakarta Commons Lang」の org.apache.commons.lang.exception.ExceptionUtils を使います。これは、例外関係に便利なメソッドを集めたユーティリティクラスです。
ExceptionUtils には、例外の原因を探る static メソッドが用意されています。
- indexOfThrowable メソッド
- indexOfType メソッド
これらのメソッドは特定の例外が何段階下のものかを調べるものです。getCause() を順々に呼び出して調べていくイメージです。対象の例外が存在しない場合は-1となります。それぞれのメソッドには、次のような違いがあります。
- indexOfThrowable メソッド
- 指定された例外のクラスのみを対象とし、そのサブクラスは対象としない。
- indexOfType メソッド
- 指定された例外のクラスとそのサブクラスを対象とする。
要するに、サブクラスを対象とするかしないかという違いです。
参考文献
DATE : 2007/06/10 (Sun)
ときどき、1行の文字数や行数を指定した文書を作る機会があります。OpenOffice.org では、
- 「書式」メニュー → 「ページ」 → 「行数と文字数」タブ
- 「行数と文字数の設定」の項目
の設定を行うことで、原稿用紙のように行数や1行の文字数を指定できます。「罫線を表示する」オプションを付けると、原稿用紙風の罫線が表示されます。
このようにして行数や1行の文字数を指定した場合、注意点がいくつかあります。
- フォントは等幅フォントを使う。
- 見出しなどでは、原稿用紙スタイルを崩すことも必要。
フォントには等幅フォントを使用します。「MS Pゴシック」「MS P明朝」を使っている場合は、「MS ゴシック」「MS 明朝」に変えます。英字用のフォントも等幅に変更します。プロポーショナルフォントのままにすると、原稿用紙の枠を無視して文字が並び、1行の文字数が固定できません。
見出しなどの場合、文字が原稿用紙1文字分のマス目よりも大きな文字を使用する場合があります。すると、原稿用紙のマス目を基準に文字が並ぶため、妙に文字間隔の空いた見出しができあがることがあります。そこで、見出しの部分だけ原稿用紙の枠を無視して文字を並べます。方法は次の通りです。
- 見出しにカーソルを合わせる。
- 「書式」メニュー → 「段落」 → 「配置」タブを選択。
- 「罫線で位置合わせ」オプションを外す。
ただし、見出しが1行分の文字数を越えないように、自分で管理しなければなりません。
ところで、OpenOffice.org Writer で1行の文字数や行数を指定するには、多少の慣れが必要です。というのも、他の設定項目(ルビ文字の最大サイズなど)が影響して、文字数や行数の値に制限がかかったり自動的に変わったりするためです。ネットを検索していると、「文字数+行数指定ダイアログ付き原稿用紙テンプレート」が見つかったので、ここで紹介しておきます。
参考文献
DATE : 2007/06/09 (Sat)
標準で用意されている箇条書きの記号を使用すると、フォントの大きさによっては箇条書きの点だけが妙に目立つ結果になることがあります。
そのため、箇条書きの記号を中点に変えることにしました。中点なので、文字との親和性も良く、点だけが目立つこともありません。
点を変えるには、次のようにします。(OpenOffice.org 2.2.0 で確認しました)
- 右クリックメニューなどから「箇条書きと番号付け」を選択。
- 「オプション」タブを選択。
- 「文字」ラベルの付いた「...」ボタンを押す。
- 「記号と特殊文字」ダイアログの「種類」プルダウンメニューから「普通の句読点」を選択。
- 文字表の中から「・」(U+2027)を選択。
ところで、旧バージョンから OpenOffice.org を使っていた場合、行間を広げると、箇条書きの記号が上にずれてしまうことがあります。その場合は、ユーザープロファイル(Windows の場合、C:\Document and Settings\...\Application Data\OpenOffice.org2)をいったん削除すると不具合が直ります(参考:「faq/1/159 箇条書きの傍点がずれる。」)。
DATE : 2007/06/08 (Fri)
JSTL Core タグライブラリ の c:url を使用すると、URL を変数に記憶しておくことができます。しかも、「/」から始まる絶対パスを指定した場合、ルートはコンテキストルートとなります。
これは JSF を使用しているページに a タグで直接 URL を埋め込む場合にとても便利です。JSF は post-back で動作するため、JSF 上で次のページに遷移した場合の URL は前のページの URL となります。すると、a タグに相対パスを指定した場合、リンクの内容は遷移元のページの URL からの相対パスとなります。これでは、全ページがコンテキストルート直下に存在しないと、遷移元のページのあったディレクトリによってリンクの内容が変化してしまいます。かと言って、絶対パスを埋め込んだ場合、開発用サーバ上から公開用サーバにページを移す場合に、リンク中の絶対パスを全て公開用サーバのものに置き換えなければなりません。
c:url を使えばこの問題は解決できます。「/」から始まる絶対パスのルートはコンテキストルートなので、「/」から始まるパスを埋め込んでおけば公開用サーバに移す場合でもリンクを修正する必要がありません。
c:url を使うには、page ディレクティブて EL 式を有効にし、 taglib ディレクティブで JSTL Core タグライブラリの使用を宣言します。(「...」は省略を表します)
<%@ page ... isELIgnored="false"> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
value 属性に URL を、var 属性に変数名を指定することで、変数に URL を記憶できます。
<c:url var="top_url" value="/index.jsp" />
この変数は次のような EL 式で参照できます。
${top_url}
つまり、a タグに c:url で変数に記憶させた URL を指定するには、次のようになります。
<a href="${top_url}">...</a>
私は、トップページなどの特殊な URL を別の JSP ファイルで記憶させています。そして実際にその URL を使用するページでその JSP ファイルを取り込んで、EL 式から URL を参照しています。よく使う URL を1ファイルにまとめられるので、管理が楽になります。