Dropwizard and Guice: injecting Environment

大城市里の小女人 提交于 2019-12-03 13:20:59

I had the same issue as OP but using Hibernate rather than JDBI. My simple solution is applicable to JDBI, though - just switch DBIFactory for SessionFactory.

First add an injection provider for a singleton SessionFactory in your Guice module:

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;
    }
}

You need to set the singleton SessionFactory from your application's run() method. In your case, using JDBI, this is where you would create and configure your DBIFactory before handing it over to the Guice module:

public void run(MyConfiguration configuration, Environment environment) {

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

Now SessionFactory can be injected wherever it is needed. I now use implicit binding for my DAO classes by just annotating the constructor with @Inject and injecting the SessionFactory singleton. I don't explicitly create providers for DAO classes:

@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));
    }
    ...
}

Now I can inject my DAO singleton instances into resources:

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

    private final WidgetDAO widgetDAO;

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

Note that this approach follows the Guice recommendation of injecting direct dependencies only. Don't try to inject Envrionment and Configuration just so that you can create a DBI factory - inject the prebuilt DBI factory itself.

Abhijeet Kushe

This is how I use Guice with Dropwizard. Inside your run() method add the line

Guice.createInjector(new ConsoleModule()); 

You cannot inject Environ

Create the class ConsoleModule

public class ConsoleModule extends AbstractModule {

    //configuration and env variable declaration

    public  ConsoleModule(ConsoleConfiguration consoleConfig, Environment env)
    {
        this.consoleConfig = consoleConfig;
        this.env= env;
    }

    protected void configure()
    {
        //You should not inject Configuration and Environment in your provider since you are mixing     
        //dropwizard framework stuff with Guice.Neverthless you will have to bind them in the below order

        bind(Configuration.class).toInstance(consoleConfig.class);
        bind(Environment.class).toInstance(env.class);
        bind(UserDAO.class).toProvider(UserDAOProvider.class).in(Singleton.class);
    }
}

We have the same configuration (dw-jdbi-guice) and also an abstract 'base' Application class which complicates things even more.

Since a lot of things happen during run method, and many things depend on the configuration objects we ended up creating the injector in the run method. But since we need objects from bootsrap also (e.g. ObjectMapper), we ended up having a List<Module> field in the Application class. Not the prettiest solution but can handle variety of scenarios.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!