Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
manjunath_b
Advisor
Advisor
This blog is Part 4 of the blog series on "Developing Multi-tenant applications on the SAP HANA Cloud Platform".

In Part1, we introduced the concept of multi-tenant applications and the use case,
in Part2, we showcased a technical overview of the demo application built in the series and in Part3, the setup of the project for building the multi-tenant application was discussed.

In this blog, we will focus on how we can achieve data isolation using the multi-tenancy of the Persistence Service on the SAP HANA Cloud Platform. We will also start with Data Initialization for our multi-tenant application of Pollution Monitoring, which we are building as a part of the blog series.

Consider the following scenario:


Robert wants his application to isolate the data of each his customers, when it is stored. This is very important to ensure the security of every customer's data and the application. Robert is wondering how this can be achieved?

The solution which Robert is looking for, can be achieved using database or persistence multi-tenancy. Persistence Multi-tenancy allows for data from different consumers to be stored, separately in the database.






There are three possible methods to achieve database/persistence multi-tenancy.




  1. Using a 'Tenant Discriminator' column




  2. Using a 'Table-per-tenant' multi-tenancy




  3. Using Multi-tenant Database Containers




Let us look at what these 3 methods have to offer:

Tenant Discriminator Column: This method uses a single column in the table to ensure data isolation. In this approach a single DB schema is shared between all application consumers. The tenant identifier provided by the Tenant Runtime can be used as the value in the discriminator column. To ensure data separation in the application, each SQL statement must include the tenant identifier.



To implement such a separation via a discriminator column, the multi-tenancy annotations of EclipseLink/JPA may be used. Entities which shall be tenant aware are annotated with the @Multitenant annotation. The discriminator column is defined via the @TenantDiscriminatorColumn annotation. As the length of the tenantId which is provided by the tenant runtime differs from the default length for the discriminator column in EclipseLink, it is important to set the correct length of 36 characters. When accessing data for a multi-tenant entity, the tenantId must be provided to the entity manager.
@Entity
@Table(name = "PERSON")
@Multitenant
@TenantDiscriminatorColumn(name = "TenantId",
contextProperty = "eclipselink-tenant.id", length = 36)
@NamedQuery(name = "AllPersons", query = "select p from Person p")
public class Person {
...
}


Table-per-tenant multi-tenancy
: This method allows multiple tenants of an application to isolate their data in one or more tenant-specific tables. This is achieved by creating a different table or schema in the database for each tenant. A tenant table discriminator specifies how to discriminate the tenant's tables from the other tenants' tables. The tenants' tables can be in the same schema, using a prefix or suffix naming pattern to distinguish them; or they can be in separate schema, using a schema tenant table discriminator.






To implement such a separation, the multi-tenancy annotations of EclipseLink/JPA may be used again. EclipseLink supports a flavor of multitenancy called the ‘TABLE_PER_TENANT’ multitenancy. So, entities which shall be tenant aware are annotated with the @Multitenant(TABLE_PER_TENANT) annotation.

As mentioned earlier, multiple tenants' tables can be in a shared schema, identified using a prefix or suffix naming pattern; or they can be in separate, tenant-specific schema based on the @TenantTableDiscriminator annotation. Using this annotation we can specify which tables are associated with which tenants. The tenant table discriminator must include a type and a context property:

  • The type attribute can be one of the following:

    • Use PREFIX to apply the tenant table discriminator as a prefix to all multi-tenant tables.

    • Use SUFFIX to apply the tenant table discriminator as a suffix to all multi-tenant tables.

    • Use SCHEMA to apply the tenant table discriminator as a schema to all multi-tenant tables.



  • The value of the contextproperty attribute is a tenant ID that identifies the tenant.


@Entity
@Table(name = "EMPLOYEE")
@Multitenant(TABLE_PER_TENANT)
@TenantTableDiscriminator(type=SCHEMA,
contextProperty="eclipselink-tenant.id")
public class Employee {
...
}

Multitenant Database Containers - MDC (*BETA): This method allows for data Isolation to be achieved by creating a different database container, also known as a tenant database, for each consumer. SAP HANA supports multiple isolated databases in a single HANA system. With this method we can achieve a high degree of isolation and security with less impact on the SQL query performance, as we do not have to worry about the complex authorizations we need to create for data isolation. More details on consumption of MDC in applications will follow once it is Generally Available (GA) on the SAP HANA Cloud Platform.






As a first step, Robert decides to go with the first and the easiest approach, to use a Tenant Discriminator Column for data isolation.

