内部クラスでハマる

SAStrutsで、Actionの中に内部クラスを作って、そいつをSessionスコープのFormに持ってユースケース中で使いまわす…
というようなことをしようと思ったら以下のような感じではまりました。

Formのインスタンスが新しいリクエストを送っても新しくならずに古いもののままで、リセットメソッドを実行しようとしているところで「java.lang.IllegalArgumentException: object is not an instance of declaring class」が発生。
原因がわからず数時間首をひねりつづけた後にHotdeployUtil$RebuilderImpl#rebuildでシリアライズ中にNotSerializableExceptionが発生しているのを発見。
ここで例外が発生した場合はcatch節の中で古いインスタンスをそのまま戻すようになっており、エラーやら警告やらのメッセージは特に出ないようになっているので特定に時間がかかったのでした。

しかし、なぜシリアライズに失敗するんでしょう?
内部クラスやForm、それらのフィールドのクラスは全てSerializableを実装しています。なぜ…?
こちらの原因はすぐに判明しました。
内部クラスはその外部のクラスもSerializableを実装している必要があったのです。なるほど…。

ActionクラスにもSerializableを実装し、フィールドとして持っているServiceやらHttpServletRequestやらにはtransientを付けました。
これでうまくいく…と思ったら今度はClassNotFoundExceptionです。
見つからないといわれているクラスは…「HogeAction$$EnhancedByS2AOP$$1a27a13」。
そりゃあ見つからないですね。エンハンスされたクラスはクラスファイルなんかないですもんね。
終了〜

というわけで、結論。
大人しく外部クラスにする。
今回は使ってないけど、もしAOPを使うならコンポーネント名だけSessionスコープに持たせるなりしてDIする。

しかしHotDeployは私のような素人がちょっと変なことをしようとするとおかしくなるのが困りモノ。
玄人がいる場所で使うか、無難そうなやりかた以外はやらないのが生産性を上げるコツではある…。