Sunday, August 14, 2016

Writing a multi-tenant web app with Java and Spring

Hello everyone.

The goal for this post is to discuss how to develop and deploy to Tomcat an example of a multi-tenant Java web application.

Before we start, here's a couple of links that discuss the principles and challenges involved:
Here's the list of software you'll need for this project:

1. Java 1.8
2. Spring 4
3. Tomcat 8
4. PostgreSQL 9.4
5. Maven 2
6. Eclipse IDE 4.5
7. EclipseLink 2.6.3

First, let's consider the major steps needed to finish the project:

1. Install and configure the server environment where the Java app will be deployed to
2. Choose the data separation architecture at the database level
3. Write the application
4. Deploy to Tomcat

Now, let's consider the details of each of the above steps:

1. Install and configure the server
Because item number 1 above is time-consuming and may be new to a number of developers, I actually wrote a companion article dealing specifically with that: Setting up Tomcat + PostgreSQL for multi-tenant web apps in Linux.

2. Choose the data segregation architecture
Data segregation can be achieved in a number of ways for multi-tenancy apps. One of them is by creating different database "schemas", where each tenant's data set is stored in a different schema of the same database. That's the approach I've chosen for the sample application we'll discuss.

Using this technique, the database is organized as depicted in the following screenshot:

This allows the application to preface the table name by the tenant's identification name as the schema. For example, for tenant1's PRODUCT table, the application refers to it as tenant1.PRODUCT.

3. Write the application
I used Java + Spring + JPA + PostgreSQL to develop this application.

Please keep in mind that this application is contrived in some ways because my goal was to experiment with some concepts and get a refresher on others. For example, I wanted to find out how well - and how much coding would be required for - JPA to handle one-to-many relationships for database records; it actually require little extra code but there is definitely a learning curve to anyone new to this.

And especially I wanted to find out how much change would be required to migrate a single-tenant web app to a multi-tenant one. The design I chose is simple but works very well: One single database with multiple schemas (one per tenant) as shown in the picture above.

Here's the screenshot of the database structure showing 2 tenants:


So, here's a list of different techniques and technologies I employed in this app:

AJAX: nothing too fancy. In this app, I used it to invoke a web service and update only a portion of the page; who could possibly tolerate a full page refresh every time?
Spring: I used multiple modules of Spring: Spring MVC, Spring Security, Java only Spring configuration through Java annotations.
Pictures: I wanted to get a refresher on multi-part picture upload and handling of response in JavaScript.
JPA: I chose EclipseLink, but could very easily have chosen Hibernate, which is another JPA provider.
Restful web services: Spring allows you to easily create RESTful webservice. You just need to correctly configure your "controller" through Java annotations.
JSON: JSON is used in most - if not all - responses from the web services.
Multi-tenancy: Take a look at the RepositoryUtilityImpl class, which is a Singleton, and you'll see that I use the tenant's name string as schema name, also known as table qualifer.
Database: I used PostgreSQL, but you could easily migrate it to another DB by making a few changes to persistence.xml and the DB.properties file where the driver name is read from.

Again, I have to stress that this is just a contrived demo web app that I wrote in my spare time; hence, much can be improved. For example, of course a USER table would have to be created; will be working on that next. However, the multi-tenancy principle is there: data is securely separate from one tenant to the next.

4. Deploy the app to Tomcat
After this is all finished and tested locally as a single instance, the application can finally be copied to multiple directories in Tomcat and renamed to ROOT.war. There will be one directory for each of the tenants we have in our portfolio of clients.

Here's a screenshot of what tenant1 sees on the Menu page of the application:


And here's what tenant2 sees on the Menu page:

You haven't even started yet and already got 2 big clients?!!! Wow! 

Having a sub-domain named after its company's name gives the client/tenant a sense of ownership; he will also be able to change some aspects of the tenant's custom data at the Tenant Info page.

Is that sub-domain strategy and data segregation what you had in mind when you thought about multi-tenancy? Please share your comments below.

And lastly, and very important!, here's the link for the source code and the WAR file:
https://github.com/blueriversys/SpringMvcJpaApp


Thanks.
Joe


No comments:

Post a Comment