dbflute / dbflute-core

DBFlute core libraries for Java8
http://dbflute.seasar.org/
23 stars 18 forks source link

DBFlute Engine: support multipleDB for Google Guice #144

Closed jflute closed 2 years ago

jflute commented 2 years ago

Feedback from DBFlute Slack: https://dbflute.slack.com/archives/CAPH91CH2/p1651136409033359

XenonAbe commented 2 years ago

f1c4690 の修正は、 behaviorSelector を Named("behaviorSelector") として取得する、ということですよね? これだと、複数DBが3つ目になると同じように破綻してしまうと思います。

Named({DB名}) で取得出来るようにするのが良いと思います。

利用するクラスのコンストラクタが下記のようになるのがいいんじゃないでしょうか。

@Inject
public Foo(BehaviorSelector behaviorSelectorForMainDB, 
           Named("subDB") BehaviorSelector behaviorSelectorForSubDB,
           Named("subDB2") BehaviorSelector behaviorSelectorForSubDB2) {
  ...
}
追記

複数DBが3つ目になると同じように破綻してしまうと思います。

これは誤りでした。DBごとの名前がついていました。

しかし、Namedにクラス名までつけるのは冗長ですので、 prefixだけNamedに与える方が良いと思うのです。

jflute commented 2 years ago

@XenonAbe ありがとうございます。 このコンポーネント名ですが、projectPrefix もしくは allcommonPrefix と連動するようになっています。

// 複数DB - クラス名の prefix を (必要であれば) 設定する https://dbflute.seasar.org/ja/manual/function/genbafit/projectfit/multipledb/index.html#prefixunique

なるほど、ここはGoogle Guiceと他のDIコンテナとのコンポーネント名に対する扱いの違いでしょうかね。

Spring, Lasta Diだと、コンポーネント名だけでコンポーネントが取得ができます。 (場合によってはフィールドの変数名とかをコンポーネント名と一致させてDIすることも)

BehaviorSelector selector = context.getBean("behaviorSelector"); // spring

ゆえに、コンポーネント名にクラス名っぽいものを入れてコンポーネント全体でユニークに識別しないとなのですが...

Guiceだと、名前だけで取得するような機能はなく、あくまで同じ型の識別情報になるので...

injector.getInstance("behaviorSelector"); // String引数のメソッドはない

同じ型でユニークでありさえすれば良いというところでしょうか?

確かに全部同じ名前で登録してもエラーにはならないんですね。

bind(BehaviorSelector.class).annotatedWith(Names.named("resola")).toInstance(behaviorSelector);
bind(BehaviorCommandInvoker.class).annotatedWith(Names.named("resola")).toInstance(behaviorCommandInvoker);
bind(InvokerAssistant.class).annotatedWith(Names.named("resola")).toInstance(invokerAssistant);
bind(CommonColumnAutoSetupper.class).annotatedWith(Names.named("resola")).toInstance(commonColumnAutoSetupper);

ただ、injector.getInstance(Key key); という Key で取得するメソッドが気になっています。 でもこれも、型を指定すること前提ですかね。ちょっと調べてみます。

jflute commented 2 years ago

@XenonAbe injector.getInstance(Key key)も基本的には型をベースに名前を補足的に使う感じのようですね。

DBFluteの中でコンポーネント名がDIコンテナ間でルールが変わってしまうので、何かそこに依存するロジックがあったら?ってのが若干不安ですが... 恐らくないはずですし、あってもGuiceに閉じる話なので気軽に対応できると思うので、アプリ側で利用しやすい形に直したいと思います。

ただ、isDBFluteModuleGuiceRuntimeComponentByName=trueのときで、 projectPrefixやallcommonPrefixが設定されていないときはエラーになるようにしました。 isDBFluteModuleGuiceRuntimeComponentByNameはprefixがあること前提となります。

jflute commented 2 years ago

jflute memo: prefixが設定されてないのにbyNameのときのエラーハンドリングを実装。

ただ、isDBFluteModuleGuiceRuntimeComponentByName=trueのときで、 projectPrefixやallcommonPrefixが設定されていないときはエラーになるようにしました。

こんな感じのエラーを出すようにした。

[df-generate]   ... 34 more
[df-generate] Caused by: org.dbflute.exception.DfIllegalPropertySettingException: Look! Read the message below.
[df-generate] /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
[df-generate] Guice byName requires projectPrefix or allcommonPrefix.
[df-generate] 
[df-generate] [Advice]
[df-generate] If isDBFluteModuleGuiceRuntimeComponentByName=true,
[df-generate] then use projectPrefix or allcommonPrefix.
[df-generate] 
[df-generate] isDBFluteModuleGuiceRuntimeComponentByName is on dependencyInjectionMap.dfprop.
[df-generate] projectPrefix, allcommonPrefix are on basicInfoMap.dfprop.
[df-generate] 
[df-generate] [componentName (for debug)]
[df-generate] behaviorSelector
[df-generate] * * * * * * * * * */
jflute commented 2 years ago

@XenonAbe prefixのみがnamedに入るようにしました。

bind(BehaviorSelector.class).annotatedWith(Names.named("resola")).toInstance(behaviorSelector);
bind(BehaviorCommandInvoker.class).annotatedWith(Names.named("resola")).toInstance(behaviorCommandInvoker);
bind(InvokerAssistant.class).annotatedWith(Names.named("resola")).toInstance(invokerAssistant);
bind(CommonColumnAutoSetupper.class).annotatedWith(Names.named("resola")).toInstance(commonColumnAutoSetupper);

active-hangarプロジェクトで試しています。 https://github.com/dbflute-test/dbflute-test-active-hangar

ドキュメントにも反映しました https://dbflute.seasar.org/ja/manual/function/genbafit/projectfit/multipledb/index.html#runtimebyname

jflute commented 2 years ago

done, released at 1.2.6