I am working on a project using Spring Data JPA (on Tomcat 7). I'am implementing a BeanFactoryPostProcessor
to dynamically create my DataSource
s. But the problem is that my DataSource
's information (name, url, etc..) is stored in a database itself.
@Component
class DatasourceRegisteringBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
// This doesn't work
@Autowired DatabaseService databaseService;
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// my code here ...
// ...
}
}
As you can see, i was trying to inject a service which can get me a list of all DataSource
s from my database, but it doesn't work. Is the anyway to connect to the database and get that list within the BeanFactoryPostProcessor
class? Any other workaround will be welcome. :)
BeanFactoryPostProcessor
s are a very special kind of concept in Spring. They are components that operate onBeanDefinition
instances, which are a metamodel of the bean instances to be created.That means, that at the point in time when the
BFPP
s are invoked, no bean instances have been created yet as the metamodel is about to be post processed (as the name suggests). Hence beans depended on by theBFPP
will be initialized extremely early in the lifecycle of the container. Thus it's highly recommended to not depend on application components fromBFPP
s or - if really required - only on beans that don't necessarily trigger the creation of a lot of downstream components.That said, you shouldn't depend on especially repositories from
BFPP
s as they usually require the creation of a lot of infrastructure components. I'd recommend getting the configuration properties that are required to connect to the configuration database (JDBC URL, username, password, etc.) and just create a throw-awayDataSource
that's only used to create a newBeanDefinition
for a newDataSource
that's going to be used by the application eventually.So here are the recommended steps (from the top of my head - might need some tweaking):
DataSource
@PropertySource
pointing to the properties containing the coordinates to connectinject the values of that
PropertySource
into the constructor of theBFPP
: