Multi-Tenancy
in Java applications
@ladislavGazo
gazo@seges.sk
The application
user
|
bunch of JavaScript
|
service
|
domain model
Implication
user1 ... userN
|
same bunch of JavaScript
|
service
|
ONE database
One application to rule them all
The term multi-tenancy in general is applied to software development to indicate an architecture in which a single running instance of an application simultaneously serves multiple clients (tenants).
This is highly common in SaaS solutions.
Isolating information (data, customizations, etc) pertaining to the various tenants is a particular challenge in these systems.
Split me now!
user1 -> BA, user2 -> BA, user 3 -> KE, user 4 -> ZA
|
again the same JavaScript
|
(almost) the same service
|
DB (BA), DB (KE), DB (ZA)
- a lot of "tenant" dependent data - high volumes
- performance
- separation -> easier backup and restore
- scalability of front-end and service layer
Hibernate is the easiest
Multi-tenant configuration
<property name="hibernate.multiTenancy" value="DATABASE" />
<property name="hibernate.tenant_identifier_resolver" value="sk.seges.hroddelenie.configuration.MultiTenantIdentifierResolver" />
<property name="hibernate.multi_tenant_connection_provider" value="org.hibernate.service.jdbc.connections.spi.DataSourceBasedMultiTenantConnectionProviderImpl" />
<property name="hibernate.connection.datasource" value="java:comp/env/jdbc/hr" />
<property name="hibernate.multi_tenant.datasource.identifier_for_any" value="default" />
Switch it ON
hibernate.multiTenancy
Configure where to look for the current tenant identifier
hibernate.tenant_identifier_resolver
Where are my connections?
hibernate.multi_tenant_connection_provider
Hibernate's DataSourceBasedMultiTenantConnectionProviderImpl utilizes JNDI lookups
Point to JNDI root for datasources
hibernate.connection.datasource
... and the default
hibernate.multi_tenant.datasource.identifier_for_any
So in the end = java:comp/env/jdbc/hr/default
But there are things that don't work
- EHCache configuration from previous version is different
- Hibernate's internal schema update does not work
- NPE !!! ........ who would have said that
Migration
Hibernate exporter
is not helpful
Do you have Envers?
then you need custom exporter
It is easy to write
but don't forget the AuditConfiguration
Ejb3Configuration jpaConfiguration = new Ejb3Configuration().configure(
unitName, null);
Configuration hibernateConfiguration = jpaConfiguration
.getHibernateConfiguration();
hibernateConfiguration.buildMappings();
AuditConfiguration auditConfiguration = AuditConfiguration.getFor(hibernateConfiguration);
and use EnversSchemaGenerator at last
Get rid of NPE bug
{ "hibernate.multiTenancy",
"hibernate.tenant_identifier_resolver",
"hibernate.multi_tenant_connection_provider",
"hibernate.connection.datasource",
"hibernate.multi_tenant.datasource.identifier_for_any" }
Run the exporter from Maven
Combine it with Liquibase
version 3.0.6 contains feature to populate all tenant databases
MultiTenantSpringLiquibase
Don't forget...
it is maintenable but generated SQL needs to be checked
existing databases must be moved to "point 0"
A bit of logging
Importance of logging - using MDC to track requests
MDC.put("tenant", clientOrgz);
log4j.appender.stdout.layout.ConversionPattern = APP [%d{ISO8601}] - %-5p [%t|%X{tenant}|%X{requestId}] %F:%M %-30.30c{1} - %m%n
And the most boring...
Design
your app to be multi-tenant
Send tenant identification
- in HTTP Header
- use Filter to get it out
- in Service parameters
- using ThreadLocal variable
- via tenant-URL-based service calls
- rmi://localhost:12345/<tenant>/<service>
- etc...
Thanks for listening
@ladislavGazo
gazo@seges.sk
Multi-tenant applications in Java
By lgazo
Multi-tenant applications in Java
- 1,327