Configuring Multi-Tenancy¶
Use the -tenant option in server-app.options to specify that your service needs to support multiple tenants.
Corresponding TenantServlet and TenantServletBase classes will be generated into your project when it is built/rebuilt.
You can customize the code in the tenant servlet's tenantIdentifier method to determine the tenant ID for an incoming OData request. By default that method will use the ext_attr/zdn field of the client-provided Bearer token JWT payload (within the Authorization header).
For SAP Business Technology Platform (Cloud Foundry environment), the tenant servlet will also respond to Subscription callbacks from the SAP SaaS Provisioning Service. For custom tenant provisioning you may wish to customize one or more of the other methods in the tenant servlet.
In the bound SQL database, the xs_data_tenants table keeps track of each provisioned tenant ID, as well as a corresponding serial ID which is used elsewhere to compactly represent the tenant. Another table <appname>_xs_tenant_history_<version> keeps track of the status of each tenant and audit information regarding the date/time and admin user who initiated any tenant provisioning calls.
Other tables in the bound database will (by default) include a tenant_id column (also known as a tenant discriminator column), containing the serial ID of the tenant that each stored row belongs to. For each OData entity set in the service metadata, there is a separate table named after that entity set, and data for that entity set from multiple tenants is kept in the same table. The primary key of each table includes the tenant_id, and all access to such tables is limited to rows that match the appropriate tenant ID, as determined by the aforementioned tenantIdentifier method.
Database Schema per Tenant¶
You may want to keep data for different tenants in separate database schemas or even on separate database servers. Doing so requires some custom code.
-
In the
createSchemamethod of the tenant servlet, add code to create the tenant's database schema (e.g. using Service Manager APIs). -
In the
deleteSchemamethod of the tenant servlet, add code to remove the tenant's database schema (e.g. using Service Manager APIs). -
In the
ProviderSettingsclass, methodinit(SQLDatabaseProvider provider), add this code:provider.setDataSourceForTenant(tenantID -> createDataSourceForTenant(tenantID)); -
In the
ProviderSettingsclass, add acreateDataSourceForTenant(String tenantID)method. Use a third-party JDBC pooling data source layer, such as Apache or Hikari, to obtain and return a JDBCDataSource. Ensure it's configured correctly for connecting to the tenant's database. -
When using
Apache Commons DBCP, it's recommended to include thetestOnBorrowandvalidationQueryproperties. These help ensure that OData services recover gracefully from broken database connections. Additionally, use themaxTotalproperty to set the maximum number of concurrent database connections allowed.If you're using another JDBC data source provider, like Hikari, consult the relevant documentation to find equivalent configuration properties.
-
If you need customer-managed encryption keys, check out the
SAP HANA Database Key Management System. Add suitable custom code to yourcreateDataSourceForTenantmethod.