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

Toshihiro Nakamura [E-MAIL ADDRESS DELETED]
2011年 10月 10日 (月) 04:29:37 JST


中村(taedium)です。

> クライアントからリクエストが来た際、ActionをgetComponentによって取得する
> のですが、同じタイミングでService/DAOもインスタンス化されることを
> 確認しました。

「getComponentによって取得する」とありますが、これは、
net.arnx.jsonic.web.extension.S2ContainerクラスのgetComponentメソッド
の中で行われる処理を指しているのでしょうか?
アプリケーションで行っている処理を指しているのかJSONICによる処理を
指しているのかわかりませんでした。

SelectDataSourceInterceptorはS2コンテナに登録できていますか?
SMART deployを使って登録するのであれば、
SelectDataSourceInterceptorが「ルートパッケージ名.interceptor」という
名前のパッケージに配置されていることを確認してください。
さらに、creator.diconに次の記述があることを確認してください。
<component class="org.seasar.framework.container.creator.InterceptorCreator"/>

creator.diconで以下の記述はされていますか?
<component class="org.seasar.framework.container.creator.ActionCreator"/>
この記述がないと、customizer.diconのactionCustomizerの設定が反映されません。
(ActionをSMART deployで登録しているのであれば記述されているはずですが)

> しかし、Interceptorが実行されず、DAOにてConfigからDatasourceNameを取得
> できないというエラーが発生してしまいました。

念のために、Interceptorは実行されているけれども
DatasourceNameにnullが設定されることでエラーが発生している、
という可能性はないか確認してみるとよいかもしれません。

> Interceptorは、コンストラクタ(getComponent)の前に実行させることが
> できないのでしょうか?

Interceptorを使うと特定のメソッド呼び出しの前後で任意の処理を実行できます。
今回やりたいことはまさにそれだと思います(Actionのメソッドの前後で処理をする)。
コンストラクタとgetComponentは別物ですし、それらの前に実行させるというの
とはちがうんじゃないでしょうか。

要件に対して、現在やろうとしていることの方向性はまちがっていないと思います。
何らかの理由で、InterceptorがActionに適用されていないようですが
適切に設定すれば解決できると思います。

2011年10月9日22:00  <[E-MAIL ADDRESS DELETED]>:
> はじめまして。
> 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 mailing list
> [E-MAIL ADDRESS DELETED]
> https://ml.seasar.org/mailman/listinfo/seasar-user
>



-- 
Toshihiro Nakamura


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