I'm planning to work on a multi-tenancy application and for now I'm just looking at different implementations on the web to understand the requirements needed to implement such task.
Hibernate + Spring boot are the technologies I'm planning to use.
From my readings, all the different tutorials are using the same approach which is to declare the data sources in a config file so that session factories are launched with the boot of the application, but I really want to have a higher level of the app, where I can add tenants dynamically and input their data sources informations.
This way the application can get the information of the new tenant without the need to touch the config files and re-boot the app.
I thought about having a separate database where I can store my tenants data source credentials or something like that. Can you give me another approach to solve this requirement or a link to an existing implementation that I can refer to.
Thanks
I got similar requirements in the past.
I implemented DataSource proxy class. The class has tenant resolver and a map of simple DataSources. All the places where we need a DataSource use the proxy.
On any method call e.g. getConnection() it resolves tenant, check whether the map contains already created DataSource (if not a new DataSource is created for the tenant and stored in the DB). Then the same method of real DataSource from the map is invoked.
Tenant resolver is ThreadLocal based where tenant value is stored in a filter (got tenant from request header) and used in the DataSource proxy.
What you need to do is using dynamic datasource routing of Spring Framweork via AbstractRoutingDataSource. This answer explains all for you.
In my question.I implements MultiTenantConnectionProvider and CurrentTenantIdentifierResolver.And use DataSourceLookup to choose datasource by tenant.This links is helpful to me.
Here is a full working example of a database-per-tenant multitenat app I built using Spring Boot 2, Spring JPA (Hibernate), Spring Security 5 running on MySQL.
I have explained how it all works and have shared the entire code too.
Take a look here.
Related
I'm looking to extend the user session in a Spring MVC app with Spring boot and Tomcat. Looking at the documentation there seems to be 2 relevant properties:
server.servlet.session.timeout
spring.session.timeout
Most examples out there seem to suggest to use server.servlet.session.timeout; what is the purpose of spring.session.timeout? Which one should be used to extend the user session?
spring.session.timeout is the property from a Spring sub-project called Spring Session. It will fallback to server.servlet.session.timeout if it is not set.
In short , Spring Session allows you to store HttpSession in RDBMS / Redis / Hazelcast Cluster / MongoDB rather than an internal map inside Tomcat .So the sessions is stored in the container agnostic way and make session clustering easier as you do not need to configure a Tomcat cluster.
So if you do not use Spring Session , you should use server.servlet.session.timeout
You should be able to set the server.session.timeout in your application.properties file to do the same
I think, If you add spring.session.timeout in application.properties the session timeout value mentioned using server.session.timeout will be overridden
After several readings about multi tenancy and how to implement it. I finally got my application working using Spring boot 2, Jpa and hibernate.
What I have for now is a schema per tenant architecture and every request use an X-tenantID header key to define the tenant from which the data should be queried.
Once I tried to implement security I found myself limited by this header key. What I want to achieve is to have a shared tenant where I should store all my users with the tenant identifier for each one of them, along with some other informations that should be used from all tenants. If it's possible how can I achieve such behavior? Is there a github project reference ? If a solution like eclipselink is proposed can you please reference an article explaining it's integration with spring boot?
The second question is how to create at runtime a new schema in database once a use is registered? A sample code or a documentation reference should be very welcomed.
Thanks
I am trying to figure out how can I dynamically update/reload externalized configuration in a Spring Boot application without restarting the whole application.
Most of the advice involves reloading ApplicationContext after changing the externalized configuration, but that is equivalent to restarting the entire application, so this is not really all that useful.
Reading through SpringBoot reference documentation, I found a chapter 23.7 Typesafe Configuration Properties.
If I understand it correctly, this allows to define simple POJO classes that will hold your application (externalized) configuration values as attributes.
In theory at least, this scheme could be used to bind beans only once to the required configuration POJO and upon configuration change just update the values in the POJO. Components could easily pick up the changes next time they access getters on the POJO...
However, I have yet not managed to figure out how to enable this type of behavior. Is there some glaringly obvious way to dynamically update components annotated with #ConfigurationProperties when relevant configuration has changed?
It sounds like you're looking for #RefreshScope which is provided by Spring Cloud. From the Spring Cloud documentation:
A Spring #Bean that is marked as #RefreshScope will get special treatment when there is a configuration change. This addresses the problem of stateful beans that only get their configuration injected when they are initialized. For instance if a DataSource has open connections when the database URL is changed via the Environment, we probably want the holders of those connections to be able to complete what they are doing. Then the next time someone borrows a connection from the pool he gets one with the new URL.
I am programming service for getting data from database and providing them via REST service. It uses spring mvc. My database connection cofiguration is in property file from where it is loaded by spring as a data source bean during context initialization.
Now my problem is - I want to change configuration in properties file (for example change database info) but I can't afford to restart the application server so the new configuration does not load.
How can I re-initialize spring context or some particular beans so the newly defined properties are used?
If you want multiple data source in spring and need to deciding appropriate data source dynamically at runtime you can do this with AbstractRoutingDataSource provided with spring. You have to implement your lookup key logic for determining data-source in method determineCurrentLookupKey(). With this you can map different beans to different data-sources at runtime. following are few questions relating to this context.
How to programatically change databases in Spring with one DataSource?
Also
dynamically change Spring data source
I have a requirement where i need to configure a Spring based application to work with two databases. We have two databases, one that we use to keep the live data and the other database is used as a datawarehouse and contains archived data (which has the exact structure as the Live db).
To keep it simple, assume that there is a request to search for a product. What the application should do is to search for the product details in the Live database and if not found it will check the archive database.
If i need to configure such a setup, do i still need to configure to datasources and would the search code have to use the first datasource to check the live database and if not found it will run another query using the archive database?
The above is probably doable but i am wondering whether there is a better way of doing this. For example, is it possible for the application to work on a single datasource even though behind the scenes it actually works with two databases?
The application is based on Spring, JPA/Hibernate, SOAP and Mysql database and Jboss 7 as the application server.
Any examples showing how this is configured using Spring and Jboss would be very useful.
Thanks
Spring has exactly what you want - the AbstractRoutingDataSource. See this blog post on how to use it. In your case, you need to switch the datasource during one request, so you'll need to have 2 transactions, switching the datasource between them by changing the datasource indicator on the ThreadLocal:
For these DAOs, demarcate the wrapping Service-layer either with distinct packages, class names, or method names
Indicate to Spring that the Service-layer method calls should run in their own transactional contexts by annotating with #Transactional(propogation=Propogation.REQUIRES_NEW)
Create an Aspect (using AspectJ annotation #Aspect) to fire around the service-layer method calls (using #Around) to set the ThreadLocal value before the method call, and to unset it afterwards
In the #Controller, simply call the Service-layer methods. The Aspect will take care of setting the values to indicate which datasource to use, and the AbstractRoutingDataSource will use that datasource in the context of each transaction.