本稿執筆時(2004年2月)におけるJBoss 4の最新バージョンはJBoss 4.0.0DR2でしたが、その後、2004年3月25日にJBoss 4.0.0DR3がリリースされました。DR2からDR3の間に、JBoss AOPの仕様・実装に対して多くの修正が施された結果、DR2を対象に作成した3章サンプルプログラムがそのままではDR3上では動作しなくなってしまいました。
このページでは、最新版のJBoss AOPでサンプルプログラムを動作させたいという読者の方のために、DR3向けに修正した3章サンプルプログラムを提供し、DR2からDR3への変更情報を簡単にまとめます。
DR3ではAOPモジュールをデプロイするのに、(1)JBossサーバに対してホットデプロイする方法と、(2)PrecompileしたAOPモジュールを実行する、2つの方法が提供されています。後者のPrecompilerの方式を選択すれば、専用のクラスローダは要求されないので、TomcatやJBoss 3などの既存のサーバ上でもJBoss AOPを実行させることが可能になります。
しかし、DR3用のサンプルプログラムでは、JBoss上のトランザクションマネージャやデータベースを使った例ですので、(1)のJBossサーバにホットデプロイする方法を選択しました。(2)のPrecompileをする方式の例は、JBoss AOP 1.0Betaのチュートリアルにサンプルプログラムがたくさん用意されていますので、そちらを参考にしてください。
DR2:
import org.jboss.aop.*;=>
DR3:
import org.jboss.aop.advice.Interceptor; import org.jboss.aop.joinpoint.Invocation; import org.jboss.aop.joinpoint.MethodInvocation;
DR2:
public InvocationResponse invoke(Invocation invocation) throws Throwable=>
DR3:
public Object invoke(Invocation invocation) throws Throwable
DR2:
public InvocationResponse invoke(Invocation invocation) throws Throwable {
if (invocation.getType() == InvocationType.METHOD) {
MethodInvocation mi = (MethodInvocation) invocation;
...
=>DR3:
public Object invoke(Invocation invocation) throws Throwable {
MethodInvocation mi = (MethodInvocation) invocation;
...
注意: ここで明示的にgetNextValue()のようにメソッド名を指定することもできますが、DR2用のサンプルコードの設定に合わせてこのようにしています。
DR2:
<interceptor-pointcut class="sample.pojo.CounterImpl"
>
<interceptors>
<interceptor class="sample.aop.ProfileInterceptor"
>
</interceptor>
<interceptor class="sample.aop.TransactionInterceptor"
>
</interceptor>
<interceptor class="sample.aop.LockInterceptor"
>
</interceptor>
<interceptor class="sample.aop.PersistenceInterceptor"
>
</interceptor>
</interceptors>
</interceptor-pointcut>
=>DR3:
<bind pointcut="execution(public * sample.pojo.CounterImpl->*())">
<interceptor class="sample.aop.ProfileInterceptor"/>
<interceptor class="sample.aop.TransactionInterceptor"/>
<interceptor class="sample.aop.LockInterceptor"/>
<interceptor class="sample.aop.PersistenceInterceptor"/>
</bind>
DR2:
<class-metadata group="sample" class="sample.pojo.CounterImpl">
<default>
<trans-attribute>Supports</trans-attribute>
</default>
<method name="getNextValue">
<method-params>
</method-params>
<prof-attribute>true</prof-attribute>
</method>
<method name="getNextValue">
<method-params>
</method-params>
<trans-attribute>Required</trans-attribute>
</method>
</class-metadata>
=>DR3:
<annotation tag="tran" class="sample.pojo.CounterImpl"> <default> <trans-attribute>Supports</trans-attribute> </default> </annotation> <annotation tag="tran" class="sample.pojo.CounterImpl"> <method expr="long getNextValue()"> <trans-attribute>Required</trans-attribute> </method> </annotation> <annotation tag="profile" class="sample.pojo.CounterImpl"> <method expr="long getNextValue()"> <prof-attribute>true</prof-attribute> </method> </annotation>
/** * @@tran trans-attribute=Required * @@profile prof-attribute=true */
DR3では、アノテーションの処理にQDoxというツールを採用しています(将来的にはJDK 1.5のアノテーション機能を使うようにします)。JavaDoc上のアノテーションの指定は、(Antから起動可能な)アノテーションコンパイラによってmetadata-aop.xmlという別ファイルに生成されます。プログラマはインタセプタの宣言(<bind>)とアノテーションコンパイラによって生成されたアノテーションの宣言(<annotation>)をひとつのjboss-aop.xmlとしてまとめて記述します。
注意: JBossサーバにデプロイするときは、メタデータをAOPモジュールのMETA-INF/jboss-aop.xmlにまとめる必要がありますが、Precompiler方式では、織り込み済みのクラスを実行するときにjboss-aop.xmlとmetadata-aop.xmlを別々のファイルのまま扱うことができます。詳しくはjbossaop-1.0beta/docs/examples/metadata/build.xmlを参考にしてください。