My application is built using Guice and MyBatis. Different database connections are represented using javax.sql.DataSource. All classes that need access to a DataSource are declared within the same Guice PrivateModule that provides this DataSource as well. However, these modules grow over time and are harder to manage. In addition, I would like to be able to tie different DAO and their related classes into a separate Guice module and provide that module with a data source so the above module is better encapsulated and reusable with different data sources.
Technically speaking I would like to be able to write something like:
public class MyDataSourceModule extends PrivateModule {
@Override
protected void configure() {}
@Exposed
@Named("systemDataSource")
@Singleton
@Provides
DataSource provideDataSource() {
return ...;
}
}
such that the DataSource will be still available without a name within the module but only with the name outside the module. Annotations can be changed as needed. Is that possible and how?
What you want is possible by creating two different bindings in the same module.
(Side note: if you're not familiar with BindingAnnotations, you can find out more here. In my examples, I will be using @UsingSystemDataSource
as the binding annotation.)
Using EDSL in the configure()
method:
protected void configure() {
// binding for private use
bind(DataSource.class).to(SystemDataSourceImpl.class).in(Scopes.SINGLETON);
// binding for public use
bind(DataSource.class).annotatedWith(@UsingSystemDataSource.class).to(DataSource.class);
expose(DataSource.class).annotatedWith(@UsingSystemDataSource.class);
}
Now, if you need to do this without using EDSL, then your private module @Provides
methods would look like this:
@Provides
@Exposed
@UsingSystemDataSource
DataSource provideDataSourcePublicly(DataSource privatelyBoundDatasource) {
return privatelyBoundDatasource;
}
@Provides
@Singleton
DataSource provideDataSource() {
return ...;
}
Why does this even work?
This actually creates two different bindings—one linking DataSource
to SystemDataSource
and another linking @UsingSystemDataSource DataSource
to DataSource
. Using the expose()
method or @Exposed
, the private module exposes only the annotated version of the binding. (I couldn't find a source that explicitly states that it works for this use case, so I tested it myself.)