第10章 Seam アノテーション

Seam アプリケーションを書く場合、たくさんのアノテーションを使用します。 Seam は宣言的プログラミングスタイルを実現するためにアノテーションを利用しています。 使用されるほとんどのアノテーションは EJB 3.0 仕様によって定義されています。 データ妥当性検証のためのアノテーションは Hibernate バリデータパッケージによって定義されています。 最終的に、Seam は、この章の中で説明するアノテーション一式を定義しています。

これらすべてのアノテーションは、 org.jboss.seam.annotations パッケージで定義されています。

10.1. コンポーネント定義のためのアノテーション

最初のアノテーションのグループは、Seam コンポーネントを定義します。 これらのアノテーションはコンポーネントクラスに登場します。

@Name
@Name("componentName")

クラスに Seam コンポーネント名を定義します。 このアノテーションはすべての Seam コンポーネントに必要です。

@Scope
@Scope(ScopeType.CONVERSATION)

コンポーネントのデフォルトコンテキストを定義します。 可能な値は、 ScopeType Enumeration によって定義されます。 ( EVENT、 PAGE、CONVERSATION、SESSION、BUSINESS_PROCESS、APPLICATION、STATELESS )

明示的にスコープが指定されない場合、デフォルトはコンポーネントタイプに依存します。 ステートレスセッション Bean のデフォルトは STATELESS、 エンティティ Bean とステートフルセッション Bean のデフォルトは CONVERSATION、 そして、JavaBeans のデフォルトは EVENT です。

@Role
@Role(name="roleName", scope=ScopeType.SESSION)

Seam コンポーネントは、複数のコンテキスト変数と結合することが可能です。 @Name/@Scope アノテーションは「デフォルトロール」を定義します。 各 @Role アノテーションは追加のロールを定義しています。

  • name — コンテキスト変数名

  • scope — コンテキスト変数スコープ、 明示的にスコープが指定されない場合、デフォルトは上述のデフォルトに依存します。

@Roles
@Roles({
        @Role(name="user", scope=ScopeType.CONVERSATION),
        @Role(name="currentUser", scope=ScopeType.SESSION)
    })

複数の追加ロールの仕様も許されています。

@Intercept
@Intercept(InterceptionType.ALWAYS)

いつ Seam インターセプタがアクティブであるかを決定します。 可能な値は InterceptionType Enumerationによって定義されています。 ( ALWAYS、INVOKE_APPLICATION、NEVER )

インターセプションタイプが明示的に指定されない場合、 デフォルトはコンポーネントタイプに依存します。 エンティティ Bean デフォルトは NEVER です。 セッションBean と JavaBean のデフォルトは INVOKE_APPLICATION です。 (JSF アプリケーション呼び出しフェーズでのみインターセプションが可能)

@JndiName
@JndiName("my/jndi/name")

Seam が EJB コンポーネントのを探すために使用する JNDI 名を指定します。 JNDI 名が明示的に指定されない場合、Seam はorg.jboss.seam.core.init.jndiPattern で、 指定された JNDI パターンを使用します。

@Conversational
@Conversational(ifNotBegunOutcome="error")

対話スコープコンポーネントが対話的であることを指定します。 ただし、このコンポーネントによって開始された長期対話がアクティブでなければ (あるいはこのメソッドが新しい長期対話を開始しなければ)、 このコンポーネントのメソッドを呼ぶことはできません。

  • ifNotBegunOutcome — コンポーネントが呼ばれたとき、どの長期対話もアクティブでない場合、 アクションに対する JSF 結果 (outcome) を指定します。

@Startup
@Startup(depends={"org.jboss.core.jndi", "org.jboss.core.jta"})

初期化時に、アプリケーションスコープコンポーネントが即座に起動されることを指定します。 これは主に JNDI、データソースなどの重要なインフラストラクチャを起動する特定の組込みコンポーネントに使用されます。

@Startup

セッション生成時にセッションスコープコンポーネントが即座に開始されることを指定します。

  • depends — 指定されたコンポーネントがインストールされている場合、 最初に起動されなければならないことを指定します。

10.2. バイジェクション(bijection)のためのアノテーション

