J2EEレガシーアプリケーションのJavaEEアプリケーションへのマイグレーション(4)

何回かに分けてJ2EEレガシーアプリケーションのJavaEEアプリケーションへのマイグレーションについて実際のコードを見ながら解説したいと思います。

変更前のサンプルソースはこちら
https://github.com/megascus/oi-webapp-sample/tree/initial

第一回はこちら
J2EEレガシーアプリケーションのJavaEEアプリケーションへのマイグレーション(1)

ViewとModelを分離する

さて、前回説明したとおり、今回はView層とModel層を分離を分割していきたいと思います。

ServletFilterの導入

今回のアプリケーションにおいては全てのRequestに対して行わなければいけない処理があります。
https://github.com/megascus/oi-webapp-sample/blob/initial/src/com/oisix/sample/base/ControllerServlet.java#L43-L44

文字コードの設定を指定してますが、本来はAPサーバーにおいて設定できるものです。
消してしまうと、ServletFilterを導入する対象がなくなってしまいますので、今回はそのまま残します。

https://github.com/megascus/oi-webapp-sample/blob/20140511/src/com/oisix/sample/base/SetCharactorEncodingFilter.java

第一回でもお伝えしましたが、JavaEE7ではアノテーションServletの定義ができます。ServletFilterについても同様です。
アノテーションでServletFilterであると伝えているため、古いJ2EEのようにweb.xmlでFilterの設定をする必要はありません。

note.
ServletFilterがアノテーションで定義できるようになったため、多人数で開発をしていると予期しないServletFilterがいつの間にか紛れ込んでしまう場合もあります。
アノテーションで定義できるようになったのは楽ですが、見通しが悪くなるのは間違いないのでご注意下さい。
場合によってはアノテーションを使わずweb.xmlで全てを定義するといった運用も必要になります。

認証、認可の仕組みを作りこみたい場合や、ロギングを行いたい場合にはServletFilterに実装することになります。

トランザクション管理層の作成

元々の実装ビジネスロジック内で、UIでどのようなボタンが押されたのか等を判断して、トランザクションを開始してと言った処理が混ざって記述されていました。
https://github.com/megascus/oi-webapp-sample/blob/initial/src/com/oisix/sample/bean/CustomerEditBean.java

その中からいわゆるロジック、DB操作等を切り出したクラスを作成します。
https://github.com/megascus/oi-webapp-sample/blob/20140511/src/com/oisix/sample/bean/CustomerService.java

トランザクション管理がスレッドに紐付いていることもあり、本当にしたかった処理のみが記載されています。
セッションを確立して……エラーが起きたからロールバックして……のようなことを個別で書く必要はありません。

note.
今回はEntityを直接トランザクションの外に出していますが、JPAに慣れていない場合はDAOパターンを使用し、Entityの内容を他のJavaBeansに移してからトランザクションの外にだすことも検討して下さい。
JPAではまるポイントの大半はそれだけで防ぐことが出来ます。

UI操作の分割

ビジネスロジックから分離されたUIを操作するロジックはServletに移植します。
併せて以下の様な修正を加えました。

  • Servletで実装されていたコントローラーの処理をAPサーバーに移譲しました。URLを呼び分けることでどのような処理を行ったのかを判定します。
  • 元々の実装ではGETとPOSTを分けずに処理を指定ましたが、初期表示と画面から何か操作された場合の処理を分岐させたかったので、GETとPOSTを分けて実装できるようにしました。*1

https://github.com/megascus/oi-webapp-sample/blob/20140511/src/com/oisix/sample/base/BaseServlet.java

  • サーブレットからEJBの呼び出しを@Injectアノテーションを使用し、コンテナ経由で呼び出すようにしています。
  • RequestパラメータからJavaBeansへの変換、Validation処理についてはUtilityクラスを作成しました。今は使用していませんが、モダンなフレームワークであればコントローラーが行ってくれる処理のため、本来作成する必要ない処理です。

https://github.com/megascus/oi-webapp-sample/blob/20140511/src/com/oisix/sample/base/MstCustomerUtils.java

note.
元々のアプリケーションでは単一のServletが全てのRequestを受け付けるような仕組みになっていました。
はるか昔のJ2EEではServletFilterが実装されておらず、J2EEパターンでいうところのFilterパターンを行うために多用されていた技法です。
しかしながら、ServletFilterが実装された現在*2においては他のフレームワークに処理を移譲する場合をのぞいては行わないほうが良いでしょう。

note.
MVCに分離するときにViewについてはテンプレートファイル(今回の場合はjsp)のみがViewだと言われていた時期もありますが、現在ではテンプレートファイルとその後ろ側の処理を行うModelクラスを作成して、2つを対にしてViewとして扱うことが多いです。*3テンプレートファイルだけだと単純な画面であればよいのですが、複雑な画面になるとViewの中にif文等が多発し、結果として保守性が下がってしまうことが判っています。
複雑な条件分岐等はテンプレートファイルではなく、ロジックとしてJavaで実装することを検討して下さい。

まとめ

今回はView(JSP/Servlet)とModel(EJB)の切り分けが出来ました。
次回はJSP/ServletJSFに変更したいと思います。

また、以下のタグはここまでを修正したものになっています。
動く状態にはなっていますので、参考にしてください。
https://github.com/megascus/oi-webapp-sample/tree/20140511

*1:簡易フレームワークです

*2:J2EE1.3で実装されています

*3:後ろ側の処理を行うクラスはViewModelと呼ばれることもあります