[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 メーリングリストの案内