matsukaz's blog

Agile, node.js, ruby, AWS, cocos2d-xなどなどいろいろやってます

Spring 2.x & Struts 1.3.x 連携 その2

上の実装は CreateAction を継承したクラスだったけど、せっかくの CoR パターンなので Command インタフェースを実装したクラスを組み込む方法も試してみました。
実装は以下な感じ。

public class AutowireObject extends ActionCommandBase {

  private Object lockObj = new Object();
  private WebApplicationContext webApplicationContext;
  private int autowireMode;
  private boolean dependencyCheck;

  @Override
  public boolean execute(ActionContext context) throws Exception {

    synchronized (lockObj) {
      if (webApplicationContext == null) {
        ServletActionContext saContext = (ServletActionContext) context;
        ActionServlet actionServlet = saContext.getActionServlet();
        ModuleConfig moduleConfig = context.getModuleConfig();

        webApplicationContext = initWebApplicationContext(actionServlet, moduleConfig);
        autowireMode = initAutowireMode(actionServlet, moduleConfig);
        dependencyCheck = initDependencyCheck(actionServlet, moduleConfig);
      }
    }

    Action action = context.getAction();
    if (action != null)
      webApplicationContext.getAutowireCapableBeanFactory().autowireBeanProperties(action, autowireMode, dependencyCheck);

    return false;
  }

  protected WebApplicationContext initWebApplicationContext(ActionServlet actionServlet, ModuleConfig moduleConfig) throws Exception {

    WebApplicationContext webApplicationContext = DelegatingActionUtils.findRequiredWebApplicationContext(actionServlet, moduleConfig);
    if (webApplicationContext instanceof ConfigurableApplicationContext)
      ((ConfigurableApplicationContext) webApplicationContext).getBeanFactory().ignoreDependencyType(ActionServlet.class);

    return webApplicationContext;
  }

  protected int initAutowireMode(ActionServlet actionServlet, ModuleConfig moduleConfig) {
    return DelegatingActionUtils.getAutowireMode(actionServlet);
  }

  protected boolean initDependencyCheck(ActionServlet actionServlet, ModuleConfig moduleConfig) {
    return DelegatingActionUtils.getDependencyCheck(actionServlet);
  }
}

Command インタフェースの実装ではなく、ActionCommandBase を継承したのは ActionContext へのキャストが面倒だったから。Command インタフェースの実装でも問題ないです。
適用手順は chain-config.xml の CreateAction の指定の次にこのクラスを指定するだけ。こっちの方が使いやすいかな。