[Seasar-user:21055] 【Doma】Seasar連携時の複数データソース動的切替方法について

[E-MAIL ADDRESS DELETED] [E-MAIL ADDRESS DELETED]
2011年 10月 9日 (日) 22:00:02 JST


はじめまして。
okudaと申します。

現在、Seasar2+Doma(+JSONIC REST Servlet)にて、開発を行なっております。
データ構造が同じでスキーマが異なるDBへ動的に切り替えてアクセスしたいので
すが、上手く動作しなく躓いております。
大変お手数ですが、ご教示いただけると幸いです。

【環境】
・JDK 1.6u27
・Tomacat 6.0.29
・Seasar2 2.4.44
・Doma 1.18.0
・JSONIC 1.2.7
・JDBC4 Postgresql Driver, Version 9.1-901

【要件】
・リクエストURIによって、接続するスキーマを動的に変更する
・DIを行う際はEJB3準拠で行う

【試した方法】
・Doma JPetStoreを参考に、demo.configパッケージのものをそのまま流用
(AppConfig,CommonsJdbcLogger,S2RequiresNewController,SqlFileRepositoryProxy)
DAOには、@Dao(config = AppConfig.class)アノテーションを付与しています。
・「同じ種類のデータソースを動的に切り替える」
http://s2container.seasar.org/2.4/ja/jdbc.html#DataSourceDynamicSwiching
を参考に、下記【作成ソース】のようにdiconおよびInterceptorを作成

【質問】
1.
Interceptor→Action→Service→DAOとDIを用いてアクセスしていくことを
想定しています。
クライアントからリクエストが来た際、ActionをgetComponentによって取得する
のですが、同じタイミングでService/DAOもインスタンス化されることを
確認しました。
しかし、Interceptorが実行されず、DAOにてConfigからDatasourceNameを取得
できないというエラーが発生してしまいました。
Interceptorは、コンストラクタ(getComponent)の前に実行させることが
できないのでしょうか?

2.
仮にできない場合、どのようなアプローチを取ることが好ましいのでしょうか?


【作成ソース】
[user1-jdbc.dicon および user2-jdbc.dicon]
(user2-jdbc.diconはuser2DataSourceとしてDataSourceImplを定義し、
 後は、下記user1-jdbc.diconと同じ)
<components namespace="jdbc">
  <include path="jta.dicon"/>
  <include path="jdbc-extension.dicon"/>

  <component name="user1DataSource"
     class="org.seasar.extension.dbcp.impl.DataSourceImpl"/>
  <component class="org.seasar.extension.jdbc.impl.BasicResultSetFactory"/>
  <component
class="org.seasar.extension.jdbc.impl.ConfigurableStatementFactory">
    <arg>
        <component
class="org.seasar.extension.jdbc.impl.BasicStatementFactory"/>
    </arg>
    <property name="fetchSize">100</property>
  </component>

  <!-- for PostgreSQL -->
  <component name="xaDataSource"
    class="org.seasar.extension.dbcp.impl.XADataSourceImpl">
    <property name="driverClassName">"org.postgresql.Driver"</property>
    <property name="URL">
        "jdbc:postgresql://localhost/TEST"
    </property>
    <property name="user">"user1"</property>
    <property name="password">"xxxx"</property>
  </component>
  <component name="connectionPool"
    class="org.seasar.extension.dbcp.impl.ConnectionPoolImpl">
    <property name="timeout">600</property>
    <property name="maxPoolSize">10</property>
    <property name="allowLocalTx">true</property>
    <destroyMethod name="close"/>
  </component>
</components>

[jdbc.dicon]
<components namespace="jdbc">
    <include path="user1-jdbc.dicon"/>
    <include path="user2-jdbc.dicon"/>

    <component name="dataSource"
class="org.seasar.extension.datasource.impl.SelectableDataSourceProxy"/>
    <component name="dataSourceFactory"
class="org.seasar.extension.datasource.impl.DataSourceFactoryImpl"/>
</components>

[SelectDataSourceInterceptor]
public class SelectDataSourceInterceptor implements MethodInterceptor {
    @Resource
    public DataSourceFactory dataSourceFactory;
    @Resource
    private HttpServletRequest request;

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        String currentName =
dataSourceFactory.getSelectableDataSourceName();
        try {
            String dataSourceName = getDataSourceName();
            dataSourceFactory.setSelectableDataSourceName(dataSourceName);
            return invocation.proceed();
        } finally {
            dataSourceFactory.setSelectableDataSourceName(currentName);
        }
    }

    public String getDataSourceName() {
        // request からURIを取得し、対象DataSource名("user1" or "user2")
        // を決定
    }
}

[customizer.dicon抜粋]
  <component name="actionCustomizer"
class="org.seasar.framework.container.customizer.CustomizerChain">
    <initMethod name="addAspectCustomizer">
      <arg>"selectDataSourceInterceptor"</arg>
    </initMethod>
    ....
  </component>


以上、よろしくお願いいたします。



Seasar-user メーリングリストの案内