久しぶりに地獄めぐりをさせられたので、ここに書いておく。
まず最大の責任者を非難しておこう。Javaサーブレット規格だ。フォームのPOSTのENCTYPEとして、application/x-www-form-urlencodedしか認めていない。これはenctypeとは名ばかりで、文字のエンコーディングが規格で決められていない。ならサーブレット規格のほうで「エンコーディングはUTF-8」と決めてくれればいいのに、それもしていない。ここからすべてが始まった。
さて本題に入る。
Referer Houndの管理サービスには、JBoss-3.2.7とApache MyFaces-1.0.9を使っている。この管理サービス内の、あるフォームとあるブラウザの組み合わせで、日本語に文字化けが起きていた。ほかのフォームやほかのブラウザでは文字化けは起こらない――これだけでもう逃げ出したくなるような話だ。
その文字化けのしかたは、UTF-8のバイト列をShift_JISで解釈した状態になる、というものだった。いったいどこからShift_JISがまぎれこんだのか。私は最初、自分のミスだろうと軽く考えていたが、そうではなかった。根源はつきとめきれていない。MyFacesのソースコードのどこにも、Shift_JISやWindows-31Jのたぐいはない。
ともあれ、なにか想像を絶する特定の条件が揃ったときにのみ、数MBのバイナリの闇の底から、得体の知れない強制Shift_JIS解釈が発動し、文字化けを起こすのだ。
相手が闇の底だけあって、解決方法も一筋縄ではいかない。
結論から書くと、javax.faces.webapp.FacesServletへのリクエストをサーブレットフィルタでつかまえて、setCharacterEncoding("UTF-8")をかけ、さらにgetParameterMap()する。後者が肝心なところだ。これをやらないと、setCharacterEncodingしないときとはまた違った妙な文字化けを起こす。いったんgetParameterしたら、その結果がキャッシュされて、そのあとでsetCharacterEncodingをかけてもgetParameterの結果は変わらなくなるらしい。
20世紀まで人間は、太陽のエネルギー源を知らず、地磁気の原因を知らなかった。バイナリの泥沼は、人間に、新たな尽きることのない謎を投げかけているのかもしれない(ありえない)。