次の 2 つのアノテーションはバイジェクションをコントロールします。 これらのアノテーションはコンポーネントインスタンス変数、またはプロパティのアクセサメソッドに指定できます。

@In
@In

各コンポーネント呼び出しの最初に、コンポーネント属性がコンテキスト変数からインジェクトされることを指定します。 コンテキスト変数が、null の場合、例外がスローされます。

@In(required=false)

コンポーネント呼び出しの最初に、コンポーネント属性がコンテキスト変数からインジェクトされることを指定します。 コンテキスト変数は null でも構いません。

@In(create=true)

コンポーネント呼び出しの最初に、コンポーネント属性がコンテキスト変数からインジェクトされることを指定します。 コンテキスト変数が、null の場合、Seam によってコンポーネントはインスタンス化されます。

@In(value="contextVariableName")

アノテーションを付けられたインスタンス変数名の代わりに、コンテキスト変数名を明示的に指定します。

@In(value="#{customer.addresses['shipping']}")

コンポーネント呼出しの最初に、コンポーネント属性がJSF の EL 式を評価することによってインジェクトされることを指定します。

  • value — コンテキスト変数の名前を指定します。 デフォルトはコンポーネント属性の名前になります。 あるいは、#{...}よって取り囲まれた JSF EL式を指定します。

  • create — コンテキスト変数がすべてのコンテキストにおいて未定義 (null) の場合、 Seam がコンテキスト変数と同じ名前のコンポーネントをインスタンス化することを指定します。 デフォルトは false です。

  • required — コンテキスト変数がすべてのコンテキストで未定義の場合、 Seam が例外をスローすべきことを指定します。

@Out
@Out

コンポーネント呼出しの終わりに、 Seam コンポーネントであるコンポーネント属性が、 コンテキスト変数にアウトジェクト (outject) されることを指定します。 コンテキスト変数が null の場合、例外がスローされます。

@Out(required=false)

Seam コンポーネントであるコンポーネント属性が、コンポーネント呼出しの終わりに、 コンテキスト変数にアウトジェクト (outject) されることを指定します。 コンテキスト変数が、null でも構いません。

@Out(scope=ScopeType.SESSION)

コンポーネント呼出しの終わりに、 Seamコンポーネントでないコンポーネント属性が コンテキスト変数にアウトジェクト (outject) されることを指定します。

@Out(value="contextVariableName")

アノテーションを付けられたインスタンス変数名の代わりに、コンテキスト変数名を明示的に指定します。

  • value — コンテキスト変数の名前を指定します。 デフォルトはコンポーネント属性の名前です。

  • required — コンポーネント属性がアウトジェクションの間に null の場合、 Seam が例外をスローすることを指定します。

注記:これらのアノテーションは以下の例のように同時に使用されることはごく当たり前のことです。

@In(create=true) @Out private User currentUser;

次のアノテーションは manager component パターンをサポートしています。 それは、インジェクトされたクラスのインスタンスのライフサイクルを管理する Seam コンポーネントです。

@Unwrap
@Unwrap

アノテーション付きの getter メソッドによって返されたオブジェクトが、 コンポーネントインスタンスそのものの代わりにインジェクトされたものであることを指定します。

次のアノテーションは factory component パターンをサポートしています。 そこで、Seam コンポーネントはコンテキスト変数の値の初期化に責任を持ちます。 これは特に non-faces リクエストへのレスポンスのレンダリングに必要なあらゆる状態の初期化に役立ちます。 それはコンポーネントメソッド上に登場します。

@Factory
@Factory("processInstance")

コンテキスト変数が値を持たないとき、 コンテキスト変数の値を初期化するために使用されるコンポーネントのメソッドを指定します。

このアノテーションは、 Log のインジェクションを可能にします。

@Logger
@Logger("categoryName")

コンポーネントフィールドとして、 org.jboss.seam.log.Log インスタンスをインジェクトすることを指定します。

  • value — ログカテゴリーを指定します。 デフォルトはコンポーネントクラス名です。

最後のアノテーションはリクエストパラメータ値をインジェクトします。

@RequestParameter
@RequestParameter("parameterName")

コンポーネント属性としてリクエストパラメータの値をインジェクトすることを指定します。 基本タイプの対話が自動的に行われます。

  • value — リクエストパラメータの名前を指定します。 デフォルトは、コンポーネント属性の名前になります。

