SAStrutsとS2JDBCでの排他制御後の画面制御をhogeる

お蔵入りになったネタを放出。


SAStruts+S2JDBC排他制御が発生したときにvalidateとかと同じような感じで
メッセージを出そうかという話があって、
でもActionの方でExceptionをいちいちcatchするのは面倒くさいなあということ
になって、
こんなネタを考えてみた。

まずはメッセージキーと引数を持つアノテーションを作ります。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Excl {

  /** key */
  String key();

  /** 引数 */
  Arg arg0() default @Arg(key = "");

}


次に各Serviceでupdateメソッドを継承します。
このとき先程作ったアノテーションを付けます。

@Override
@Excl(key = "message1", arg0 = @Arg(key = "labels.id"))
public int update(User user){
  return super.update(user);
}


ほんでもって、serviceの実行時にinterceptorをかまし
OptimisiticLockExceptionがthrowされるた場合、OptimisticLockExceptionの代
わりに ActionMessagesExceptionをthrowします。
アノテーションの引数はActionMessagesExceptionの引数に使用します。

public class ExclInterceptor extends AbstractInterceptor {

  public Object invoke(MethodInvocation invocation) throws Throwable {

    Excl excl = invocation.getMethod().getAnnotation(Exclusive.class);

    if (excl != null) {
      try {
        return invocation.proceed();
      } catch (OptimisticLockException lockException) {
        if (excl.arg0().key() != null && !excl.arg0().key().equals("")) {
          throw new ActionMessagesException(excl.key(), mesArg0);
        } else {
          throw new ActionMessagesException(excl.key());
        }
      }
    } else {
      return invocation.proceed();
    }
  }
}

あとはcustomizer.diconに設定を追加しておくだけ。

<component name="serviceCustomizer"
  class="org.seasar.framework.container.customizer.CustomizerChain">
  <initMethod name="addCustomizer">
    <arg>traceCustomizer</arg>
  </initMethod>
  <initMethod name="addCustomizer">
    <arg>
      <component
        class="org.seasar.framework.container.customizer.TxAttributeCustomizer"/>
    </arg>
  </initMethod>
  <initMethod name="addCustomizer">
    <arg>
      <component
        class="org.seasar.framework.container.customizer.AspectCustomizer">
        <property name="interceptorName">"ExclInterceptor"</property>
      </component>
    </arg>
  </initMethod>
</component>

これでActionでいちいちtry-catchする必要が無くなります。
ただ、すべてのServiceでOverrideしなければいけませんが・・・。

結構これ面白いなと思っていたら、結局global-exceptionで一律でやっていいよ
という話になってお蔵入りしました。ショボーン