JBoss Seamのサンプルアプリを試す。その1

 http://docs.jboss.com/seam/reference/en/html/index.htmlを読み始めました。以下は拙い日本語訳です。間違いがあればご指摘下さい。ダウンロードしたSeam一式の中にLGPLとあったので日本語訳していますが、拙いようであればご指摘下さい(Sales宛--しかcontact先はなかった--にE-Mailを送りましたが返事はありません)。


http://docs.jboss.com/seam/reference/en/html/tutorial.html
 まずはregistrationサンプルを動かしてみます。

 JBoss SeamのサンプルをEclipse上で動かす。にてCVSから持って来たソースをそのまま使います。

 で、問題なく動作します。JBoss_Home/server/default/deploy/jboss-seam-registration.earをJBossのDBをPostgreSQL 8.0へ変更する。で作成したJBoss_Home/server/postgres/deploy/へコピーしてJBoss_Home/bin/run.bat -c postgresで再起動しても問題なく動作します。もちろんPostgresのDBにはusersと言うtableが作成されていました。

 サンプルアプリケーションregistrationを詳しく見てみます。/examples/registrationの中にあるファイルは以下のものだけです。


プレゼンテーション部分のjspファイルが2つ、SessionBeanのinterfaceとBean、EntityBeanと残りは設定ファイルです。


1. The entity bean: User.java
    プロパティに

    String username;

    String password;

    String name;

    とこれらのsetter,getterと引数なしのと引数ありのコンストラクタとannotationだけです。


    AnnotationとSeam特有部分

    1. @EntityはこのクラスがEJB3.0(The Java Community Process(SM) Program - communityprocess - prJava Persistence API)で定義されたEntityBeanクラスであるとの宣言です。
    2. @Name("user")Seamコンポーネントが必要とするコンポーネント名を定義するものでSeamアプリケーション内で一意でないといけません。JSFSeamSeamコンポーネントと同じ名前を使ってコンテキスト変数を解決しようとした場合現在はコンテキスト変数は定義(Null)されていません。Seamコンポーネントインスタンス化し新しいインスタンスをコンテキスト変数へバインドします。この場合JSFがuserと名づけた変数を扱う最初にSeamはUserをインスタンス化します。
    3. @Scope(SESSION)Seamコンポーネントインスタンス化したときにはインスタンス化されたコンポーネントコンポーネントのディフォルトコンテキストにバインドされます。ディフォルトコンテキストは@Scopeで定義されます。UserBeanはセッションスコープのコンポーネントです。
    4. @TableEJB3.0で定義されたAnnotationでUserクラスはusersテーブルにマップされます。
    5. クラスのプロパティname,password,usernameはEntityBeanの属性です。全ての永続属性はアクセッサメソッドを定義する必要があります。JSFがレンダーレスポンスやアップデートモデルバリューフェイズでこのコンポーネントを使うときに必要になります。
    6. 引数なしのコンストラクタはEJB仕様とSeamの両者が必要とします。
    7. @NotNull,@LengthHibernateのValidatorフレームワークの一部です。SeamHibernateのValidatorを進化させデータのValidationに使うことが出来ます(Hibernateを永続化に使ってなくても)
    8. @IdEJB3.0で定義されたAnnotationでEntityBeanのプライマリーキーを定義します。


このファイルの最も大切なものは@Name,@Scope Annotationです。このAnnotationがこのクラスをSeamコンポーネントとして成立させます。


以降で述べるようにUserクラスのプロパティはJSFコンポーネントに直接結合されJSFがアップデートモデルバリューフェイズの間存在させます。JSPページとEntityBeanドメインモデル間でデータをコピーするような退屈なコードを書く必要はありません。


どちらにしてもEntityBeanでトランザクション管理やデータベースへのアクセスを行うべきではない。このコンポーネントJSFのAction Listerとしては使うことが出来ません。そのためにはSessionBeanが必要です。


2. The stateless session bean class: RegisterAction.java


 Seamアプリケーションで最も使うのはSessionBeanをJSFのAction Listerとしてです(代わりにJavaBeanも使えます)。


 アプリケーション内でJSFのActionとSessionBeanのメソッドは正確に対応しています。ここではステートレスSessionBeanを使い、UserBeanにより起こされたActionと全ての状態は結び付けられています。


 このサンプルアプリケーションでは一番興味あるコードです。

    1. @StatelessはこのクラスがEJB3.0(The Java Community Process(SM) Program - communityprocess - prEJB 3.0 Simplified API)で定義されたステートレスSessionBeanとしてのクラスのAnnotationです。
    2. @Scope,@Nameは上記と同じです。
    3. @Interceptor(SeamInterceptor.class)SeamコンポーネントとしてのSessionBeanには全てSeamInterceptorEJB Interceptorとしなければなりません。
    4. @InSeamによって注入されたBean属性だと明らかにするものでこの場合user(インスタンス変数名)と名付けられたコンテキスト変数から注入された属性です。
    5. @ValidHibernate Validatorから提供されたもので関連するオブジェクトに再帰的にValidationを行います。
    6. @PersistenceContextEJB3のEntityManagerを注入するのにつかわれるEJBのAnnotationです。
    7. SeamSeamjBPMコンテキストオブジェクトが注入された、さまざまなJFSが使えます。Seamに注入されたFacesContextインスタンスを得るためにfacesContextインスタンスを@Inと一緒に使っいます。
    8. @IfInvalidはAction Listenerメソッドが実行される前にHibernate Validatorを使いコンポーネントの状態をValidateするようSeamに伝えます。
    9. 通常のEJB3の EntityManager APIはAction Listerメソッドを使ってデータベースと協調し、JSFへ出力します。これはSessionBeanですが、registerメソッドが呼ばれてから自動的にトランザクションが開始され完了するとCommitされます。



 今回@Scopeが明示的に示されていませんが、その場合はSeamコンポーネントはデフォルトのスコープを持ちます。ステートレスSessionBeanの場合はデフォルトのスコープはステートレスコンテキストです。実際全てのステートレスSessionBeanはステートレスコンテキストに属します。


 このアプリケーションではSessionBean Action Listenerはビジネスと永続性のロジックを実行します。もう少し複雑なアプリケーションでは永続性ロジックはデータアクセスコンポーネントに専念するような階層にリファクタリングする必要があるでしょう。実際はそのようにされるでしょう。ただSeamは何層にも及ぶアプリケーションをあなたに課する訳ではないことをお伝えしたいのです。


 更に、SessionBeanはWebリクエスト(例えばFacesContextオブジェクト)とトランザクションリソース(EntityManager)を合わせたコンテキストへ同時にアクセス出来ます。これは従来のJ2EEアーキテクチャーを超えるものです。もしあなたが従来のJ2EE層が良いのであればSeamアプリケーションをそのように実装することも出来ます。しかし沢山のアプリケーションは単純に使い物にならないでしょう。


3. The session bean local interface: Register.java

    SessionBeanはlocal interfaceを必要とします。

 Javaのコードは以上でおしまいです。ここからはDeployment Descriptorsです。