Reputation: 629
I am writing a library which retrieves data from a specific data schema. This library holds a Datasource object which can be anything. Right now I have defined the name of the datasource within the library which I would like to avoid.
import javax.sql.DataSource
public class MyLibraryDao.java {
private static final DS_NAME = "MY_DS_NAME";
@Resource(name = "default", lookup = DS_NAME , type = DataSource.class)
protected DataSource dataSource;
}
The DAO class is not directly exposed to the client. There is a service layer inbetween:
import javax.inject.Inject;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Model;
@ApplicationScoped
@Model
public class MyLibraryService {
@Inject
MyLibraryDao dao;
}
Now, how would I pass the datasource object to the library?
I assume I need to create a constructor in the DAO with takes a DataSource but what about the service? The library will be used in a CDI environment.
Upvotes: 1
Views: 558
Reputation: 40296
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:
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.Upvotes: 2