9

私は現在、Dropwizard + Guice + Jersey ベースのアプリケーションを構築しており、当面はデータベース アクセスが JDBI によって処理されます。

私が達成しようとしているのは、リソースがサービス クラスにアクセスし、DAO クラスがデータベースにアクセスする典型的なエンタープライズ アーキテクチャを実現することです。これらすべてを適切な DI 方法で接続できればよいのですが、他のすべてが失敗した場合は、アプリケーションの run() メソッドでオブジェクト グラフを作成できると思います。

だから、私は以前にここで言及されたこの問題に遭遇しています: DBIFactory を取得するには、環境と構成の両方が必要です。これらは、run() 時ではなく、Guice が注入マジックを実行するときに何らかの形で利用可能である必要があります。 .

Dropwizard と Guice の初心者である私がこれまでにまとめることができたのは、DAO オブジェクトのプロバイダーが必要であるということです。

public class UserDAOProvider implements Provider<UserDAO> {

    @Inject
    Environment environment;
    @Inject
    Configuration configuration;

    @Override
    public UserDAO get() {
        final DBIFactory factory = new DBIFactory();
        final (MyConfiguration) config = (MyConfiguration) configuration;
        DBI jdbi = null;
        try {
            jdbi = factory.build(environment, config.getDataSourceFactory(),
                    "mysql");
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return jdbi.onDemand(UserDAO.class);
    }

}

これをシングルトン プロバイダーとして登録すると、UserDAO をサービスに挿入できるようになります。

では、実際に環境をプロバイダーに注入するにはどうすればよいでしょうか。現在、環境に適したコンストラクターが見つからないという Guice で立ち往生しているため、Dropwizard 自体から取得せずにインスタンス化しようとしています。

これは実行可能のようです。DropWizardEnvironmentModuleが私が必要としているものだと思うdropwizard-guiceパッケージがあります。しかし、物事を組み立てる方法を理解するために、ここでパズルのピースが欠けているように感じます. これまでのところ、完全に機能する例を見つけることができませんでした...

4

3 に答える 3

4

OPと同じ問題がありましたが、JDBIではなくHibernateを使用していました。ただし、私の簡単な解決策は JDBI に適用できDBIFactoryますSessionFactory

最初に、Guice モジュールにシングルトン SessionFactory のインジェクション プロバイダーを追加します。

public class MyModule extends AbstractModule {

    private SessionFactory sessionFactory;

    @Override
    protected void configure() {
    }

    @Provides
    SessionFactory providesSessionFactory() {

        if (sessionFactory == null) {
             throw new ProvisionException("The Hibernate session factory has not yet been set. This is likely caused by forgetting to call setSessionFactory during Application.run()");
        }

       return sessionFactory;
    }

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }
}

SessionFactoryアプリケーションの run() メソッドからシングルトンを設定する必要があります。あなたの場合、JDBI を使用して、ここで DBIFactory を作成および構成してから、Guice モジュールに渡します。

public void run(MyConfiguration configuration, Environment environment) {

    myModule.setSessionFactory(hibernateBundle.getSessionFactory());
    ...
}

これで、SessionFactory を必要な場所に注入できるようになりました。コンストラクターに @Inject でアノテーションを付け、SessionFactory シングルトンを注入するだけで、DAO クラスの暗黙的なバインディングを使用するようになりました。DAO クラスのプロバイダーを明示的に作成しません。

@Singleton
public class WidgetDAO extends AbstractDAO<App> {

    @Inject
    public WidgetDAO(SessionFactory factory) {
        super(factory);
    }

    public Optional<Widget> findById(Long id) {
        return Optional.fromNullable(get(id));
    }
    ...
}

これで、DAO シングルトン インスタンスをリソースに挿入できます。

@Path("/widgets")
@Produces(MediaType.APPLICATION_JSON)
public class WidgetsResource {

    private final WidgetDAO widgetDAO;

    @Inject
    public WidgetsResource(WidgetDAO widgetDAO) {
        this.widgetDAO = widgetDAO;
    }
    ...
}

このアプローチは、直接の依存関係のみを注入するという Guice の推奨に従っていることに注意してください。DBI ファクトリを作成できるようにするためだけに Envrionment と Configuration を注入しようとしないでください。ビルド済みの DBI ファクトリ自体を注入してください。

于 2015-01-22T12:16:27.667 に答える
0

同じ構成 (dw-jdbi-guice) と、Application物事をさらに複雑にする抽象的な「基本」クラスがあります。

メソッド中に多くのことが発生し、多くのrunことが構成オブジェクトに依存するため、実行メソッドでインジェクターを作成することになりました。しかし、bootsrap(ObjectMapper などの) オブジェクトも必要なので、最終的List<Module>に Application クラスにフィールドができました。最も美しいソリューションではありませんが、さまざまなシナリオを処理できます。

于 2014-11-25T21:02:04.603 に答える