10.3. コンポーネントのライフサイクルメソッドのためのアノテーション

これらのアノテーションはコンポーネントがライフサイクルイベントに反応することを可能にしています。 それらはコンポーネントメソッドで発生します。 それはコンポーネントクラスに 1 つだけかもしれません。

@Create
@Create

Seam によってコンポーネントインスタンスがインスタンス化されるとき、 メソッドが呼ばれることを指定します。 create メソッドは、JavaBean と ステートフルセッション Bean のみに対応していることに留意してください。

@Destroy
@Destroy

コンテキストが終了しコンテキスト変数が破棄されるとき、 メソッドが呼ばれるべきことを指定します。 create メソッドは、JavaBeans と ステートフルセッション Bean のみに 対応していることに留意してください。

注記: コンテキストが終了したとき、ステートフル Bean の破棄を保障するために、 すべてのステートフルセッション Bean コンポーネントには 間違いなく @Destroy @Remove アノテーション付きメソッドを定義してください。

Destroy メソッドはただクリーンアップのために使用されます。 Destroy メソッドから例外が伝播してきた場合、Seam は例外をキャッチし、ログ出力したうえで握りつぶします。

@Observer
@Observer("somethingChanged")

Specifies that 特定のタイプのコンポーネント駆動イベントが発生したとき、 メソッドが呼ばれることを指定します。

10.4. コンテキスト区分のためのアノテーション

これらのアノテーションは宣言的対話の区分を規定します。 これらは Seam コンポーネントのメソッド上に登場し、通常はアクションリスナメソッドです。

すべての WEB リクエストはそれに関連する対話的コンテキストを持っています。 ほとんどのこららの対話はリクエストの終わりで終了します。 複数のリクエストにわたる対話が必要であれば、@Begin を付けたメソッドを呼び出すことで、 長期対話(long-running conversation) に昇格させなければなりません。

@Begin
@Begin

このメソッドが例外ではなく null 以外の値を返した場合、 長期対話が開始することを指定します。

@Begin(ifOutcome={"success", "continue"})

このアクションメソッドリスナが所与の結果 (outcome) のひとつを返した場合、 長期対話が開始することを指定します。

@Begin(join=true)

長期対話が開始中の場合、 対話コンテキストは単に伝播されることを指定します。

@Begin(nested=true)

長期対話が開始中の場合、 新たなネストされた (nested) 対話的コンテキストが開始することを指定します。 次の@Endに出会うとき、 ネストされた対話は終了し、外側の対話は再開します。 同じ外側の対話において、複数のネストされた対話が同時に存在することは全く問題ありません。

@Begin(pageflow="process definition name")

対話のためのページフローを定義する jBPM プロセス定義の名前を定義します。

  • ifOutcome — JSF 結果 (outcome) あるいは、新たな長期対話的コンテキストの結果 (outcome) を指定します。

  • join — 長期対話が開始中のときの振る舞いを指定します。 trueであれば、コンテキストは伝播されます。 falseであれば、例外がスローされます。 デフォルトは falseです。 nested=trueであれば、設定は無視されます。

  • nested — 長期対話が開始されていれば、 ネストされた対話が開始されるべきことを指定します。

  • pagefloworg.jboss.seam.core.jbpm.pageflowDefinitions. によってデプロイされた jBPM プロセス定義のプロセス定義名です。

@End
@End

このメソッドが例外ではなく null 以外の値を返す場合、 長期対話が終了することを指定します。

@End(ifOutcome={"success", "error"}, evenIfException={SomeException.class, OtherException.class})

このアクションリスナメソッドが既存の結果 (outcome) の 1 つを返すかあるいは、 例外の特定クラスの 1 つがスローされた場合に、 長期対話は終了することを指定します。

  • ifOutcome — JSF 結果 (outcome) あるいは現在の長期対話の最後の結果 (outcome) を指定します。

@StartTask
@StartTask(taskIdParameter="taskId")

