2009年12月6日日曜日

コンテナ管理トランザクションであそぶ - (5/10) -

インターセプターを作成する

インターセプターを作成します。

Rollback.java
package com.mydomain.ejb;

import javax.interceptor.*;
import static com.mydomain.ejb.MessageUtil.*;

public class Rollback
{
    @AroundInvoke
    public Object action(InvocationContext ctx) throws Exception
    {
        Object[] params = ctx.getParameters();
        Message message = (Message)params[0];
        setLogMessage(message, ctx.getTarget().getClass(), ctx.getMethod().getName());
        
        Object retObj = ctx.proceed();                     
        
        doRollback(message);
        
        return retObj;
    }
}
同じクラスの同じメソッドであっても呼出される条件によってインターセプトが適用されない場合もあったので
SubActionImpl クラスの requiresNewInsert() メソッドのみにインターセプトを設定しています。
ejb-jar.xml
<ejb-jar version="3.0"
  xmlns="http://java.sun.com/xml/ns/javaee" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
                      http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd">
  <interceptors>
    <interceptor>
      <interceptor-class>com.mydomain.ejb.Rollback</interceptor-class>         
    </interceptor>
  </interceptors>
  <assembly-descriptor>
    <interceptor-binding>
      <ejb-name>subActionImpl</ejb-name>         
      <interceptor-class>com.mydomain.ejb.Rollback</interceptor-class>
      <method>
        <method-name>requiresNewInsert</method-name>
        <method-params>
          <method-param>com.mydomain.ejb.Message</method-param>
        </method-params>
      </method>
    </interceptor-binding>
  </assembly-descriptor>
</ejb-jar>
インターセプトされないメソッドの呼出し

EJBインスタンスを通して直接呼出される場合はインターセプトが適用されるようですが
メソッドの処理の中で呼出される場合にはインターセプトが 適用されないみたいでした。
今回の検証用Webアプリの例でいうとActionImplクラスのinsert()メソッドとdecorateInsert()メソッドは
regist()メソッドから呼出されるためインターセプトは適用されないようです。
(regist()メソッドはサーブレットから直接呼出されるのでインターセプトが適用できるようです。)
またSubActionImplクラスのinsert()メソッドとdecorateInsert()メソッドは
ActionImplクラスのregist()メソッドから直接呼出される場合にはインターセプトが適用されるようですが、
requiresNewInsert()メソッドの処理の中から呼出されたinsert()メソッド、
insert()メソッドの処理の中から呼出されたdecorateInsert()メソッドには インターセプトが適用されないようでした。