Seam アプリケーションを記述する場合、数多くのアノテーションを使用することになります。 Seam ではアノテーションを使用して宣言的なプログラミングを実現することができます。使用するアノテーションのほとんどは EJB 3.0 仕様で定義されています。データ検証用のアノテーションは Hibernate Validator パッケージで定義されています。そして、 Seam は Seam 独自のアノテーションセットを持っており、これについてはこの章で説明します。
すべての Seam のアノテーションはパッケージ org.jboss.seam.annotations で定義されます。
アノテーションの最初のグループは、 Seam コンポーネントを定義するものです。これらのアノテーションはコンポーネントクラスで使われます。
@Name("componentName")
クラスに対して Seam コンポーネント名を定義します。 Seam のコンポーネントにはこのアノテーションが必須です。
@Scope(ScopeType.CONVERSATION)
コンポーネントのデフォルトコンテキストを定義します。 選択可能な値は ScopeType 列挙型で定義されています: EVENT, PAGE, CONVERSATION, SESSION, BUSINESS_PROCESS, APPLICATION, STATELESS。
スコープが明示的に指定されていない場合、 デフォルトはコンポーネントタイプにより異なってきます。 ステートレスセッション Bean の場合、 デフォルトは STATELESS になります。 エンティティ Bean およびステートフルセッション Bean なら、 デフォルトは CONVERSATION になり、 JavaBeans のデフォルトは EVENT になります。
@Role(name="roleName", scope=ScopeType.SESSION)
Seam コンポーネントを複数のコンテキスト変数にバインドできるようにします。 @Name/@Scope アノテーションは「デフォルトロール」を定義します。 各 @Role アノテーションは「追加ロール」の定義となります。
name — コンテキスト変数名です。
scope — コンテキスト変数スコープです。 スコープが明示的に指定されない場合、 デフォルトは上記のとおりコンポーネントタイプにより異なります。
@Roles({ @Role(name="user", scope=ScopeType.CONVERSATION), @Role(name="currentUser", scope=ScopeType.SESSION) })
複数の追加ロールを指定することができるようになります。
@Intercept(InterceptionType.ALWAYS)
Seam インターセプタをいつアクティブにするかを指定します。 選択可能な値は InterceptionType 列挙型で定義されます: ALWAYS, AFTER_RESTORE_VIEW, AFTER_UPDATE_MODEL_VALUES, INVOKE_APPLICATION, NEVER。
インターセプタタイプが明示的に指定されない場合、 デフォルトはコンポーネントタイプにより異なります。 エンティティ Bean の場合、 デフォルトは NEVER になります。 セッション Bean、 メッセージ駆動型 Bean および JavaBeans ならデフォルトは ALWAYS になります。
@JndiName("my/jndi/name")
Seam が EJB コンポーネントのルックアップに使用する JNDI 名を指定します。 JNDI 名が明示的に指定されない場合、 Seam は org.jboss.seam.core.init.jndiPattern で指定される JNDI パターンを使用します。
@Conversational(ifNotBegunOutcome="error")
対話スコープのコンポーネントが対話形式であることを指定します。 つまり、 このコンポーネントで開始される長期の対話がアクティブでない限り (メソッドが新規の長期対話を開始しない限り) コンポーネントのメソッドは呼び出すことができないということです。
@Startup(depends={"org.jboss.core.jndi", "org.jboss.core.jta"})
アプリケーションスコープのコンポーネントが、初期化時に直ちに開始されることを指定します。 主に、 JNDI、 データソースなどの重要なインフラストラクチャをブートストラップする特定の組み込みコンポーネントに使用されます。
@Startup
セッションスコープのコンポーネントが、セッション作成時に直ちに開始されることを指定します。
depends — 指定されたコンポーネントがインストールされている場合はそのコンポーネントを先に開始されなければならないことを指定します。
@Install(false)
コンポーネントがデフォルトでインストールされる必要があるかどうかを指定します。 @Install アノテーションが無い場合、コンポーネントはインストールが必要であるという意味になります。
@Install(dependencies="org.jboss.seam.core.jbpm")
コンポーネントが、依存関係として指定されるコンポーネントがインストールされる場合にのみインストールされることを指定します。
@Install(genericDependencies=ManagedQueueSender.class)
コンポーネントが、 特定のクラスにより実装されるコンポーネントがインストールされる場合にのみインストールされることを指定します。 依存するコンポーネントの名前が不定である場合に便利です。
@Install(classDependencies="org.hibernate.Session")
コンポーネントが、指定されたクラスがクラスパス内にある場合にのみインストールされることを指定します。
@Install(precedence=BUILT_IN)
そのコンポーネントの優先度を指定します。 同じ名前のコンポーネントが複数存在する場合、 より高い優先度を持つコンポーネントがインストールされます。 定義される優先度の値は次のとおりです (昇順) :
BUILT_IN — すべての組み込み Seam コンポーネントが持つ優先度
FRAMEWORK — Seam を拡張するフレームワークのコンポーネントに対して使用する優先度
APPLICATION — アプリケーションコンポーネントの優先度 (デフォルトの優先度)
DEPLOYMENT — 特定のデプロイメントにおいてアプリケーションコンポーネントを上書きするコンポーネントに対して使用する優先度
MOCK — テストで使用される Mock オブジェクトの優先度
@Synchronized(timeout=1000)
コンポーネントが複数のクライアントによって同時にアクセスされること、 Seam はリクエストをシリアライズすることを指定します。 リクエストが特定のタイムアウト期間内にコンポーネントでロックを取得できないと例外が発生します。
@ReadOnly
JavaBean コンポーネントまたはコンポーネントメソッドが呼び出しの終わりで状態の複製を必要としないことを指定します。
次の 2 つのアノテーションはバイジェクションを制御します。 これらの属性はコンポーネントインスタンス変数またはプロパティのアクセサメソッドに指定できます。
@In
コンポーネントの属性が各コンポーネント呼び出しの開始時にコンテキスト変数からインジェクトされることを指定します。 コンテキスト変数が null の場合、 例外が発生します。
@In(required=false)
コンポーネントの属性が各コンポーネント呼び出しの開始時にコンテキスト変数からインジェクトされることを指定します。 コンテキスト変数は null でも構いません。
@In(create=true)
コンポーネント属性がコンポーネント呼び出しの開始時にコンテキスト変数からインジェクトされることを指定します。
@In(value="contextVariableName")
アノテーションを付けられたインスタンス変数名を使用せず、 コンテキスト変数名を明示的に指定します。
@In(value="#{customer.addresses['shipping']}")
コンポーネント属性が各コンポーネント呼び出しの開始時に JSF EL 式を評価することでインジェクトされることを指定します。
value — コンテキスト変数名を指定します。 デフォルトはコンポーネントの属性名です。 あるいは、 #{...} で括られた JSF EL 式を指定します。
create — コンテキスト変数がすべてのコンテキストで定義されていない (null) 場合に Seam がコンテキスト変数と同じ名前でコンポーネントをインスタンス化することを指定します。 デフォルトは false です。
required — コンテキスト変数がすべてのコンテキストで定義されていない場合に Seam が例外を発生させることを指定します。
@Out
Seam コンポーネントであるコンポーネントの属性が呼び出しの終わりでそのコンテキスト変数にアウトジェクトされることを指定します。 属性が null の場合、 例外が発生します。
@Out(required=false)
Seam コンポーネントであるコンポーネントの属性が呼び出しの終わりでそのコンテキスト変数にアウトジェクトされることを指定します。 属性は null でも構いません。
@Out(scope=ScopeType.SESSION)
Seam コンポーネントタイプではないコンポーネントの属性が呼び出しの終わりで特定スコープにアウトジェクトされることを指定します。
明示的にスコープが指定されていない場合、 代わりに @Out 属性を持つコンポーネント自体のスコープが使用されます (またはコンポーネントがステートレスであれば EVENT) 。
@Out(value="contextVariableName")
アノテーションを付けられたインスタンス変数名を使用せず、 コンテキスト変数名を明示的に指定します。
value — コンテキスト変数名を指定します。 デフォルトはコンポーネントの属性名です。
required — アウトジェクションを行ったときにコンポーネント属性が null だった場合、 Seam が例外を発生させることを指定します。
これらのアノテーションは同時に利用されます。 例:
@In(create=true) @Out private User currentUser;
次のアノテーションは マネージャコンポーネント パターンをサポートします。 このアノテーションは、インジェクトされる他のいくつかのクラスのインスタンスのライフサイクルを管理する Seam コンポーネントで利用され、コンポーネントの getter メソッドに付与されます。
次のアノテーションは ファクトリコンポーネント パターンをサポートします。 Seam コンポーネントはコンテキスト変数の値の初期化を行います。 特に非 Faces リクエストに対するレスポンスのレンダリングに必要なあらゆる状態の初期化に便利です。 コンポーネントメソッドで指定されます。
@Factory("processInstance")
コンテキスト変数に値がない場合に、 このコンポーネントのメソッドが指定コンテキスト変数の値の初期化に使用されることを指定します。 このスタイルは void を返すメソッドと併用します。
@Factory("processInstance", scope=CONVERSATION)
コンテキスト変数に値がない場合、 Seam が指定コンテキスト変数の値の初期化に使用する値をこのメソッドが返すことを指定します。 このスタイルは値を返すメソッドと併用します。 明示的にスコープが指定されていない場合、 @Factory メソッドを持つコンポーネント自体のスコープが使用されます (そのコンポーネントがステートレスではない場合。 コンポーネントがステートレスである場合はEVENT コンテキストが使用される) 。
value — コンテキスト変数名を指定します。 メソッドが getter メソッドなら、 デフォルトは JavaBeans プロパティ名となります。
scope — Seam が返された値をバインドする先のスコープを指定します。 値を返すファクトリメソッドに対してしか意味がありません。
Log をインジェクトするアノテーション:
最後のアノテーション、リクエストパラメータ値のインジェクト:
これらのアノテーションにより、 コンポーネントがそのコンポーネント自体のライフサイクルイベントに対して反応することができるようになります。 各コンポーネントクラスごとにそれぞれ 1 つのアノテーションのみ定義できます。
@Create
コンポーネントのインスタンスが Seam によってインスタンス化されたときに呼び出されるメソッドを指定します。 create メソッドは JavaBeans およびステートフルセッション Bean に対してしかサポートされないので注意してください。
@Destroy
コンテキストが終了し、そのコンテキスト変数が破棄されるときの呼び出されるメソッドを指定します。 destroy メソッドは JavaBeans およびステートフルセッション Bean に対してしかサポートされないので注意してください。
コンテキストが終了したときにステートフル Bean を必ず破棄するようにするため、 すべてのステートフルセッション Bean コンポーネントには @Destroy @Remove アノテーションを付けたメソッドを定義するようにしてください。
Destroy メソッドはクリーンアップにのみ使用するようにしてください。 Seam は destroy メソッドから伝播する例外はすべてキャッチしてログを出力し、捨ててしまいます。
@Observer("somethingChanged")
指定されたタイプのコンポーネント駆動イベントが発生すると、このメソッドが呼び出されます。
@Observer(value="somethingChanged",create=false)
指定されたタイプのイベントが発生するとこのメソッドが呼び出されますが、 インスタンスが存在しない場合はインスタンスを作成しないことを指定します。 インスタンスが存在せず create が false の場合は、 そのイベントは捕捉されません。 create のデフォルト値は true です。
これらのアノテーションは宣言的対話の境界を設定します。 これらは Seam コンポーネントのメソッド上、通常はアクションリスナメソッドに付与されます。
すべての WEB リクエストはそれに関連する対話的コンテキストを持っています。 ほとんどの対話はリクエストの終了と同時に終了します。 複数のリクエストにわたる対話が必要であれば、@Begin を付けたメソッドを呼び出すことで、 長期対話に昇格させなければなりません。
@Begin
このメソッドが例外および null 以外の outcome を返したら長期対話が開始することを指定します。
@Begin(ifOutcome={"success", "continue"})
このアクションリスナメソッドが指定された outcome を返したら長期対話が開始することを指定します。
@Begin(join=true)
長期対話がすでに開始されている場合、 対話コンテキストが単に伝播されることを指定します。
@Begin(nested=true)
長期対話がすでに開始されている場合、 新たにネストされた対話コンテキストが開始することを指定します。 次の @End が出現したときにネストされた対話が終了し、 外側の対話が再開します。 同じ外側の対話において、 複数のネストされた対話が同時に存在することは全く問題ありません。
@Begin(pageflow="process definition name")
この対話のためのページフローを定義する jBPM プロセス定義の名前を定義します。
@Begin(flushMode=FlushModeType.MANUAL)
Seam 管理の永続コンテキストのフラッシュモードを指定します。 flushMode=FlushModeType.MANUAL は atomic conversations をサポートします。 この場合、 flush () (通常、 対話終了時に呼び出される) の明示的なコールが起きるまで、 すべての書き込み動作は対話コンテキスト内にキューイングされます。
ifOutcome — 新しい長期対話コンテキストとなるJSF outcome (s) を指定します。
join — 長期対話がすでに開始されている場合の動作を指定します。 true であれば、 コンテキストは伝播されます。 false であれば、 例外が発生します。 デフォルトは false です。 nested=true が指定される場合は、 この設定は無視されます。
nested — 長期対話がすでに開始されている場合、 ネストされた対話が開始されることを指定します。
flushMode — この対話で作成される Seam 管理の Hibernate セッション、または JPA 永続コンテキストのフラッシュモードをセットします。
pageflow — org.jboss.seam.core.jbpm.pageflowDefinitions. によってデプロイされた jBPM プロセス定義のプロセス定義名です。
@End
このメソッドが例外および null 以外の outcome を返す場合、 長期対話が終了することを指定します。
@End(ifOutcome={"success", "error"}, evenIfException={SomeException.class, OtherException.class})
このアクションリスナメソッドが指定された outcome の 1 つを返すか、あるいは指定された例外の 1 つをスローする場合に、 長期対話が終了することを指定します。
ifOutcome — JSF 結果あるいは現在の長期対話の終了となるような結果を指定します。
beforeRedirect — デフォルトでは、 なんらかのリダイレクトが発生するまで対話は実際には破棄されません。 beforeRedirect=true と設定すると、 現在のリクエストの終了で対話が破棄され、 リダイレクトが新しいテンポラリ対話コンテキストで処理されるよう指定することになります。
@StartTask
jBPM タスクを「開始」します。 このメソッドが例外および null 以外の outcome を返すとき、 長期対話を開始することを指定します。 この対話は指定のリクエストパラメータ中で指定される jBPM タスクと関連しています。 この対話のコンテキスト内で、 タスクインスタンスのビジネスプロセスインスタンスに対して、 ビジネスプロセスコンテキストも定義されます。
jBPM TaskInstance は、 taskInstance という名前のリクエストコンテキスト変数として利用可能となります。 jBPM ProcessInstance は、 processInstance という名前のリクエストコンテキスト変数として利用可能です。 (もちろん、これらのオブジェクトは @In でインジェクションが可能です。)
taskIdParameter — タスクの ID を持つリクエストパラメータの名前です。 デフォルトは literal>"taskId"
flushMode — この対話で作成される Seam 管理の Hibernate セッション、または JPA 永続コンテキストのフラッシュモードをセットします。
@BeginTask
完了していない jBPM タスクの処理を再開します。 このメソッドが例外および null 以外の outcome を返すとき、 長期対話が開始することを指定します。 この対話は指定のリクエストパラメータ中で指定される jBPM タスクと関連しています。 この対話のコンテキスト内で、 タスクインスタンスのビジネスプロセスインスタンスに対して、 ビジネスプロセスコンテキストも定義されます。
jBPM TaskInstance は 、 taskInstance という名前のリクエストコンテキスト変数として利用可能になります。 jBPM ProcessInstance は、 processInstance という名前のリクエストコンテキスト変数として利用できます。
taskIdParameter — タスクの ID を持つリクエストパラメータの名前です。 デフォルトは literal>"taskId"
flushMode — この対話で作成される Seam 管理の Hibernate セッション、または JPA 永続コンテキストのフラッシュモードをセットします。
@EndTask
jBPM タスクを「終了」します。 このメソッドが null 以外の結果を返すとき、 長期対話は終了し、 現在のタスクが完了することを指定します。 jBPM トランジションを引き起こします。 アプリケーションが transition と呼ばれる組込みコンポーネントの Transition.setName () を呼んでいない限り、 引き起こされる実際のトランジッションはデフォルトのトランザクションになります。
@EndTask(transition="transitionName")
指定された jBPM トランジションを引き起こします。
@EndTask(ifOutcome={"success", "continue"})
このメソッドが指定された outcome のいずれかを返すとき、タスクが終了することを指定します。
transition — タスクが終了するときに引き起こされる jBPM トランジションの名前です。 省略された場合はデフォルトトランジションとなります。
ifOutcome — タスクを終了させる JSF outcome を指定します。
beforeRedirect — デフォルトでは、 なんらかのリダイレクトが発生するまで対話は実際には破棄されません。 beforeRedirect=true と設定すると、 現在のリクエストの終了で対話が破棄され、 リダイレクトが新しいテンポラリ対話コンテキストで処理されるよう指定することになります。
@CreateProcess(definition="process definition name")
メソッドが例外および null 以外の outcome を返すとき、 新しい jBPM プロセスインスタンスを作成します。 ProcessInstance オブジェクトは processInstance というコンテキスト変数として使用できます。
definition — org.jboss.seam.core.jbpm.processDefinitions によってデプロイされる jBPM プロセス定義の名前です。
@ResumeProcess(processIdParameter="processId")
メソッドが例外または null 以外の outcome を返すとき、 既存の jBPM プロセスインスタンスのスコープに再度入ります。 ProcessInstance オブジェクトは processInstance というコンテキスト変数で使用できます。
processIdParameter — プロセス ID を持つリクエストパラメータ名です。 デフォルトは "processId" です。
Seam は特定のアクションリスナの outcome に対すて JTA トランザクションのロールバックを強制するアノテーションを提供します。
@Rollback(ifOutcome={"failure", "not-found"})
メソッドの結果が指定された outcome のいずれかと一致する場合、 あるいは outcome を指定していない場合、 メソッドが完了したときにトランザクションがロールバックされるよう設定されます。
ifOutcome — トランザクションロールバックを引き起こす JSF の outcome です。 (outcome を指定しない場合、全ての outcome が指定されたものと解釈されます。)
@Transactional
JavaBean コンポーネントにセッション Bean コンポーネントのデフォルト動作と同じようなトランザクション動作を持たせることを指定します。 例えば、 メソッド呼び出しはトランザクション内で起こるべきであり、 メソッドが呼び出されたときにトランザクションが存在しない場合は、 トランザクションがそのメソッドのためだけに開始されます。 このアノテーションはクラスレベルでもメソッドレベルでも適用可能です。
Seam アプリケーションは通常、 トランザクション境界については標準の EJB3 のアノテーションを使用します。
これらのアノテーションにより Seam コンポーネントから伝播する例外を処理する方法を指定することができます。
@Redirect(viewId="error.jsp")
このアノテーション付いている例外は、指定されたビュー ID にブラウザをリダイレクトします。
viewId — リダイレクトする JSF ビュー ID です。
message — 表示するメッセージです。 デフォルトはその例外のメッセージです。
end — 長期対話が終了するよう指定します。 デフォルトは false です。
@HttpError(errorCode=404)
このアノテーションが付いている例外は、 HTTP エラーが送信されます。
errorCode — HTTP エラーコードです。 デフォルトは 500 です。
message — HTTP エラーで送信されるメッセージです。 デフォルトはその例外のメッセージです。
end — 長期対話が終了するよう指定します。 デフォルトは false です。
このアノテーションは Hibernate Validator を起動します。 Seam コンポーネントのメソッド、主にアクションリスナメソッドに付与されます。
Hibernate Validator フレームワークにより定義されたアノテーションに関する詳細は、 Hibernate Annotations パッケージのドキュメントを参照してください。
@IfInvalid の使用はほぼ廃止予定になっており、 現在は <s:validateAll> の使用を推奨しているので注意してください。
@IfInvalid(outcome="invalid", refreshEntities=true)
メソッドが呼び出される前に Hibernate Validator がコンポーネントを検証するよう指定します。 呼び出しが失敗した場合、 指定された outcocme が返され、 Hibernate Validator から返される検証失敗のメッセージが FacesContext に追加されます。 これ以外は、 呼び出しは続行されます。
outcome — 検証が失敗したときの JSF の outcome です。
refreshEntities — 検証が失敗したときに、 状態管理されている無効なエンティティは、 データベースの値でリフレッシュされます。 デフォルトは false です。 (拡張永続コンテキストで有用です。)
Seam Remotingは、 以下のアノテーションを付けた セッション Bean のローカルインタフェースが必要です。
以下のアノテーションは、Seam インターセプタクラスで使われます。
EJB インターセプタ定義に必要なアノテーションに関する詳細は EJB 3.0 仕様のドキュメントを参照してください。
@Interceptor(stateless=true)
このインターセプタはステートレスであることを指定するので、 Seam は複製処理を最適化することができます。
@Interceptor(type=CLIENT)
このインターセプタは EJB コンテナより前に呼ばれる「クライアントサイド」インターセプタであることを指定します。
@Interceptor(around={SomeInterceptor.class, OtherInterceptor.class})
このインターセプタは特定のインターセプタよりスタック内でより高い位置に配置されることを指定します。
@Interceptor(within={SomeInterceptor.class, OtherInterceptor.class})
このインターセプタは特定のインターセプタよりスタック内でより深い位置に配置されることを指定します。
次のアノテーションは非同期メソッドの宣言に使用されます。 例:
@Asynchronous public void scheduleAlert(Alert alert, @Expiration Date date) { ... }
@Asynchronous public Timer scheduleAlerts(Alert alert, @Expiration Date date, @IntervalDuration long interval) { ... }
@Asynchronous
メソッドコールは非同期で処理されることを指定します。
@Duration
非同期コールのパラメータが、 そのコールが処理されるまでの期間であることを指定します (または反復コールの場合は初めての処理が行われるまで) 。
@Expiration
非同期コールのパラメータが、 そのコールが処理される (または反復コールの場合は初めての処理が行われる) 日付と時刻であることを指定します。
@IntervalDuration
このアノテーションが付いている再帰呼び出しを行う非同期メソッドコールのパラメータが、 再帰呼び出し間の期間であることを指定します。
以下のアノテーションはステートフルセッション Bean を使ったクリッカブルリストの実装を容易にします。 これらのアノテーションは属性に付与されます。
@DataModel("variableName")
List、 Map、 Set、 Object[] のタイプの属性を JSF の DataModel として所有するコンポーネントのスコープで公開します。 (あるいは、所有するコンポーネントが STATELESS の場合は EVENT スコープとなります) 。 Map の場合、 DataModel の各行は、 Map.Entry になります。
value — 対話コンテキスト変数の名前です。 デフォルトは属性名です。
scope — scope=ScopeType.PAGE が明示的に指定される場合、 DataModel は PAGE コンテキストに保持されます。
@DataModelSelection
JSF DataModel から選択された値をインジェクトします。 ( これは、内在する Collection の要素、または Map の値です。)
value — 対話コンテキスト変数の名前です。 コンポーネントの中に @DataModel が一つだけの場合は不要です。
@DataModelSelectionIndex
JSF の DataModel の選択されたインデックスをコンポーネントの属性として公開します。 (これは、 Collection の行番号、または Map のキーとなります。)
value — 対話コンテキスト変数の名前です。 コンポーネントの中に @DataModel が一つだけの場合は不要です。
これらのメタアノテーションは、一覧とは別に他のデータベース構造に対して @DataModel や @DataModelSelection と同様の機能の実装を可能にします。
このアノテーションは、 一緒にパッケージングするコンポーネントセットに関する情報を宣言するメカニズムを提供します。 どの Java パッケージに対しても適用できます。
@Namespace(value="http://jboss.com/products/seam/example/seampay")
現在のパッケージにあるコンポーネントを特定のネームスペースに関連付けられることを指定します。 宣言されたネームスペースは components.xml ファイル内で XML ネームスペースとして使用することでアプリケーションの設定を単純化することができます。
@Namespace(value="http://jboss.com/products/seam/core", prefix="org.jboss.seam.core")
ネームスペースを特定のパッケージに関連付けるよう指定します。 また、 コンポーネント名のプレフィックスが XML ファイル内で指定されるコンポーネント名に適用されるよう指定します。 たとえば、 このネームスペースに関連付けられる microcontainer という XML エレメントは実際には org.jboss.seam.core.microcontainer というコンポーネントを参照するように解釈されます。