jBPM タスクを「開始」します。 このメソッドが例外ではなく null 以外の結果 (outcome) を返すとき、 長期対話を開始することを指定します。 この対話は指定されたリクエストパラメータ中で指定された jBPM タスクと関連しています。 この対話的コンテキスト中で、 タスクインスタンスのビジネスプロセスインスタンスのために、 ビジネスプロセスコンテキストも定義されます。

jBPM TaskInstance は、taskInstance という名前のリクエストコンテキスト変数中で利用可能になります。 jPBM ProcessInstance は、processInstance という名前のリクエストコンテテキスト変数中では利用可能になります。 (もちろん、これらのオブジェクトは、@In でインジェクションが使用可能です。)

  • taskIdParameter — タスクの ID を持つリクエストパラメータの名前です。 デフォルトは "taskId" です。 それはまた Seam taskList JSF コンポーネントでもデフォルトとして使用されます。

@BeginTask
@BeginTask(taskIdParameter="taskId")

不完全な jBPM タスクの処理を再開します。 このメソッドが例外ではなく null 以外の結果 (outcome) を返すとき、 長期対話を開始することを指定します。 この対話は指定されたリクエストパラメータ中で指定された jBPM タスクと関連しています。 この対話のコンテキストの中で、 タスクインスタンスのビジネスプロセスインスタンスのために、 ビジネスプロセスコンテキストもまた定義されます。

jBPM TaskInstance は 、taskInstance という名前のリクエストコンテキスト変数中で利用可能になります。 jPBM ProcessInstance は、 processInstance という名前のリクエストコンテテキスト変数中で利用可能になります。

  • taskIdParameter — タスクの ID を持つリクエストパラメータの名前。 デフォルトは "taskId" です。 それはまた Seam taskList JSF コンポーネントでもデフォルトとして使用されます。

@EndTask
@EndTask

jBPM タスクを「終了」します。 このメソッドが null ではない結果 (outcome) を返すとき、 長期対話は終了し、現在のタスクが完了したことを指定します。 jBPM トランジション (transition) を引き起こします。 アプリケーションが transition と呼ばれる組込みコンポーネントの Transition.setName() を呼ばない限り、 引き起こされる実際のトランザクションは、デフォルトのトランザクションです。

@EndTask(transition="transitionName")

既存の jBMP トランジションを引き起こします。

@EndTask(ifOutcome={"success", "continue"})

このメソッドがリストされた結果 (outcome) の 1 つを返すとき、タスクが終了することを指定します。

@CreateProcess
@CreateProcess(definition="process definition name")

メソッドが例外でない null 以外の結果 (outcome) を返すとき、新たな jBPM プロセスインスタンスを生成します。 ProcessInstance オブジェクトは、processInstance の名前のコンテキスト変数中で利用可能となります。

  • definitionorg.jboss.seam.core.jbpm.processDefinitions によってデプロイされた jBPM プロセス定義の名前。

@ResumeProcess
@ResumeProcess(processIdParameter="processId")

そのメソッドが例外以外の非 null 結果 (outcome) を返すとき、 既存の jBPM プロセスインスタンスのスコープに再入します。 ProcessInstance オブジェクトは 、 processInstance の名前のコンテキスト変数中で利用可能となります。

  • processIdParameter — プロセス ID を持つリクエストパラメータ名です。 デフォルトは "processId" です。

10.5. トランザクション区分のためのアノテーション

Seam は特定のアクションリスナの結果 (outcome) ために、 JTA トランザクションの ロールバックを強制するアノテーションを提供します。

@Rollback
@Rollback(ifOutcome={"failure", "not-found"})

メソッドの結果 (outcome) がリストされた結果 (outcome) のどれかにマッチした場合、 あるいは、結果 (outcome) がリストされた中になかった場合、 メソッドが完了するときに、トランザクションをロールバックオンリーに設定します。

  • ifOutcome — トランザクションロールバックを引き起こす JSF の結果 (outcome)です。 (どのような結果 (outcome) も意味のあるものして解釈されません。)

@Transactional
@Transactional

JavaBean コンポーネントに、 セッション Bean コンポーネントのデフォルトの振る舞いと同じトランザクションの振る舞いを、 持たせることを指定します。 例えば、メソッド呼び出しはトランザクション内で起こるべきであり、 メソッドが呼び出されたときに、トランザクションが存在しない場合、 トランザクションがそのメソッドのために開始されます。 このアノテーションはクラスレベルでもメソッドレベルでも適用可能です。

