tamuraです

DropwizardでGoogle Guiceを使ってDependency Injection(DI)を行いました。

DIを使った理由としてはデータベースコネクションを引き回したくなかったためです。


構成

dw6

リポジトリ

DAOを管理するクラスです。

クラス定義

Dropwizardでデータベースpart4 でやったように、abstractなDAOを用意します。

public abstract class Repository implements ransactional<Repository> {

    @CreateSqlObject
    public abstract SelectDAO createSelectDAO();

}

SelectDAOなどはこのabstractなDAOを継承して作ります。

使い方

DBIを使ってインスタンス化するところまでは一緒です。

public class Main extends Application<AppConfiguration> {

    ....

    @Override
    public void run(AppConfiguration configuration, Environment environment) throws Exception {
        final DBIFactory factory = new DBIFactory();
        final DBI jdbi = factory.build(environment, configuration.getDataSourceFactory(), "app");
        final Repository repository = dbi.onDemand(Repository.class);
    }
}

この後、GuiceのInjectorにこのインスタンスを登録します。

常にこのインスタンスが使われるように登録しておきます。

Injector injector = Guice.createInjector(new AbstractModule() {
    @Override
    protected void configure() {
        // SomeServiceはSomeServiceImplが毎回新しいインスタンスが生成される
        bind(SomeService.class).to(SomeServiceImpl.class);

        // Repository.class は常に同じインスタンスが使われる
        bind(Repository.class).toInstance(repository);
    }
});

Resourceの定義

SomeResourceの実装の例です。

privateなフィールドに@Injectをつけてもちゃんとインジェクションしてくれますが、 テストを行いやすいようにsetterを用意しています。

@Path("/some")
@Produces(MediaType.APPLICATION_JSON)
public class SomeResource {

    private SomeService someService;
    @Inject
    public void setSomeService(SomeService someService) {
        this.someService = someService;
    }

    @GET
    public String getSome() {
        return someService.getSome();
    }
}

Jerseyへの登録

environment.jersey().register(injector.getInstance(SomeResource.class));

上記のやり方で大丈夫です。

getInstanceSomeResourceのインスタンスを取得できます。 特に何も紐付けしていない場合はSomeResourcenewされます。

Serviceの定義

まずはインターフェース。

public interface SomeService {

    public String getSome();
}

続いて実装です。

ここでもsetterを用意してテストを行いやすくしています。

public class SomeServiceImpl implements SomeService {

    private Repository repository;
    @Inject
    public void setRepository(Repository repository) {
        this.repository = repository;
    }

    @Override
    public String getSome() {
        SelectDAO dao = repository.createSelectDAO();
        Optional result = dao.selectSome();
        if (result.isPresent()) {
            return result.get();
        }
        else {
            return "not found";
        }
    }
}

まとめ

Google Guiceを使うことで、データベースコネクションを引きずり回さなくてよくなりました。

1点注意が必要で、Guiceを使ってインスタンス化しないとインスタンスがインジェクションされません。 そのため「この条件の場合はこのロジッククラスをインスタンス化する」というようなロジックがあると、今回の方法は使えません。 (そういう作りはあまりないと思うのですが)