一時メモ

仕事でレガシーのStruts1.0.2+Tomcat4なアプリをリファクタリングする必要があって、悩んだ末S2ContainerServletを入れて無理やりS2化しました。
NDAとかいろいろあって細かく書いちゃだめだけどあとで忘れると大変なことになりそうなので、忘れないうちに記憶に基づいてメモ。

経緯・現状

  • S2にする理由。
    • スコープ管理が面倒。singletonとかサービスロケータとか、車輪の再発明はぶっちゃけありえない。
    • 依存関係があると、テストしずらい。
  • app.diconは最初SAStrutsのtutorialかなんかから適当に持っていったがconventionやらcustomizerやらを直さなければだめで、結局aop.diconのinclude以外はさくっと削除。
  • Eclipse以前の時代からあるアプリなので、Mavenのartifactのやつ?とかと違って、たとえば以下のようなフォルダ構成になっている。


+---java/src
| +---com.example.commons
| .foo
| .bar
+---foo
| +----webapps
| +----web
| +----WEB-INF/
+--bar
| +----webapps
| +----web
| +----WEB-INF/
こういう今日では変則的なあれこれがあり、さらにfoo,barそれぞれAntのbuild.xmlが存在しているので、どちらでbuildしてもdiconやlog4jが適切にロードされるように気を使う必要がある。

  • S2ContainerServletの説明には、他のサーブレットよりさきにロードするようにと書いてあるが、レガシーのサーブレットのinit()でlog4jの初期化をしており、これをそのまま使いたいので、S2ContainerServletのloadはその次にくるようにweb.xmlのload-on-startup要素を2に設定した。
  • レガシーのsingletonは最初diconのcomponent要素にinstance属性をouterとして置こうとしたが、たぶんロード順序の関係で他のコンポーネントへのDIがうまくいかないので、とりあえずあきらめた。(S2経由で取得するほかのクラスのコンストラクタ内で、singletonを参照するようにした。当然依存関係は生じてしまうが、スコープ管理などのメリットを買ってS2にしているのでこれでやむなし)
  • サービス部分と、バックエンドのサーバへの通信のファサードの部分を、それぞれS2コンテナ管理することにした。Strutsのアクション、ないし非Strutsアプリではサーブレットのservice()の中から、SingletonS2ContainerFactoryで取得する。

課題

  • S2によってどれぐらいメモリ使用量増えるの?HPJMeterでは大してわからなかったけど、特に連続運転時にどうなるのかが心配。S2Strutsとかではある程度実績あるし、TeedaSAStrutsはそれぞれ考えて作られているはずなのでよいのだが、自前でS2ContainerServletを置いている以上、そのへん自分でけつをふくしかない
  • 結局ベースはレガシーなので、どこかでSingletonS2ContainerFactory.getContainer().getComponent(....)を使って明示的にコンポーネントを採ってこなきゃいけない。レガシーからは高級サービスロケータ的な使い方なのでこれはこれでいいけど、使いどころのガイドラインをきめてかないと今後おかしくなる
  • トランザクション境界は、serviceにおいていて、今のところ、レガシーとそろえるために、S2Txなどは使わず、service内で手打ちでトランザクション制御を行っている。