Seam アプリケーションは、他のトランザクション区分を使う必要があれば、通常標準の EJB3 のアノテーションを使用します。

10.6. データ妥当性検証のためのアノテーション

このアノテーションは Hibernate のデータ妥当性検証機能 (バリデータ) を呼び出します。 それは Seam コンポーネントのメソッドの上に、ほぼアクションリスナメソッドとして登場します。

Hibernate 妥当性検証 フレームワークにより定義されたアノテーションに関する情報は、 Hibernate アノテーションパッケージのドキュメントを参照してください。

@IfInvalid
@IfInvalid(outcome="invalid", refreshEntities=true)

メソッドの呼び出し前に、Hibernate バリデータがコンポーネントのデータ妥当性検証することを指定します。 呼び出しが失敗した場合、特定の結果 (outcome) が返され、 Hibernate バリデータから返されたデータ妥当性検証の失敗のメッセージが FacesContext に追加されます。 そうでなければ、呼び出しはそのまま進みます。

  • outcome — データ妥当性検証が失敗したときの、JSF の結果 (outcome) です。

  • refreshEntities — データ妥当性検証が失敗したとき、状態管理されている無効なエンティティは、 データベースから更新されることを指定します。 デフォルトは false です。(拡張永続コンテキストで有用です。)

10.7. Seam リモーティングのためのアノテーション

Seam リモーティングは、 以下のアノテーションを付けた セッション Bean のローカルインタフェースが必要です。

@WebRemote
@WebRemote

アノテーション付きのメソッドは クライアントサイドの JavaScript から呼ばれることを示しています。

10.8. Seam インターセプタのためのアノテーション

以下のアノテーションは、Seam インターセプタクラスに登場します。

EJB インターセプタ定義に必要なアノテーションに関する情報は EJB 3.0 仕様のドキュメントを参照してください。

@Around
@Around({SomeInterceptor.class, OtherInterceptor.class})

このインターセプタは既存のインターセプタよりスタック中で上位に位置づけられることを指定します。

@Within
@Within({SomeInterceptor.class, OtherInterceptor.class})

このインターセプタは既存のインターセプタよりスタックの中で下位に位置づけられることを指定します。

10.9. JSF dataTable を使用するためのアノテーション

以下のアノテーションはステートフルセッション Bean の機能に支えられたクリッカブルなリストの実装を容易にします。 それらは属性の上に登場します。

@DataModel
@DataModel("variableName")

ListMapSet 、また、Object[] タイプの属性を、 JSF の DataModel として、 所有するコンポーネントのスコープに入れることで公開します。 (あるいは、所有するコンポーネントが STATELESS の場合、 EVENT スコープ) Map の場合、 DataModel の各行は、Map.Entry になります。

  • value — 対話コンテキスト変数の名前。 デフォルトは属性名です。

  • scopescope=ScopeType.PAGE が明示的に指定された場合、 DataModelPAGE コンテキストに保持されます。

@DataModelSelection
@DataModelSelection

JSF DataModel から選択された値をインジェクトします。 ( これは、内在する Collection の要素、または Map の値です。 )

  • value — 対話コンテキスト変数の名前。 コンポーネントの中にただ1つ @DataModel があれば不要です。

@DataModelSelectionIndex
@DataModelSelectionIndex

JSF の DataModel の選択されたインデックスをコンポーネントの属性として公開します。 ( これは、内在する Collection の行番号、または Map のキーです。 )

  • value — 対話コンテキスト変数の名前。 コンポーネントの中にちょうど1つ @DataModel があれば不要です。

10.10. データバインディングのためのメタアノテーション

これらのメタアノテーションは、リストは別として他のデータベース構造のために、 @DataModel または、@DataModelSelection と同様な機能の実装を可能にします。

@DataBinderClass
@DataBinderClass(DataModelBinder.class)

アノテーションがデータバインディングのアノテーションであることを指定します。

@DataSelectorClass
@DataSelectorClass(DataModelSelector.class)

アノテーションがデータ選択 (dataselection) のアノテーションであることを指定します。