I am currently using Tapestry 5 in my application, where the datasource is set via hibernate.cfg.xml. I want to be able to change the datasource dynamically at runtime to a non-JNDI datasource. I achieved to do it programmatically using the following code:
Configuration configuration = new Configuration();
configuration.setProperty("hibernate.connection.driver_class", "org.postgresql.Driver");
configuration.setProperty("hibernate.connection.url", dbUrl + "?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory");
configuration.setProperty("hibernate.connection.username", username);
configuration.setProperty("hibernate.connection.password", password);
SessionFactory sf = configuration.buildSessionFactory();
Session newSession = sf.openSession();
newSession.clear();
This works. When I am using this session, I successfully have access to my datasource. However, when I call
session.saveOrUpdate(entry);
at some point Hibernate tries to use the datasource set in hibernate.cfg.xml. Do you have any idea, how to solve this problem?
I assume you are familiar with Tapestry IOC concepts. You need to override HibernateSessionSource service (org.apache.tapestry5.hibernate.HibernateSessionSource). There are several other ways to make it happen, but you could create HibernateConfigurationUpdater service that knows about your local, overridden version of HibernateSessionSourceImpl (i.e. set a reference of the impl to the HibernateConfigurationUpdater service while you are building it). HibernateConfigurationUpdater.changeConfiguration(Configuration configuration) would then call (your) CustomHibernateSessionSourceImpl.setSessionFactory() once it receives a new configuration. You need to think through synchronization issues. Also, make sure you really need dynamic configuration - is multitenant not enough for your case? (At least JPA supports multitenancy perfectly - the only difference is that you need to know all your datasources at start-up time).