As mentioned earlier, this method uses a single column in a table to differentiate data from multiple consumers. This means that different consumers should have different values for the tenant discriminator column.

But how do we generate this value? Is this hardcoded? Manually created??

A brief note on the 'tenantid' concept:


We know that in a provider-managed application scenario, like the one Robert is creating, each application consumer gets his own consumer-specific URL for the provider application. This is because the consumer has subscribed to the provider application. When an application is launched via a consumer-specific URL, the Tenant Runtime will be able to identify the current consumer of the application. The tenant runtime also provides an API to retrieve the current application consumer. Each application consumer is identified by a unique ID which is called tenantId.



 




Coming back to the application we are building, let us check out how Persistence Multitenancy is implemented in the project. In the previous blog (Part3), we have imported the project from Github to Eclipse. We will use the same imported project for the subsequent steps:



















Steps Screenshot
In the imported project,
navigate to
/pollutionmonitoring/src
/main/java/

com/sap/hana
/cloud/samples

/pollutionmonitoring/model
/BaseObject.java
.Open the java file.
In the code, you can see how the
persistence multi-tenancy
has been achieved using
the Tenant Discriminator
column
method
In the imported project,
navigate to
/pollutionmonitoring/src
/main/webapp/WEB-INF/web.xml.
We can see that the
data source (db) has been bound
to the application as the default db.






Robert is aware that the consumer of his application would require to load data into the app for them to use it. So he has to build and expose a service in the application, which can be used by consumers (like Emily) to push data into the app.


For this demo app, we implement this using a data initialization servlet, which is explained later. Let’s check out how this servlet is setup:















Steps Screenshot
In the imported project,
check the servlet /pollutionmonitoring/src/main/java
/com/sap/hana/cloud/samples
/pollutionmonitoring/api
/DataInitializationServlet.java
 
In the imported project, navigate to
/pollutionmonitoring/src/main
/webapp/WEB-INF/web.xml.
We can see that the servlet is
accessible using the path '/initialize'
 

The setup on the Provider account looks complete!

 




Emily, from ABC PetroCorp (consumer) will now access the Pollution Monitoring application using the subscription created (in previous blog Part3). The Pollution Monitoring Application, deals with 2 types of data,


    1. Pollution Data: which is read from sources like external APIs, Pollution sensors, etc.



For this demo we create this data using a Data Initialization Servlet, which is included in the project. This data is stored/persisted in the HANA DB on HCP, which is attached/bound to the application in the provider account.

 


    1. Plant Data: which is generally read from Systems of record like ERP systems, which is mostly On-Premise within the consumer private network.



This data is read ‘On-demand’ by the application, from the consumer system, i.e. does not persist on the HANA DB on HCP.
For more details on this flavor check out our upcoming blog (Part6) on Connectivity Service in a Multitenancy application.



Emily now needs to load the Pollution Data into her application.

Pollution Data Initialization


As mentioned earlier, for the purpose of demonstration, we have included a Data Initialization Servlet in the project, which can be utilized to push simulated (prepared) data to the HANA database. Let us check out how the data looks like and how this can be initialized using the servlet.

View prepared data:















Steps Screenshot
In the imported project,
navigate to /pollutionmonitoring/src
/main/java/com

/sap/hana/cloud
/samples/pollutionmonitoring

/api/DataInitializationServlet.java.Open the java file.
 
The prepared data for both the consumers
ABC PetroCorp and XYZ EnergyCorp
can be seen in the code.
 

Initialize the pollution data for consumer ABC PetroCorp by calling the Data Initialization Servlet:



























Steps Screenshot
In the HCP Cockpit,
go to the ABC Petro Corp (Consumer)
account.
 
Navigate to Applications -> Subscriptions  
List of subscribed Java and
HTML5 applications is displayed.
Click on the Java application pollutionmonitoring
 
In the Subscribed Java Application
Overview page, copy the Application URLs.
 
In a new browser tab/window,
paste the copied URL and add
/initialize?company=ABC PetroCorp to it.
Initialization should complete and
the data that was pushed to the
application should be displayed.
 

Stephen from XYZ EnergyCorp can also follow the same steps mentioned above, to create a tenant and load his data into it.

 




Done! We have introduced Persistence Multi-tenancy in our Pollution Monitoring application on HCP and initialized the application with the pollution data it needs.

In our next blog, we will look at setting up the Security and Identity Management to our application and move one step further in getting the Multi-tenant Application up and running!

See you there!
7 Comments