Announcement Announcement Module
Collapse
No announcement yet.
Issues with implementing multiTenancy in a webapplication. Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Issues with implementing multiTenancy in a webapplication.

    We are facing issues in implementing multiTenancy from Hibernate 4.1.9 in a web application which is using Spring MVC framework (Spring 3.1). Our Application is deployed on Apache Tomcat server 6.0.35
    We are maintaining one database per customer. We look at the customer identification from a properties file.

    We have separate instances of Tomcat server for each customer. We are hoping that using multiTenancy, we can have one instance of tomcat identifying the customer and directing the request to appropriate database depending on the customer identification.

    Following are the step by step details of the implementation we have done to incorporate MultiTenancy in our application:


    1) Tenant identifies and database login details are stored in a properties file. We have a bean that reads the properties file and creates a c3p0 ComboPooledDataSource for each customer.

    Code:
    <bean id="dataSourceFactory" class="com.....CustomerDataSourceFactory">
    <!-- details omitted, reads a properties file and has methods like: “DataSource getDataSource(int customerId)” -->
    </bean>

    2) A servlet filter sets a thread local variable with the tenant identifier based on the URL

    3) We’ve implemented CurrentTenantIdentifierResolver (references the thread local set in step 2)

    4) Implemented MultiTenantConnectionProvider. Our implementation fetches the data source for the customer from the bean created
    in step 1. We used the depends-on attribute to ensure that the CustomerDataSourceFactory is created before the SessionFactory.

    5) In applicationContext.xml, added support for multiTenancy by setting hibernate properties.

    Code:
     <bean id="dbTransactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager" depends-on="dbSessionFactory">
      		<property name="sessionFactory"><ref local="dbSessionFactory"/></property>
      		<property name="failEarlyOnGlobalRollbackOnly">
      			<value>true</value>
      		</property>
      	</bean>
      	
      	<!-- enable the configuration of transactional behavior based on annotations -->
      	<tx:annotation-driven transaction-manager="dbTransactionManager"/>
      	
      	<bean id="dbSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" depends-on="beanLocator">
            <property name="mappingResources">
            <list>
            	......................................
            </list>
            </property>
            <property name="hibernateProperties">
                <props>
                    <prop key="hibernate.dialect">org.hibernate.dialect.FirebirdDialect</prop>
    				<prop key="hibernate.multi_tenant_connection_provider">com.....MultiTenantDbConnectionProviderImpl</prop>
    				<prop key="hibernate.multiTenancy">DATABASE</prop>
    				<prop key="hibernate.tenant_identifier_resolver">com.....CurrentTenantIdentifierResolverImpl</prop>
    				
    			</props>
            </property>    </bean>


    With the above implementation, we are currently facing the following issues. Even if we have injected the sessionFactory in TransactionManager, the creation of the Transaction Manager bean fails with a null pointer Exception for sessionFactory bean.

    java.lang.IllegalStateException: Failed to load ApplicationContext
    at org.springframework.test.context.TestContext.getAp plicationContext(TestContext.java:157)
    at org.springframework.test.context.support.Dependenc yInjectionTestExecutionListener.injectDependencies (DependencyInjectionTestExecutionListener.java:109 )
    at org.springframework.test.context.support.Dependenc yInjectionTestExecutionListener.prepareTestInstanc e(DependencyInjectionTestExecutionListener.java:75 )
    at org.springframework.test.context.TestContextManage r.prepareTestInstance(TestContextManager.java:321)
    at org.springframework.test.context.junit4.SpringJUni t4ClassRunner.createTest(SpringJUnit4ClassRunner.j ava:211)
    at org.springframework.test.context.junit4.SpringJUni t4ClassRunner$1.runReflectiveCall(SpringJUnit4Clas sRunner.java:288)
    at org.junit.internal.runners.model.ReflectiveCallabl e.run(ReflectiveCallable.java:15)
    at org.springframework.test.context.junit4.SpringJUni t4ClassRunner.methodBlock(SpringJUnit4ClassRunner. java:290)
    at org.springframework.test.context.junit4.SpringJUni t4ClassRunner.runChild(SpringJUnit4ClassRunner.jav a:231)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild( BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner. java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRu nner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentR unner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRu nner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRu nner.java:184)
    at org.springframework.test.context.junit4.statements .RunBeforeTestClassCallbacks.evaluate(RunBeforeTes tClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements .RunAfterTestClassCallbacks.evaluate(RunAfterTestC lassCallbacks.java:71)
    at org.junit.runners.ParentRunner.run(ParentRunner.ja va:236)
    at org.springframework.test.context.junit4.SpringJUni t4ClassRunner.run(SpringJUnit4ClassRunner.java:174 )
    at org.apache.maven.surefire.junit4.JUnit4TestSet.exe cute(JUnit4TestSet.java:53)
    at org.apache.maven.surefire.junit4.JUnit4Provider.ex ecuteTestSet(JUnit4Provider.java:123)
    at org.apache.maven.surefire.junit4.JUnit4Provider.in voke(JUnit4Provider.java:104)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.apache.maven.surefire.util.ReflectionUtils.inv okeMethodWithArray(ReflectionUtils.java:164)
    at org.apache.maven.surefire.booter.ProviderFactory$P roviderProxy.invoke(ProviderFactory.java:110)
    Last edited by AbigailJasmine; Mar 22nd, 2013, 12:58 PM.

  • #2
    you could use an
    Code:
    AbstractRoutingDataSource
    for your use case

    Comment

    Working...
    X