この 2 日ほど仕事で悶々とハマったお話を。
Amazon は通販だけじゃない
Amazon と言えば「宇宙最大の品揃え」と言われる通販サイトを思い浮かべると思いますが、IT 系のエンジニアはもうひとつ知っていることがあります。
です。略して AWS です。昨今すっかり定着した「クラウドコンピューティング」の最大手でもあります。iPhone をお使いの方は iCloud とか利用されている方も多いでしょう。Dropbox とか Google Drive とかのクラウドストレージなどもひっくるめて「クラウド」というのが最近の IT 系の「常識」とも言える用語になってまいりました。
簡単に言えば「AWS に契約するとサーバマシンを好きなだけ作って運用できるぜ」というものです。おまけに 1 台作ったらそれをコピーして同じ環境をいくつもいくつも作ることもできます。昔、会社で古くなった PC に Linux を入れてサーバにしていた世代の人間からすると夢物語のようなお話です。
タダではありませんが。
会社で契約なのであまり料金が高くなるとつっつかれますが、1 年間は一定の条件下で無料利用が可能ですので結構いろいろ弄り倒せます。
AWS に乗せ変えてね
とある日、東京から指令が届きました。
サラリーマンには国連の常任理事国のように拒否権はありませんので、上司から指示がくれば得意だろうが不得意だろうがやるしかないのですが、あいにく 10 年以上も Java で仕事をしていたので自社サービスとやらを別のサーバに乗せ変えるのは過去何度もやってきた作業です。
「勅命、謹んでお受けいたします」
と返事をいたしました。
JSP が表示されません
それからさくっと 1 日くらいで新しい環境でシステムが動くようになったのですが、お客様へ提供するものなのでちゃんと動いているか検証する必要があります。典型的な O 型人間なので勢いでプログラム書いたり資料を作ったりシステムを動かす環境を構築するのは得意なのですが、きちんと順序立ててもれなく検証するのは苦手なので得意な若手に任せてのんびりモードで仕事をしていました(不良社員)。
とある日の午後、お昼ご飯を食べて満足していたところに若手社員から報告を受けました。
「JSP が表示されないのですが」
ふむ。システムのほとんどは Flash で動くシステムなのですが、一部というかほぼ一箇所だけ JSP で動きます。それが表示されず真っ白な画面になるらしい。
エンジニアの好きな言葉
- 何もいじってないのですが。
- そのままコピっただけなのですが。
- コメント書いただけなのですが。
- ログを埋め込んだだけなのですが。
という言葉を聞くときは大抵なにかやってます。今回の私の場合は「そのままコピっただけなのですが」です。すでに稼働しているサーバの資材をそのまま AWS の環境へコピーしただけです。
時代は変わる
ですが、やっているのです。以前の環境から今回の環境へ変えるに当たってイロイロと。
Java のバージョンを最新にして Tomcat を最新にした。
これだけインパクトのあることをやっておきながら「コピっただけ」とのたまうのがエンジニアの華麗なる振る舞いなのですが、数年前に作られたシステムが稼働する Java のバージョンは 6 です。Tomcat も 6 です。今回は Java 8 にして Tomcat も 8 にしました。
Windows で言えば Windows XP から Windows 10 に変えたくらいのインパクトです。何もおこならない方がおかしい。
JSP とは
JSP とは JavaServer Pages の略です。HTML で記述された HTML ファイルに Java 言語のプログラムを埋め込んで動的に表示を切り替えるためのものです。
Sample.jsp
がSample_jsp.java
に変換される。Sample_jsp.java
がSample_jsp.class
にコンパイルされる。
という処理がシステム内部で行われてブラウザに表示されます。
ログは隅々まで確認を
どんなシステムでもそうですが、システムが稼働しているときはログという記録が残されていきます。厳格なシステムだと何かオペレーションしたときにその操作記録が残っていたりするのですが、簡単なシステムだと何かエラーが発生したときにエラーの情報が残っているだけで、平常運転のときは何も記録されないとか。
で、Tomcat が通常出力しているログは ${TOMCAT_HOME}/logs/Catalina.out
になります。なのでずっとこのログと自分たちが常時出力しているログだけを見て解析を進めていました。
(・・・何もエラーが出ていない・・・)
心の叫び。初日は結局解決しないで悶々としたまま帰宅しました。
翌日、ふと Tomcat が別のログを出力しているのでそっちをチラッと見てみたところ重大な情報が出力されていました。 localhost.yyyy-mm-dd.log
です。普段見ないので完全にスルーしていたのですが、手がかりがなくて片っ端から様々な情報をチェックしていたらこれを見つけました。
The method getDispatcherType() is undefined for the type HttpServletRequest
うぇーい。
まあよくわからないのでインターネッツで調べてみたら、どうやらサーブレットのバージョンが古いのが原因な様子。
謎は全て解けた!犯人はこの中にいる!
システムを作った当初はサーブレットは 2.5 だったのですが、今現在は 3.1 のようです。で、上のエラー「HttpServletRequest
型では getDispatcherType()
なんてメソッドは未定義なんだぜ」というエラーが出ていたのです。
要は上に書いた通り Sample.jsp
が Sample_jsp.java
へ新しい Tomcat が変換してくれたのですが、getDispatcherType()
を使うプログラムに変換したものの、いざ Sample_jsp.class
にコンパイルするときには古いサーブレットとしてコンパイルしようとしていたため新しい方に登場する getDispatcherType()
メソッドがありませんぜ、ということになったのです。
ということは、どこかに古いサーブレットの情報があるはずです。WEB-INF/lib
に servlet-2_5-api.jar
が置いてありました。そもそもこの jar ファイルが WEB-INF/lib
に置いてあるのも不可解なのですが、人様の作ったものにケチをつけても仕方ないのでこのファイルをぢっと見つめてみると「2_5」という文字列が怪しい。古いバージョン 2.5 を意味しているはずなので、これを新しくすればいいんじゃね?と誰でも思うはずです。
${TOMCAT_HOME}/lib
に servlet-api.jar
というファイルがありました。うーん。もはやバージョンすらつけないファイル名になったのか。とりあえず servlet-2_5-api.jar
を /tmp
に移動して servlet-api.jar
をコピーしてきました。
Tomcat を再起動したらあっさり JSP が表示。2 日ハマって最終的には jar ファイルの入れ替えだけで解決しました。
教訓
ログはちゃんと隅々までチェックすべし
これでどうやら AWS への移行作業も終わりが見えてきました。
だがちょっと待ってほしい
根本的に問題を解決するよりも対処療法の方が楽なのでいつもそうしているのですが、本来は「servlet-api.jar
を WEB-INF/lib
で抱え持つなよ」というご指摘が来るのです。Java のサーブレットは Tomcat などの Web コンテナと呼ばれるソフトウェア上で動作するため、通常はサーブレットが動作・コンパイルするのに必要なライブラリは Tomcat がそのバージョンに応じたものを同梱しています。アプリケーションを開発するエンジニアは Tomcat が同梱するライブラリを参照するのが正しい作法です。
ところが今回は「自分のお腹に抱え持ったライブラリが古かった」ために起きた事案です。
対応も自分のところに抱え持たないように Tomcat の方を参照するようにするのが真っ当なのですが、その辺は「高度に政治的な判断を要する」のであえて対処療法にさせていただきました。サラリーマンはつらいのです。