First things first your library needs a datasource, let's declare the dependency:
public class MyLibraryDao {
@Inject
protected DataSource dataSource;
}
Now the rest of the application that is using the library is responsible to provide a datasource to CDI; a simple way is:
// Example; your implementation may vary
public class AppDatasourceProducer {
private static final DS_NAME = "MY_APP_DS_NAME";
@Resource(name = "default", lookup = DS_NAME , type = DataSource.class)
protected DataSource dataSource;
@Produces
@ApplicationScoped
public DataSource getDatasource() {
return dataSource;
}
}
What's changed? Now your application is responsible for knowing the datasource name AND providing the datasource itself. The example above can work in JEE environments that honor the @Resource
annotation. Using a different implementation for the provider would work in e.g. a desktop environment (standalone application), making your library reusable.
The exact datasource name may be fixed, just like in the example, or read from configuration, e.g. from system properties (like mentioned in a comment); e.g.:
// Example 2, DS name from system properties
@ApplicationScoped
public class AppDatasourceProducer {
protected DataSource dataSource;
@PostConstruct
void init() throws Exception {
String dsName = System.getProperty("XXXXX");
InitialContext ic = new InitialContext();
dataSource = (DataSource) ic.lookup(dsName);
}
@Produces
@ApplicationScoped
public DataSource getDatasource() {
return dataSource;
}
}
Going further:
- An application that uses your library may be using several datasources, for whatever reason. You may want to provide a qualifier to specify the datasource to be used by your app.
- I used field injection in
MyLibraryDao
for simplicity. If you change to constructor injection then, at least MyLibraryDao
, will be usable in non-CDI environments as well, i.e. if you have obtained a DataSource
somehow, you can now do new MyLibraryDao(datasource)
. Even more reusability.