2005年08月23日

Apache MyFacesと文字化け

 久しぶりに地獄めぐりをさせられたので、ここに書いておく。
 まず最大の責任者を非難しておこう。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世紀まで人間は、太陽のエネルギー源を知らず、地磁気の原因を知らなかった。バイナリの泥沼は、人間に、新たな尽きることのない謎を投げかけているのかもしれない(ありえない)。

Posted by hajime at 2005年08月23日 22:32