multi-tenancy in java
DESCRIPTION
An introduction to multi-tenancy in Java enterprise applications. It covers the steps needed to use Hibernate's support, integration with migration framework Liquibase and logging.TRANSCRIPT
![Page 2: Multi-tenancy in Java](https://reader033.vdocuments.net/reader033/viewer/2022051312/546efc78b4af9f040c8b4569/html5/thumbnails/2.jpg)
THE APPLICATIONuser
|
bunch of JavaScript
|
service
|
domain model
![Page 3: Multi-tenancy in Java](https://reader033.vdocuments.net/reader033/viewer/2022051312/546efc78b4af9f040c8b4569/html5/thumbnails/3.jpg)
IMPLICATIONuser1 ... userN
|
same bunch of JavaScript
|
service
|
ONE database
![Page 4: Multi-tenancy in Java](https://reader033.vdocuments.net/reader033/viewer/2022051312/546efc78b4af9f040c8b4569/html5/thumbnails/4.jpg)
ONE APPLICATION TO RULE THEM ALLThe term multi-tenancy in general is applied to software
development to indicate an architecture in which a single runninginstance of an application simultaneously serves multiple clients
(tenants).
This is highly common in SaaS solutions.
Isolating information (data, customizations, etc) pertaining to thevarious tenants is a particular challenge in these systems.
![Page 5: Multi-tenancy in Java](https://reader033.vdocuments.net/reader033/viewer/2022051312/546efc78b4af9f040c8b4569/html5/thumbnails/5.jpg)
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)
![Page 6: Multi-tenancy in Java](https://reader033.vdocuments.net/reader033/viewer/2022051312/546efc78b4af9f040c8b4569/html5/thumbnails/6.jpg)
a lot of "tenant" dependent data - high volumesperformanceseparation -> easier backup and restorescalability of front-end and service layer
![Page 7: Multi-tenancy in Java](https://reader033.vdocuments.net/reader033/viewer/2022051312/546efc78b4af9f040c8b4569/html5/thumbnails/7.jpg)
HIBERNATE IS THE EASIEST
![Page 8: Multi-tenancy in Java](https://reader033.vdocuments.net/reader033/viewer/2022051312/546efc78b4af9f040c8b4569/html5/thumbnails/8.jpg)
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" />
![Page 9: Multi-tenancy in Java](https://reader033.vdocuments.net/reader033/viewer/2022051312/546efc78b4af9f040c8b4569/html5/thumbnails/9.jpg)
SWITCH IT ON
hibernate.multiTenancy
![Page 10: Multi-tenancy in Java](https://reader033.vdocuments.net/reader033/viewer/2022051312/546efc78b4af9f040c8b4569/html5/thumbnails/10.jpg)
CONFIGURE WHERE TO LOOK FOR THECURRENT TENANT IDENTIFIER
hibernate.tenant_identifier_resolver
![Page 11: Multi-tenancy in Java](https://reader033.vdocuments.net/reader033/viewer/2022051312/546efc78b4af9f040c8b4569/html5/thumbnails/11.jpg)
WHERE ARE MY CONNECTIONS?
hibernate.multi_tenant_connection_provider
Hibernate'sDataSourceBasedMultiTenantConnectionProviderImpl
utilizes JNDI lookups
![Page 12: Multi-tenancy in Java](https://reader033.vdocuments.net/reader033/viewer/2022051312/546efc78b4af9f040c8b4569/html5/thumbnails/12.jpg)
POINT TO JNDI ROOT FOR DATASOURCES
hibernate.connection.datasource
![Page 13: Multi-tenancy in Java](https://reader033.vdocuments.net/reader033/viewer/2022051312/546efc78b4af9f040c8b4569/html5/thumbnails/13.jpg)
... AND THE DEFAULT
So in the end = java:comp/env/jdbc/hr/default
hibernate.multi_tenant.datasource.identifier_for_any
![Page 14: Multi-tenancy in Java](https://reader033.vdocuments.net/reader033/viewer/2022051312/546efc78b4af9f040c8b4569/html5/thumbnails/14.jpg)
BUT THERE ARE THINGS THAT DON'T WORKEHCache configuration from previous version is differentHibernate's internal schema update does not work
NPE !!! ........ who would have said that
![Page 15: Multi-tenancy in Java](https://reader033.vdocuments.net/reader033/viewer/2022051312/546efc78b4af9f040c8b4569/html5/thumbnails/15.jpg)
MIGRATION
![Page 16: Multi-tenancy in Java](https://reader033.vdocuments.net/reader033/viewer/2022051312/546efc78b4af9f040c8b4569/html5/thumbnails/16.jpg)
HIBERNATE EXPORTER is not helpful
![Page 17: Multi-tenancy in Java](https://reader033.vdocuments.net/reader033/viewer/2022051312/546efc78b4af9f040c8b4569/html5/thumbnails/17.jpg)
DO YOU HAVE ENVERS?then you need custom exporter
![Page 18: Multi-tenancy in Java](https://reader033.vdocuments.net/reader033/viewer/2022051312/546efc78b4af9f040c8b4569/html5/thumbnails/18.jpg)
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
![Page 19: Multi-tenancy in Java](https://reader033.vdocuments.net/reader033/viewer/2022051312/546efc78b4af9f040c8b4569/html5/thumbnails/19.jpg)
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" }
![Page 20: Multi-tenancy in Java](https://reader033.vdocuments.net/reader033/viewer/2022051312/546efc78b4af9f040c8b4569/html5/thumbnails/20.jpg)
RUN THE EXPORTER FROM MAVEN
![Page 21: Multi-tenancy in Java](https://reader033.vdocuments.net/reader033/viewer/2022051312/546efc78b4af9f040c8b4569/html5/thumbnails/21.jpg)
COMBINE IT WITH LIQUIBASE
version 3.0.6 contains feature to populate all tenant databases
MultiTenantSpringLiquibase
![Page 22: Multi-tenancy in Java](https://reader033.vdocuments.net/reader033/viewer/2022051312/546efc78b4af9f040c8b4569/html5/thumbnails/22.jpg)
DON'T FORGET...it is maintenable but generated SQL needs to be checked
existing databases must be moved to "point 0"
![Page 23: Multi-tenancy in Java](https://reader033.vdocuments.net/reader033/viewer/2022051312/546efc78b4af9f040c8b4569/html5/thumbnails/23.jpg)
A BIT OF LOGGING http://www.slf4j.org/faq.html#logging_performance
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
![Page 24: Multi-tenancy in Java](https://reader033.vdocuments.net/reader033/viewer/2022051312/546efc78b4af9f040c8b4569/html5/thumbnails/24.jpg)
AND THE MOST BORING...
DESIGNyour app to be multi-tenant
![Page 25: Multi-tenancy in Java](https://reader033.vdocuments.net/reader033/viewer/2022051312/546efc78b4af9f040c8b4569/html5/thumbnails/25.jpg)
SEND TENANT IDENTIFICATIONin HTTP Header
use Filter to get it outin Service parametersusing ThreadLocal variablevia tenant-URL-based service calls
rmi://localhost:12345/<tenant>/<service>etc...