[Seasar-user:21067] Re: 【Doma】Seasar連携時の複数データソース動的切替方法について
.
[E-MAIL ADDRESS DELETED]
2011年 10月 12日 (水) 14:27:13 JST
返信ありがとうございます。
okudaです。
なるほど、threadlocalでしたか。
納得しました。
迅速な対応と回答に、改めて感謝いたします。
有り難うございました。
以上、よろしくお願いいたします。
2011/10/12 12:41 "Toshihiro Nakamura" <[E-MAIL ADDRESS DELETED]>:
> 中村(taedium)です。
>
> 確認ありがとうございました。
> 1.19.0として今週末あたりにリリースしたいと思います。
>
> > 例えば、対象とするデータソースが異なる2つのリクエストが同時に来た場合、
> > 僅かなタイミングで前者となったリクエストは、
> > 後者のデータソース名で取得しにいってしまうということはないのでしょうか?
>
> 結論から言えば、そういうことは起きません。
> DataSourceFactoryImplに設定されたデータソース名は
> java.lang.ThreadLocalで管理されているからです。
> つまり、リクエストごとに別の領域で管理されるので
> 競合しないというわけです。
>
> 2011年10月12日11:17 . <[E-MAIL ADDRESS DELETED]>:
> > 返信ありがとうございます。
> > okudaです。
> >
> >> 次のものをお使いください。
> > 動作確認したところ、無事2つのデータソースが切り替えて
> > アクセスしていることが確認できました。
> > 本当にありがとうございました。
> >
> > 最後に1点だけ確認したいことがあるのですが、よろしいでしょうか?
> > (
> http://s2container.seasar.org/2.4/ja/jdbc.html#DataSourceDynamicSwiching)
> > サンプルにあるSelectDataSourceInterceptorにて、
> > dataSourceFactory.setSelectableDataSourceName( "anyname" );
> > とDataSourceFactoryに対して名前を設定していますが、
> > 例えば、対象とするデータソースが異なる2つのリクエストが同時に来た場合、
> > 僅かなタイミングで前者となったリクエストは、
> > 後者のデータソース名で取得しにいってしまうということはないのでしょうか?
> > つまり、リクエストA.setSelectableDataSourceName("A") →
> > リクエストB.setSelectableDataSourceName("B")
> > →リクエストA.ActionExecute... → リクエストB.ActionExecute...
> > という状態が起こりえるのか、という点と、仮に起こりえる場合にS2やDomaが
> > それを吸収してくれるのか、という点が気になっています。
> > (検討違いな質問をしているようでしたら、すみません。)
> >
> > 以上、よろしくお願いいたします。
> >
> >
> > 2011年10月11日23:06 Toshihiro Nakamura <[E-MAIL ADDRESS DELETED]>:
> >> 中村(taedium)です。
> >>
> >>> 先のメールのSNAPSHOT版Domaを試してみたのですが、
> >>> やはり、DataSourceNameが取得できないとエラーとなってしまいます。
> >>
> >> すみません。情けないミスをしていました。
> >> SNAPSHOTを作り直しました。
> >> 次のものをお使いください。
> >>
> >>
> http://maven.seasar.org/maven2-snapshot/org/seasar/doma/doma/1.19.0-SNAPSHOT/doma-1.19.0-20111011.140035-2.jar
> >>
> >>
> >> 2011年10月11日13:39 . <[E-MAIL ADDRESS DELETED]>:
> >>> 返信ありがとうございます。
> >>> okuda です。
> >>>
> >>> ご回答ありがとうございました。
> >>> 自分の認識がそれ程ずれていなくて安心しました。
> >>>
> >>> 先のメールのSNAPSHOT版Domaを試してみたのですが、
> >>> やはり、DataSourceNameが取得できないとエラーとなってしまいます。
> >>>
> >>> 改めてデバッグ実行で追ってみたところ、
> >>>
> AnyTableDaoImplのコンストラクタから[doma...AbstractDao.]constructor(config)がコールされ、
> >>> その中のvalidateConfigにて、getDataSourceName == nullとなり、ConfigExceptionが
> >>> 発生していました。
> >>> RuntimeConfigのインスタンス化までは行っていると思っていたのですが、
> >>> 以前の1.18.0に戻しても、同じところでエラーとなっていましたので、
> >>> 私の勘違いだったのかもしれません。
> >>> (前述のDAOを利用するActionと利用しないActionで動きが異なるという点は変わりません。)
> >>> スタックトレースを転記いたします。
> >>> 他に何か必要な情報がありましたら、仰ってください。
> >>> 大変お手数ですが、お力添えを重ねてお願いいたします。
> >>>
> >>>
> >>> 【スタックトレース】
> >>> 2011-10-11 12:21:23,880 [http-8080-2] DEBUG
> >>> org.seasar.framework.container.hotdeploy.HotdeployBehavior - HOT
> >>> deployを開始します
> >>> 2011-10-11 12:21:23,896 [http-8080-2] WARN
> >>> org.seasar.framework.container.hotdeploy.HotdeployClassLoader - HOT
> >>>
> deploy対象クラス(xxx.package.exception.MyRuntimeException)が非対象クラスから参照されて通常のクラスローダにロードされています。
> >>> 2011-10-11 12:21:23,896 [http-8080-2] WARN
> >>> org.seasar.framework.container.hotdeploy.HotdeployClassLoader - HOT
> >>>
> deploy対象クラス(xxx.package.config.MyConfig)が非対象クラスから参照されて通常のクラスローダにロードされています。
> >>> 2011-10-11 12:21:23,896 [http-8080-2] WARN
> >>> org.seasar.framework.container.hotdeploy.HotdeployClassLoader - HOT
> >>> deploy対象クラス(xxx.package.log.MyLogger)が非対象クラスから参照されて通常のクラスローダにロードされています。
> >>> 2011-10-11 12:21:23,896 [http-8080-2] WARN
> >>> org.seasar.framework.container.hotdeploy.HotdeployClassLoader - HOT
> >>>
> deploy対象クラス(xxx.package.config.TenantData)が非対象クラスから参照されて通常のクラスローダにロードされています。
> >>> 2011-10-11 12:21:23,896 [http-8080-2] DEBUG
> >>> org.seasar.framework.container.util.S2ContainerUtil -
> >>>
> クラス(xxx.package.action.test.TestAction[test_testAction])のコンポーネント定義を登録します
> >>> 2011-10-11 12:21:23,927 [http-8080-2] DEBUG
> >>> org.seasar.framework.container.util.S2ContainerUtil -
> >>>
> クラス(xxx.package.service.test.TestService[test_testService])のコンポーネント定義を登録します
> >>> 2011-10-11 12:21:24,005 [http-8080-2] DEBUG
> >>> org.seasar.framework.container.util.S2ContainerUtil -
> >>>
> クラス(xxx.package.dao.base.impl.AnyTableDaoImpl[base_anyTableDao])のコンポーネント定義を登録します
> >>> 2011-10-11 12:21:34,240 [http-8080-2] ERROR
> >>> xxx.package.servlet.MyRESTServlet - Internal error occurred.
> >>> org.seasar.framework.beans.IllegalPropertyRuntimeException:
> >>>
> [ESSR0059]クラス(xxx.package.action.test.TestAction$$EnhancedByS2AOP$$8d1749)のプロパティ(testService)の設定に失敗しました。理由はorg.seasar.framework.beans.IllegalPropertyRuntimeException:
> >>>
> [ESSR0059]クラス(xxx.package.service.test.TestService$$EnhancedByS2AOP$$114a3c6)のプロパティ(anyTableDao)の設定に失敗しました。理由はorg.seasar.framework.exception.InvocationTargetRuntimeException:
> >>>
> [ESSR0043]xxx.package.dao.base.impl.AnyTableDaoImpl$$EnhancedByS2AOP$$17ccb2fが呼び出した対象が不正です。理由はorg.seasar.doma.jdbc.ConfigException:
> >>> [DOMA2035]
> org.seasar.doma.jdbc.Configの実装クラス[xxx.package.config.doma.DomaConfig]のメソッド[getDataSourceName]からnullが返されました。
> >>> at
> org.seasar.framework.container.assembler.AbstractBindingTypeDef.getValue(AbstractBindingTypeDef.java:297)
> >>> at
> org.seasar.framework.container.assembler.AbstractBindingTypeDef.bindAuto(AbstractBindingTypeDef.java:149)
> >>> at
> org.seasar.framework.container.assembler.BindingTypeMustDef.doBind(BindingTypeMustDef.java:45)
> >>> at
> org.seasar.framework.container.assembler.AbstractBindingTypeDef.bind(AbstractBindingTypeDef.java:91)
> >>> at
> org.seasar.framework.container.assembler.AccessTypeFieldDef.bind(AccessTypeFieldDef.java:50)
> >>> at
> org.seasar.framework.container.assembler.AccessTypeFieldDef.bind(AccessTypeFieldDef.java:42)
> >>> at
> org.seasar.framework.container.assembler.AutoPropertyAssembler.assemble(AutoPropertyAssembler.java:56)
> >>> at
> org.seasar.framework.container.deployer.RequestComponentDeployer.deploy(RequestComponentDeployer.java:67)
> >>> at
> org.seasar.framework.container.impl.ComponentDefImpl.getComponent(ComponentDefImpl.java:111)
> >>> at
> org.seasar.framework.container.impl.S2ContainerImpl.getComponent(S2ContainerImpl.java:129)
> >>> at
> xxx.package.servlet.container.extension.S2MyContainer.getComponent(S2MyContainer.java:28)
> >>> at net.arnx.jsonic.web.RESTServlet.doREST(RESTServlet.java:221)
> >>> at net.arnx.jsonic.web.RESTServlet.doPost(RESTServlet.java:141)
> >>> at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
> >>> at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
> >>> at
> org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
> >>> at
> org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
> >>> at
> org.seasar.framework.container.hotdeploy.HotdeployFilter.doHotdeployFilter(HotdeployFilter.java:99)
> >>> at
> org.seasar.framework.container.hotdeploy.HotdeployFilter.doFilter(HotdeployFilter.java:67)
> >>> at
> org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
> >>> at
> org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
> >>> at
> org.seasar.framework.container.filter.S2ContainerFilter.doFilter(S2ContainerFilter.java:79)
> >>> at
> org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
> >>> at
> org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
> >>> at
> org.seasar.extension.filter.EncodingFilter.doFilter(EncodingFilter.java:69)
> >>> at
> org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
> >>> at
> org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
> >>> at
> org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
> >>> at
> org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
> >>> at
> org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
> >>> at
> org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
> >>> at
> org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
> >>> at
> org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
> >>> at
> org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)
> >>> at
> org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
> >>> at
> org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
> >>> at java.lang.Thread.run(Thread.java:662)
> >>> Caused by: org.seasar.framework.beans.IllegalPropertyRuntimeException:
> >>>
> [ESSR0059]クラス(xxx.package.service.test.TestService$$EnhancedByS2AOP$$114a3c6)のプロパティ(anyTableDao)の設定に失敗しました。理由はorg.seasar.framework.exception.InvocationTargetRuntimeException:
> >>>
> [ESSR0043]xxx.package.dao.base.impl.AnyTableDaoImpl$$EnhancedByS2AOP$$17ccb2fが呼び出した対象が不正です。理由はorg.seasar.doma.jdbc.ConfigException:
> >>> [DOMA2035]
> org.seasar.doma.jdbc.Configの実装クラス[xxx.package.config.doma.DomaConfig]のメソッド[getDataSourceName]からnullが返されました。
> >>> at
> org.seasar.framework.container.assembler.AbstractBindingTypeDef.getValue(AbstractBindingTypeDef.java:297)
> >>> at
> org.seasar.framework.container.assembler.AbstractBindingTypeDef.bindAuto(AbstractBindingTypeDef.java:149)
> >>> at
> org.seasar.framework.container.assembler.BindingTypeMustDef.doBind(BindingTypeMustDef.java:45)
> >>> at
> org.seasar.framework.container.assembler.AbstractBindingTypeDef.bind(AbstractBindingTypeDef.java:91)
> >>> at
> org.seasar.framework.container.assembler.AccessTypeFieldDef.bind(AccessTypeFieldDef.java:50)
> >>> at
> org.seasar.framework.container.assembler.AccessTypeFieldDef.bind(AccessTypeFieldDef.java:42)
> >>> at
> org.seasar.framework.container.assembler.AutoPropertyAssembler.assemble(AutoPropertyAssembler.java:56)
> >>> at
> org.seasar.framework.container.deployer.PrototypeComponentDeployer.deploy(PrototypeComponentDeployer.java:43)
> >>> at
> org.seasar.framework.container.impl.ComponentDefImpl.getComponent(ComponentDefImpl.java:111)
> >>> at
> org.seasar.framework.container.impl.S2ContainerImpl.getComponent(S2ContainerImpl.java:129)
> >>> at
> org.seasar.framework.container.assembler.AbstractBindingTypeDef.getValue(AbstractBindingTypeDef.java:295)
> >>> ... 36 more
> >>> Caused by:
> org.seasar.framework.exception.InvocationTargetRuntimeException:
> >>>
> [ESSR0043]xxx.package.dao.base.impl.AnyTableDaoImpl$$EnhancedByS2AOP$$17ccb2fが呼び出した対象が不正です。理由はorg.seasar.doma.jdbc.ConfigException:
> >>> [DOMA2035]
> org.seasar.doma.jdbc.Configの実装クラス[xxx.package.config.doma.DomaConfig]のメソッド[getDataSourceName]からnullが返されました。
> >>> at
> org.seasar.framework.util.ConstructorUtil.newInstance(ConstructorUtil.java:65)
> >>> at
> org.seasar.framework.container.assembler.AbstractConstructorAssembler.assembleDefault(AbstractConstructorAssembler.java:115)
> >>> at
> org.seasar.framework.container.assembler.AutoConstructorAssembler.doAssemble(AutoConstructorAssembler.java:44)
> >>> at
> org.seasar.framework.container.assembler.AbstractConstructorAssembler.assemble(AbstractConstructorAssembler.java:55)
> >>> at
> org.seasar.framework.container.deployer.PrototypeComponentDeployer.deploy(PrototypeComponentDeployer.java:42)
> >>> at
> org.seasar.framework.container.impl.ComponentDefImpl.getComponent(ComponentDefImpl.java:111)
> >>> at
> org.seasar.framework.container.impl.S2ContainerImpl.getComponent(S2ContainerImpl.java:129)
> >>> at
> org.seasar.framework.container.assembler.AbstractBindingTypeDef.getValue(AbstractBindingTypeDef.java:295)
> >>> ... 46 more
> >>> Caused by: org.seasar.doma.jdbc.ConfigException: [DOMA2035]
> >>>
> org.seasar.doma.jdbc.Configの実装クラス[xxx.package.config.doma.DomaConfig]のメソッド[getDataSourceName]からnullが返されました。
> >>> at
> org.seasar.doma.internal.jdbc.dao.AbstractDao.validateConfig(AbstractDao.java:120)
> >>> at
> org.seasar.doma.internal.jdbc.dao.AbstractDao.<init>(AbstractDao.java:56)
> >>> at
> xxx.package.dao.base.impl.AnyTableDaoImpl.<init>(AnyTableDaoImpl.java:13)
> >>> at
> xxx.package.dao.base.impl.AnyTableDaoImpl$$EnhancedByS2AOP$$17ccb2f.<init>(AnyTableDaoImpl$$EnhancedByS2AOP$$17ccb2f.java)
> >>> at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native
> Method)
> >>> at
> sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
> >>> at
> sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
> >>> at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
> >>> at
> org.seasar.framework.util.ConstructorUtil.newInstance(ConstructorUtil.java:57)
> >>> ... 53 more
> >>> 2011-10-11 12:21:34,255 [http-8080-2] DEBUG
> >>> org.seasar.framework.container.hotdeploy.HotdeployBehavior - HOT
> >>> deployを終了しました
> >>>
> >>> 以上、よろしくお願いいたします。
> >>>
> >>> 2011年10月11日11:40 Toshihiro Nakamura <[E-MAIL ADDRESS DELETED]>:
> >>>>
> >>>> 中村(taedium)です。
> >>>>
> >>>> > <component name="actionCustomizer"
> >>>> > class="org.seasar.framework.container.customizer.CustomizerChain">
> >>>> > <initMethod name="addAspectCustomizer">
> >>>> > <arg>"selectDataSourceInterceptor"</arg>
> >>>> > <arg>true</arg> // ←追加
> >>>> > </initMethod>
> >>>> > ....
> >>>> > </component>
> >>>> > とするだけで宜しかったでしょうか?
> >>>>
> >>>> はい、大丈夫です。
> >>>>
> >>>> > 1リクエストの間であれば、複数のprototypeオブジェクトの間で同じrequestオブジェクトが使いまわされる、
> >>>> > という認識で合っているでしょうか?
> >>>>
> >>>> 合っています。
> >>>>
> >>>>
> >>>> 2011年10月11日10:44 . <[E-MAIL ADDRESS DELETED]>:
> >>>> > 返信ありがとうございます。
> >>>> > okudaです。
> >>>> >
> >>>> >> 修正してSNAPSHOTを作成したのでdoma-1.18.0.jarの代わりに
> >>>> >> 次のjarで試していただけないでしょうか。
> >>>> > 早速のご対応ありがとうございます。
> >>>> > 動作確認が終わりましたら、改めてご報告いたします。
> >>>> >
> >>>> >> インターセプタをカスタマイザで設定する際useLookupAdapterをtrueにする必要があります。
> >>>> > 情報ありがとうございます。
> >>>> > <component name="actionCustomizer"
> >>>> > class="org.seasar.framework.container.customizer.CustomizerChain">
> >>>> > <initMethod name="addAspectCustomizer">
> >>>> > <arg>"selectDataSourceInterceptor"</arg>
> >>>> > <arg>true</arg> // ←追加
> >>>> > </initMethod>
> >>>> > ....
> >>>> > </component>
> >>>> > とするだけで宜しかったでしょうか?
> >>>> > (記載いただいたリンクの上段AspectCustomizer を利用する例は、コンポーネント自動登録を利用しない場合の
> >>>> > addCustomizerのコード例の認識です。)
> >>>> >
> >>>> > 少し話が逸れてしまうのですが、S2のインスタンス管理について質問させてください。
> >>>> > インスタンス属性として、singleton, prototype, request, etc..とありますが、
> >>>> > 下のレベルから上のレベルをDIで保持するとき、例えば、
> >>>> > prototypeスコープのオブジェクトのメンバフィールドでrequestスコープのResourceが定義されている場合、
> >>>> > 1リクエストの間であれば、複数のprototypeオブジェクトの間で同じrequestオブジェクトが使いまわされる、
> >>>> > という認識で合っているでしょうか?
> >>>> > (凄く初歩的な質問かと思いますが、DIを初めて利用するものでして。。)
> >>>> > 以上、よろしくお願いいたします。
> >>>> >
> >>>> >
> >>>> > 2011年10月10日22:39 Toshihiro Nakamura <[E-MAIL ADDRESS DELETED]>:
> >>>> >>
> >>>> >> 中村(taedium)です。
> >>>> >>
> >>>> >> > また、デバッグ実行で追ってみた限りでは、AnyTableDaoImpl(doma...AbstractDao)のコンストラクタから
> >>>> >> > RuntimeConfigをインスタンス化する際の
> >>>> >> > AssertionUtil.assertNotNull(config.getDataSourceName()); にて
> >>>> >> > 前述のようにnullで取得されるため、エラーが発生しているようでした。
> >>>> >>
> >>>> >> この挙動は、Domaのバグですね。。。
> >>>> >> 修正してSNAPSHOTを作成したのでdoma-1.18.0.jarの代わりに
> >>>> >> 次のjarで試していただけないでしょうか。
> >>>> >>
> >>>> >>
> http://maven.seasar.org/maven2-snapshot/org/seasar/doma/doma/1.19.0-SNAPSHOT/doma-1.19.0-20111010.130704-1.jar
> >>>> >>
> >>>> >> それと、今回の現象と直接は関係ありませんが、
> >>>> >> インターセプタをカスタマイザで設定する際useLookupAdapterをtrueにする必要があります。
> >>>> >> (そうしないと、COOL deploy時に、インターセプタがprototypeとして動作しません)
> >>>> >> 設定方法は次のリンク先が参考になります。
> >>>> >> http://www.seasar.org/wiki/index.php?FAQ%2FS2AOP#q69751d4
> >>>> >>
> >>>> >> 2011年10月10日12:29 . <[E-MAIL ADDRESS DELETED]>:
> >>>> >> > 返信ありがとうございます。
> >>>> >> > okduaです。
> >>>> >> >
> >>>> >> >> 「getComponentによって取得する」とありますが、これは、
> >>>> >> >> net.arnx.jsonic.web.extension.S2ContainerクラスのgetComponentメソッド
> >>>> >> >> の中で行われる処理を指しているのでしょうか?
> >>>> >> > 申し訳ありません。
> >>>> >> >
> net.arnx.jsonic.web.extension.S2ContainerクラスのgetComponentを指していました。
> >>>> >> >
> >>>> >> >
> (補足ですが、net.arnx.jsonic.web.RESTServletの中では、S2ContainerからSingletonS2ContainerFactoryへ
> >>>> >> > 委譲してgetComponentからcomponentを取得し、別途呼び出すメソッド名を決定してから、
> >>>> >> > componentにexecuteをかけているようです。)
> >>>> >> >
> >>>> >> >> SelectDataSourceInterceptorはS2コンテナに登録できていますか?
> >>>> >> > はい、パッケージ名.interceptor.SelectDataSourceInterceptorとして作成しております。
> >>>> >> > また、creator.dicon には、InterceptorCreator および ActionCreatorを
> >>>> >> > 定義しております。
> >>>> >> > (Service/DAOについても、該当のCreatorを定義し、自動登録を利用しています。)
> >>>> >> >
> >>>> >> >> コンストラクタとgetComponentは別物ですし、それらの前に実行させるというの
> >>>> >> >> とはちがうんじゃないでしょうか。
> >>>> >> > ActionCreatorを利用した場合、Actionは request スコープで作成されると
> >>>> >> > リファレンスにありましたので、てっきりgetComponentがコールされた時に
> >>>> >> > インスタンス化を行っているものと思っていました。
> >>>> >> > また、Actionインスタンス化時に、Serviceのインスタンス化も行われ、
> >>>> >> > 更にその中でDAOのインスタンス化が行われ、、と伝播するものと解釈していました。
> >>>> >> > (スコープによってsingletonで準備するものは、インスタンス化されないという意味
> >>>> >> > で、厳格には別物と表現されているのでしたら、すみません。)
> >>>> >> >
> >>>> >> > 何故、コンストラクタと私が思ったのかというと、
> >>>> >> > ・DAOを利用するAction (厳密には「DAOを利用するService」を利用するAction)
> >>>> >> > ・DAOを利用しないAction
> >>>> >> > の二つで試してみたところ、後者のDAOを利用しないActionでは、
> >>>> >> > SelectDataSourceInterceptor.invoke()が実行されたためです。
> >>>> >> > (実行はブレークポイント&ログ出力で確認しました。)
> >>>> >> > また、前者のDAOを利用するActionの場合は、
> >>>> >> > 下記のようなログが出力されていました。
> >>>> >> > ですので、実際のリクエストに対するメソッドの実行の前にDAOのインスタンス化が行われ、
> >>>> >> > Dao.constructor() → SelectDataSourceInterceptor.invoke()
> >>>> >> >
> >>>> >> >
> のようになってしまい、SelectDataSourceInterceptor.invoke()の前にAppConfigからDataSourceNameを
> >>>> >> > 取得しようとしているのではないか?と解釈したためです。
> >>>> >> > また、デバッグ実行で追ってみた限りでは、AnyTableDaoImpl(doma...AbstractDao)のコンストラクタから
> >>>> >> > RuntimeConfigをインスタンス化する際の
> >>>> >> > AssertionUtil.assertNotNull(config.getDataSourceName()); にて
> >>>> >> > 前述のようにnullで取得されるため、エラーが発生しているようでした。
> >>>> >> >
> >>>> >> > あと一歩のような気がするのですが、どう設定すればよいのか分からない次第です。。
> >>>> >> > 言葉足らずな部分もあるかと思いますが、ご教示いただけると幸いです。
> >>>> >> >
> >>>> >> >
> >>>> >> > 【ログ】
> >>>> >> > ...
> >>>> >> >
> >>>> >> >
> クラス(foo.bar.package.action.LoginAction[login_loginAction])のコンポーネント定義を登録します
> >>>> >> > ...
> >>>> >> >
> >>>> >> >
> クラス(foo.bar.package.interceptor.SelectDataSourceInterceptor[selectDataSourceInterceptor])のコンポーネント定義を登録します
> >>>> >> > ...
> >>>> >> >
> >>>> >> >
> クラス(foo.bar.package.service.LoginService[login_loginService])のコンポーネント定義を登録します
> >>>> >> > ...
> >>>> >> >
> >>>> >> >
> クラス(foo.bar.package.dao.base.impl.AnyTableDaoImpl[base_anyTableDao])のコンポーネント定義を登録します
> >>>> >> >
> >>>> >> > 以上、よろしくお願いいたします。
> >>>> >> >
> >>>> >> > 2011年10月10日4:29 Toshihiro Nakamura <[E-MAIL ADDRESS DELETED]
> >:
> >>>> >> >>
> >>>> >> >> 中村(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 mailing list
> >>>> >> >> [E-MAIL ADDRESS DELETED]
> >>>> >> >> https://ml.seasar.org/mailman/listinfo/seasar-user
> >>>> >> >
> >>>> >> >
> >>>> >> > _______________________________________________
> >>>> >> > Seasar-user mailing list
> >>>> >> > [E-MAIL ADDRESS DELETED]
> >>>> >> > https://ml.seasar.org/mailman/listinfo/seasar-user
> >>>> >> >
> >>>> >> >
> >>>> >>
> >>>> >>
> >>>> >>
> >>>> >> --
> >>>> >> Toshihiro Nakamura
> >>>> >> _______________________________________________
> >>>> >> Seasar-user mailing list
> >>>> >> [E-MAIL ADDRESS DELETED]
> >>>> >> https://ml.seasar.org/mailman/listinfo/seasar-user
> >>>> >
> >>>> >
> >>>> > _______________________________________________
> >>>> > Seasar-user mailing list
> >>>> > [E-MAIL ADDRESS DELETED]
> >>>> > https://ml.seasar.org/mailman/listinfo/seasar-user
> >>>> >
> >>>> >
> >>>>
> >>>>
> >>>>
> >>>> --
> >>>> Toshihiro Nakamura
> >>>> _______________________________________________
> >>>> Seasar-user mailing list
> >>>> [E-MAIL ADDRESS DELETED]
> >>>> https://ml.seasar.org/mailman/listinfo/seasar-user
> >>> _______________________________________________
> >>> Seasar-user mailing list
> >>> [E-MAIL ADDRESS DELETED]
> >>> https://ml.seasar.org/mailman/listinfo/seasar-user
> >>>
> >>
> >>
> >>
> >> --
> >> Toshihiro Nakamura
> >> _______________________________________________
> >> Seasar-user mailing list
> >> [E-MAIL ADDRESS DELETED]
> >> https://ml.seasar.org/mailman/listinfo/seasar-user
> >>
> > _______________________________________________
> > Seasar-user mailing list
> > [E-MAIL ADDRESS DELETED]
> > https://ml.seasar.org/mailman/listinfo/seasar-user
> >
>
>
>
> --
> Toshihiro Nakamura
> _______________________________________________
> Seasar-user mailing list
> [E-MAIL ADDRESS DELETED]
> https://ml.seasar.org/mailman/listinfo/seasar-user
>
-------------- next part --------------
HTMLの添付ファイルを保管しました...
URL: <http://ml.seasar.org/archives/seasar-user/attachments/20111012/5844d75b/attachment.html>
Seasar-user メーリングリストの案内