ひがやすを技術ブログ

電通国際情報サービスのプログラマ

EJB3時代のアーキテクチャパターン

EJB3JSFJPAを使ったときのアーキテクチャは、ある一定のパターンで説明できると思っています。私見ですが、説明したいと思います。
まず、プレゼンテーション層であるJSFですが、ページ(View)ごとにManagedBean(s)を定義します。ManagedBeanの作り方は3パターンあり

  1. イベント処理専用(Action)でモデルとしてはEntity(ドメインモデル)を使う(Action only)
  2. イベント処理とプレゼンテーションモデルを兼用(Page only。Pageでイベントも処理)
  3. イベント処理(Action)とプレゼンテーションモデル(Page)を分離(Action + Page)

があります。
私は、ドメインモデルは、ドメイン層でのみ使い、プレゼンテーション層では、専用のプレゼンテーションモデルを使うべきだと思っています。なぜなら、ドメイン層とプレゼンテーション層では、モデルとして必要な構造・役割が異なるからです。
ただ、頑固にドメインモデルをプレゼンテーション層で使いたがる人もいて、プレゼンテーションモデル(昔のDTO)を使うことは、OOではないと言い張る人もいます。OOとは、それぞれの役割に応じて適切にクラスを分割することであり、データと振る舞いを単純に一緒にすることではないと思いますが、まぁいいでしょう。2のPage onlyのパターンは、プレゼンテーション層におけるデータと振る舞いを一緒にしたものであり、頑固なOO派も満足するかもしれません(笑)。
プレゼンテーションモデルを使うほうが、より適切な役割にもとづいているので、OO的に望ましいと思いますが、問題点は、ドメインモデルとプレゼンテーションモデルとの変換コストです。これについては、Dxoを使うことで解決することができます。Dxoの説明は、ここを見てください。近日中(たぶん1週間以内)にリリースします。
プレゼンテーション層でEntityを使うときの問題点は、Viewのレンダリングのときに、Entityの関連をたどる場合があることです。例えば、#{employee.department.name}。lazy loadの場合、関連をたどるとき(関連をたどるのがはじめての場合)に永続コンテキストを必要とします。JPAでは、コンテナ管理の場合、永続コンテキストは、トランザクションに関連付けられているため、Viewのレンダリングのときも、トランザクションが必要だということになってしまいます。
この問題を解決するために登場するのが、ServletFilterを使ったトランザクション管理です。レンダリングという本来ならトランザクションに無関係な処理で、フレームワークの都合のためにトランザクション処理をするというのは、好ましくないことですし、無駄にトランザクションが長くなってしまうのも好ましくないことですが、目をつぶることにします。今後、ServletFilterを使ったトランザクション管理をするための機能を提供するフレームワークもいろいろ現れるでしょうが、このような問題があることは認識しておくべきです。これらの問題は、プレゼンテーションモデルを使えば、起きることはありません。どう考えてもプレゼンテーションモデルを使うべきだと思うのですが、まぁいいでしょう。詳しくは、ここを見てください。
ManagedBeanのパターンは、この3つです。次は、業務ロジックの実装の仕方を説明したいのですが、とりあえず時間切れ。