Technology: hibernate-core4.2.5, Spring3.1
Project Type: Web Application
Problem Statement: We are implementing hibernate multi tenancy using SCHEMA approach.We are facing problem while getting sessionfactory by making a rest call to RegisterController.java(/login)
hibernate.cfg.xml
Code:
```
`<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="hibernate.connection.url">jdbc:mysql://localhost/</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password"></property>
<property name="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Drop and re-create the database schema on startup
<property name="hbm2ddl.auto">none</property>-->
<property name="hibernate.multiTenancy">SCHEMA</property>
<property name="hibernate.tenant_identifier_resolver">com.techmust.SchemaResolver</property>
<property name="hibernate.multi_tenant_connection_provider">com.techmust.MultiTenantProvider</property>
<!-- <mapping resource="com/techmust/resource/login.hbm.xml"/> -->
</session-factory>
</hibernate-configuration> `
```
HibernateUtil.java
Code:
```
Configuration oConfiguration = new Configuration ();
oConfiguration.configure("hibernate.cfg.xml");
m_oLogger.debug("HibernateUtil Configuration:" + oConfiguration);
ServiceRegistryBuilder oServiceRegistryBuilder = new ServiceRegistryBuilder();
ServiceRegistryBuilder oBuilder = oServiceRegistryBuilder.applySettings( oConfiguration.getProperties() );
ServiceRegistry oServiceRegistry = oBuilder.buildServiceRegistry();
m_oLogger.debug("HibernateUtil :oServiceRegistry " + oServiceRegistry);
sessionFactory = oConfiguration.buildSessionFactory(oServiceRegistry);
m_oLogger.debug("HibernateUtil :" + sessionFactory);
```
MultiTenantProvider.java
Code:
```
public class MultiTenantProvider implements MultiTenantConnectionProvider , ServiceRegistryAwareService {
private static final long serialVersionUID = 4368575201221677384L;
private DriverManagerConnectionProviderImpl connectionProvider = new DriverManagerConnectionProviderImpl ();
@Override
public boolean supportsAggressiveRelease() {
return false;
}
@Override
public void injectServices(ServiceRegistryImplementor serviceRegistry)
{
Map lSettings = serviceRegistry.getService(ConfigurationService.class).getSettings();
connectionProvider.injectServices(serviceRegistry);
connectionProvider.configure(lSettings);
}
@Override
public boolean isUnwrappableAs(Class clazz) {
return false;
}
@Override
public <T> T unwrap(Class<T> clazz) {
return null;
}
@Override
public Connection getAnyConnection() throws SQLException {
final Connection connection = connectionProvider.getConnection();
return connection;
}
@Override
public Connection getConnection(String tenantIdentifier) throws SQLException {
final Connection connection = getAnyConnection();
try {
connection.createStatement().execute( "USE " + tenantIdentifier );
}
catch (SQLException e) {
throw new HibernateException("Could not alter JDBC connection to specified schema [" + tenantIdentifier + "]", e);
}
return connection;
}
@Override
public void releaseAnyConnection(Connection connection) throws SQLException {
try {
connection.createStatement().execute( "USE 'public'" );
}
catch (SQLException e) {
throw new HibernateException("Could not alter JDBC connection to specified schema [public]", e);
}
connectionProvider.closeConnection(connection);
}
@Override
public void releaseConnection(String tenantIdentifier, Connection connection) throws SQLException {
releaseAnyConnection(connection);
}
}
```
SchemaResolver.java
Code:
```
public class SchemaResolver implements CurrentTenantIdentifierResolver {
@Override
public String resolveCurrentTenantIdentifier() {
return "db1"; //TODO: Implement service to identify tenant like: userService.getCurrentlyAuthUser().getTenantId();
}
@Override
public boolean validateExistingCurrentSessions() {
return false;
}
}
```
RegiaterController.java
Code:
```
@Controller
@RequestMapping(value="/login")
public class RegisterController
{
static final Logger m_oLogger = Logger.getLogger(RegisterController.class);
@RequestMapping(method = RequestMethod.POST, headers = {"Content-type=application/json"})
@ResponseBody
public boolean login(@RequestBody RegisterData oData)
{
boolean bIsSaved = false;
PropertyConfigurator.configure("C:\\Program Files (x86)\\Apache Software Foundation\\Tomcat 7.0\\webapps\\register\\WEB-INF\\classes\\com\\techmust\\resource\\log4j.properties");
SessionFactory oSessionFactory = HibernateUtil.buildSessionFactory();
SessionBuilder oSessionBuilder = oSessionFactory.withOptions();
SessionBuilder oBuilder = oSessionBuilder.tenantIdentifier("db1");
Session oSession = oBuilder.openSession();
// Session oSession = oSessionFactory.openSession();
m_oLogger.info("login [IN] : " + oSession);
try
{
if(!(oData.getStrPassword().equals("") && oData.getStrUserName().equals("")))
{
Transaction oTransaction = oSession.beginTransaction();
System.out.println(oData.getStrUserName());
System.out.println(oData.getStrPassword());
System.out.println(oSession);
oSession.save(oData);
oTransaction.commit();
bIsSaved = oTransaction.wasCommitted();
oSession.flush();
}
}
catch (Exception oException)
{
m_oLogger.error ("login - oException : " + oException);
}
return bIsSaved;
}
}
```
Please find the Log
Code:
```
Caused by: java.lang.NullPointerException
at org.hibernate.engine.jdbc.internal.JdbcServicesImpl$MultiTenantConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcServicesImpl.java:271)
at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:119)
at org.hibernate.service.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:75)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:159)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:131)
at org.hibernate.cfg.SettingsFactory.buildSettings(SettingsFactory.java:71)
at org.hibernate.cfg.Configuration.buildSettingsInternal(Configuration.java:2270)
at org.hibernate.cfg.Configuration.buildSettings(Configuration.java:2266)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1735)
at com.techmust.HibernateUtil.buildSessionFactory(HibernateUtil.java:36)
... 37 more
```
The above code is for web application.
Below is the java application code which uses same hibernate files as above and gives the desired output
Code:
```
public class RegisterController
{
public static void main(String args[]){
RegisterControllerMethod oController = new RegisterControllerMethod();
oController.getSampleDetails("db1");
oController.getSampleDetails("db2");
}
}
class RegisterControllerMethod {
static final Logger m_oLogger = Logger.getLogger(RegisterController.class);
public void getSampleDetails(String strSchema)
{
PropertyConfigurator.configure("E:\\Development\\javaprojects\\Register_Server\\src\\com\\techmust\\resource\\log4j.properties");
Session oSession = HibernateUtil.buildSessionFactory().withOptions().tenantIdentifier(strSchema).openSession();
m_oLogger.info("login [IN] : " + oSession);
RegisterData oData = new RegisterData();
oData.setStrPassword("admin");
oData.setStrUserName("admin");
try
{
Transaction oTransaction = oSession.beginTransaction();
System.out.println(oSession);
oSession.save(oData);
oTransaction.commit();
oTransaction.wasCommitted();
oSession.flush();
}
catch (Exception oException)
{
m_oLogger.error ("login - oException : " + oException);
}
}
}
```
Please guide us on running the above code as web application.