- Datasource name context: it's in fact a class to store the name of the DataSource et a class (a simple ThreadLocal) to hold it (the known place).
Here is an example of these two classes and interfaces:
public class DataSourceContextHolder {
private static ThreadLocal contextHolder = new ThreadLocal();
public static void setContext(DataSourceContext context) {
contextHolder.set(context);
}
public static DataSourceContext getContext() {
return (DataSourceContext) contextHolder.get();
}
}
public interface DataSourceContext {
public void setId(String id);
public String getId();
}
public class DataSourceContextImpl implements DataSourceContext {
private String id;
public void setId(String id) {
this.id=id;
}
public String getId() {
return id;
}
}
- Filter to detect context: the filter look for an datasource id in the session and put it in the context holder. The filter might be enhanced to have the feature to select the id and block this change when a user is authenticated on a database.
- Datasource selector: thanks to Spring, there is a datasource abstraction so we can put a proxy between our datasource and application. Our datasource proxy could select another datasource configure in Spring at runtime using the datasource context.
Here is an example of this proxy:
public class DataSourceSelector extends AbstractDataSource
implements BeanFactoryAware {
private BeanFactory beanFactory;
public void setBeanFactory(BeanFactory beanFactory)
throws BeansException {
this.beanFactory=beanFactory;
}
public Connection getConnection() throws SQLException {
DataSourceContext context=DataSourceContextHolder.getContext();
DataSource datasource=(DataSource)beanFactory.getBean(
context.getId());
return datasource.getConnection();
}
public Connection getConnection(String login,String password)
throws SQLException {
DataSourceContext context=DataSourceContextHolder.getContext();
DataSource datasource=(DataSource)beanFactory.getBean(
context.getId());
return datasource.getConnection(arg0,arg1);
}
}
This mechanism is independant of the application (Spring offers this
facility!) but we must be carefull to not permit to access a database
without be authenticated. The order of filter (with use of security filter such Acegi's) could be dangerous... The solution is not to permit to switch from
a datasource to another when a user is authenticated.