SeamFramework.orgCommunity Documentation
SeamはJSFに替わるプレゼンテーション層のための手段としてWicketをサポートします。Seam上で動作するwicket
の例を見ていくことにしましょう。例は予約サンプルをWicketに移行させたものです。
WicketサポートはSeamにとって新しいものであり、それゆえJSFを使って実現可能ないくつかの機能を、Wicketを使ってまだ実現することができません(例えば、ページフロー)。またドキュメントはJSFを想定して書かれているため、Wicketサポートを使いこなすためには、ドキュメントの読み替えが必要になってくることに気づかれることでしょう。
Wicketサポートが提供する機能は、バイジェクションとオーケストレーションの二つに分類されます。これらについては、後で詳細に説明します。
Wicketアプリケーションを作成する際、通常、内部クラスを多用することになります。このような場合、コンポーネント木はコンストラクタ内で構築されることになります。Seamは内部クラスやコンストラクタ内でのアノテーションを用いた制御を完全にサポートします(通常のSeamコンポーネントとは異なります)。
アノテーションはすべての親クラスに対する呼び出しが終わった後で動作します。これは、this()
やsuper()
の中ではいかなる属性もインジェクションされていないということを意味します。
この点については改善を行っているところです。
内部クラスにおいてメソッドの呼び出しが行われる際、その内部クラスを内包するすべてのクラスでバイジェクションが行われます。これによって、バイジェクションのための変数をクラスに宣言しておいて、その内部クラスからバイジェクションされた変数を参照することが可能となります。
Seam上で動作するWicketアプリケーションでは、すべての標準的なSeamコンテキスト(EVENT
、CONVERSATION
、SESSION
、APPLICATION
、BUSINESS_PROCESS
)を完全に操作することが可能です。
WicketからSeamコンポーネントを操作するためにすることは、@In
を使ってインジェクションを行うことだけです。
@In(create=true)
private HotelBooking hotelBooking;
Wicketクラスは完全なSeamコンポーネントではありませんので、クラスに@Name
をつける必要はありません。
Wicketコンポーネントから、Seamコンテキストに対してオブジェクトをアウトジェクトすることも可能です。
@Out(scope=ScopeType.EVENT, required=false)
private String verify;
TODO ここはもう少し実際の用途に沿って書く
Wicketコンポーネントに対して@Restrict
アノテーションを使用することができます。このアノテーションはクラスに記述することも、その内部クラスに記述することもできます。@Restrict
が指定されると、コンポーネントは自動的にログインユーザーのみの使用に限定されます。value
属性にEL式を使うことで、限定方法を指定することもできます。詳しくは、章 15. セキュリティを参照して下さい。
例:
@Restrict
public class Main extends WebPage {
...
Seamは、制限を、自動的にその入れ子クラスに対しても適用します。
Wicketコンポーネントの中で、@Begin
や@End
を使用することにより、対話の境界を定めることができます。これらのアノテーションの使い方は、Seamコンポーネントの中で使うのと同じです。@Begin
や@End
は、すべてのメソッドで定義することができます。
ifOutcome
属性はサポートされません。
例:
item.add(new Link("viewHotel") {
@Override
@Begin
public void onClick() {
hotelBooking.selectHotel(hotel);
setResponsePage(org.jboss.seam.example.wicket.Hotel.class);
}
};
ユーザーの長期対話が有効な状態であっても、そこでは対話を使用せず、ただアクセスだけさせたいページもあるでしょう。そのような場合は、@NoConversationPage
アノテーションを使用することができます。
@Restrict @NoConversationPage(Main.class) public class Hotel extends WebPage {
アプリケーション内のクラス同士を疎結合にさせたい場合は、Seamイベントを使用することができます。もちろんEvents.instance().raiseEvent("foo")
のようにしてイベントを使用することもできますし、@RaiseEvent("foo")
のようにメソッドにアノテーションをつけることもできます。後者の場合、メソッドがnullでない結果 (outcome)を返し、例外が発生しない場合のみ、イベントが発生します。
Wicketクラスの中で@CreateProcess
、@ResumeTask
、@BeginTask
、@EndTask
、@StartTask
、@Transition
を使用して、タスクやプロセスの制御を行うことも可能です。
TODO - BPM制御を実装する - JBSEAM-3194
Seamは、WicketのクラスがSeamのアノテーションに対してインタセプトするためのバイトコード操作を行う必要があります。最初に決めるべきことは、そのバイトコード操作を実行時、アプリケーションの動作中に行うのか、それともコンパイル時に行うのかということです。前者の場合、ビルド環境について特に気をつけるべきことはありませんが、バイトコード操作が行われたクラスが最初にロードされる際のパフォーマンスが犠牲になります。後者の場合、パフォーマンスは犠牲になりませんが、ビルド環境に、バイトコード操作を行うための機能を統合する必要があります。
実行時バイトコード操作を行うためには、二つの方法があります。一つの方法は、バイトコード操作が行われるべきWicketコンポーネントをWAR内の特定のディレクトリに配置することで実現します。この方法を用いたくない、あるいは用いるのが不可能な場合には、バイトコード操作のためのエージェントを使用することもできます。この場合には、コンテナを起動する際のコマンドラインで、エージェントを指定する必要があります。
WAR内のWEB-INF/wicket
ディレクトリ以下に置かれたすべてのクラスは seam-wicket ランタイムによって自動的にバイトコード操作の対象となります。IDEやAntの設定を変更し、ビルド時の出力先を指定することによって、Wicketページやコンポーネントをここに配置するようにすることができます。
jarファイルjboss-seam-wicket.jar
は、Java Instrumentation APIを通じて、バイトコード操作のためのエージェントとして用いられます。それは、以下のステップで実現されます。
jboss-seam-wicket.jar
を絶対パス指定可能な位置に配置します。Java Instrumentation APIでは、エージェントライブラリの位置を指定する際に、相対パスを使用することはできません。
javaagent:/path/to/jboss-seam-wicket.jar
を、webアプリケーションコンテナを起動する際のコマンドラインオプションに追加します。
加えて、エージェントがバイトコード操作を行うべきパッケージを特定するための環境変数を追加する必要があります。これは、カンマ区切りの、複数パッケージ名のリストによって、指定します。
-Dorg.jboss.seam.wicket.instrumented-packages=my.package.one,my.other.package
パッケージAを指定した場合には、Aのサブパッケージにあるクラスすべてが対象となることに注意して下さい。次の指定によって、バイトコード操作を行うクラスをさらに限定することもできます。
-Dorg.jboss.seam.wicket.scanAnnotations=true
この指定の下では、@SeamWicketComponent
アノテーションをつけることによって、バイトコード操作可能なクラスを指定します。アノテーションについては項12.2.3. 「@SeamWicketComponent
アノテーション」を参照して下さい。
Seamは、Apache Ant、もしくはApache Mavenを通じて、コンパイル時バイトコード操作を行います。
Seamはjboss-seam-wicket-ant.jar
でAntタスクを提供します。Antタスクは以下のようにして使用します。
<!-- XML : generated by JHighlight v1.0 (http://jhighlight.dev.java.net) --> <span class="xml_tag_symbols"><</span><span class="xml_tag_name">taskdef</span><span class="xml_plain"> </span><span class="xml_attribute_name">name</span><span class="xml_tag_symbols">=</span><span class="xml_attribute_value">"instrumentWicket"</span><span class="xml_plain"> </span><br /> <span class="xml_plain"> </span><span class="xml_attribute_name">classname</span><span class="xml_tag_symbols">=</span><span class="xml_attribute_value">"org.jboss.seam.wicket.ioc.WicketInstrumentationTask"</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">classpath</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">pathelement</span><span class="xml_plain"> </span><span class="xml_attribute_name">location</span><span class="xml_tag_symbols">=</span><span class="xml_attribute_value">"lib/jboss-seam-wicket-ant.jar"</span><span class="xml_tag_symbols">/></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">pathelement</span><span class="xml_plain"> </span><span class="xml_attribute_name">location</span><span class="xml_tag_symbols">=</span><span class="xml_attribute_value">"web/WEB-INF/lib/jboss-seam-wicket.jar"</span><span class="xml_tag_symbols">/></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">pathelement</span><span class="xml_plain"> </span><span class="xml_attribute_name">location</span><span class="xml_tag_symbols">=</span><span class="xml_attribute_value">"lib/javassist.jar"</span><span class="xml_tag_symbols">/></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">pathelement</span><span class="xml_plain"> </span><span class="xml_attribute_name">location</span><span class="xml_tag_symbols">=</span><span class="xml_attribute_value">"lib/jboss-seam.jar"</span><span class="xml_tag_symbols">/></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">classpath</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_tag_symbols"></</span><span class="xml_tag_name">taskdef</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"></span><br /> <span class="xml_tag_symbols"><</span><span class="xml_tag_name">instrumentWicket</span><span class="xml_plain"> </span><span class="xml_attribute_name">outputDirectory</span><span class="xml_tag_symbols">=</span><span class="xml_attribute_value">"${build.instrumented}"</span><span class="xml_plain"> </span><span class="xml_attribute_name">useAnnotations</span><span class="xml_tag_symbols">=</span><span class="xml_attribute_value">"true"</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">classpath</span><span class="xml_plain"> </span><span class="xml_attribute_name">refid</span><span class="xml_tag_symbols">=</span><span class="xml_attribute_value">"build.classpath"</span><span class="xml_tag_symbols">/></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">fileset</span><span class="xml_plain"> </span><span class="xml_attribute_name">dir</span><span class="xml_tag_symbols">=</span><span class="xml_attribute_value">"${build.classes}"</span><span class="xml_plain"> </span><span class="xml_attribute_name">includes</span><span class="xml_tag_symbols">=</span><span class="xml_attribute_value">"**/*.class"</span><span class="xml_tag_symbols">/></span><span class="xml_plain"></span><br /> <span class="xml_tag_symbols"></</span><span class="xml_tag_name">instrumentWicket</span><span class="xml_plain"></span><br /> <span class="xml_tag_symbols">></span><span class="xml_plain"></span><br />
このAntタスクを実行した結果、バイトコード操作の行われたクラスは、${build.instrumented}
で指定されたディレクトリの下に配置されます。これらのクラスを、WEB-INF/classes
下にコピーするよう、Antを設定してやる必要があります。もし、Wicketコンポーネントをホットデプロイしたい場合は、これらのクラスをWEB-INF/dev
下にコピーすることもできます。ただし、Wicketコンポーネントをホットデプロイした場合は、WicketApplication
クラスもまたホットデプロイされることを確認して下さい。ホットデプロイされたクラスが再読み込みされることによって、WicketApplicationインスタンス全体も、配備されたページクラスの新しいリファレンスを獲得するために、再初期化される必要があります。
useAnnotations
属性を使用することで、Antタスクが@SeamWicketComponent
アノテーションによって指定されたクラスのみを対象とするようにすることができます。アノテーションについては項12.2.3. 「@SeamWicketComponent
アノテーション」を参照して下さい。
JBossのMavenレポジトリrepository.jboss.org
は、process-classes
mojoで動作するプラグインprocess-classes
を提供します。以下は、pom.xmlの設定例になります。
<!-- XML : generated by JHighlight v1.0 (http://jhighlight.dev.java.net) --> <span class="xml_tag_symbols"><</span><span class="xml_tag_name">build</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">plugins</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">plugin</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">groupId</span><span class="xml_plain"></span><br /> <span class="xml_tag_symbols">></span><span class="xml_plain">org.jboss.seam</span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">groupId</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">artifactId</span><span class="xml_plain"></span><br /> <span class="xml_tag_symbols">></span><span class="xml_plain">seam-instrument-wicket</span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">artifactId</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">version</span><span class="xml_plain"></span><br /> <span class="xml_tag_symbols">></span><span class="xml_plain">2.2.0</span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">version</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">configuration</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">scanAnnotations</span><span class="xml_plain"></span><br /> <span class="xml_tag_symbols">></span><span class="xml_plain">true</span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">scanAnnotations</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">includes</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">include</span><span class="xml_plain"></span><br /> <span class="xml_tag_symbols">></span><span class="xml_plain">your.package.name</span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">include</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">includes</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">configuration</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">executions</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">execution</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">id</span><span class="xml_plain"></span><br /> <span class="xml_tag_symbols">></span><span class="xml_plain">instrument</span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">id</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">phase</span><span class="xml_plain"></span><br /> <span class="xml_tag_symbols">></span><span class="xml_plain">process-classes</span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">phase</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">goals</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"><</span><span class="xml_tag_name">goal</span><span class="xml_plain"></span><br /> <span class="xml_tag_symbols">></span><span class="xml_plain">instrument</span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">goal</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">goals</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">execution</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">executions</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">plugin</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_plain"> </span><span class="xml_tag_symbols"></</span><span class="xml_tag_name">plugins</span><span class="xml_tag_symbols">></span><span class="xml_plain"></span><br /> <span class="xml_tag_symbols"></</span><span class="xml_tag_name">build</span><span class="xml_plain"></span><br /> <span class="xml_tag_symbols">></span><span class="xml_plain"></span><br />
上の例では、バイトコード操作は、includes
で指定されたクラスに限定されます。また、この例では、scanAnnotations
が指定されていますが、アノテーションについては項12.2.3. 「@SeamWicketComponent
アノテーション」を参照して下さい。
WEB-INF/wicket下に配置されたクラスは無条件にバイトコード操作の対象となります。それ以外の方法の場合、@SeamWicketComponent
アノテーションがつけられたクラスのみにバイトコード操作を適用することが可能です。このアノテーションは継承されます、すなわち、アノテーションをつけられたクラスのすべてのサブクラスもまたバイトコード操作の対象となります。以下は、その例です。
<!-- <br/> --><span class="java_keyword">import</span><!-- <br/> --><span class="java_plain"> org</span><!-- <br/> --><span class="java_separator">.</span><!-- <br/> --><span class="java_plain">jboss</span><!-- <br/> --><span class="java_separator">.</span><!-- <br/> --><span class="java_plain">seam</span><!-- <br/> --><span class="java_separator">.</span><!-- <br/> --><span class="java_plain">wicket</span><!-- <br/> --><span class="java_separator">.</span><!-- <br/> --><span class="java_plain">ioc</span><!-- <br/> --><span class="java_separator">.</span><!-- <br/> --><span class="java_type">SeamWicketComponent</span><!-- <br/> --><span class="java_separator">;</span> <!-- --><br/><span class="java_plain">@</span><span class="java_type">SeamWicketComponent</span> <!-- --><br/><span class="java_keyword">public</span><span class="java_plain"> </span><span class="java_keyword">class</span><span class="java_plain"> </span><span class="java_type">MyPage</span><span class="java_plain"> </span><span class="java_keyword">extends</span><span class="java_plain"> </span><span class="java_type">WebPage</span><span class="java_separator">{</span> <!-- --><br/><span class="java_plain"> </span><span class="java_separator">...</span> <!-- --><br/><span class="java_separator">}</span>
Seamの機能を使用するために、WicketのWebApplicationクラスはSeamWebApplication
クラスを継承する必要があります。これは、Wicketのライフサイクル中にフックを作成し、Seamが対話を自動的に伝播させていくために必要です。また、ページにステータスメッセージを付加します。
例:
SeamAuthorizationStrategy
は、Wicketコンポーネント上で@Restrict
の使用を可能にする、Seamセキュリティ機構のための認証を任されます。SeamWebApplication
クラスは、それを可能にします。クラスにgetLoginPage()
メソッドを実装することによって、認証のためのページを指定することができます。
また、クラスにgetHomePage()
メソッドを実装することによって、ホームページを指定することができます。
public class WicketBookingApplication extends SeamWebApplication {
@Override
public Class getHomePage() {
return Home.class;
}
@Override
protected Class getLoginPage() {
return Home.class;
}
}
Seamは自動的にWicketフィルタを設定します(適切な位置に挿入されます)が、WebApplication
クラスがどれなのかはWicketに指示する必要があります。
<components xmlns="http://jboss.com/products/seam/components"
xmlns:wicket="http://jboss.com/products/seam/wicket"
xsi:schemaLocation=
"http://jboss.com/products/seam/wicket
http://jboss.com/products/seam/wicket-2.2.xsd">
<wicket:web-application
application-class="org.jboss.seam.example.wicket.WicketBookingApplication" />
</components
加えて、もし同じアプリケーションの中で、JSFベースのページとWicketのページを併用する場合には、JSFの例外フィルタがJSFのURLにのみ作用するように設定する必要があります。
<components xmlns="http://jboss.com/products/seam/components"
xmlns:web="http://jboss.com/products/seam/web"
xmlns:wicket="http://jboss.com/products/seam/wicket"
xsi:schemaLocation=
"http://jboss.com/products/seam/web
http://jboss.com/products/seam/web-2.2.xsd">
<!-- Only map the seam jsf exception filter to jsf paths, which we identify with the *.seam path -->
<web:exception-filter url-pattern="*.seam"/>
</components
認証機構に関するさらに詳細な情報や、Application
クラスでオーバーライド可能なその他のメソッドに関しては、Wicketのドキュメントを参照して下さい。